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