ProgramCache.cpp revision 63553478130f78d44c8fbeaebc610e19925544a5
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include <utils/String8.h> 20 21#include "Caches.h" 22#include "ProgramCache.h" 23 24namespace android { 25namespace uirenderer { 26 27/////////////////////////////////////////////////////////////////////////////// 28// Defines 29/////////////////////////////////////////////////////////////////////////////// 30 31#define MODULATE_OP_NO_MODULATE 0 32#define MODULATE_OP_MODULATE 1 33#define MODULATE_OP_MODULATE_A8 2 34 35/////////////////////////////////////////////////////////////////////////////// 36// Vertex shaders snippets 37/////////////////////////////////////////////////////////////////////////////// 38 39const char* gVS_Header_Attributes = 40 "attribute vec4 position;\n"; 41const char* gVS_Header_Attributes_TexCoords = 42 "attribute vec2 texCoords;\n"; 43const char* gVS_Header_Attributes_AAParameters = 44 "attribute float vtxWidth;\n" 45 "attribute float vtxLength;\n"; 46const char* gVS_Header_Uniforms_TextureTransform = 47 "uniform mat4 mainTextureTransform;\n"; 48const char* gVS_Header_Uniforms = 49 "uniform mat4 transform;\n"; 50const char* gVS_Header_Uniforms_IsPoint = 51 "uniform mediump float pointSize;\n"; 52const char* gVS_Header_Uniforms_HasGradient[3] = { 53 // Linear 54 "uniform mat4 screenSpace;\n", 55 // Circular 56 "uniform mat4 screenSpace;\n", 57 // Sweep 58 "uniform mat4 screenSpace;\n" 59}; 60const char* gVS_Header_Uniforms_HasBitmap = 61 "uniform mat4 textureTransform;\n" 62 "uniform mediump vec2 textureDimension;\n"; 63const char* gVS_Header_Varyings_HasTexture = 64 "varying vec2 outTexCoords;\n"; 65const char* gVS_Header_Varyings_IsAA = 66 "varying float widthProportion;\n" 67 "varying float lengthProportion;\n"; 68const char* gVS_Header_Varyings_HasBitmap = 69 "varying highp vec2 outBitmapTexCoords;\n"; 70const char* gVS_Header_Varyings_PointHasBitmap = 71 "varying highp vec2 outPointBitmapTexCoords;\n"; 72// TODO: These values are used to sample from textures, 73// they may need to be highp 74const char* gVS_Header_Varyings_HasGradient[3] = { 75 // Linear 76 "varying highp vec2 linear;\n", 77 // Circular 78 "varying highp vec2 circular;\n", 79 // Sweep 80 "varying highp vec2 sweep;\n" 81}; 82const char* gVS_Main = 83 "\nvoid main(void) {\n"; 84const char* gVS_Main_OutTexCoords = 85 " outTexCoords = texCoords;\n"; 86const char* gVS_Main_OutTransformedTexCoords = 87 " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n"; 88const char* gVS_Main_OutGradient[3] = { 89 // Linear 90 " linear = vec2((screenSpace * position).x, 0.5);\n", 91 // Circular 92 " circular = (screenSpace * position).xy;\n", 93 // Sweep 94 " sweep = (screenSpace * position).xy;\n" 95}; 96const char* gVS_Main_OutBitmapTexCoords = 97 " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; 98const char* gVS_Main_OutPointBitmapTexCoords = 99 " outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; 100const char* gVS_Main_Position = 101 " gl_Position = transform * position;\n"; 102const char* gVS_Main_PointSize = 103 " gl_PointSize = pointSize;\n"; 104const char* gVS_Main_AA = 105 " widthProportion = vtxWidth;\n" 106 " lengthProportion = vtxLength;\n"; 107const char* gVS_Footer = 108 "}\n\n"; 109 110/////////////////////////////////////////////////////////////////////////////// 111// Fragment shaders snippets 112/////////////////////////////////////////////////////////////////////////////// 113 114const char* gFS_Header_Extension_FramebufferFetch = 115 "#extension GL_NV_shader_framebuffer_fetch : enable\n\n"; 116const char* gFS_Header_Extension_ExternalTexture = 117 "#extension GL_OES_EGL_image_external : require\n\n"; 118const char* gFS_Header = 119 "precision mediump float;\n\n"; 120const char* gFS_Uniforms_Color = 121 "uniform vec4 color;\n"; 122const char* gFS_Uniforms_AA = 123 "uniform float boundaryWidth;\n" 124 "uniform float inverseBoundaryWidth;\n" 125 "uniform float boundaryLength;\n" 126 "uniform float inverseBoundaryLength;\n"; 127const char* gFS_Header_Uniforms_PointHasBitmap = 128 "uniform vec2 textureDimension;\n" 129 "uniform float pointSize;\n"; 130const char* gFS_Uniforms_TextureSampler = 131 "uniform sampler2D sampler;\n"; 132const char* gFS_Uniforms_ExternalTextureSampler = 133 "uniform samplerExternalOES sampler;\n"; 134const char* gFS_Uniforms_GradientSampler[3] = { 135 // Linear 136 "uniform sampler2D gradientSampler;\n", 137 // Circular 138 "uniform sampler2D gradientSampler;\n", 139 // Sweep 140 "uniform sampler2D gradientSampler;\n" 141}; 142const char* gFS_Uniforms_BitmapSampler = 143 "uniform sampler2D bitmapSampler;\n"; 144const char* gFS_Uniforms_ColorOp[4] = { 145 // None 146 "", 147 // Matrix 148 "uniform mat4 colorMatrix;\n" 149 "uniform vec4 colorMatrixVector;\n", 150 // Lighting 151 "uniform vec4 lightingMul;\n" 152 "uniform vec4 lightingAdd;\n", 153 // PorterDuff 154 "uniform vec4 colorBlend;\n" 155}; 156const char* gFS_Uniforms_Gamma = 157 "uniform float gamma;\n"; 158 159const char* gFS_Main = 160 "\nvoid main(void) {\n" 161 " lowp vec4 fragColor;\n"; 162 163const char* gFS_Main_PointBitmapTexCoords = 164 " highp vec2 outBitmapTexCoords = outPointBitmapTexCoords + " 165 "((gl_PointCoord - vec2(0.5, 0.5)) * textureDimension * vec2(pointSize, pointSize));\n"; 166 167// Fast cases 168const char* gFS_Fast_SingleColor = 169 "\nvoid main(void) {\n" 170 " gl_FragColor = color;\n" 171 "}\n\n"; 172const char* gFS_Fast_SingleTexture = 173 "\nvoid main(void) {\n" 174 " gl_FragColor = texture2D(sampler, outTexCoords);\n" 175 "}\n\n"; 176const char* gFS_Fast_SingleModulateTexture = 177 "\nvoid main(void) {\n" 178 " gl_FragColor = color.a * texture2D(sampler, outTexCoords);\n" 179 "}\n\n"; 180const char* gFS_Fast_SingleA8Texture = 181 "\nvoid main(void) {\n" 182 " gl_FragColor = texture2D(sampler, outTexCoords);\n" 183 "}\n\n"; 184const char* gFS_Fast_SingleA8Texture_ApplyGamma = 185 "\nvoid main(void) {\n" 186 " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(sampler, outTexCoords).a, gamma));\n" 187 "}\n\n"; 188const char* gFS_Fast_SingleModulateA8Texture = 189 "\nvoid main(void) {\n" 190 " gl_FragColor = color * texture2D(sampler, outTexCoords).a;\n" 191 "}\n\n"; 192const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma = 193 "\nvoid main(void) {\n" 194 " gl_FragColor = color * pow(texture2D(sampler, outTexCoords).a, gamma);\n" 195 "}\n\n"; 196const char* gFS_Fast_SingleGradient = 197 "\nvoid main(void) {\n" 198 " gl_FragColor = texture2D(gradientSampler, linear);\n" 199 "}\n\n"; 200const char* gFS_Fast_SingleModulateGradient = 201 "\nvoid main(void) {\n" 202 " gl_FragColor = color.a * texture2D(gradientSampler, linear);\n" 203 "}\n\n"; 204 205// General case 206const char* gFS_Main_FetchColor = 207 " fragColor = color;\n"; 208const char* gFS_Main_ModulateColor = 209 " fragColor *= color.a;\n"; 210const char* gFS_Main_ModulateColor_ApplyGamma = 211 " fragColor *= pow(color.a, gamma);\n"; 212const char* gFS_Main_AccountForAA = 213 " if (widthProportion < boundaryWidth) {\n" 214 " fragColor *= (widthProportion * inverseBoundaryWidth);\n" 215 " } else if (widthProportion > (1.0 - boundaryWidth)) {\n" 216 " fragColor *= ((1.0 - widthProportion) * inverseBoundaryWidth);\n" 217 " }\n" 218 " if (lengthProportion < boundaryLength) {\n" 219 " fragColor *= (lengthProportion * inverseBoundaryLength);\n" 220 " } else if (lengthProportion > (1.0 - boundaryLength)) {\n" 221 " fragColor *= ((1.0 - lengthProportion) * inverseBoundaryLength);\n" 222 " }\n"; 223const char* gFS_Main_FetchTexture[2] = { 224 // Don't modulate 225 " fragColor = texture2D(sampler, outTexCoords);\n", 226 // Modulate 227 " fragColor = color * texture2D(sampler, outTexCoords);\n" 228}; 229const char* gFS_Main_FetchA8Texture[2] = { 230 // Don't modulate 231 " fragColor = texture2D(sampler, outTexCoords);\n", 232 // Modulate 233 " fragColor = color * texture2D(sampler, outTexCoords).a;\n" 234}; 235const char* gFS_Main_FetchGradient[3] = { 236 // Linear 237 " vec4 gradientColor = texture2D(gradientSampler, linear);\n", 238 // Circular 239 " highp float index = length(circular);\n" 240 " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n", 241 // Sweep 242 " highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" 243 " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n" 244}; 245const char* gFS_Main_FetchBitmap = 246 " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; 247const char* gFS_Main_FetchBitmapNpot = 248 " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n"; 249const char* gFS_Main_BlendShadersBG = 250 " fragColor = blendShaders(gradientColor, bitmapColor)"; 251const char* gFS_Main_BlendShadersGB = 252 " fragColor = blendShaders(bitmapColor, gradientColor)"; 253const char* gFS_Main_BlendShaders_Modulate[3] = { 254 // Don't modulate 255 ";\n", 256 // Modulate 257 " * fragColor.a;\n", 258 // Modulate with alpha 8 texture 259 " * texture2D(sampler, outTexCoords).a;\n" 260}; 261const char* gFS_Main_GradientShader_Modulate[3] = { 262 // Don't modulate 263 " fragColor = gradientColor;\n", 264 // Modulate 265 " fragColor = gradientColor * fragColor.a;\n", 266 // Modulate with alpha 8 texture 267 " fragColor = gradientColor * texture2D(sampler, outTexCoords).a;\n" 268 }; 269const char* gFS_Main_BitmapShader_Modulate[3] = { 270 // Don't modulate 271 " fragColor = bitmapColor;\n", 272 // Modulate 273 " fragColor = bitmapColor * fragColor.a;\n", 274 // Modulate with alpha 8 texture 275 " fragColor = bitmapColor * texture2D(sampler, outTexCoords).a;\n" 276 }; 277const char* gFS_Main_FragColor = 278 " gl_FragColor = fragColor;\n"; 279const char* gFS_Main_FragColor_Blend = 280 " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n"; 281const char* gFS_Main_FragColor_Blend_Swap = 282 " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n"; 283const char* gFS_Main_ApplyColorOp[4] = { 284 // None 285 "", 286 // Matrix 287 // TODO: Fix premultiplied alpha computations for color matrix 288 " fragColor *= colorMatrix;\n" 289 " fragColor += colorMatrixVector;\n" 290 " fragColor.rgb *= fragColor.a;\n", 291 // Lighting 292 " float lightingAlpha = fragColor.a;\n" 293 " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n" 294 " fragColor.a = lightingAlpha;\n", 295 // PorterDuff 296 " fragColor = blendColors(colorBlend, fragColor);\n" 297}; 298const char* gFS_Footer = 299 "}\n\n"; 300 301/////////////////////////////////////////////////////////////////////////////// 302// PorterDuff snippets 303/////////////////////////////////////////////////////////////////////////////// 304 305const char* gBlendOps[18] = { 306 // Clear 307 "return vec4(0.0, 0.0, 0.0, 0.0);\n", 308 // Src 309 "return src;\n", 310 // Dst 311 "return dst;\n", 312 // SrcOver 313 "return src + dst * (1.0 - src.a);\n", 314 // DstOver 315 "return dst + src * (1.0 - dst.a);\n", 316 // SrcIn 317 "return src * dst.a;\n", 318 // DstIn 319 "return dst * src.a;\n", 320 // SrcOut 321 "return src * (1.0 - dst.a);\n", 322 // DstOut 323 "return dst * (1.0 - src.a);\n", 324 // SrcAtop 325 "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n", 326 // DstAtop 327 "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n", 328 // Xor 329 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, " 330 "src.a + dst.a - 2.0 * src.a * dst.a);\n", 331 // Add 332 "return min(src + dst, 1.0);\n", 333 // Multiply 334 "return src * dst;\n", 335 // Screen 336 "return src + dst - src * dst;\n", 337 // Overlay 338 "return clamp(vec4(mix(" 339 "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), " 340 "src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), " 341 "step(dst.a, 2.0 * dst.rgb)), " 342 "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n", 343 // Darken 344 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 345 "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 346 // Lighten 347 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 348 "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 349}; 350 351/////////////////////////////////////////////////////////////////////////////// 352// Constructors/destructors 353/////////////////////////////////////////////////////////////////////////////// 354 355ProgramCache::ProgramCache() { 356} 357 358ProgramCache::~ProgramCache() { 359 clear(); 360} 361 362/////////////////////////////////////////////////////////////////////////////// 363// Cache management 364/////////////////////////////////////////////////////////////////////////////// 365 366void ProgramCache::clear() { 367 PROGRAM_LOGD("Clearing program cache"); 368 369 size_t count = mCache.size(); 370 for (size_t i = 0; i < count; i++) { 371 delete mCache.valueAt(i); 372 } 373 mCache.clear(); 374} 375 376Program* ProgramCache::get(const ProgramDescription& description) { 377 programid key = description.key(); 378 ssize_t index = mCache.indexOfKey(key); 379 Program* program = NULL; 380 if (index < 0) { 381 description.log("Could not find program"); 382 program = generateProgram(description, key); 383 mCache.add(key, program); 384 } else { 385 program = mCache.valueAt(index); 386 } 387 return program; 388} 389 390/////////////////////////////////////////////////////////////////////////////// 391// Program generation 392/////////////////////////////////////////////////////////////////////////////// 393 394Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) { 395 String8 vertexShader = generateVertexShader(description); 396 String8 fragmentShader = generateFragmentShader(description); 397 398 Program* program = new Program(description, vertexShader.string(), fragmentShader.string()); 399 return program; 400} 401 402String8 ProgramCache::generateVertexShader(const ProgramDescription& description) { 403 // Add attributes 404 String8 shader(gVS_Header_Attributes); 405 if (description.hasTexture || description.hasExternalTexture) { 406 shader.append(gVS_Header_Attributes_TexCoords); 407 } 408 if (description.isAA) { 409 shader.append(gVS_Header_Attributes_AAParameters); 410 } 411 // Uniforms 412 shader.append(gVS_Header_Uniforms); 413 if (description.hasTextureTransform) { 414 shader.append(gVS_Header_Uniforms_TextureTransform); 415 } 416 if (description.hasGradient) { 417 shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); 418 } 419 if (description.hasBitmap) { 420 shader.append(gVS_Header_Uniforms_HasBitmap); 421 } 422 if (description.isPoint) { 423 shader.append(gVS_Header_Uniforms_IsPoint); 424 } 425 // Varyings 426 if (description.hasTexture || description.hasExternalTexture) { 427 shader.append(gVS_Header_Varyings_HasTexture); 428 } 429 if (description.isAA) { 430 shader.append(gVS_Header_Varyings_IsAA); 431 } 432 if (description.hasGradient) { 433 shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); 434 } 435 if (description.hasBitmap) { 436 shader.append(description.isPoint ? 437 gVS_Header_Varyings_PointHasBitmap : 438 gVS_Header_Varyings_HasBitmap); 439 } 440 441 // Begin the shader 442 shader.append(gVS_Main); { 443 if (description.hasTextureTransform) { 444 shader.append(gVS_Main_OutTransformedTexCoords); 445 } else if (description.hasTexture || description.hasExternalTexture) { 446 shader.append(gVS_Main_OutTexCoords); 447 } 448 if (description.isAA) { 449 shader.append(gVS_Main_AA); 450 } 451 if (description.hasGradient) { 452 shader.append(gVS_Main_OutGradient[description.gradientType]); 453 } 454 if (description.hasBitmap) { 455 shader.append(description.isPoint ? 456 gVS_Main_OutPointBitmapTexCoords : 457 gVS_Main_OutBitmapTexCoords); 458 } 459 if (description.isPoint) { 460 shader.append(gVS_Main_PointSize); 461 } 462 // Output transformed position 463 shader.append(gVS_Main_Position); 464 } 465 // End the shader 466 shader.append(gVS_Footer); 467 468 PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string()); 469 470 return shader; 471} 472 473String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { 474 String8 shader; 475 476 const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; 477 if (blendFramebuffer) { 478 shader.append(gFS_Header_Extension_FramebufferFetch); 479 } 480 if (description.hasExternalTexture) { 481 shader.append(gFS_Header_Extension_ExternalTexture); 482 } 483 484 shader.append(gFS_Header); 485 486 // Varyings 487 if (description.hasTexture || description.hasExternalTexture) { 488 shader.append(gVS_Header_Varyings_HasTexture); 489 } 490 if (description.isAA) { 491 shader.append(gVS_Header_Varyings_IsAA); 492 } 493 if (description.hasGradient) { 494 shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]); 495 } 496 if (description.hasBitmap) { 497 shader.append(description.isPoint ? 498 gVS_Header_Varyings_PointHasBitmap : 499 gVS_Header_Varyings_HasBitmap); 500 } 501 502 // Uniforms 503 int modulateOp = MODULATE_OP_NO_MODULATE; 504 const bool singleColor = !description.hasTexture && !description.hasExternalTexture && 505 !description.hasGradient && !description.hasBitmap; 506 507 if (description.modulate || singleColor) { 508 shader.append(gFS_Uniforms_Color); 509 if (!singleColor) modulateOp = MODULATE_OP_MODULATE; 510 } 511 if (description.hasTexture) { 512 shader.append(gFS_Uniforms_TextureSampler); 513 } else if (description.hasExternalTexture) { 514 shader.append(gFS_Uniforms_ExternalTextureSampler); 515 } 516 if (description.isAA) { 517 shader.append(gFS_Uniforms_AA); 518 } 519 if (description.hasGradient) { 520 shader.append(gFS_Uniforms_GradientSampler[description.gradientType]); 521 } 522 if (description.hasBitmap && description.isPoint) { 523 shader.append(gFS_Header_Uniforms_PointHasBitmap); 524 } 525 if (description.hasGammaCorrection) { 526 shader.append(gFS_Uniforms_Gamma); 527 } 528 529 // Optimization for common cases 530 if (!description.isAA && !blendFramebuffer && 531 description.colorOp == ProgramDescription::kColorNone && !description.isPoint) { 532 bool fast = false; 533 534 const bool noShader = !description.hasGradient && !description.hasBitmap; 535 const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && 536 !description.hasAlpha8Texture && noShader; 537 const bool singleA8Texture = description.hasTexture && 538 description.hasAlpha8Texture && noShader; 539 const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && 540 description.hasGradient && !description.hasBitmap && 541 description.gradientType == ProgramDescription::kGradientLinear; 542 543 if (singleColor) { 544 shader.append(gFS_Fast_SingleColor); 545 fast = true; 546 } else if (singleTexture) { 547 if (!description.modulate) { 548 shader.append(gFS_Fast_SingleTexture); 549 } else { 550 shader.append(gFS_Fast_SingleModulateTexture); 551 } 552 fast = true; 553 } else if (singleA8Texture) { 554 if (!description.modulate) { 555 if (description.hasGammaCorrection) { 556 shader.append(gFS_Fast_SingleA8Texture_ApplyGamma); 557 } else { 558 shader.append(gFS_Fast_SingleA8Texture); 559 } 560 } else { 561 if (description.hasGammaCorrection) { 562 shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma); 563 } else { 564 shader.append(gFS_Fast_SingleModulateA8Texture); 565 } 566 } 567 fast = true; 568 } else if (singleGradient) { 569 if (!description.modulate) { 570 shader.append(gFS_Fast_SingleGradient); 571 } else { 572 shader.append(gFS_Fast_SingleModulateGradient); 573 } 574 fast = true; 575 } 576 577 if (fast) { 578#if DEBUG_PROGRAMS 579 PROGRAM_LOGD("*** Fast case:\n"); 580 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 581 printLongString(shader); 582#endif 583 584 return shader; 585 } 586 } 587 588 if (description.hasBitmap) { 589 shader.append(gFS_Uniforms_BitmapSampler); 590 } 591 shader.append(gFS_Uniforms_ColorOp[description.colorOp]); 592 593 // Generate required functions 594 if (description.hasGradient && description.hasBitmap) { 595 generateBlend(shader, "blendShaders", description.shadersMode); 596 } 597 if (description.colorOp == ProgramDescription::kColorBlend) { 598 generateBlend(shader, "blendColors", description.colorMode); 599 } 600 if (blendFramebuffer) { 601 generateBlend(shader, "blendFramebuffer", description.framebufferMode); 602 } 603 if (description.isBitmapNpot) { 604 generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); 605 } 606 607 // Begin the shader 608 shader.append(gFS_Main); { 609 // Stores the result in fragColor directly 610 if (description.hasTexture || description.hasExternalTexture) { 611 if (description.hasAlpha8Texture) { 612 if (!description.hasGradient && !description.hasBitmap) { 613 shader.append(gFS_Main_FetchA8Texture[modulateOp]); 614 } 615 } else { 616 shader.append(gFS_Main_FetchTexture[modulateOp]); 617 } 618 } else { 619 if ((!description.hasGradient && !description.hasBitmap) || description.modulate) { 620 shader.append(gFS_Main_FetchColor); 621 } 622 } 623 if (description.isAA) { 624 shader.append(gFS_Main_AccountForAA); 625 } 626 if (description.hasGradient) { 627 shader.append(gFS_Main_FetchGradient[description.gradientType]); 628 } 629 if (description.hasBitmap) { 630 if (description.isPoint) { 631 shader.append(gFS_Main_PointBitmapTexCoords); 632 } 633 if (!description.isBitmapNpot) { 634 shader.append(gFS_Main_FetchBitmap); 635 } else { 636 shader.append(gFS_Main_FetchBitmapNpot); 637 } 638 } 639 bool applyModulate = false; 640 // Case when we have two shaders set 641 if (description.hasGradient && description.hasBitmap) { 642 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 643 if (description.isBitmapFirst) { 644 shader.append(gFS_Main_BlendShadersBG); 645 } else { 646 shader.append(gFS_Main_BlendShadersGB); 647 } 648 shader.append(gFS_Main_BlendShaders_Modulate[op]); 649 applyModulate = true; 650 } else { 651 if (description.hasGradient) { 652 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 653 shader.append(gFS_Main_GradientShader_Modulate[op]); 654 applyModulate = true; 655 } else if (description.hasBitmap) { 656 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 657 shader.append(gFS_Main_BitmapShader_Modulate[op]); 658 applyModulate = true; 659 } 660 } 661 if (description.modulate && applyModulate) { 662 if (description.hasGammaCorrection) { 663 shader.append(gFS_Main_ModulateColor_ApplyGamma); 664 } else { 665 shader.append(gFS_Main_ModulateColor); 666 } 667 } 668 // Apply the color op if needed 669 shader.append(gFS_Main_ApplyColorOp[description.colorOp]); 670 // Output the fragment 671 if (!blendFramebuffer) { 672 shader.append(gFS_Main_FragColor); 673 } else { 674 shader.append(!description.swapSrcDst ? 675 gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap); 676 } 677 } 678 // End the shader 679 shader.append(gFS_Footer); 680 681#if DEBUG_PROGRAMS 682 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 683 printLongString(shader); 684#endif 685 686 return shader; 687} 688 689void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) { 690 shader.append("\nvec4 "); 691 shader.append(name); 692 shader.append("(vec4 src, vec4 dst) {\n"); 693 shader.append(" "); 694 shader.append(gBlendOps[mode]); 695 shader.append("}\n"); 696} 697 698void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) { 699 shader.append("\nhighp vec2 wrap(highp vec2 texCoords) {\n"); 700 if (wrapS == GL_MIRRORED_REPEAT) { 701 shader.append(" highp float xMod2 = mod(texCoords.x, 2.0);\n"); 702 shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n"); 703 } 704 if (wrapT == GL_MIRRORED_REPEAT) { 705 shader.append(" highp float yMod2 = mod(texCoords.y, 2.0);\n"); 706 shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n"); 707 } 708 shader.append(" return vec2("); 709 switch (wrapS) { 710 case GL_CLAMP_TO_EDGE: 711 shader.append("texCoords.x"); 712 break; 713 case GL_REPEAT: 714 shader.append("mod(texCoords.x, 1.0)"); 715 break; 716 case GL_MIRRORED_REPEAT: 717 shader.append("xMod2"); 718 break; 719 } 720 shader.append(", "); 721 switch (wrapT) { 722 case GL_CLAMP_TO_EDGE: 723 shader.append("texCoords.y"); 724 break; 725 case GL_REPEAT: 726 shader.append("mod(texCoords.y, 1.0)"); 727 break; 728 case GL_MIRRORED_REPEAT: 729 shader.append("yMod2"); 730 break; 731 } 732 shader.append(");\n"); 733 shader.append("}\n"); 734} 735 736void ProgramCache::printLongString(const String8& shader) const { 737 ssize_t index = 0; 738 ssize_t lastIndex = 0; 739 const char* str = shader.string(); 740 while ((index = shader.find("\n", index)) > -1) { 741 String8 line(str, index - lastIndex); 742 if (line.length() == 0) line.append("\n"); 743 PROGRAM_LOGD("%s", line.string()); 744 index++; 745 str += (index - lastIndex); 746 lastIndex = index; 747 } 748} 749 750}; // namespace uirenderer 751}; // namespace android 752