ProgramCache.cpp revision 0990ffbc4d407e174423a4a04b5902ed83f71db5
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 baseSampler;\n"; 144const char* gFS_Uniforms_ExternalTextureSampler = 145 "uniform samplerExternalOES baseSampler;\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(baseSampler, outTexCoords);\n" 203 "}\n\n"; 204const char* gFS_Fast_SingleModulateTexture = 205 "\nvoid main(void) {\n" 206 " gl_FragColor = color.a * texture2D(baseSampler, outTexCoords);\n" 207 "}\n\n"; 208const char* gFS_Fast_SingleA8Texture = 209 "\nvoid main(void) {\n" 210 " gl_FragColor = texture2D(baseSampler, 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(baseSampler, outTexCoords).a, gamma));\n" 215 "}\n\n"; 216const char* gFS_Fast_SingleModulateA8Texture = 217 "\nvoid main(void) {\n" 218 " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n" 219 "}\n\n"; 220const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma = 221 "\nvoid main(void) {\n" 222 " gl_FragColor = color * pow(texture2D(baseSampler, 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_AccountForAA = 247 " fragColor *= (1.0 - smoothstep(boundaryWidth, 0.5, abs(0.5 - widthProportion)))\n" 248 " * (1.0 - smoothstep(boundaryLength, 0.5, abs(0.5 - lengthProportion)));\n"; 249const char* gFS_Main_AccountForAARect = 250 " fragColor *= alpha;\n"; 251 252const char* gFS_Main_FetchTexture[2] = { 253 // Don't modulate 254 " fragColor = texture2D(baseSampler, outTexCoords);\n", 255 // Modulate 256 " fragColor = color * texture2D(baseSampler, outTexCoords);\n" 257}; 258const char* gFS_Main_FetchA8Texture[4] = { 259 // Don't modulate 260 " fragColor = texture2D(baseSampler, outTexCoords);\n", 261 " fragColor = texture2D(baseSampler, outTexCoords);\n", 262 // Modulate 263 " fragColor = color * texture2D(baseSampler, outTexCoords).a;\n", 264 " fragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\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[6] = { 293 // Don't modulate 294 ";\n", 295 ";\n", 296 // Modulate 297 " * color.a;\n", 298 " * color.a;\n", 299 // Modulate with alpha 8 texture 300 " * texture2D(baseSampler, outTexCoords).a;\n", 301 " * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" 302}; 303const char* gFS_Main_GradientShader_Modulate[6] = { 304 // Don't modulate 305 " fragColor = gradientColor;\n", 306 " fragColor = gradientColor;\n", 307 // Modulate 308 " fragColor = gradientColor * color.a;\n", 309 " fragColor = gradientColor * color.a;\n", 310 // Modulate with alpha 8 texture 311 " fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n", 312 " fragColor = gradientColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" 313 }; 314const char* gFS_Main_BitmapShader_Modulate[6] = { 315 // Don't modulate 316 " fragColor = bitmapColor;\n", 317 " fragColor = bitmapColor;\n", 318 // Modulate 319 " fragColor = bitmapColor * color.a;\n", 320 " fragColor = bitmapColor * color.a;\n", 321 // Modulate with alpha 8 texture 322 " fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n", 323 " fragColor = bitmapColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" 324 }; 325const char* gFS_Main_FragColor = 326 " gl_FragColor = fragColor;\n"; 327const char* gFS_Main_FragColor_Blend = 328 " gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n"; 329const char* gFS_Main_FragColor_Blend_Swap = 330 " gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n"; 331const char* gFS_Main_ApplyColorOp[4] = { 332 // None 333 "", 334 // Matrix 335 // TODO: Fix premultiplied alpha computations for color matrix 336 " fragColor *= colorMatrix;\n" 337 " fragColor += colorMatrixVector;\n" 338 " fragColor.rgb *= fragColor.a;\n", 339 // Lighting 340 " float lightingAlpha = fragColor.a;\n" 341 " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n" 342 " fragColor.a = lightingAlpha;\n", 343 // PorterDuff 344 " fragColor = blendColors(colorBlend, fragColor);\n" 345}; 346const char* gFS_Footer = 347 "}\n\n"; 348 349/////////////////////////////////////////////////////////////////////////////// 350// PorterDuff snippets 351/////////////////////////////////////////////////////////////////////////////// 352 353const char* gBlendOps[18] = { 354 // Clear 355 "return vec4(0.0, 0.0, 0.0, 0.0);\n", 356 // Src 357 "return src;\n", 358 // Dst 359 "return dst;\n", 360 // SrcOver 361 "return src + dst * (1.0 - src.a);\n", 362 // DstOver 363 "return dst + src * (1.0 - dst.a);\n", 364 // SrcIn 365 "return src * dst.a;\n", 366 // DstIn 367 "return dst * src.a;\n", 368 // SrcOut 369 "return src * (1.0 - dst.a);\n", 370 // DstOut 371 "return dst * (1.0 - src.a);\n", 372 // SrcAtop 373 "return vec4(src.rgb * dst.a + (1.0 - src.a) * dst.rgb, dst.a);\n", 374 // DstAtop 375 "return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n", 376 // Xor 377 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, " 378 "src.a + dst.a - 2.0 * src.a * dst.a);\n", 379 // Add 380 "return min(src + dst, 1.0);\n", 381 // Multiply 382 "return src * dst;\n", 383 // Screen 384 "return src + dst - src * dst;\n", 385 // Overlay 386 "return clamp(vec4(mix(" 387 "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), " 388 "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), " 389 "step(dst.a, 2.0 * dst.rgb)), " 390 "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n", 391 // Darken 392 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 393 "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 394 // Lighten 395 "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + " 396 "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n", 397}; 398 399/////////////////////////////////////////////////////////////////////////////// 400// Constructors/destructors 401/////////////////////////////////////////////////////////////////////////////// 402 403ProgramCache::ProgramCache() { 404} 405 406ProgramCache::~ProgramCache() { 407 clear(); 408} 409 410/////////////////////////////////////////////////////////////////////////////// 411// Cache management 412/////////////////////////////////////////////////////////////////////////////// 413 414void ProgramCache::clear() { 415 PROGRAM_LOGD("Clearing program cache"); 416 417 size_t count = mCache.size(); 418 for (size_t i = 0; i < count; i++) { 419 delete mCache.valueAt(i); 420 } 421 mCache.clear(); 422} 423 424Program* ProgramCache::get(const ProgramDescription& description) { 425 programid key = description.key(); 426 ssize_t index = mCache.indexOfKey(key); 427 Program* program = NULL; 428 if (index < 0) { 429 description.log("Could not find program"); 430 program = generateProgram(description, key); 431 mCache.add(key, program); 432 } else { 433 program = mCache.valueAt(index); 434 } 435 return program; 436} 437 438/////////////////////////////////////////////////////////////////////////////// 439// Program generation 440/////////////////////////////////////////////////////////////////////////////// 441 442Program* ProgramCache::generateProgram(const ProgramDescription& description, programid key) { 443 String8 vertexShader = generateVertexShader(description); 444 String8 fragmentShader = generateFragmentShader(description); 445 446 return new Program(description, vertexShader.string(), fragmentShader.string()); 447} 448 449static inline size_t gradientIndex(const ProgramDescription& description) { 450 return description.gradientType * 2 + description.isSimpleGradient; 451} 452 453String8 ProgramCache::generateVertexShader(const ProgramDescription& description) { 454 // Add attributes 455 String8 shader(gVS_Header_Attributes); 456 if (description.hasTexture || description.hasExternalTexture) { 457 shader.append(gVS_Header_Attributes_TexCoords); 458 } 459 if (description.isAARect) { 460 shader.append(gVS_Header_Attributes_AARectParameters); 461 } else if (description.isAA) { 462 shader.append(gVS_Header_Attributes_AAParameters); 463 } 464 // Uniforms 465 shader.append(gVS_Header_Uniforms); 466 if (description.hasTextureTransform) { 467 shader.append(gVS_Header_Uniforms_TextureTransform); 468 } 469 if (description.hasGradient) { 470 shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); 471 } 472 if (description.hasBitmap) { 473 shader.append(gVS_Header_Uniforms_HasBitmap); 474 } 475 if (description.isPoint) { 476 shader.append(gVS_Header_Uniforms_IsPoint); 477 } 478 // Varyings 479 if (description.hasTexture || description.hasExternalTexture) { 480 shader.append(gVS_Header_Varyings_HasTexture); 481 } 482 if (description.isAARect) { 483 shader.append(gVS_Header_Varyings_IsAARect); 484 } else if (description.isAA) { 485 shader.append(gVS_Header_Varyings_IsAA); 486 } 487 if (description.hasGradient) { 488 shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]); 489 } 490 if (description.hasBitmap) { 491 shader.append(description.isPoint ? 492 gVS_Header_Varyings_PointHasBitmap : 493 gVS_Header_Varyings_HasBitmap); 494 } 495 496 // Begin the shader 497 shader.append(gVS_Main); { 498 if (description.hasTextureTransform) { 499 shader.append(gVS_Main_OutTransformedTexCoords); 500 } else if (description.hasTexture || description.hasExternalTexture) { 501 shader.append(gVS_Main_OutTexCoords); 502 } 503 if (description.isAARect) { 504 shader.append(gVS_Main_AARect); 505 } else if (description.isAA) { 506 shader.append(gVS_Main_AA); 507 } 508 if (description.hasGradient) { 509 shader.append(gVS_Main_OutGradient[gradientIndex(description)]); 510 } 511 if (description.hasBitmap) { 512 shader.append(description.isPoint ? 513 gVS_Main_OutPointBitmapTexCoords : 514 gVS_Main_OutBitmapTexCoords); 515 } 516 if (description.isPoint) { 517 shader.append(gVS_Main_PointSize); 518 } 519 // Output transformed position 520 shader.append(gVS_Main_Position); 521 } 522 // End the shader 523 shader.append(gVS_Footer); 524 525 PROGRAM_LOGD("*** Generated vertex shader:\n\n%s", shader.string()); 526 527 return shader; 528} 529 530static bool shaderOp(const ProgramDescription& description, String8& shader, 531 const int modulateOp, const char** snippets) { 532 int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; 533 op = op * 2 + description.hasGammaCorrection; 534 shader.append(snippets[op]); 535 return description.hasAlpha8Texture; 536} 537 538String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) { 539 String8 shader; 540 541 const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode; 542 if (blendFramebuffer) { 543 shader.append(gFS_Header_Extension_FramebufferFetch); 544 } 545 if (description.hasExternalTexture) { 546 shader.append(gFS_Header_Extension_ExternalTexture); 547 } 548 549 shader.append(gFS_Header); 550 551 // Varyings 552 if (description.hasTexture || description.hasExternalTexture) { 553 shader.append(gVS_Header_Varyings_HasTexture); 554 } 555 if (description.isAARect) { 556 shader.append(gVS_Header_Varyings_IsAARect); 557 } else if (description.isAA) { 558 shader.append(gVS_Header_Varyings_IsAA); 559 } 560 if (description.hasGradient) { 561 shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]); 562 } 563 if (description.hasBitmap) { 564 shader.append(description.isPoint ? 565 gVS_Header_Varyings_PointHasBitmap : 566 gVS_Header_Varyings_HasBitmap); 567 } 568 569 // Uniforms 570 int modulateOp = MODULATE_OP_NO_MODULATE; 571 const bool singleColor = !description.hasTexture && !description.hasExternalTexture && 572 !description.hasGradient && !description.hasBitmap; 573 574 if (description.modulate || singleColor) { 575 shader.append(gFS_Uniforms_Color); 576 if (!singleColor) modulateOp = MODULATE_OP_MODULATE; 577 } 578 if (description.hasTexture) { 579 shader.append(gFS_Uniforms_TextureSampler); 580 } else if (description.hasExternalTexture) { 581 shader.append(gFS_Uniforms_ExternalTextureSampler); 582 } 583 if (description.isAA) { 584 shader.append(gFS_Uniforms_AA); 585 } 586 if (description.hasGradient) { 587 shader.append(gFS_Uniforms_GradientSampler[gradientIndex(description)]); 588 } 589 if (description.hasBitmap && description.isPoint) { 590 shader.append(gFS_Header_Uniforms_PointHasBitmap); 591 } 592 if (description.hasGammaCorrection) { 593 shader.append(gFS_Uniforms_Gamma); 594 } 595 596 // Optimization for common cases 597 if (!description.isAA && !blendFramebuffer && 598 description.colorOp == ProgramDescription::kColorNone && 599 !description.isPoint && !description.isAARect) { 600 bool fast = false; 601 602 const bool noShader = !description.hasGradient && !description.hasBitmap; 603 const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && 604 !description.hasAlpha8Texture && noShader; 605 const bool singleA8Texture = description.hasTexture && 606 description.hasAlpha8Texture && noShader; 607 const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && 608 description.hasGradient && !description.hasBitmap && 609 description.gradientType == ProgramDescription::kGradientLinear; 610 611 if (singleColor) { 612 shader.append(gFS_Fast_SingleColor); 613 fast = true; 614 } else if (singleTexture) { 615 if (!description.modulate) { 616 shader.append(gFS_Fast_SingleTexture); 617 } else { 618 shader.append(gFS_Fast_SingleModulateTexture); 619 } 620 fast = true; 621 } else if (singleA8Texture) { 622 if (!description.modulate) { 623 if (description.hasGammaCorrection) { 624 shader.append(gFS_Fast_SingleA8Texture_ApplyGamma); 625 } else { 626 shader.append(gFS_Fast_SingleA8Texture); 627 } 628 } else { 629 if (description.hasGammaCorrection) { 630 shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma); 631 } else { 632 shader.append(gFS_Fast_SingleModulateA8Texture); 633 } 634 } 635 fast = true; 636 } else if (singleGradient) { 637 if (!description.modulate) { 638 shader.append(gFS_Fast_SingleGradient[description.isSimpleGradient]); 639 } else { 640 shader.append(gFS_Fast_SingleModulateGradient[description.isSimpleGradient]); 641 } 642 fast = true; 643 } 644 645 if (fast) { 646#if DEBUG_PROGRAMS 647 PROGRAM_LOGD("*** Fast case:\n"); 648 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 649 printLongString(shader); 650#endif 651 652 return shader; 653 } 654 } 655 656 if (description.hasBitmap) { 657 shader.append(gFS_Uniforms_BitmapSampler); 658 } 659 shader.append(gFS_Uniforms_ColorOp[description.colorOp]); 660 661 // Generate required functions 662 if (description.hasGradient && description.hasBitmap) { 663 generateBlend(shader, "blendShaders", description.shadersMode); 664 } 665 if (description.colorOp == ProgramDescription::kColorBlend) { 666 generateBlend(shader, "blendColors", description.colorMode); 667 } 668 if (blendFramebuffer) { 669 generateBlend(shader, "blendFramebuffer", description.framebufferMode); 670 } 671 if (description.isBitmapNpot) { 672 generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT); 673 } 674 675 // Begin the shader 676 shader.append(gFS_Main); { 677 // Stores the result in fragColor directly 678 if (description.hasTexture || description.hasExternalTexture) { 679 if (description.hasAlpha8Texture) { 680 if (!description.hasGradient && !description.hasBitmap) { 681 shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 + 682 description.hasGammaCorrection]); 683 } 684 } else { 685 shader.append(gFS_Main_FetchTexture[modulateOp]); 686 } 687 } else { 688 if (!description.hasGradient && !description.hasBitmap) { 689 shader.append(gFS_Main_FetchColor); 690 } 691 } 692 if (description.hasGradient) { 693 shader.append(gFS_Main_FetchGradient[gradientIndex(description)]); 694 shader.append(gFS_Main_AddDitherToGradient); 695 } 696 if (description.hasBitmap) { 697 if (description.isPoint) { 698 shader.append(gFS_Main_PointBitmapTexCoords); 699 } 700 if (!description.isBitmapNpot) { 701 shader.append(gFS_Main_FetchBitmap); 702 } else { 703 shader.append(gFS_Main_FetchBitmapNpot); 704 } 705 } 706 bool applyModulate = false; 707 // Case when we have two shaders set 708 if (description.hasGradient && description.hasBitmap) { 709 if (description.isBitmapFirst) { 710 shader.append(gFS_Main_BlendShadersBG); 711 } else { 712 shader.append(gFS_Main_BlendShadersGB); 713 } 714 applyModulate = shaderOp(description, shader, modulateOp, 715 gFS_Main_BlendShaders_Modulate); 716 } else { 717 if (description.hasGradient) { 718 applyModulate = shaderOp(description, shader, modulateOp, 719 gFS_Main_GradientShader_Modulate); 720 } else if (description.hasBitmap) { 721 applyModulate = shaderOp(description, shader, modulateOp, 722 gFS_Main_BitmapShader_Modulate); 723 } 724 } 725 726 if (description.modulate && applyModulate) { 727 shader.append(gFS_Main_ModulateColor); 728 } 729 730 // Apply the color op if needed 731 shader.append(gFS_Main_ApplyColorOp[description.colorOp]); 732 733 if (description.isAARect) { 734 shader.append(gFS_Main_AccountForAARect); 735 } else if (description.isAA) { 736 shader.append(gFS_Main_AccountForAA); 737 } 738 739 // Output the fragment 740 if (!blendFramebuffer) { 741 shader.append(gFS_Main_FragColor); 742 } else { 743 shader.append(!description.swapSrcDst ? 744 gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap); 745 } 746 } 747 // End the shader 748 shader.append(gFS_Footer); 749 750#if DEBUG_PROGRAMS 751 PROGRAM_LOGD("*** Generated fragment shader:\n\n"); 752 printLongString(shader); 753#endif 754 755 return shader; 756} 757 758void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) { 759 shader.append("\nvec4 "); 760 shader.append(name); 761 shader.append("(vec4 src, vec4 dst) {\n"); 762 shader.append(" "); 763 shader.append(gBlendOps[mode]); 764 shader.append("}\n"); 765} 766 767void ProgramCache::generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT) { 768 shader.append("\nhighp vec2 wrap(highp vec2 texCoords) {\n"); 769 if (wrapS == GL_MIRRORED_REPEAT) { 770 shader.append(" highp float xMod2 = mod(texCoords.x, 2.0);\n"); 771 shader.append(" if (xMod2 > 1.0) xMod2 = 2.0 - xMod2;\n"); 772 } 773 if (wrapT == GL_MIRRORED_REPEAT) { 774 shader.append(" highp float yMod2 = mod(texCoords.y, 2.0);\n"); 775 shader.append(" if (yMod2 > 1.0) yMod2 = 2.0 - yMod2;\n"); 776 } 777 shader.append(" return vec2("); 778 switch (wrapS) { 779 case GL_CLAMP_TO_EDGE: 780 shader.append("texCoords.x"); 781 break; 782 case GL_REPEAT: 783 shader.append("mod(texCoords.x, 1.0)"); 784 break; 785 case GL_MIRRORED_REPEAT: 786 shader.append("xMod2"); 787 break; 788 } 789 shader.append(", "); 790 switch (wrapT) { 791 case GL_CLAMP_TO_EDGE: 792 shader.append("texCoords.y"); 793 break; 794 case GL_REPEAT: 795 shader.append("mod(texCoords.y, 1.0)"); 796 break; 797 case GL_MIRRORED_REPEAT: 798 shader.append("yMod2"); 799 break; 800 } 801 shader.append(");\n"); 802 shader.append("}\n"); 803} 804 805void ProgramCache::printLongString(const String8& shader) const { 806 ssize_t index = 0; 807 ssize_t lastIndex = 0; 808 const char* str = shader.string(); 809 while ((index = shader.find("\n", index)) > -1) { 810 String8 line(str, index - lastIndex); 811 if (line.length() == 0) line.append("\n"); 812 PROGRAM_LOGD("%s", line.string()); 813 index++; 814 str += (index - lastIndex); 815 lastIndex = index; 816 } 817} 818 819}; // namespace uirenderer 820}; // namespace android 821