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