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