Home | History | Annotate | Download | only in output
      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                                             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
   1539