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 
     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 
     19 using gpu::gles2::GLES2Interface;
     20 
     21 namespace cc {
     22 
     23 namespace {
     24 
     25 static 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 
     37 static 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 
     65 static 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 
     74 TexCoordPrecision 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 
     97 static 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 
    136 TexCoordPrecision 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 
    145 TexCoordPrecision 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 
    154 VertexShaderPosTex::VertexShaderPosTex()
    155       : matrix_location_(-1) {}
    156 
    157 void 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 
    174 std::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 
    187 VertexShaderPosTexYUVStretchOffset::VertexShaderPosTexYUVStretchOffset()
    188     : matrix_location_(-1), tex_scale_location_(-1), tex_offset_location_(-1) {}
    189 
    190 void 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 
    211 std::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 
    227 VertexShaderPos::VertexShaderPos()
    228     : matrix_location_(-1) {}
    229 
    230 void 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 
    247 std::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 
    257 VertexShaderPosTexTransform::VertexShaderPosTexTransform()
    258     : matrix_location_(-1),
    259       tex_transform_location_(-1),
    260       vertex_opacity_location_(-1) {}
    261 
    262 void 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 
    283 std::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 
    303 std::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 
    314 VertexShaderQuad::VertexShaderQuad()
    315     : matrix_location_(-1),
    316       quad_location_(-1) {}
    317 
    318 void 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 
    337 std::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 
    369 VertexShaderQuadAA::VertexShaderQuadAA()
    370     : matrix_location_(-1),
    371       viewport_location_(-1),
    372       quad_location_(-1),
    373       edge_location_(-1) {}
    374 
    375 void 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 
    398 std::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 
    425 VertexShaderQuadTexTransformAA::VertexShaderQuadTexTransformAA()
    426     : matrix_location_(-1),
    427       viewport_location_(-1),
    428       quad_location_(-1),
    429       edge_location_(-1),
    430       tex_transform_location_(-1) {}
    431 
    432 void 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 
    457 std::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 
    487 VertexShaderTile::VertexShaderTile()
    488     : matrix_location_(-1),
    489       quad_location_(-1),
    490       vertex_tex_transform_location_(-1) {}
    491 
    492 void 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 
    513 std::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 
    529 VertexShaderTileAA::VertexShaderTileAA()
    530     : matrix_location_(-1),
    531       viewport_location_(-1),
    532       quad_location_(-1),
    533       edge_location_(-1),
    534       vertex_tex_transform_location_(-1) {}
    535 
    536 void 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 
    561 std::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 
    591 VertexShaderVideoTransform::VertexShaderVideoTransform()
    592     : matrix_location_(-1),
    593       tex_matrix_location_(-1) {}
    594 
    595 void 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 
    614 std::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 
    629 FragmentTexAlphaBinding::FragmentTexAlphaBinding()
    630     : sampler_location_(-1),
    631       alpha_location_(-1) {}
    632 
    633 void 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 
    652 FragmentTexColorMatrixAlphaBinding::FragmentTexColorMatrixAlphaBinding()
    653     : sampler_location_(-1),
    654       alpha_location_(-1),
    655       color_matrix_location_(-1),
    656       color_offset_location_(-1) {}
    657 
    658 void 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 
    681 FragmentTexOpaqueBinding::FragmentTexOpaqueBinding()
    682     : sampler_location_(-1) {}
    683 
    684 void 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 
    701 std::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 
    715 std::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 
    736 std::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 
    750 std::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 
    765 FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
    766     : background_color_location_(-1),
    767       sampler_location_(-1) {
    768 }
    769 
    770 void 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 
    793 std::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 
    809 std::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 
    826 std::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 
    839 std::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 
    851 std::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 
    866 std::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 
    879 FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA()
    880     : sampler_location_(-1),
    881       alpha_location_(-1) {}
    882 
    883 void 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 
    902 std::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 
    921 FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
    922     : sampler_location_(-1),
    923       alpha_location_(-1),
    924       fragment_tex_transform_location_(-1) {}
    925 
    926 void 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 
    947 std::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 
    970 std::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 
    994 FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask()
    995     : sampler_location_(-1),
    996       mask_sampler_location_(-1),
    997       alpha_location_(-1),
    998       mask_tex_coord_scale_location_(-1) {}
    999 
   1000 void 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 
   1025 std::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 
   1046 FragmentShaderRGBATexAlphaMaskAA::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 
   1053 void 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 
   1078 std::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 
   1104 FragmentShaderRGBATexAlphaMaskColorMatrixAA::
   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 
   1113 void 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 
   1143 std::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 
   1176 FragmentShaderRGBATexAlphaColorMatrixAA::
   1177     FragmentShaderRGBATexAlphaColorMatrixAA()
   1178         : sampler_location_(-1),
   1179           alpha_location_(-1),
   1180           color_matrix_location_(-1),
   1181           color_offset_location_(-1) {}
   1182 
   1183 void 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 
   1207 std::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 
   1233 FragmentShaderRGBATexAlphaMaskColorMatrix::
   1234     FragmentShaderRGBATexAlphaMaskColorMatrix()
   1235         : sampler_location_(-1),
   1236           mask_sampler_location_(-1),
   1237           alpha_location_(-1),
   1238           mask_tex_coord_scale_location_(-1) {}
   1239 
   1240 void 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 
   1270 std::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 
   1298 FragmentShaderYUVVideo::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 
   1306 void 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 
   1333 std::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 
   1356 FragmentShaderYUVAVideo::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 
   1366 void 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 
   1395 std::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 
   1420 FragmentShaderColor::FragmentShaderColor()
   1421     : color_location_(-1) {}
   1422 
   1423 void 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 
   1440 std::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 
   1451 FragmentShaderColorAA::FragmentShaderColorAA()
   1452     : color_location_(-1) {}
   1453 
   1454 void 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 
   1471 std::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 
   1487 FragmentShaderCheckerboard::FragmentShaderCheckerboard()
   1488     : alpha_location_(-1),
   1489       tex_transform_location_(-1),
   1490       frequency_location_(-1) {}
   1491 
   1492 void 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 
   1515 std::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