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 #include <utils/String8.h> 18 19 #include "Caches.h" 20 #include "Dither.h" 21 #include "ProgramCache.h" 22 23 namespace android { 24 namespace uirenderer { 25 26 /////////////////////////////////////////////////////////////////////////////// 27 // Defines 28 /////////////////////////////////////////////////////////////////////////////// 29 30 #define MODULATE_OP_NO_MODULATE 0 31 #define MODULATE_OP_MODULATE 1 32 #define MODULATE_OP_MODULATE_A8 2 33 34 #define STR(x) STR1(x) 35 #define STR1(x) #x 36 37 /////////////////////////////////////////////////////////////////////////////// 38 // Vertex shaders snippets 39 /////////////////////////////////////////////////////////////////////////////// 40 41 const char* gVS_Header_Start = 42 "#version 100\n" 43 "attribute vec4 position;\n"; 44 const char* gVS_Header_Attributes_TexCoords = 45 "attribute vec2 texCoords;\n"; 46 const char* gVS_Header_Attributes_Colors = 47 "attribute vec4 colors;\n"; 48 const char* gVS_Header_Attributes_VertexAlphaParameters = 49 "attribute float vtxAlpha;\n"; 50 const char* gVS_Header_Uniforms_TextureTransform = 51 "uniform mat4 mainTextureTransform;\n"; 52 const char* gVS_Header_Uniforms = 53 "uniform mat4 projection;\n" \ 54 "uniform mat4 transform;\n"; 55 const char* gVS_Header_Uniforms_HasGradient = 56 "uniform mat4 screenSpace;\n"; 57 const char* gVS_Header_Uniforms_HasBitmap = 58 "uniform mat4 textureTransform;\n" 59 "uniform mediump vec2 textureDimension;\n"; 60 const char* gVS_Header_Uniforms_HasRoundRectClip = 61 "uniform mat4 roundRectInvTransform;\n"; 62 const char* gVS_Header_Varyings_HasTexture = 63 "varying vec2 outTexCoords;\n"; 64 const char* gVS_Header_Varyings_HasColors = 65 "varying vec4 outColors;\n"; 66 const char* gVS_Header_Varyings_HasVertexAlpha = 67 "varying float alpha;\n"; 68 const char* gVS_Header_Varyings_HasBitmap = 69 "varying highp vec2 outBitmapTexCoords;\n"; 70 const char* gVS_Header_Varyings_HasGradient[6] = { 71 // Linear 72 "varying highp vec2 linear;\n" 73 "varying vec2 ditherTexCoords;\n", 74 "varying float linear;\n" 75 "varying vec2 ditherTexCoords;\n", 76 77 // Circular 78 "varying highp vec2 circular;\n" 79 "varying vec2 ditherTexCoords;\n", 80 "varying highp vec2 circular;\n" 81 "varying vec2 ditherTexCoords;\n", 82 83 // Sweep 84 "varying highp vec2 sweep;\n" 85 "varying vec2 ditherTexCoords;\n", 86 "varying highp vec2 sweep;\n" 87 "varying vec2 ditherTexCoords;\n", 88 }; 89 const char* gVS_Header_Varyings_HasRoundRectClip = 90 "varying highp vec2 roundRectPos;\n"; 91 const char* gVS_Main = 92 "\nvoid main(void) {\n"; 93 const char* gVS_Main_OutTexCoords = 94 " outTexCoords = texCoords;\n"; 95 const char* gVS_Main_OutColors = 96 " outColors = colors;\n"; 97 const char* gVS_Main_OutTransformedTexCoords = 98 " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n"; 99 const char* gVS_Main_OutGradient[6] = { 100 // Linear 101 " linear = vec2((screenSpace * position).x, 0.5);\n" 102 " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n", 103 " linear = (screenSpace * position).x;\n" 104 " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n", 105 106 // Circular 107 " circular = (screenSpace * position).xy;\n" 108 " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n", 109 " circular = (screenSpace * position).xy;\n" 110 " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n", 111 112 // Sweep 113 " sweep = (screenSpace * position).xy;\n" 114 " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n", 115 " sweep = (screenSpace * position).xy;\n" 116 " ditherTexCoords = (transform * position).xy * " STR(DITHER_KERNEL_SIZE_INV) ";\n", 117 }; 118 const char* gVS_Main_OutBitmapTexCoords = 119 " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; 120 const char* gVS_Main_Position = 121 " vec4 transformedPosition = projection * transform * position;\n" 122 " gl_Position = transformedPosition;\n"; 123 124 const char* gVS_Main_VertexAlpha = 125 " alpha = vtxAlpha;\n"; 126 127 const char* gVS_Main_HasRoundRectClip = 128 " roundRectPos = (roundRectInvTransform * transformedPosition).xy;\n"; 129 const char* gVS_Footer = 130 "}\n\n"; 131 132 /////////////////////////////////////////////////////////////////////////////// 133 // Fragment shaders snippets 134 /////////////////////////////////////////////////////////////////////////////// 135 136 const char* gFS_Header_Start = 137 "#version 100\n"; 138 const char* gFS_Header_Extension_FramebufferFetch = 139 "#extension GL_NV_shader_framebuffer_fetch : enable\n\n"; 140 const char* gFS_Header_Extension_ExternalTexture = 141 "#extension GL_OES_EGL_image_external : require\n\n"; 142 const char* gFS_Header = 143 "precision mediump float;\n\n"; 144 const char* gFS_Uniforms_Color = 145 "uniform vec4 color;\n"; 146 const char* gFS_Uniforms_TextureSampler = 147 "uniform sampler2D baseSampler;\n"; 148 const char* gFS_Uniforms_ExternalTextureSampler = 149 "uniform samplerExternalOES baseSampler;\n"; 150 const char* gFS_Uniforms_Dither = 151 "uniform sampler2D ditherSampler;"; 152 const char* gFS_Uniforms_GradientSampler[2] = { 153 "%s\n" 154 "uniform sampler2D gradientSampler;\n", 155 "%s\n" 156 "uniform vec4 startColor;\n" 157 "uniform vec4 endColor;\n" 158 }; 159 const char* gFS_Uniforms_BitmapSampler = 160 "uniform sampler2D bitmapSampler;\n"; 161 const char* gFS_Uniforms_ColorOp[3] = { 162 // None 163 "", 164 // Matrix 165 "uniform mat4 colorMatrix;\n" 166 "uniform vec4 colorMatrixVector;\n", 167 // PorterDuff 168 "uniform vec4 colorBlend;\n" 169 }; 170 171 const char* gFS_Uniforms_HasRoundRectClip = 172 "uniform vec4 roundRectInnerRectLTRB;\n" 173 "uniform float roundRectRadius;\n"; 174 175 const char* gFS_Main = 176 "\nvoid main(void) {\n" 177 " lowp vec4 fragColor;\n"; 178 179 const char* gFS_Main_Dither[2] = { 180 // ES 2.0 181 "texture2D(ditherSampler, ditherTexCoords).a * " STR(DITHER_KERNEL_SIZE_INV_SQUARE), 182 // ES 3.0 183 "texture2D(ditherSampler, ditherTexCoords).a" 184 }; 185 const char* gFS_Main_AddDitherToGradient = 186 " gradientColor += %s;\n"; 187 188 // Fast cases 189 const char* gFS_Fast_SingleColor = 190 "\nvoid main(void) {\n" 191 " gl_FragColor = color;\n" 192 "}\n\n"; 193 const char* gFS_Fast_SingleTexture = 194 "\nvoid main(void) {\n" 195 " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" 196 "}\n\n"; 197 const char* gFS_Fast_SingleModulateTexture = 198 "\nvoid main(void) {\n" 199 " gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n" 200 "}\n\n"; 201 const char* gFS_Fast_SingleA8Texture = 202 "\nvoid main(void) {\n" 203 " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" 204 "}\n\n"; 205 const char* gFS_Fast_SingleModulateA8Texture = 206 "\nvoid main(void) {\n" 207 " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n" 208 "}\n\n"; 209 const char* gFS_Fast_SingleGradient[2] = { 210 "\nvoid main(void) {\n" 211 " gl_FragColor = %s + texture2D(gradientSampler, linear);\n" 212 "}\n\n", 213 "\nvoid main(void) {\n" 214 " gl_FragColor = %s + mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n" 215 "}\n\n", 216 }; 217 const char* gFS_Fast_SingleModulateGradient[2] = { 218 "\nvoid main(void) {\n" 219 " gl_FragColor = %s + color.a * texture2D(gradientSampler, linear);\n" 220 "}\n\n", 221 "\nvoid main(void) {\n" 222 " gl_FragColor = %s + color.a * mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n" 223 "}\n\n" 224 }; 225 226 // General case 227 const char* gFS_Main_FetchColor = 228 " fragColor = color;\n"; 229 const char* gFS_Main_ModulateColor = 230 " fragColor *= color.a;\n"; 231 const char* gFS_Main_ApplyVertexAlphaLinearInterp = 232 " fragColor *= alpha;\n"; 233 const char* gFS_Main_ApplyVertexAlphaShadowInterp = 234 // map alpha through shadow alpha sampler 235 " fragColor *= texture2D(baseSampler, vec2(alpha, 0.5)).a;\n"; 236 const char* gFS_Main_FetchTexture[2] = { 237 // Don't modulate 238 " fragColor = texture2D(baseSampler, outTexCoords);\n", 239 // Modulate 240 " fragColor = color * texture2D(baseSampler, outTexCoords);\n" 241 }; 242 const char* gFS_Main_FetchA8Texture[2] = { 243 // Don't modulate 244 " fragColor = texture2D(baseSampler, outTexCoords);\n", 245 // Modulate 246 " fragColor = color * texture2D(baseSampler, outTexCoords).a;\n", 247 }; 248 const char* gFS_Main_FetchGradient[6] = { 249 // Linear 250 " vec4 gradientColor = texture2D(gradientSampler, linear);\n", 251 252 " vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n", 253 254 // Circular 255 " vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n", 256 257 " vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n", 258 259 // Sweep 260 " highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" 261 " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n", 262 263 " highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n" 264 " vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n" 265 }; 266 const char* gFS_Main_FetchBitmap = 267 " vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n"; 268 const char* gFS_Main_FetchBitmapNpot = 269 " vec4 bitmapColor = texture2D(bitmapSampler, wrap(outBitmapTexCoords));\n"; 270 const char* gFS_Main_BlendShadersBG = 271 " fragColor = blendShaders(gradientColor, bitmapColor)"; 272 const char* gFS_Main_BlendShadersGB = 273 " fragColor = blendShaders(bitmapColor, gradientColor)"; 274 const char* gFS_Main_BlendShaders_Modulate[3] = { 275 // Don't modulate 276 ";\n", 277 // Modulate 278 " * color.a;\n", 279 // Modulate with alpha 8 texture 280 " * texture2D(baseSampler, outTexCoords).a;\n", 281 }; 282 const char* gFS_Main_GradientShader_Modulate[3] = { 283 // Don't modulate 284 " fragColor = gradientColor;\n", 285 // Modulate 286 " fragColor = gradientColor * color.a;\n", 287 // Modulate with alpha 8 texture 288 " fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n", 289 }; 290 const char* gFS_Main_BitmapShader_Modulate[3] = { 291 // Don't modulate 292 " fragColor = bitmapColor;\n", 293 // Modulate 294 " fragColor = bitmapColor * color.a;\n", 295 // Modulate with alpha 8 texture 296 " fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n", 297 }; 298 const char* gFS_Main_FragColor = 299 " gl_FragColor = fragColor;\n"; 300 const char* gFS_Main_FragColor_HasColors = 301 " gl_FragColor *= outColors;\n"; 302 const char* gFS_Main_FragColor_Blend = 303 " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n"; 304 const char* gFS_Main_FragColor_Blend_Swap = 305 " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n"; 306 const char* gFS_Main_ApplyColorOp[3] = { 307 // None 308 "", 309 // Matrix 310 " fragColor.rgb /= (fragColor.a + 0.0019);\n" // un-premultiply 311 " fragColor *= colorMatrix;\n" 312 " fragColor += colorMatrixVector;\n" 313 " fragColor.rgb *= (fragColor.a + 0.0019);\n", // re-premultiply 314 // PorterDuff 315 " fragColor = blendColors(colorBlend, fragColor);\n" 316 }; 317 318 // Note: LTRB -> xyzw 319 const char* gFS_Main_FragColor_HasRoundRectClip = 320 " mediump vec2 fragToLT = roundRectInnerRectLTRB.xy - roundRectPos;\n" 321 " mediump vec2 fragFromRB = roundRectPos - roundRectInnerRectLTRB.zw;\n" 322 323 // divide + multiply by 128 to avoid falling out of range in length() function 324 " mediump vec2 dist = max(max(fragToLT, fragFromRB), vec2(0.0, 0.0)) / 128.0;\n" 325 " mediump float linearDist = roundRectRadius - (length(dist) * 128.0);\n" 326 " gl_FragColor *= clamp(linearDist, 0.0, 1.0);\n"; 327 328 const char* gFS_Main_DebugHighlight = 329 " gl_FragColor.rgb = vec3(0.0, gl_FragColor.a, 0.0);\n"; 330 const char* gFS_Footer = 331 "}\n\n"; 332 333 /////////////////////////////////////////////////////////////////////////////// 334 // PorterDuff snippets 335 /////////////////////////////////////////////////////////////////////////////// 336 337 const char* gBlendOps[18] = { 338 // Clear 339 "return vec4(0.0, 0.0, 0.0, 0.0);\n", 340 // Src 341 "return src;\n", 342 // Dst 343 "return dst;\n", 344 // SrcOver 345 "return src + dst * (1.0 - src.a);\n", 346 // DstOver 347 "return dst + src * (1.0 - dst.a);\n", 348 // SrcIn 349 "return src * dst.a;\n", 350 // DstIn 351 "return dst * src.a;\n", 352 // SrcOut 353 "return src * (1.0 - dst.a);\n", 354 // DstOut 355 "return dst * (1.0 - src.a);\n", 356 // SrcAtop 357 "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n", 358 // DstAtop 359 "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n", 360 // Xor 361 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, " 362 "src.a + dst.a - 2.0 * src.a * dst.a);\n", 363 // Plus 364 "return min(src + dst, 1.0);\n", 365 // Modulate 366 "return src * dst;\n", 367 // Screen 368 "return src + dst - src * dst;\n", 369 // Overlay 370 "return clamp(vec4(mix(" 371 "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), " 372 "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), " 373 "step(dst.a, 2.0 * dst.rgb)), " 374 "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n", 375 // Darken 376 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 377 "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 378 // Lighten 379 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 380 "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 381 }; 382 383 /////////////////////////////////////////////////////////////////////////////// 384 // Constructors/destructors 385 /////////////////////////////////////////////////////////////////////////////// 386 387 ProgramCache::ProgramCache(Extensions& extensions) 388 : mHasES3(extensions.getMajorGlVersion() >= 3) { 389 } 390 391 ProgramCache::~ProgramCache() { 392 clear(); 393 } 394 395 /////////////////////////////////////////////////////////////////////////////// 396 // Cache management 397 /////////////////////////////////////////////////////////////////////////////// 398 399 void ProgramCache::clear() { 400 PROGRAM_LOGD("Clearing program cache"); 401 mCache.clear(); 402 } 403 404 Program* ProgramCache::get(const ProgramDescription& description) { 405 programid key = description.key(); 406 if (key == (PROGRAM_KEY_TEXTURE | PROGRAM_KEY_A8_TEXTURE)) { 407 // program for A8, unmodulated, texture w/o shader (black text/path textures) is equivalent 408 // to standard texture program (bitmaps, patches). Consider them equivalent. 409 key = PROGRAM_KEY_TEXTURE; 410 } 411 412 auto iter = mCache.find(key); 413 Program* program = nullptr; 414 if (iter == mCache.end()) { 415 description.log("Could not find program"); 416 program = generateProgram(description, key); 417 mCache[key] = std::unique_ptr<Program>(program); 418 } else { 419 program = iter->second.get(); 420 } 421 return program; 422 } 423 424 /////////////////////////////////////////////////////////////////////////////// 425 // Program generation 426 /////////////////////////////////////////////////////////////////////////////// 427 428 Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) { 429 String8 vertexShader = generateVertexShader(description); 430 String8 fragmentShader = generateFragmentShader(description); 431 432 return new Program(description, vertexShader.string(), fragmentShader.string()); 433 } 434 435 static inline size_t gradientIndex(const ProgramDescription& description) { 436 return description.gradientType * 2 + description.isSimpleGradient; 437 } 438 439 String8 ProgramCache::generateVertexShader(const ProgramDescription& description) { 440 // Add attributes 441 String8 shader(gVS_Header_Start); 442 if (description.hasTexture || description.hasExternalTexture) { 443 shader.append(gVS_Header_Attributes_TexCoords); 444 } 445 if (description.hasVertexAlpha) { 446 shader.append(gVS_Header_Attributes_VertexAlphaParameters); 447 } 448 if (description.hasColors) { 449 shader.append(gVS_Header_Attributes_Colors); 450 } 451 // Uniforms 452 shader.append(gVS_Header_Uniforms); 453 if (description.hasTextureTransform) { 454 shader.append(gVS_Header_Uniforms_TextureTransform); 455 } 456 if (description.hasGradient) { 457 shader.append(gVS_Header_Uniforms_HasGradient); 458 } 459 if (description.hasBitmap) { 460 shader.append(gVS_Header_Uniforms_HasBitmap); 461 } 462 if (description.hasRoundRectClip) { 463 shader.append(gVS_Header_Uniforms_HasRoundRectClip); 464 } 465 // Varyings 466 if (description.hasTexture || description.hasExternalTexture) { 467 shader.append(gVS_Header_Varyings_HasTexture); 468 } 469 if (description.hasVertexAlpha) { 470 shader.append(gVS_Header_Varyings_HasVertexAlpha); 471 } 472 if (description.hasColors) { 473 shader.append(gVS_Header_Varyings_HasColors); 474 } 475 if (description.hasGradient) { 476 shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]); 477 } 478 if (description.hasBitmap) { 479 shader.append(gVS_Header_Varyings_HasBitmap); 480 } 481 if (description.hasRoundRectClip) { 482 shader.append(gVS_Header_Varyings_HasRoundRectClip); 483 } 484 485 // Begin the shader 486 shader.append(gVS_Main); { 487 if (description.hasTextureTransform) { 488 shader.append(gVS_Main_OutTransformedTexCoords); 489 } else if (description.hasTexture || description.hasExternalTexture) { 490 shader.append(gVS_Main_OutTexCoords); 491 } 492 if (description.hasVertexAlpha) { 493 shader.append(gVS_Main_VertexAlpha); 494 } 495 if (description.hasColors) { 496 shader.append(gVS_Main_OutColors); 497 } 498 if (description.hasBitmap) { 499 shader.append(gVS_Main_OutBitmapTexCoords); 500 } 501 // Output transformed position 502 shader.append(gVS_Main_Position); 503 if (description.hasGradient) { 504 shader.append(gVS_Main_OutGradient[gradientIndex(description)]); 505 } 506 if (description.hasRoundRectClip) { 507 shader.append(gVS_Main_HasRoundRectClip); 508 } 509 } 510 // End the shader 511 shader.append(gVS_Footer); 512 513 PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string()); 514 515 return shader; 516 } 517 518 static bool shaderOp(const ProgramDescription& description, String8& shader, 519 const int modulateOp, const char** snippets) { 520 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 521 shader.append(snippets[op]); 522 return description.hasAlpha8Texture; 523 } 524 525 String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { 526 String8 shader(gFS_Header_Start); 527 528 const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; 529 if (blendFramebuffer) { 530 shader.append(gFS_Header_Extension_FramebufferFetch); 531 } 532 if (description.hasExternalTexture) { 533 shader.append(gFS_Header_Extension_ExternalTexture); 534 } 535 536 shader.append(gFS_Header); 537 538 // Varyings 539 if (description.hasTexture || description.hasExternalTexture) { 540 shader.append(gVS_Header_Varyings_HasTexture); 541 } 542 if (description.hasVertexAlpha) { 543 shader.append(gVS_Header_Varyings_HasVertexAlpha); 544 } 545 if (description.hasColors) { 546 shader.append(gVS_Header_Varyings_HasColors); 547 } 548 if (description.hasGradient) { 549 shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]); 550 } 551 if (description.hasBitmap) { 552 shader.append(gVS_Header_Varyings_HasBitmap); 553 } 554 if (description.hasRoundRectClip) { 555 shader.append(gVS_Header_Varyings_HasRoundRectClip); 556 } 557 558 // Uniforms 559 int modulateOp = MODULATE_OP_NO_MODULATE; 560 const bool singleColor = !description.hasTexture && !description.hasExternalTexture && 561 !description.hasGradient && !description.hasBitmap; 562 563 if (description.modulate || singleColor) { 564 shader.append(gFS_Uniforms_Color); 565 if (!singleColor) modulateOp = MODULATE_OP_MODULATE; 566 } 567 if (description.hasTexture || description.useShadowAlphaInterp) { 568 shader.append(gFS_Uniforms_TextureSampler); 569 } else if (description.hasExternalTexture) { 570 shader.append(gFS_Uniforms_ExternalTextureSampler); 571 } 572 if (description.hasGradient) { 573 shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient], 574 gFS_Uniforms_Dither); 575 } 576 if (description.hasRoundRectClip) { 577 shader.append(gFS_Uniforms_HasRoundRectClip); 578 } 579 580 // Optimization for common cases 581 if (!description.hasVertexAlpha 582 && !blendFramebuffer 583 && !description.hasColors 584 && description.colorOp == ProgramDescription::ColorFilterMode::None 585 && !description.hasDebugHighlight 586 && !description.hasRoundRectClip) { 587 bool fast = false; 588 589 const bool noShader = !description.hasGradient && !description.hasBitmap; 590 const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && 591 !description.hasAlpha8Texture && noShader; 592 const bool singleA8Texture = description.hasTexture && 593 description.hasAlpha8Texture && noShader; 594 const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && 595 description.hasGradient && !description.hasBitmap && 596 description.gradientType == ProgramDescription::kGradientLinear; 597 598 if (singleColor) { 599 shader.append(gFS_Fast_SingleColor); 600 fast = true; 601 } else if (singleTexture) { 602 if (!description.modulate) { 603 shader.append(gFS_Fast_SingleTexture); 604 } else { 605 shader.append(gFS_Fast_SingleModulateTexture); 606 } 607 fast = true; 608 } else if (singleA8Texture) { 609 if (!description.modulate) { 610 shader.append(gFS_Fast_SingleA8Texture); 611 } else { 612 shader.append(gFS_Fast_SingleModulateA8Texture); 613 } 614 fast = true; 615 } else if (singleGradient) { 616 if (!description.modulate) { 617 shader.appendFormat(gFS_Fast_SingleGradient[description.isSimpleGradient], 618 gFS_Main_Dither[mHasES3]); 619 } else { 620 shader.appendFormat(gFS_Fast_SingleModulateGradient[description.isSimpleGradient], 621 gFS_Main_Dither[mHasES3]); 622 } 623 fast = true; 624 } 625 626 if (fast) { 627 #if DEBUG_PROGRAMS 628 PROGRAM_LOGD("*** Fast case:\n"); 629 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 630 printLongString(shader); 631 #endif 632 633 return shader; 634 } 635 } 636 637 if (description.hasBitmap) { 638 shader.append(gFS_Uniforms_BitmapSampler); 639 } 640 shader.append(gFS_Uniforms_ColorOp[static_cast<int>(description.colorOp)]); 641 642 // Generate required functions 643 if (description.hasGradient && description.hasBitmap) { 644 generateBlend(shader, "blendShaders", description.shadersMode); 645 } 646 if (description.colorOp == ProgramDescription::ColorFilterMode::Blend) { 647 generateBlend(shader, "blendColors", description.colorMode); 648 } 649 if (blendFramebuffer) { 650 generateBlend(shader, "blendFramebuffer", description.framebufferMode); 651 } 652 if (description.isBitmapNpot) { 653 generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); 654 } 655 656 // Begin the shader 657 shader.append(gFS_Main); { 658 // Stores the result in fragColor directly 659 if (description.hasTexture || description.hasExternalTexture) { 660 if (description.hasAlpha8Texture) { 661 if (!description.hasGradient && !description.hasBitmap) { 662 shader.append(gFS_Main_FetchA8Texture[modulateOp]); 663 } 664 } else { 665 shader.append(gFS_Main_FetchTexture[modulateOp]); 666 } 667 } else { 668 if (!description.hasGradient && !description.hasBitmap) { 669 shader.append(gFS_Main_FetchColor); 670 } 671 } 672 if (description.hasGradient) { 673 shader.append(gFS_Main_FetchGradient[gradientIndex(description)]); 674 shader.appendFormat(gFS_Main_AddDitherToGradient, gFS_Main_Dither[mHasES3]); 675 } 676 if (description.hasBitmap) { 677 if (!description.isBitmapNpot) { 678 shader.append(gFS_Main_FetchBitmap); 679 } else { 680 shader.append(gFS_Main_FetchBitmapNpot); 681 } 682 } 683 bool applyModulate = false; 684 // Case when we have two shaders set 685 if (description.hasGradient && description.hasBitmap) { 686 if (description.isBitmapFirst) { 687 shader.append(gFS_Main_BlendShadersBG); 688 } else { 689 shader.append(gFS_Main_BlendShadersGB); 690 } 691 applyModulate = shaderOp(description, shader, modulateOp, 692 gFS_Main_BlendShaders_Modulate); 693 } else { 694 if (description.hasGradient) { 695 applyModulate = shaderOp(description, shader, modulateOp, 696 gFS_Main_GradientShader_Modulate); 697 } else if (description.hasBitmap) { 698 applyModulate = shaderOp(description, shader, modulateOp, 699 gFS_Main_BitmapShader_Modulate); 700 } 701 } 702 703 if (description.modulate && applyModulate) { 704 shader.append(gFS_Main_ModulateColor); 705 } 706 707 // Apply the color op if needed 708 shader.append(gFS_Main_ApplyColorOp[static_cast<int>(description.colorOp)]); 709 710 if (description.hasVertexAlpha) { 711 if (description.useShadowAlphaInterp) { 712 shader.append(gFS_Main_ApplyVertexAlphaShadowInterp); 713 } else { 714 shader.append(gFS_Main_ApplyVertexAlphaLinearInterp); 715 } 716 } 717 718 // Output the fragment 719 if (!blendFramebuffer) { 720 shader.append(gFS_Main_FragColor); 721 } else { 722 shader.append(!description.swapSrcDst ? 723 gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap); 724 } 725 if (description.hasColors) { 726 shader.append(gFS_Main_FragColor_HasColors); 727 } 728 if (description.hasRoundRectClip) { 729 shader.append(gFS_Main_FragColor_HasRoundRectClip); 730 } 731 if (description.hasDebugHighlight) { 732 shader.append(gFS_Main_DebugHighlight); 733 } 734 } 735 // End the shader 736 shader.append(gFS_Footer); 737 738 #if DEBUG_PROGRAMS 739 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 740 printLongString(shader); 741 #endif 742 743 return shader; 744 } 745 746 void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) { 747 shader.append("\nvec4 "); 748 shader.append(name); 749 shader.append("(vec4 src, vec4 dst) {\n"); 750 shader.append(" "); 751 shader.append(gBlendOps[mode]); 752 shader.append("}\n"); 753 } 754 755 void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) { 756 shader.append("\nhighp vec2 wrap(highp vec2 texCoords) {\n"); 757 if (wrapS == GL_MIRRORED_REPEAT) { 758 shader.append(" highp float xMod2 = mod(texCoords.x, 2.0);\n"); 759 shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n"); 760 } 761 if (wrapT == GL_MIRRORED_REPEAT) { 762 shader.append(" highp float yMod2 = mod(texCoords.y, 2.0);\n"); 763 shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n"); 764 } 765 shader.append(" return vec2("); 766 switch (wrapS) { 767 case GL_CLAMP_TO_EDGE: 768 shader.append("texCoords.x"); 769 break; 770 case GL_REPEAT: 771 shader.append("mod(texCoords.x, 1.0)"); 772 break; 773 case GL_MIRRORED_REPEAT: 774 shader.append("xMod2"); 775 break; 776 } 777 shader.append(", "); 778 switch (wrapT) { 779 case GL_CLAMP_TO_EDGE: 780 shader.append("texCoords.y"); 781 break; 782 case GL_REPEAT: 783 shader.append("mod(texCoords.y, 1.0)"); 784 break; 785 case GL_MIRRORED_REPEAT: 786 shader.append("yMod2"); 787 break; 788 } 789 shader.append(");\n"); 790 shader.append("}\n"); 791 } 792 793 void ProgramCache::printLongString(const String8& shader) const { 794 ssize_t index = 0; 795 ssize_t lastIndex = 0; 796 const char* str = shader.string(); 797 while ((index = shader.find("\n", index)) > -1) { 798 String8 line(str, index - lastIndex); 799 if (line.length() == 0) line.append("\n"); 800 ALOGD("%s", line.string()); 801 index++; 802 str += (index - lastIndex); 803 lastIndex = index; 804 } 805 } 806 807 }; // namespace uirenderer 808 }; // namespace android 809