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