OSDN Git Service

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