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