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