Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / cc / output / shader.cc
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/output/shader.h"
6
7 #include <algorithm>
8
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "cc/output/gl_renderer.h"  // For the GLC() macro.
12 #include "gpu/command_buffer/client/gles2_interface.h"
13 #include "third_party/khronos/GLES2/gl2.h"
14
15 #define SHADER0(Src) #Src
16 #define VERTEX_SHADER(Src) SetVertexTexCoordPrecision(SHADER0(Src))
17 #define FRAGMENT_SHADER(Src) SetFragmentTexCoordPrecision( \
18     precision, SetFragmentSamplerType(sampler, SHADER0(Src)))
19
20 using gpu::gles2::GLES2Interface;
21
22 namespace cc {
23
24 namespace {
25
26 static void GetProgramUniformLocations(GLES2Interface* context,
27                                        unsigned program,
28                                        size_t count,
29                                        const char** uniforms,
30                                        int* locations,
31                                        int* base_uniform_index) {
32   for (size_t i = 0; i < count; i++) {
33     locations[i] = (*base_uniform_index)++;
34     context->BindUniformLocationCHROMIUM(program, locations[i], uniforms[i]);
35   }
36 }
37
38 static std::string SetFragmentTexCoordPrecision(
39     TexCoordPrecision requested_precision, std::string shader_string) {
40   switch (requested_precision) {
41     case TexCoordPrecisionHigh:
42       DCHECK_NE(shader_string.find("TexCoordPrecision"), std::string::npos);
43       return
44           "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
45           "  #define TexCoordPrecision highp\n"
46           "#else\n"
47           "  #define TexCoordPrecision mediump\n"
48           "#endif\n" +
49           shader_string;
50     case TexCoordPrecisionMedium:
51       DCHECK_NE(shader_string.find("TexCoordPrecision"), std::string::npos);
52       return "#define TexCoordPrecision mediump\n" +
53           shader_string;
54     case TexCoordPrecisionNA:
55       DCHECK_EQ(shader_string.find("TexCoordPrecision"), std::string::npos);
56       DCHECK_EQ(shader_string.find("texture2D"), std::string::npos);
57       DCHECK_EQ(shader_string.find("texture2DRect"), std::string::npos);
58       return shader_string;
59     default:
60       NOTREACHED();
61       break;
62   }
63   return shader_string;
64 }
65
66 static std::string SetVertexTexCoordPrecision(const char* shader_string) {
67   // We unconditionally use highp in the vertex shader since
68   // we are unlikely to be vertex shader bound when drawing large quads.
69   // Also, some vertex shaders mutate the texture coordinate in such a
70   // way that the effective precision might be lower than expected.
71   return "#define TexCoordPrecision highp\n" +
72       std::string(shader_string);
73 }
74
75 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
76                                             int *highp_threshold_cache,
77                                             int highp_threshold_min,
78                                             int x, int y) {
79   if (*highp_threshold_cache == 0) {
80     // Initialize range and precision with minimum spec values for when
81     // GetShaderPrecisionFormat is a test stub.
82     // TODO(brianderson): Implement better stubs of GetShaderPrecisionFormat
83     // everywhere.
84     GLint range[2] = { 14, 14 };
85     GLint precision = 10;
86     GLC(context, context->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER,
87                                                    GL_MEDIUM_FLOAT,
88                                                    range, &precision));
89     *highp_threshold_cache = 1 << precision;
90   }
91
92   int highp_threshold = std::max(*highp_threshold_cache, highp_threshold_min);
93   if (x > highp_threshold || y > highp_threshold)
94     return TexCoordPrecisionHigh;
95   return TexCoordPrecisionMedium;
96 }
97
98 static std::string SetFragmentSamplerType(
99     SamplerType requested_type, std::string shader_string) {
100   switch (requested_type) {
101     case SamplerType2D:
102       DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
103       DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
104       return
105           "#define SamplerType sampler2D\n"
106           "#define TextureLookup texture2D\n" +
107           shader_string;
108     case SamplerType2DRect:
109       DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
110       DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
111       return
112           "#extension GL_ARB_texture_rectangle : require\n"
113           "#define SamplerType sampler2DRect\n"
114           "#define TextureLookup texture2DRect\n" +
115           shader_string;
116     case SamplerTypeExternalOES:
117       DCHECK_NE(shader_string.find("SamplerType"), std::string::npos);
118       DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos);
119       return
120           "#extension GL_OES_EGL_image_external : require\n"
121           "#define SamplerType samplerExternalOES\n"
122           "#define TextureLookup texture2D\n" +
123           shader_string;
124     case SamplerTypeNA:
125       DCHECK_EQ(shader_string.find("SamplerType"), std::string::npos);
126       DCHECK_EQ(shader_string.find("TextureLookup"), std::string::npos);
127       return shader_string;
128     default:
129       NOTREACHED();
130       break;
131   }
132   return shader_string;
133 }
134
135 }  // namespace
136
137 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
138                                             int *highp_threshold_cache,
139                                             int highp_threshold_min,
140                                             gfx::Point max_coordinate) {
141   return TexCoordPrecisionRequired(context,
142                                    highp_threshold_cache, highp_threshold_min,
143                                    max_coordinate.x(), max_coordinate.y());
144 }
145
146 TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
147                                             int *highp_threshold_cache,
148                                             int highp_threshold_min,
149                                             const gfx::Size& max_size) {
150   return TexCoordPrecisionRequired(context,
151                                    highp_threshold_cache, highp_threshold_min,
152                                    max_size.width(), max_size.height());
153 }
154
155 VertexShaderPosTex::VertexShaderPosTex()
156       : matrix_location_(-1) {}
157
158 void VertexShaderPosTex::Init(GLES2Interface* context,
159                               unsigned program,
160                               int* base_uniform_index) {
161   static const char* uniforms[] = {
162       "matrix",
163   };
164   int locations[arraysize(uniforms)];
165
166   GetProgramUniformLocations(context,
167                              program,
168                              arraysize(uniforms),
169                              uniforms,
170                              locations,
171                              base_uniform_index);
172   matrix_location_ = locations[0];
173 }
174
175 std::string VertexShaderPosTex::GetShaderString() const {
176   return VERTEX_SHADER(
177     attribute vec4 a_position;
178     attribute TexCoordPrecision vec2 a_texCoord;
179     uniform mat4 matrix;
180     varying TexCoordPrecision vec2 v_texCoord;
181     void main() {
182       gl_Position = matrix * a_position;
183       v_texCoord = a_texCoord;
184     }
185   );  // NOLINT(whitespace/parens)
186 }
187
188 VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch()
189     : matrix_location_(-1),
190       tex_scale_location_(-1) {}
191
192 void VertexShaderPosTexYUVStretch::Init(GLES2Interface* context,
193                                         unsigned program,
194                                         int* base_uniform_index) {
195   static const char* uniforms[] = {
196     "matrix",
197     "texScale",
198   };
199   int locations[arraysize(uniforms)];
200
201   GetProgramUniformLocations(context,
202                              program,
203                              arraysize(uniforms),
204                              uniforms,
205                              locations,
206                              base_uniform_index);
207   matrix_location_ = locations[0];
208   tex_scale_location_ = locations[1];
209 }
210
211 std::string VertexShaderPosTexYUVStretch::GetShaderString() const {
212   return VERTEX_SHADER(
213     precision mediump float;
214     attribute vec4 a_position;
215     attribute TexCoordPrecision vec2 a_texCoord;
216     uniform mat4 matrix;
217     varying TexCoordPrecision vec2 v_texCoord;
218     uniform TexCoordPrecision vec2 texScale;
219     void main() {
220         gl_Position = matrix * a_position;
221         v_texCoord = a_texCoord * texScale;
222     }
223   );  // NOLINT(whitespace/parens)
224 }
225
226 VertexShaderPos::VertexShaderPos()
227     : matrix_location_(-1) {}
228
229 void VertexShaderPos::Init(GLES2Interface* context,
230                            unsigned program,
231                            int* base_uniform_index) {
232   static const char* uniforms[] = {
233       "matrix",
234   };
235   int locations[arraysize(uniforms)];
236
237   GetProgramUniformLocations(context,
238                              program,
239                              arraysize(uniforms),
240                              uniforms,
241                              locations,
242                              base_uniform_index);
243   matrix_location_ = locations[0];
244 }
245
246 std::string VertexShaderPos::GetShaderString() const {
247   return VERTEX_SHADER(
248     attribute vec4 a_position;
249     uniform mat4 matrix;
250     void main() {
251         gl_Position = matrix * a_position;
252     }
253   );  // NOLINT(whitespace/parens)
254 }
255
256 VertexShaderPosTexTransform::VertexShaderPosTexTransform()
257     : matrix_location_(-1),
258       tex_transform_location_(-1),
259       vertex_opacity_location_(-1) {}
260
261 void VertexShaderPosTexTransform::Init(GLES2Interface* context,
262                                        unsigned program,
263                                        int* base_uniform_index) {
264   static const char* uniforms[] = {
265     "matrix",
266     "texTransform",
267     "opacity",
268   };
269   int locations[arraysize(uniforms)];
270
271   GetProgramUniformLocations(context,
272                              program,
273                              arraysize(uniforms),
274                              uniforms,
275                              locations,
276                              base_uniform_index);
277   matrix_location_ = locations[0];
278   tex_transform_location_ = locations[1];
279   vertex_opacity_location_ = locations[2];
280 }
281
282 std::string VertexShaderPosTexTransform::GetShaderString() const {
283   return VERTEX_SHADER(
284     attribute vec4 a_position;
285     attribute TexCoordPrecision vec2 a_texCoord;
286     attribute float a_index;
287     uniform mat4 matrix[8];
288     uniform TexCoordPrecision vec4 texTransform[8];
289     uniform float opacity[32];
290     varying TexCoordPrecision vec2 v_texCoord;
291     varying float v_alpha;
292     void main() {
293       int quad_index = int(a_index * 0.25);  // NOLINT
294       gl_Position = matrix[quad_index] * a_position;
295       TexCoordPrecision vec4 texTrans = texTransform[quad_index];
296       v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
297       v_alpha = opacity[int(a_index)]; // NOLINT
298     }
299   );  // NOLINT(whitespace/parens)
300 }
301
302 std::string VertexShaderPosTexIdentity::GetShaderString() const {
303   return VERTEX_SHADER(
304     attribute vec4 a_position;
305     varying TexCoordPrecision vec2 v_texCoord;
306     void main() {
307       gl_Position = a_position;
308       v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
309     }
310   );  // NOLINT(whitespace/parens)
311 }
312
313 VertexShaderQuad::VertexShaderQuad()
314     : matrix_location_(-1),
315       quad_location_(-1) {}
316
317 void VertexShaderQuad::Init(GLES2Interface* context,
318                             unsigned program,
319                             int* base_uniform_index) {
320   static const char* uniforms[] = {
321     "matrix",
322     "quad",
323   };
324   int locations[arraysize(uniforms)];
325
326   GetProgramUniformLocations(context,
327                              program,
328                              arraysize(uniforms),
329                              uniforms,
330                              locations,
331                              base_uniform_index);
332   matrix_location_ = locations[0];
333   quad_location_ = locations[1];
334 }
335
336 std::string VertexShaderQuad::GetShaderString() const {
337 #if defined(OS_ANDROID)
338 // TODO(epenner): Find the cause of this 'quad' uniform
339 // being missing if we don't add dummy variables.
340 // http://crbug.com/240602
341   return VERTEX_SHADER(
342     attribute TexCoordPrecision vec4 a_position;
343     attribute float a_index;
344     uniform mat4 matrix;
345     uniform TexCoordPrecision vec2 quad[4];
346     uniform TexCoordPrecision vec2 dummy_uniform;
347     varying TexCoordPrecision vec2 dummy_varying;
348     void main() {
349       vec2 pos = quad[int(a_index)];  // NOLINT
350       gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
351       dummy_varying = dummy_uniform;
352     }
353   );  // NOLINT(whitespace/parens)
354 #else
355   return VERTEX_SHADER(
356     attribute TexCoordPrecision vec4 a_position;
357     attribute float a_index;
358     uniform mat4 matrix;
359     uniform TexCoordPrecision vec2 quad[4];
360     void main() {
361       vec2 pos = quad[int(a_index)];  // NOLINT
362       gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
363     }
364   );  // NOLINT(whitespace/parens)
365 #endif
366 }
367
368 VertexShaderQuadAA::VertexShaderQuadAA()
369     : matrix_location_(-1),
370       viewport_location_(-1),
371       quad_location_(-1),
372       edge_location_(-1) {}
373
374 void VertexShaderQuadAA::Init(GLES2Interface* context,
375                             unsigned program,
376                             int* base_uniform_index) {
377   static const char* uniforms[] = {
378     "matrix",
379     "viewport",
380     "quad",
381     "edge",
382   };
383   int locations[arraysize(uniforms)];
384
385   GetProgramUniformLocations(context,
386                              program,
387                              arraysize(uniforms),
388                              uniforms,
389                              locations,
390                              base_uniform_index);
391   matrix_location_ = locations[0];
392   viewport_location_ = locations[1];
393   quad_location_ = locations[2];
394   edge_location_ = locations[3];
395 }
396
397 std::string VertexShaderQuadAA::GetShaderString() const {
398   return VERTEX_SHADER(
399     attribute TexCoordPrecision vec4 a_position;
400     attribute float a_index;
401     uniform mat4 matrix;
402     uniform vec4 viewport;
403     uniform TexCoordPrecision vec2 quad[4];
404     uniform TexCoordPrecision vec3 edge[8];
405     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
406
407     void main() {
408       vec2 pos = quad[int(a_index)];  // NOLINT
409       gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
410       vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
411       vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
412       edge_dist[0] = vec4(dot(edge[0], screen_pos),
413                           dot(edge[1], screen_pos),
414                           dot(edge[2], screen_pos),
415                           dot(edge[3], screen_pos)) * gl_Position.w;
416       edge_dist[1] = vec4(dot(edge[4], screen_pos),
417                           dot(edge[5], screen_pos),
418                           dot(edge[6], screen_pos),
419                           dot(edge[7], screen_pos)) * gl_Position.w;
420     }
421   );  // NOLINT(whitespace/parens)
422 }
423
424 VertexShaderQuadTexTransformAA::VertexShaderQuadTexTransformAA()
425     : matrix_location_(-1),
426       viewport_location_(-1),
427       quad_location_(-1),
428       edge_location_(-1),
429       tex_transform_location_(-1) {}
430
431 void VertexShaderQuadTexTransformAA::Init(GLES2Interface* context,
432                                         unsigned program,
433                                         int* base_uniform_index) {
434   static const char* uniforms[] = {
435     "matrix",
436     "viewport",
437     "quad",
438     "edge",
439     "texTrans",
440   };
441   int locations[arraysize(uniforms)];
442
443   GetProgramUniformLocations(context,
444                              program,
445                              arraysize(uniforms),
446                              uniforms,
447                              locations,
448                              base_uniform_index);
449   matrix_location_ = locations[0];
450   viewport_location_ = locations[1];
451   quad_location_ = locations[2];
452   edge_location_ = locations[3];
453   tex_transform_location_ = locations[4];
454 }
455
456 std::string VertexShaderQuadTexTransformAA::GetShaderString() const {
457   return VERTEX_SHADER(
458     attribute TexCoordPrecision vec4 a_position;
459     attribute float a_index;
460     uniform mat4 matrix;
461     uniform vec4 viewport;
462     uniform TexCoordPrecision vec2 quad[4];
463     uniform TexCoordPrecision vec3 edge[8];
464     uniform TexCoordPrecision vec4 texTrans;
465     varying TexCoordPrecision vec2 v_texCoord;
466     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
467
468     void main() {
469       vec2 pos = quad[int(a_index)];  // NOLINT
470       gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
471       vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
472       vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
473       edge_dist[0] = vec4(dot(edge[0], screen_pos),
474                           dot(edge[1], screen_pos),
475                           dot(edge[2], screen_pos),
476                           dot(edge[3], screen_pos)) * gl_Position.w;
477       edge_dist[1] = vec4(dot(edge[4], screen_pos),
478                           dot(edge[5], screen_pos),
479                           dot(edge[6], screen_pos),
480                           dot(edge[7], screen_pos)) * gl_Position.w;
481       v_texCoord = (pos.xy + vec2(0.5)) * texTrans.zw + texTrans.xy;
482     }
483   );  // NOLINT(whitespace/parens)
484 }
485
486 VertexShaderTile::VertexShaderTile()
487     : matrix_location_(-1),
488       quad_location_(-1),
489       vertex_tex_transform_location_(-1) {}
490
491 void VertexShaderTile::Init(GLES2Interface* context,
492                             unsigned program,
493                             int* base_uniform_index) {
494   static const char* uniforms[] = {
495     "matrix",
496     "quad",
497     "vertexTexTransform",
498   };
499   int locations[arraysize(uniforms)];
500
501   GetProgramUniformLocations(context,
502                              program,
503                              arraysize(uniforms),
504                              uniforms,
505                              locations,
506                              base_uniform_index);
507   matrix_location_ = locations[0];
508   quad_location_ = locations[1];
509   vertex_tex_transform_location_ = locations[2];
510 }
511
512 std::string VertexShaderTile::GetShaderString() const {
513   return VERTEX_SHADER(
514     attribute TexCoordPrecision vec4 a_position;
515     attribute float a_index;
516     uniform mat4 matrix;
517     uniform TexCoordPrecision vec2 quad[4];
518     uniform TexCoordPrecision vec4 vertexTexTransform;
519     varying TexCoordPrecision vec2 v_texCoord;
520     void main() {
521       vec2 pos = quad[int(a_index)];  // NOLINT
522       gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
523       v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
524     }
525   );  // NOLINT(whitespace/parens)
526 }
527
528 VertexShaderTileAA::VertexShaderTileAA()
529     : matrix_location_(-1),
530       viewport_location_(-1),
531       quad_location_(-1),
532       edge_location_(-1),
533       vertex_tex_transform_location_(-1) {}
534
535 void VertexShaderTileAA::Init(GLES2Interface* context,
536                               unsigned program,
537                               int* base_uniform_index) {
538   static const char* uniforms[] = {
539     "matrix",
540     "viewport",
541     "quad",
542     "edge",
543     "vertexTexTransform",
544   };
545   int locations[arraysize(uniforms)];
546
547   GetProgramUniformLocations(context,
548                              program,
549                              arraysize(uniforms),
550                              uniforms,
551                              locations,
552                              base_uniform_index);
553   matrix_location_ = locations[0];
554   viewport_location_ = locations[1];
555   quad_location_ = locations[2];
556   edge_location_ = locations[3];
557   vertex_tex_transform_location_ = locations[4];
558 }
559
560 std::string VertexShaderTileAA::GetShaderString() const {
561   return VERTEX_SHADER(
562     attribute TexCoordPrecision vec4 a_position;
563     attribute float a_index;
564     uniform mat4 matrix;
565     uniform vec4 viewport;
566     uniform TexCoordPrecision vec2 quad[4];
567     uniform TexCoordPrecision vec3 edge[8];
568     uniform TexCoordPrecision vec4 vertexTexTransform;
569     varying TexCoordPrecision vec2 v_texCoord;
570     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
571
572     void main() {
573       vec2 pos = quad[int(a_index)];  // NOLINT
574       gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
575       vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
576       vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
577       edge_dist[0] = vec4(dot(edge[0], screen_pos),
578                           dot(edge[1], screen_pos),
579                           dot(edge[2], screen_pos),
580                           dot(edge[3], screen_pos)) * gl_Position.w;
581       edge_dist[1] = vec4(dot(edge[4], screen_pos),
582                           dot(edge[5], screen_pos),
583                           dot(edge[6], screen_pos),
584                           dot(edge[7], screen_pos)) * gl_Position.w;
585       v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
586     }
587   );  // NOLINT(whitespace/parens)
588 }
589
590 VertexShaderVideoTransform::VertexShaderVideoTransform()
591     : matrix_location_(-1),
592       tex_matrix_location_(-1) {}
593
594 void VertexShaderVideoTransform::Init(GLES2Interface* context,
595                                       unsigned program,
596                                       int* base_uniform_index) {
597   static const char* uniforms[] = {
598     "matrix",
599     "texMatrix",
600   };
601   int locations[arraysize(uniforms)];
602
603   GetProgramUniformLocations(context,
604                              program,
605                              arraysize(uniforms),
606                              uniforms,
607                              locations,
608                              base_uniform_index);
609   matrix_location_ = locations[0];
610   tex_matrix_location_ = locations[1];
611 }
612
613 std::string VertexShaderVideoTransform::GetShaderString() const {
614   return VERTEX_SHADER(
615     attribute vec4 a_position;
616     attribute TexCoordPrecision vec2 a_texCoord;
617     uniform mat4 matrix;
618     uniform TexCoordPrecision mat4 texMatrix;
619     varying TexCoordPrecision vec2 v_texCoord;
620     void main() {
621         gl_Position = matrix * a_position;
622         v_texCoord =
623             vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0));
624     }
625   );  // NOLINT(whitespace/parens)
626 }
627
628 FragmentTexAlphaBinding::FragmentTexAlphaBinding()
629     : sampler_location_(-1),
630       alpha_location_(-1) {}
631
632 void FragmentTexAlphaBinding::Init(GLES2Interface* context,
633                                    unsigned program,
634                                    int* base_uniform_index) {
635   static const char* uniforms[] = {
636     "s_texture",
637     "alpha",
638   };
639   int locations[arraysize(uniforms)];
640
641   GetProgramUniformLocations(context,
642                              program,
643                              arraysize(uniforms),
644                              uniforms,
645                              locations,
646                              base_uniform_index);
647   sampler_location_ = locations[0];
648   alpha_location_ = locations[1];
649 }
650
651 FragmentTexColorMatrixAlphaBinding::FragmentTexColorMatrixAlphaBinding()
652     : sampler_location_(-1),
653       alpha_location_(-1),
654       color_matrix_location_(-1),
655       color_offset_location_(-1) {}
656
657 void FragmentTexColorMatrixAlphaBinding::Init(GLES2Interface* context,
658                                               unsigned program,
659                                               int* base_uniform_index) {
660   static const char* uniforms[] = {
661     "s_texture",
662     "alpha",
663     "colorMatrix",
664     "colorOffset",
665   };
666   int locations[arraysize(uniforms)];
667
668   GetProgramUniformLocations(context,
669                              program,
670                              arraysize(uniforms),
671                              uniforms,
672                              locations,
673                              base_uniform_index);
674   sampler_location_ = locations[0];
675   alpha_location_ = locations[1];
676   color_matrix_location_ = locations[2];
677   color_offset_location_ = locations[3];
678 }
679
680 FragmentTexOpaqueBinding::FragmentTexOpaqueBinding()
681     : sampler_location_(-1) {}
682
683 void FragmentTexOpaqueBinding::Init(GLES2Interface* context,
684                                     unsigned program,
685                                     int* base_uniform_index) {
686   static const char* uniforms[] = {
687     "s_texture",
688   };
689   int locations[arraysize(uniforms)];
690
691   GetProgramUniformLocations(context,
692                              program,
693                              arraysize(uniforms),
694                              uniforms,
695                              locations,
696                              base_uniform_index);
697   sampler_location_ = locations[0];
698 }
699
700 std::string FragmentShaderRGBATexAlpha::GetShaderString(
701     TexCoordPrecision precision, SamplerType sampler) const {
702   return FRAGMENT_SHADER(
703     precision mediump float;
704     varying TexCoordPrecision vec2 v_texCoord;
705     uniform SamplerType s_texture;
706     uniform float alpha;
707     void main() {
708       vec4 texColor = TextureLookup(s_texture, v_texCoord);
709       gl_FragColor = texColor * alpha;
710     }
711   );  // NOLINT(whitespace/parens)
712 }
713
714 std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
715     TexCoordPrecision precision, SamplerType sampler) const {
716   return FRAGMENT_SHADER(
717     precision mediump float;
718     varying TexCoordPrecision vec2 v_texCoord;
719     uniform SamplerType s_texture;
720     uniform float alpha;
721     uniform mat4 colorMatrix;
722     uniform vec4 colorOffset;
723     void main() {
724       vec4 texColor = TextureLookup(s_texture, v_texCoord);
725       float nonZeroAlpha = max(texColor.a, 0.00001);
726       texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
727       texColor = colorMatrix * texColor + colorOffset;
728       texColor.rgb *= texColor.a;
729       texColor = clamp(texColor, 0.0, 1.0);
730       gl_FragColor = texColor * alpha;
731     }
732   );  // NOLINT(whitespace/parens)
733 }
734
735 std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
736     TexCoordPrecision precision, SamplerType sampler) const {
737   return FRAGMENT_SHADER(
738     precision mediump float;
739     varying TexCoordPrecision vec2 v_texCoord;
740     varying float v_alpha;
741     uniform SamplerType s_texture;
742     void main() {
743       vec4 texColor = TextureLookup(s_texture, v_texCoord);
744       gl_FragColor = texColor * v_alpha;
745     }
746   );  // NOLINT(whitespace/parens)
747 }
748
749 std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
750     TexCoordPrecision precision, SamplerType sampler) const {
751   return FRAGMENT_SHADER(
752     precision mediump float;
753     varying TexCoordPrecision vec2 v_texCoord;
754     varying float v_alpha;
755     uniform SamplerType s_texture;
756     void main() {
757       vec4 texColor = TextureLookup(s_texture, v_texCoord);
758       texColor.rgb *= texColor.a;
759       gl_FragColor = texColor * v_alpha;
760     }
761   );  // NOLINT(whitespace/parens)
762 }
763
764 FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
765     : background_color_location_(-1),
766       sampler_location_(-1) {
767 }
768
769 void FragmentTexBackgroundBinding::Init(GLES2Interface* context,
770                                         unsigned program,
771                                         int* base_uniform_index) {
772   static const char* uniforms[] = {
773     "s_texture",
774     "background_color",
775   };
776   int locations[arraysize(uniforms)];
777
778   GetProgramUniformLocations(context,
779                              program,
780                              arraysize(uniforms),
781                              uniforms,
782                              locations,
783                              base_uniform_index);
784
785   sampler_location_ = locations[0];
786   DCHECK_NE(sampler_location_, -1);
787
788   background_color_location_ = locations[1];
789   DCHECK_NE(background_color_location_, -1);
790 }
791
792 std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
793     TexCoordPrecision precision, SamplerType sampler) const {
794   return FRAGMENT_SHADER(
795     precision mediump float;
796     varying TexCoordPrecision vec2 v_texCoord;
797     varying float v_alpha;
798     uniform vec4 background_color;
799     uniform SamplerType s_texture;
800     void main() {
801       vec4 texColor = TextureLookup(s_texture, v_texCoord);
802       texColor += background_color * (1.0 - texColor.a);
803       gl_FragColor = texColor * v_alpha;
804     }
805   );  // NOLINT(whitespace/parens)
806 }
807
808 std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderString(
809     TexCoordPrecision precision, SamplerType sampler) const {
810   return FRAGMENT_SHADER(
811     precision mediump float;
812     varying TexCoordPrecision vec2 v_texCoord;
813     varying float v_alpha;
814     uniform vec4 background_color;
815     uniform SamplerType s_texture;
816     void main() {
817       vec4 texColor = TextureLookup(s_texture, v_texCoord);
818       texColor.rgb *= texColor.a;
819       texColor += background_color * (1.0 - texColor.a);
820       gl_FragColor = texColor * v_alpha;
821     }
822   );  // NOLINT(whitespace/parens)
823 }
824
825 std::string FragmentShaderRGBATexOpaque::GetShaderString(
826     TexCoordPrecision precision, SamplerType sampler) const {
827   return FRAGMENT_SHADER(
828     precision mediump float;
829     varying TexCoordPrecision vec2 v_texCoord;
830     uniform SamplerType s_texture;
831     void main() {
832       vec4 texColor = TextureLookup(s_texture, v_texCoord);
833       gl_FragColor = vec4(texColor.rgb, 1.0);
834     }
835   );  // NOLINT(whitespace/parens)
836 }
837
838 std::string FragmentShaderRGBATex::GetShaderString(
839     TexCoordPrecision precision, SamplerType sampler) const {
840   return FRAGMENT_SHADER(
841     precision mediump float;
842     varying TexCoordPrecision vec2 v_texCoord;
843     uniform SamplerType s_texture;
844     void main() {
845       gl_FragColor = TextureLookup(s_texture, v_texCoord);
846     }
847   );  // NOLINT(whitespace/parens)
848 }
849
850 std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderString(
851     TexCoordPrecision precision, SamplerType sampler) const {
852   return FRAGMENT_SHADER(
853     precision mediump float;
854     varying TexCoordPrecision vec2 v_texCoord;
855     uniform SamplerType s_texture;
856     uniform float alpha;
857     void main() {
858         vec4 texColor = TextureLookup(s_texture, v_texCoord);
859         gl_FragColor =
860             vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
861     }
862   );  // NOLINT(whitespace/parens)
863 }
864
865 std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderString(
866     TexCoordPrecision precision, SamplerType sampler) const {
867   return FRAGMENT_SHADER(
868     precision mediump float;
869     varying TexCoordPrecision vec2 v_texCoord;
870     uniform SamplerType s_texture;
871     void main() {
872       vec4 texColor = TextureLookup(s_texture, v_texCoord);
873       gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
874     }
875   );  // NOLINT(whitespace/parens)
876 }
877
878 FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA()
879     : sampler_location_(-1),
880       alpha_location_(-1) {}
881
882 void FragmentShaderRGBATexAlphaAA::Init(GLES2Interface* context,
883                                         unsigned program,
884                                         int* base_uniform_index) {
885   static const char* uniforms[] = {
886     "s_texture",
887     "alpha",
888   };
889   int locations[arraysize(uniforms)];
890
891   GetProgramUniformLocations(context,
892                              program,
893                              arraysize(uniforms),
894                              uniforms,
895                              locations,
896                              base_uniform_index);
897   sampler_location_ = locations[0];
898   alpha_location_ = locations[1];
899 }
900
901 std::string FragmentShaderRGBATexAlphaAA::GetShaderString(
902     TexCoordPrecision precision, SamplerType sampler) const {
903   return FRAGMENT_SHADER(
904     precision mediump float;
905     uniform SamplerType s_texture;
906     uniform float alpha;
907     varying TexCoordPrecision vec2 v_texCoord;
908     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
909
910     void main() {
911       vec4 texColor = TextureLookup(s_texture, v_texCoord);
912       vec4 d4 = min(edge_dist[0], edge_dist[1]);
913       vec2 d2 = min(d4.xz, d4.yw);
914       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
915       gl_FragColor = texColor * alpha * aa;
916     }
917   );  // NOLINT(whitespace/parens)
918 }
919
920 FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
921     : sampler_location_(-1),
922       alpha_location_(-1),
923       fragment_tex_transform_location_(-1) {}
924
925 void FragmentTexClampAlphaAABinding::Init(GLES2Interface* context,
926                                           unsigned program,
927                                           int* base_uniform_index) {
928   static const char* uniforms[] = {
929     "s_texture",
930     "alpha",
931     "fragmentTexTransform",
932   };
933   int locations[arraysize(uniforms)];
934
935   GetProgramUniformLocations(context,
936                              program,
937                              arraysize(uniforms),
938                              uniforms,
939                              locations,
940                              base_uniform_index);
941   sampler_location_ = locations[0];
942   alpha_location_ = locations[1];
943   fragment_tex_transform_location_ = locations[2];
944 }
945
946 std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
947     TexCoordPrecision precision, SamplerType sampler) const {
948   return FRAGMENT_SHADER(
949     precision mediump float;
950     uniform SamplerType s_texture;
951     uniform float alpha;
952     uniform TexCoordPrecision vec4 fragmentTexTransform;
953     varying TexCoordPrecision vec2 v_texCoord;
954     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
955
956     void main() {
957       TexCoordPrecision vec2 texCoord =
958           clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
959           fragmentTexTransform.xy;
960       vec4 texColor = TextureLookup(s_texture, texCoord);
961       vec4 d4 = min(edge_dist[0], edge_dist[1]);
962       vec2 d2 = min(d4.xz, d4.yw);
963       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
964       gl_FragColor = texColor * alpha * aa;
965     }
966   );  // NOLINT(whitespace/parens)
967 }
968
969 std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderString(
970     TexCoordPrecision precision, SamplerType sampler) const {
971   return FRAGMENT_SHADER(
972     precision mediump float;
973     uniform SamplerType s_texture;
974     uniform float alpha;
975     uniform TexCoordPrecision vec4 fragmentTexTransform;
976     varying TexCoordPrecision vec2 v_texCoord;
977     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
978
979     void main() {
980       TexCoordPrecision vec2 texCoord =
981           clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
982           fragmentTexTransform.xy;
983       vec4 texColor = TextureLookup(s_texture, texCoord);
984       vec4 d4 = min(edge_dist[0], edge_dist[1]);
985       vec2 d2 = min(d4.xz, d4.yw);
986       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
987       gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) *
988           alpha * aa;
989     }
990   );  // NOLINT(whitespace/parens)
991 }
992
993 FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask()
994     : sampler_location_(-1),
995       mask_sampler_location_(-1),
996       alpha_location_(-1),
997       mask_tex_coord_scale_location_(-1) {}
998
999 void FragmentShaderRGBATexAlphaMask::Init(GLES2Interface* context,
1000                                           unsigned program,
1001                                           int* base_uniform_index) {
1002   static const char* uniforms[] = {
1003     "s_texture",
1004     "s_mask",
1005     "alpha",
1006     "maskTexCoordScale",
1007     "maskTexCoordOffset",
1008   };
1009   int locations[arraysize(uniforms)];
1010
1011   GetProgramUniformLocations(context,
1012                              program,
1013                              arraysize(uniforms),
1014                              uniforms,
1015                              locations,
1016                              base_uniform_index);
1017   sampler_location_ = locations[0];
1018   mask_sampler_location_ = locations[1];
1019   alpha_location_ = locations[2];
1020   mask_tex_coord_scale_location_ = locations[3];
1021   mask_tex_coord_offset_location_ = locations[4];
1022 }
1023
1024 std::string FragmentShaderRGBATexAlphaMask::GetShaderString(
1025     TexCoordPrecision precision, SamplerType sampler) const {
1026   return FRAGMENT_SHADER(
1027     precision mediump float;
1028     varying TexCoordPrecision vec2 v_texCoord;
1029     uniform SamplerType s_texture;
1030     uniform SamplerType s_mask;
1031     uniform TexCoordPrecision vec2 maskTexCoordScale;
1032     uniform TexCoordPrecision vec2 maskTexCoordOffset;
1033     uniform float alpha;
1034     void main() {
1035       vec4 texColor = TextureLookup(s_texture, v_texCoord);
1036       TexCoordPrecision vec2 maskTexCoord =
1037           vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1038                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1039       vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1040       gl_FragColor = texColor * alpha * maskColor.w;
1041     }
1042   );  // NOLINT(whitespace/parens)
1043 }
1044
1045 FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA()
1046     : sampler_location_(-1),
1047       mask_sampler_location_(-1),
1048       alpha_location_(-1),
1049       mask_tex_coord_scale_location_(-1),
1050       mask_tex_coord_offset_location_(-1) {}
1051
1052 void FragmentShaderRGBATexAlphaMaskAA::Init(GLES2Interface* context,
1053                                             unsigned program,
1054                                             int* base_uniform_index) {
1055   static const char* uniforms[] = {
1056     "s_texture",
1057     "s_mask",
1058     "alpha",
1059     "maskTexCoordScale",
1060     "maskTexCoordOffset",
1061   };
1062   int locations[arraysize(uniforms)];
1063
1064   GetProgramUniformLocations(context,
1065                              program,
1066                              arraysize(uniforms),
1067                              uniforms,
1068                              locations,
1069                              base_uniform_index);
1070   sampler_location_ = locations[0];
1071   mask_sampler_location_ = locations[1];
1072   alpha_location_ = locations[2];
1073   mask_tex_coord_scale_location_ = locations[3];
1074   mask_tex_coord_offset_location_ = locations[4];
1075 }
1076
1077 std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
1078     TexCoordPrecision precision, SamplerType sampler) const {
1079   return FRAGMENT_SHADER(
1080     precision mediump float;
1081     uniform SamplerType s_texture;
1082     uniform SamplerType s_mask;
1083     uniform TexCoordPrecision vec2 maskTexCoordScale;
1084     uniform TexCoordPrecision vec2 maskTexCoordOffset;
1085     uniform float alpha;
1086     varying TexCoordPrecision vec2 v_texCoord;
1087     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
1088
1089     void main() {
1090       vec4 texColor = TextureLookup(s_texture, v_texCoord);
1091       TexCoordPrecision vec2 maskTexCoord =
1092           vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1093                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1094       vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1095       vec4 d4 = min(edge_dist[0], edge_dist[1]);
1096       vec2 d2 = min(d4.xz, d4.yw);
1097       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1098       gl_FragColor = texColor * alpha * maskColor.w * aa;
1099     }
1100   );  // NOLINT(whitespace/parens)
1101 }
1102
1103 FragmentShaderRGBATexAlphaMaskColorMatrixAA::
1104     FragmentShaderRGBATexAlphaMaskColorMatrixAA()
1105         : sampler_location_(-1),
1106           mask_sampler_location_(-1),
1107           alpha_location_(-1),
1108           mask_tex_coord_scale_location_(-1),
1109           color_matrix_location_(-1),
1110           color_offset_location_(-1) {}
1111
1112 void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init(
1113     GLES2Interface* context,
1114     unsigned program,
1115     int* base_uniform_index) {
1116   static const char* uniforms[] = {
1117     "s_texture",
1118     "s_mask",
1119     "alpha",
1120     "maskTexCoordScale",
1121     "maskTexCoordOffset",
1122     "colorMatrix",
1123     "colorOffset",
1124   };
1125   int locations[arraysize(uniforms)];
1126
1127   GetProgramUniformLocations(context,
1128                              program,
1129                              arraysize(uniforms),
1130                              uniforms,
1131                              locations,
1132                              base_uniform_index);
1133   sampler_location_ = locations[0];
1134   mask_sampler_location_ = locations[1];
1135   alpha_location_ = locations[2];
1136   mask_tex_coord_scale_location_ = locations[3];
1137   mask_tex_coord_offset_location_ = locations[4];
1138   color_matrix_location_ = locations[5];
1139   color_offset_location_ = locations[6];
1140 }
1141
1142 std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
1143     TexCoordPrecision precision, SamplerType sampler) const {
1144   return FRAGMENT_SHADER(
1145     precision mediump float;
1146     uniform SamplerType s_texture;
1147     uniform SamplerType s_mask;
1148     uniform vec2 maskTexCoordScale;
1149     uniform vec2 maskTexCoordOffset;
1150     uniform mat4 colorMatrix;
1151     uniform vec4 colorOffset;
1152     uniform float alpha;
1153     varying TexCoordPrecision vec2 v_texCoord;
1154     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
1155
1156     void main() {
1157       vec4 texColor = TextureLookup(s_texture, v_texCoord);
1158       float nonZeroAlpha = max(texColor.a, 0.00001);
1159       texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1160       texColor = colorMatrix * texColor + colorOffset;
1161       texColor.rgb *= texColor.a;
1162       texColor = clamp(texColor, 0.0, 1.0);
1163       TexCoordPrecision vec2 maskTexCoord =
1164           vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1165                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1166       vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1167       vec4 d4 = min(edge_dist[0], edge_dist[1]);
1168       vec2 d2 = min(d4.xz, d4.yw);
1169       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1170       gl_FragColor = texColor * alpha * maskColor.w * aa;
1171     }
1172   );  // NOLINT(whitespace/parens)
1173 }
1174
1175 FragmentShaderRGBATexAlphaColorMatrixAA::
1176     FragmentShaderRGBATexAlphaColorMatrixAA()
1177         : sampler_location_(-1),
1178           alpha_location_(-1),
1179           color_matrix_location_(-1),
1180           color_offset_location_(-1) {}
1181
1182 void FragmentShaderRGBATexAlphaColorMatrixAA::Init(
1183       GLES2Interface* context,
1184       unsigned program,
1185       int* base_uniform_index) {
1186   static const char* uniforms[] = {
1187     "s_texture",
1188     "alpha",
1189     "colorMatrix",
1190     "colorOffset",
1191   };
1192   int locations[arraysize(uniforms)];
1193
1194   GetProgramUniformLocations(context,
1195                              program,
1196                              arraysize(uniforms),
1197                              uniforms,
1198                              locations,
1199                              base_uniform_index);
1200   sampler_location_ = locations[0];
1201   alpha_location_ = locations[1];
1202   color_matrix_location_ = locations[2];
1203   color_offset_location_ = locations[3];
1204 }
1205
1206 std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
1207     TexCoordPrecision precision, SamplerType sampler) const {
1208   return FRAGMENT_SHADER(
1209     precision mediump float;
1210     uniform SamplerType s_texture;
1211     uniform float alpha;
1212     uniform mat4 colorMatrix;
1213     uniform vec4 colorOffset;
1214     varying TexCoordPrecision vec2 v_texCoord;
1215     varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
1216
1217     void main() {
1218       vec4 texColor = TextureLookup(s_texture, v_texCoord);
1219       float nonZeroAlpha = max(texColor.a, 0.00001);
1220       texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1221       texColor = colorMatrix * texColor + colorOffset;
1222       texColor.rgb *= texColor.a;
1223       texColor = clamp(texColor, 0.0, 1.0);
1224       vec4 d4 = min(edge_dist[0], edge_dist[1]);
1225       vec2 d2 = min(d4.xz, d4.yw);
1226       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1227       gl_FragColor = texColor * alpha * aa;
1228     }
1229   );  // NOLINT(whitespace/parens)
1230 }
1231
1232 FragmentShaderRGBATexAlphaMaskColorMatrix::
1233     FragmentShaderRGBATexAlphaMaskColorMatrix()
1234         : sampler_location_(-1),
1235           mask_sampler_location_(-1),
1236           alpha_location_(-1),
1237           mask_tex_coord_scale_location_(-1) {}
1238
1239 void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(
1240     GLES2Interface* context,
1241     unsigned program,
1242     int* base_uniform_index) {
1243   static const char* uniforms[] = {
1244     "s_texture",
1245     "s_mask",
1246     "alpha",
1247     "maskTexCoordScale",
1248     "maskTexCoordOffset",
1249     "colorMatrix",
1250     "colorOffset",
1251   };
1252   int locations[arraysize(uniforms)];
1253
1254   GetProgramUniformLocations(context,
1255                              program,
1256                              arraysize(uniforms),
1257                              uniforms,
1258                              locations,
1259                              base_uniform_index);
1260   sampler_location_ = locations[0];
1261   mask_sampler_location_ = locations[1];
1262   alpha_location_ = locations[2];
1263   mask_tex_coord_scale_location_ = locations[3];
1264   mask_tex_coord_offset_location_ = locations[4];
1265   color_matrix_location_ = locations[5];
1266   color_offset_location_ = locations[6];
1267 }
1268
1269 std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
1270     TexCoordPrecision precision, SamplerType sampler) const {
1271   return FRAGMENT_SHADER(
1272     precision mediump float;
1273     varying TexCoordPrecision vec2 v_texCoord;
1274     uniform SamplerType s_texture;
1275     uniform SamplerType s_mask;
1276     uniform vec2 maskTexCoordScale;
1277     uniform vec2 maskTexCoordOffset;
1278     uniform mat4 colorMatrix;
1279     uniform vec4 colorOffset;
1280     uniform float alpha;
1281     void main() {
1282       vec4 texColor = TextureLookup(s_texture, v_texCoord);
1283       float nonZeroAlpha = max(texColor.a, 0.00001);
1284       texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
1285       texColor = colorMatrix * texColor + colorOffset;
1286       texColor.rgb *= texColor.a;
1287       texColor = clamp(texColor, 0.0, 1.0);
1288       TexCoordPrecision vec2 maskTexCoord =
1289           vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
1290                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
1291       vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
1292       gl_FragColor = texColor * alpha * maskColor.w;
1293     }
1294   );  // NOLINT(whitespace/parens)
1295 }
1296
1297 FragmentShaderYUVVideo::FragmentShaderYUVVideo()
1298     : y_texture_location_(-1),
1299       u_texture_location_(-1),
1300       v_texture_location_(-1),
1301       alpha_location_(-1),
1302       yuv_matrix_location_(-1),
1303       yuv_adj_location_(-1) {}
1304
1305 void FragmentShaderYUVVideo::Init(GLES2Interface* context,
1306                                   unsigned program,
1307                                   int* base_uniform_index) {
1308   static const char* uniforms[] = {
1309     "y_texture",
1310     "u_texture",
1311     "v_texture",
1312     "alpha",
1313     "yuv_matrix",
1314     "yuv_adj",
1315   };
1316   int locations[arraysize(uniforms)];
1317
1318   GetProgramUniformLocations(context,
1319                              program,
1320                              arraysize(uniforms),
1321                              uniforms,
1322                              locations,
1323                              base_uniform_index);
1324   y_texture_location_ = locations[0];
1325   u_texture_location_ = locations[1];
1326   v_texture_location_ = locations[2];
1327   alpha_location_ = locations[3];
1328   yuv_matrix_location_ = locations[4];
1329   yuv_adj_location_ = locations[5];
1330 }
1331
1332 std::string FragmentShaderYUVVideo::GetShaderString(
1333     TexCoordPrecision precision, SamplerType sampler) const {
1334   return FRAGMENT_SHADER(
1335     precision mediump float;
1336     precision mediump int;
1337     varying TexCoordPrecision vec2 v_texCoord;
1338     uniform SamplerType y_texture;
1339     uniform SamplerType u_texture;
1340     uniform SamplerType v_texture;
1341     uniform float alpha;
1342     uniform vec3 yuv_adj;
1343     uniform mat3 yuv_matrix;
1344     void main() {
1345       float y_raw = TextureLookup(y_texture, v_texCoord).x;
1346       float u_unsigned = TextureLookup(u_texture, v_texCoord).x;
1347       float v_unsigned = TextureLookup(v_texture, v_texCoord).x;
1348       vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
1349       vec3 rgb = yuv_matrix * yuv;
1350       gl_FragColor = vec4(rgb, 1.0) * alpha;
1351     }
1352   );  // NOLINT(whitespace/parens)
1353 }
1354
1355 FragmentShaderYUVAVideo::FragmentShaderYUVAVideo()
1356     : y_texture_location_(-1),
1357       u_texture_location_(-1),
1358       v_texture_location_(-1),
1359       a_texture_location_(-1),
1360       alpha_location_(-1),
1361       yuv_matrix_location_(-1),
1362       yuv_adj_location_(-1) {
1363 }
1364
1365 void FragmentShaderYUVAVideo::Init(GLES2Interface* context,
1366                                    unsigned program,
1367                                    int* base_uniform_index) {
1368   static const char* uniforms[] = {
1369       "y_texture",
1370       "u_texture",
1371       "v_texture",
1372       "a_texture",
1373       "alpha",
1374       "cc_matrix",
1375       "yuv_adj",
1376   };
1377   int locations[arraysize(uniforms)];
1378
1379   GetProgramUniformLocations(context,
1380                              program,
1381                              arraysize(uniforms),
1382                              uniforms,
1383                              locations,
1384                              base_uniform_index);
1385   y_texture_location_ = locations[0];
1386   u_texture_location_ = locations[1];
1387   v_texture_location_ = locations[2];
1388   a_texture_location_ = locations[3];
1389   alpha_location_ = locations[4];
1390   yuv_matrix_location_ = locations[5];
1391   yuv_adj_location_ = locations[6];
1392 }
1393
1394 std::string FragmentShaderYUVAVideo::GetShaderString(
1395     TexCoordPrecision precision, SamplerType sampler) const {
1396   return FRAGMENT_SHADER(
1397     precision mediump float;
1398     precision mediump int;
1399     varying TexCoordPrecision vec2 v_texCoord;
1400     uniform SamplerType y_texture;
1401     uniform SamplerType u_texture;
1402     uniform SamplerType v_texture;
1403     uniform SamplerType a_texture;
1404     uniform float alpha;
1405     uniform vec3 yuv_adj;
1406     uniform mat3 yuv_matrix;
1407     void main() {
1408       float y_raw = TextureLookup(y_texture, v_texCoord).x;
1409       float u_unsigned = TextureLookup(u_texture, v_texCoord).x;
1410       float v_unsigned = TextureLookup(v_texture, v_texCoord).x;
1411       float a_raw = TextureLookup(a_texture, v_texCoord).x;
1412       vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
1413       vec3 rgb = yuv_matrix * yuv;
1414       gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
1415     }
1416   );  // NOLINT(whitespace/parens)
1417 }
1418
1419 FragmentShaderColor::FragmentShaderColor()
1420     : color_location_(-1) {}
1421
1422 void FragmentShaderColor::Init(GLES2Interface* context,
1423                                unsigned program,
1424                                int* base_uniform_index) {
1425   static const char* uniforms[] = {
1426     "color",
1427   };
1428   int locations[arraysize(uniforms)];
1429
1430   GetProgramUniformLocations(context,
1431                              program,
1432                              arraysize(uniforms),
1433                              uniforms,
1434                              locations,
1435                              base_uniform_index);
1436   color_location_ = locations[0];
1437 }
1438
1439 std::string FragmentShaderColor::GetShaderString(
1440     TexCoordPrecision precision, SamplerType sampler) const {
1441   return FRAGMENT_SHADER(
1442     precision mediump float;
1443     uniform vec4 color;
1444     void main() {
1445       gl_FragColor = color;
1446     }
1447   );  // NOLINT(whitespace/parens)
1448 }
1449
1450 FragmentShaderColorAA::FragmentShaderColorAA()
1451     : color_location_(-1) {}
1452
1453 void FragmentShaderColorAA::Init(GLES2Interface* context,
1454                                  unsigned program,
1455                                  int* base_uniform_index) {
1456   static const char* uniforms[] = {
1457     "color",
1458   };
1459   int locations[arraysize(uniforms)];
1460
1461   GetProgramUniformLocations(context,
1462                              program,
1463                              arraysize(uniforms),
1464                              uniforms,
1465                              locations,
1466                              base_uniform_index);
1467   color_location_ = locations[0];
1468 }
1469
1470 std::string FragmentShaderColorAA::GetShaderString(
1471     TexCoordPrecision precision, SamplerType sampler) const {
1472   return FRAGMENT_SHADER(
1473     precision mediump float;
1474     uniform vec4 color;
1475     varying vec4 edge_dist[2];  // 8 edge distances.
1476
1477     void main() {
1478       vec4 d4 = min(edge_dist[0], edge_dist[1]);
1479       vec2 d2 = min(d4.xz, d4.yw);
1480       float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
1481       gl_FragColor = color * aa;
1482     }
1483   );  // NOLINT(whitespace/parens)
1484 }
1485
1486 FragmentShaderCheckerboard::FragmentShaderCheckerboard()
1487     : alpha_location_(-1),
1488       tex_transform_location_(-1),
1489       frequency_location_(-1) {}
1490
1491 void FragmentShaderCheckerboard::Init(GLES2Interface* context,
1492                                       unsigned program,
1493                                       int* base_uniform_index) {
1494   static const char* uniforms[] = {
1495     "alpha",
1496     "texTransform",
1497     "frequency",
1498     "color",
1499   };
1500   int locations[arraysize(uniforms)];
1501
1502   GetProgramUniformLocations(context,
1503                              program,
1504                              arraysize(uniforms),
1505                              uniforms,
1506                              locations,
1507                              base_uniform_index);
1508   alpha_location_ = locations[0];
1509   tex_transform_location_ = locations[1];
1510   frequency_location_ = locations[2];
1511   color_location_ = locations[3];
1512 }
1513
1514 std::string FragmentShaderCheckerboard::GetShaderString(
1515     TexCoordPrecision precision, SamplerType sampler) const {
1516   // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
1517   // by Munshi, Ginsburg, Shreiner.
1518   return FRAGMENT_SHADER(
1519     precision mediump float;
1520     precision mediump int;
1521     varying vec2 v_texCoord;
1522     uniform float alpha;
1523     uniform float frequency;
1524     uniform vec4 texTransform;
1525     uniform vec4 color;
1526     void main() {
1527       vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
1528       vec4 color2 = color;
1529       vec2 texCoord =
1530           clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
1531       vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
1532       float picker = abs(coord.x - coord.y);  // NOLINT
1533       gl_FragColor = mix(color1, color2, picker) * alpha;
1534     }
1535   );  // NOLINT(whitespace/parens)
1536 }
1537
1538 }  // namespace cc