| Index: cc/output/shader.cc
 | 
| diff --git a/cc/output/shader.cc b/cc/output/shader.cc
 | 
| index eb0dede1d5b9863d7338e16c76eca40f027e80f9..0a33e5352da1087999323bbf21c35b3454d16a89 100644
 | 
| --- a/cc/output/shader.cc
 | 
| +++ b/cc/output/shader.cc
 | 
| @@ -11,12 +11,24 @@
 | 
|  #include "cc/output/gl_renderer.h"  // For the GLC() macro.
 | 
|  #include "gpu/command_buffer/client/gles2_interface.h"
 | 
|  
 | 
| -#define SHADER0(Src) #Src
 | 
| -#define VERTEX_SHADER(Src) SetVertexTexCoordPrecision(SHADER0(Src))
 | 
| -#define FRAGMENT_SHADER(Src)    \
 | 
| -  SetFragmentTexCoordPrecision( \
 | 
| -      precision,                \
 | 
| -      SetFragmentSamplerType(sampler, SetBlendModeFunctions(SHADER0(Src))))
 | 
| +template <size_t size>
 | 
| +std::string StripLambda(const char(&shader)[size]) {
 | 
| +  // Must contain at least "[]() {}" and trailing null (included in size).
 | 
| +  static_assert(size >= 8,
 | 
| +                "String passed to StripLambda must be at least 8 characters");
 | 
| +  DCHECK_EQ(strncmp("[]() {", shader, 6), 0);
 | 
| +  DCHECK_EQ(shader[size - 2], '}');
 | 
| +  return std::string(shader + 6, shader + size - 2);
 | 
| +}
 | 
| +
 | 
| +// Shaders are passed in with lambda syntax, which tricks clang-format into
 | 
| +// handling them correctly. StipLambda removes this.
 | 
| +#define SHADER0(Src) StripLambda(#Src)
 | 
| +#define VERTEX_SHADER(Head, Body) SetVertexTexCoordPrecision(Head + Body)
 | 
| +#define FRAGMENT_SHADER(Head, Body) \
 | 
| +  SetFragmentTexCoordPrecision(     \
 | 
| +      precision,                    \
 | 
| +      SetFragmentSamplerType(sampler, SetBlendModeFunctions(Head + Body)))
 | 
|  
 | 
|  using gpu::gles2::GLES2Interface;
 | 
|  
 | 
| @@ -63,12 +75,13 @@ static std::string SetFragmentTexCoordPrecision(
 | 
|    return shader_string;
 | 
|  }
 | 
|  
 | 
| -static std::string SetVertexTexCoordPrecision(const char* shader_string) {
 | 
| +static std::string SetVertexTexCoordPrecision(
 | 
| +    const std::string& shader_string) {
 | 
|    // We unconditionally use highp in the vertex shader since
 | 
|    // we are unlikely to be vertex shader bound when drawing large quads.
 | 
|    // Also, some vertex shaders mutate the texture coordinate in such a
 | 
|    // way that the effective precision might be lower than expected.
 | 
| -  return "#define TexCoordPrecision highp\n" + std::string(shader_string);
 | 
| +  return "#define TexCoordPrecision highp\n" + shader_string;
 | 
|  }
 | 
|  
 | 
|  TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
 | 
| @@ -174,20 +187,25 @@ void VertexShaderPosTex::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderPosTex::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute vec4 a_position;
 | 
| -      attribute TexCoordPrecision vec2 a_texCoord;
 | 
| -      uniform mat4 matrix;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      void main() {
 | 
| -        gl_Position = matrix * a_position;
 | 
| -        v_texCoord = a_texCoord;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTex::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute vec4 a_position;
 | 
| +    attribute TexCoordPrecision vec2 a_texCoord;
 | 
| +    uniform mat4 matrix;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTex::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      gl_Position = matrix * a_position;
 | 
| +      v_texCoord = a_texCoord;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderPosTexYUVStretchOffset::VertexShaderPosTexYUVStretchOffset()
 | 
| @@ -214,23 +232,28 @@ void VertexShaderPosTexYUVStretchOffset::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderPosTexYUVStretchOffset::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      attribute vec4 a_position;
 | 
| -      attribute TexCoordPrecision vec2 a_texCoord;
 | 
| -      uniform mat4 matrix;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform TexCoordPrecision vec2 texScale;
 | 
| -      uniform TexCoordPrecision vec2 texOffset;
 | 
| -      void main() {
 | 
| -        gl_Position = matrix * a_position;
 | 
| -        v_texCoord = a_texCoord * texScale + texOffset;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTexYUVStretchOffset::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    attribute vec4 a_position;
 | 
| +    attribute TexCoordPrecision vec2 a_texCoord;
 | 
| +    uniform mat4 matrix;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform TexCoordPrecision vec2 texScale;
 | 
| +    uniform TexCoordPrecision vec2 texOffset;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTexYUVStretchOffset::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      gl_Position = matrix * a_position;
 | 
| +      v_texCoord = a_texCoord * texScale + texOffset;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderPos::VertexShaderPos() : matrix_location_(-1) {
 | 
| @@ -254,15 +277,20 @@ void VertexShaderPos::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderPos::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute vec4 a_position;
 | 
| -      uniform mat4 matrix;
 | 
| -      void main() { gl_Position = matrix * a_position; }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPos::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute vec4 a_position;
 | 
| +    uniform mat4 matrix;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPos::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() { gl_Position = matrix * a_position; }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderPosTexTransform::VertexShaderPosTexTransform()
 | 
| @@ -291,42 +319,52 @@ void VertexShaderPosTexTransform::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderPosTexTransform::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute vec4 a_position;
 | 
| -      attribute TexCoordPrecision vec2 a_texCoord;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix[8];
 | 
| -      uniform TexCoordPrecision vec4 texTransform[8];
 | 
| -      uniform float opacity[32];
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying float v_alpha;
 | 
| -      void main() {
 | 
| -        int quad_index = int(a_index * 0.25);  // NOLINT
 | 
| -        gl_Position = matrix[quad_index] * a_position;
 | 
| -        TexCoordPrecision vec4 texTrans = texTransform[quad_index];
 | 
| -        v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
 | 
| -        v_alpha = opacity[int(a_index)];  // NOLINT
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTexTransform::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute vec4 a_position;
 | 
| +    attribute TexCoordPrecision vec2 a_texCoord;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix[8];
 | 
| +    uniform TexCoordPrecision vec4 texTransform[8];
 | 
| +    uniform float opacity[32];
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying float v_alpha;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTexTransform::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      int quad_index = int(a_index * 0.25);  // NOLINT
 | 
| +      gl_Position = matrix[quad_index] * a_position;
 | 
| +      TexCoordPrecision vec4 texTrans = texTransform[quad_index];
 | 
| +      v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
 | 
| +      v_alpha = opacity[int(a_index)];  // NOLINT
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderPosTexIdentity::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute vec4 a_position;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      void main() {
 | 
| -        gl_Position = a_position;
 | 
| -        v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTexIdentity::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute vec4 a_position;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderPosTexIdentity::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      gl_Position = a_position;
 | 
| +      v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderQuad::VertexShaderQuad()
 | 
| @@ -352,42 +390,48 @@ void VertexShaderQuad::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderQuad::GetShaderString() const {
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderQuad::GetShaderHead() {
 | 
|  #if defined(OS_ANDROID)
 | 
|    // TODO(epenner): Find the cause of this 'quad' uniform
 | 
|    // being missing if we don't add dummy variables.
 | 
|    // http://crbug.com/240602
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute TexCoordPrecision vec4 a_position;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform TexCoordPrecision vec2 quad[4];
 | 
| -      uniform TexCoordPrecision vec2 dummy_uniform;
 | 
| -      varying TexCoordPrecision vec2 dummy_varying;
 | 
| -      void main() {
 | 
| -        vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| -        gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| -        dummy_varying = dummy_uniform;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -// clang-format on
 | 
| +  return SHADER0([]() {
 | 
| +    attribute TexCoordPrecision vec4 a_position;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform TexCoordPrecision vec2 quad[4];
 | 
| +    uniform TexCoordPrecision vec2 dummy_uniform;
 | 
| +    varying TexCoordPrecision vec2 dummy_varying;
 | 
| +  });
 | 
|  #else
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute TexCoordPrecision vec4 a_position;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform TexCoordPrecision vec2 quad[4];
 | 
| -      void main() {
 | 
| -        vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| -        gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -// clang-format on
 | 
| +  return SHADER0([]() {
 | 
| +    attribute TexCoordPrecision vec4 a_position;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform TexCoordPrecision vec2 quad[4];
 | 
| +  });
 | 
| +#endif
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderQuad::GetShaderBody() {
 | 
| +#if defined(OS_ANDROID)
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| +      gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| +      dummy_varying = dummy_uniform;
 | 
| +    }
 | 
| +  });
 | 
| +#else
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| +      gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| +    }
 | 
| +  });
 | 
|  #endif
 | 
|  }
 | 
|  
 | 
| @@ -419,36 +463,36 @@ void VertexShaderQuadAA::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderQuadAA::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute TexCoordPrecision vec4 a_position;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform vec4 viewport;
 | 
| -      uniform TexCoordPrecision vec2 quad[4];
 | 
| -      uniform TexCoordPrecision vec3 edge[8];
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| -        gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| -        vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
 | 
| -        vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
 | 
| -        edge_dist[0] = vec4(dot(edge[0], screen_pos),
 | 
| -                            dot(edge[1], screen_pos),
 | 
| -                            dot(edge[2], screen_pos),
 | 
| -                            dot(edge[3], screen_pos)) *
 | 
| -                       gl_Position.w;
 | 
| -        edge_dist[1] = vec4(dot(edge[4], screen_pos),
 | 
| -                            dot(edge[5], screen_pos),
 | 
| -                            dot(edge[6], screen_pos),
 | 
| -                            dot(edge[7], screen_pos)) *
 | 
| -                       gl_Position.w;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderQuadAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute TexCoordPrecision vec4 a_position;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform vec4 viewport;
 | 
| +    uniform TexCoordPrecision vec2 quad[4];
 | 
| +    uniform TexCoordPrecision vec3 edge[8];
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderQuadAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| +      gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| +      vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
 | 
| +      vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
 | 
| +      edge_dist[0] = vec4(dot(edge[0], screen_pos), dot(edge[1], screen_pos),
 | 
| +                          dot(edge[2], screen_pos), dot(edge[3], screen_pos)) *
 | 
| +                     gl_Position.w;
 | 
| +      edge_dist[1] = vec4(dot(edge[4], screen_pos), dot(edge[5], screen_pos),
 | 
| +                          dot(edge[6], screen_pos), dot(edge[7], screen_pos)) *
 | 
| +                     gl_Position.w;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderQuadTexTransformAA::VertexShaderQuadTexTransformAA()
 | 
| @@ -481,39 +525,39 @@ void VertexShaderQuadTexTransformAA::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderQuadTexTransformAA::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute TexCoordPrecision vec4 a_position;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform vec4 viewport;
 | 
| -      uniform TexCoordPrecision vec2 quad[4];
 | 
| -      uniform TexCoordPrecision vec3 edge[8];
 | 
| -      uniform TexCoordPrecision vec4 texTrans;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| -        gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| -        vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
 | 
| -        vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
 | 
| -        edge_dist[0] = vec4(dot(edge[0], screen_pos),
 | 
| -                            dot(edge[1], screen_pos),
 | 
| -                            dot(edge[2], screen_pos),
 | 
| -                            dot(edge[3], screen_pos)) *
 | 
| -                       gl_Position.w;
 | 
| -        edge_dist[1] = vec4(dot(edge[4], screen_pos),
 | 
| -                            dot(edge[5], screen_pos),
 | 
| -                            dot(edge[6], screen_pos),
 | 
| -                            dot(edge[7], screen_pos)) *
 | 
| -                       gl_Position.w;
 | 
| -        v_texCoord = (pos.xy + vec2(0.5)) * texTrans.zw + texTrans.xy;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderQuadTexTransformAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute TexCoordPrecision vec4 a_position;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform vec4 viewport;
 | 
| +    uniform TexCoordPrecision vec2 quad[4];
 | 
| +    uniform TexCoordPrecision vec3 edge[8];
 | 
| +    uniform TexCoordPrecision vec4 texTrans;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderQuadTexTransformAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| +      gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| +      vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
 | 
| +      vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
 | 
| +      edge_dist[0] = vec4(dot(edge[0], screen_pos), dot(edge[1], screen_pos),
 | 
| +                          dot(edge[2], screen_pos), dot(edge[3], screen_pos)) *
 | 
| +                     gl_Position.w;
 | 
| +      edge_dist[1] = vec4(dot(edge[4], screen_pos), dot(edge[5], screen_pos),
 | 
| +                          dot(edge[6], screen_pos), dot(edge[7], screen_pos)) *
 | 
| +                     gl_Position.w;
 | 
| +      v_texCoord = (pos.xy + vec2(0.5)) * texTrans.zw + texTrans.xy;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderTile::VertexShaderTile()
 | 
| @@ -542,24 +586,29 @@ void VertexShaderTile::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderTile::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute TexCoordPrecision vec4 a_position;
 | 
| -      attribute TexCoordPrecision vec2 a_texCoord;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform TexCoordPrecision vec2 quad[4];
 | 
| -      uniform TexCoordPrecision vec4 vertexTexTransform;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      void main() {
 | 
| -        vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| -        gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| -        v_texCoord = a_texCoord * vertexTexTransform.zw + vertexTexTransform.xy;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderTile::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute TexCoordPrecision vec4 a_position;
 | 
| +    attribute TexCoordPrecision vec2 a_texCoord;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform TexCoordPrecision vec2 quad[4];
 | 
| +    uniform TexCoordPrecision vec4 vertexTexTransform;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderTile::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| +      gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| +      v_texCoord = a_texCoord * vertexTexTransform.zw + vertexTexTransform.xy;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderTileAA::VertexShaderTileAA()
 | 
| @@ -592,39 +641,39 @@ void VertexShaderTileAA::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderTileAA::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute TexCoordPrecision vec4 a_position;
 | 
| -      attribute float a_index;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform vec4 viewport;
 | 
| -      uniform TexCoordPrecision vec2 quad[4];
 | 
| -      uniform TexCoordPrecision vec3 edge[8];
 | 
| -      uniform TexCoordPrecision vec4 vertexTexTransform;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| -        gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| -        vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
 | 
| -        vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
 | 
| -        edge_dist[0] = vec4(dot(edge[0], screen_pos),
 | 
| -                            dot(edge[1], screen_pos),
 | 
| -                            dot(edge[2], screen_pos),
 | 
| -                            dot(edge[3], screen_pos)) *
 | 
| -                       gl_Position.w;
 | 
| -        edge_dist[1] = vec4(dot(edge[4], screen_pos),
 | 
| -                            dot(edge[5], screen_pos),
 | 
| -                            dot(edge[6], screen_pos),
 | 
| -                            dot(edge[7], screen_pos)) *
 | 
| -                       gl_Position.w;
 | 
| -        v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderTileAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute TexCoordPrecision vec4 a_position;
 | 
| +    attribute float a_index;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform vec4 viewport;
 | 
| +    uniform TexCoordPrecision vec2 quad[4];
 | 
| +    uniform TexCoordPrecision vec3 edge[8];
 | 
| +    uniform TexCoordPrecision vec4 vertexTexTransform;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderTileAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 pos = quad[int(a_index)];  // NOLINT
 | 
| +      gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
 | 
| +      vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
 | 
| +      vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
 | 
| +      edge_dist[0] = vec4(dot(edge[0], screen_pos), dot(edge[1], screen_pos),
 | 
| +                          dot(edge[2], screen_pos), dot(edge[3], screen_pos)) *
 | 
| +                     gl_Position.w;
 | 
| +      edge_dist[1] = vec4(dot(edge[4], screen_pos), dot(edge[5], screen_pos),
 | 
| +                          dot(edge[6], screen_pos), dot(edge[7], screen_pos)) *
 | 
| +                     gl_Position.w;
 | 
| +      v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  VertexShaderVideoTransform::VertexShaderVideoTransform()
 | 
| @@ -650,22 +699,27 @@ void VertexShaderVideoTransform::Init(GLES2Interface* context,
 | 
|  }
 | 
|  
 | 
|  std::string VertexShaderVideoTransform::GetShaderString() const {
 | 
| -  // clang-format off
 | 
| -  return VERTEX_SHADER(
 | 
| -      // clang-format on
 | 
| -      attribute vec4 a_position;
 | 
| -      attribute TexCoordPrecision vec2 a_texCoord;
 | 
| -      uniform mat4 matrix;
 | 
| -      uniform TexCoordPrecision mat4 texMatrix;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      void main() {
 | 
| -        gl_Position = matrix * a_position;
 | 
| -        v_texCoord =
 | 
| -            vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0));
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderVideoTransform::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    attribute vec4 a_position;
 | 
| +    attribute TexCoordPrecision vec2 a_texCoord;
 | 
| +    uniform mat4 matrix;
 | 
| +    uniform TexCoordPrecision mat4 texMatrix;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string VertexShaderVideoTransform::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      gl_Position = matrix * a_position;
 | 
| +      v_texCoord =
 | 
| +          vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0));
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  #define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect"
 | 
| @@ -692,183 +746,166 @@ std::string FragmentTexBlendMode::SetBlendModeFunctions(
 | 
|      return "#define ApplyBlendMode(X) (X)\n" + shader_string;
 | 
|    }
 | 
|  
 | 
| -  // clang-format off
 | 
| -  static const std::string kFunctionApplyBlendMode = SHADER0(
 | 
| -      // clang-format on
 | 
| -      uniform sampler2D s_backdropTexture;
 | 
| -      uniform TexCoordPrecision vec4 backdropRect;
 | 
| -
 | 
| -      vec4 GetBackdropColor() {
 | 
| -        TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
 | 
| -        bgTexCoord.x /= backdropRect.z;
 | 
| -        bgTexCoord.y /= backdropRect.w;
 | 
| -        return texture2D(s_backdropTexture, bgTexCoord);
 | 
| -      }
 | 
| +  static const std::string kFunctionApplyBlendMode = SHADER0([]() {
 | 
| +    uniform sampler2D s_backdropTexture;
 | 
| +    uniform TexCoordPrecision vec4 backdropRect;
 | 
|  
 | 
| -      vec4 ApplyBlendMode(vec4 src) {
 | 
| -        vec4 dst = GetBackdropColor();
 | 
| -        return Blend(src, dst);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +    vec4 GetBackdropColor() {
 | 
| +      TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
 | 
| +      bgTexCoord.x /= backdropRect.z;
 | 
| +      bgTexCoord.y /= backdropRect.w;
 | 
| +      return texture2D(s_backdropTexture, bgTexCoord);
 | 
| +    }
 | 
| +
 | 
| +    vec4 ApplyBlendMode(vec4 src) {
 | 
| +      vec4 dst = GetBackdropColor();
 | 
| +      return Blend(src, dst);
 | 
| +    }
 | 
| +  });
 | 
|  
 | 
|    return "precision mediump float;" + GetHelperFunctions() +
 | 
|           GetBlendFunction() + kFunctionApplyBlendMode + shader_string;
 | 
|  }
 | 
|  
 | 
|  std::string FragmentTexBlendMode::GetHelperFunctions() const {
 | 
| -  // clang-format off
 | 
| -  static const std::string kFunctionHardLight = SHADER0(
 | 
| -      // clang-format on
 | 
| -      vec3 hardLight(vec4 src, vec4 dst) {
 | 
| -        vec3 result;
 | 
| -        result.r =
 | 
| -            (2.0 * src.r <= src.a)
 | 
| -                ? (2.0 * src.r * dst.r)
 | 
| -                : (src.a * dst.a - 2.0 * (dst.a - dst.r) * (src.a - src.r));
 | 
| -        result.g =
 | 
| -            (2.0 * src.g <= src.a)
 | 
| -                ? (2.0 * src.g * dst.g)
 | 
| -                : (src.a * dst.a - 2.0 * (dst.a - dst.g) * (src.a - src.g));
 | 
| -        result.b =
 | 
| -            (2.0 * src.b <= src.a)
 | 
| -                ? (2.0 * src.b * dst.b)
 | 
| -                : (src.a * dst.a - 2.0 * (dst.a - dst.b) * (src.a - src.b));
 | 
| -        result.rgb += src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
 | 
| -        return result;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -
 | 
| -  static const std::string kFunctionColorDodgeComponent = SHADER0(
 | 
| -      // clang-format on
 | 
| -      float getColorDodgeComponent(
 | 
| -          float srcc, float srca, float dstc, float dsta) {
 | 
| -        if (0.0 == dstc)
 | 
| -          return srcc * (1.0 - dsta);
 | 
| -        float d = srca - srcc;
 | 
| -        if (0.0 == d)
 | 
| -          return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| -        d = min(dsta, dstc * srca / d);
 | 
| -        return d * srca + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -
 | 
| -  static const std::string kFunctionColorBurnComponent = SHADER0(
 | 
| -      // clang-format on
 | 
| -      float getColorBurnComponent(
 | 
| -          float srcc, float srca, float dstc, float dsta) {
 | 
| -        if (dsta == dstc)
 | 
| -          return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| -        if (0.0 == srcc)
 | 
| -          return dstc * (1.0 - srca);
 | 
| -        float d = max(0.0, dsta - (dsta - dstc) * srca / srcc);
 | 
| -        return srca * d + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -
 | 
| -  static const std::string kFunctionSoftLightComponentPosDstAlpha = SHADER0(
 | 
| -      // clang-format on
 | 
| -      float getSoftLightComponent(
 | 
| -          float srcc, float srca, float dstc, float dsta) {
 | 
| -        if (2.0 * srcc <= srca) {
 | 
| -          return (dstc * dstc * (srca - 2.0 * srcc)) / dsta +
 | 
| -                 (1.0 - dsta) * srcc + dstc * (-srca + 2.0 * srcc + 1.0);
 | 
| -        } else if (4.0 * dstc <= dsta) {
 | 
| -          float DSqd = dstc * dstc;
 | 
| -          float DCub = DSqd * dstc;
 | 
| -          float DaSqd = dsta * dsta;
 | 
| -          float DaCub = DaSqd * dsta;
 | 
| -          return (-DaCub * srcc +
 | 
| -                  DaSqd * (srcc - dstc * (3.0 * srca - 6.0 * srcc - 1.0)) +
 | 
| -                  12.0 * dsta * DSqd * (srca - 2.0 * srcc) -
 | 
| -                  16.0 * DCub * (srca - 2.0 * srcc)) /
 | 
| -                 DaSqd;
 | 
| -        } else {
 | 
| -          return -sqrt(dsta * dstc) * (srca - 2.0 * srcc) - dsta * srcc +
 | 
| -                 dstc * (srca - 2.0 * srcc + 1.0) + srcc;
 | 
| -        }
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -
 | 
| -  static const std::string kFunctionLum = SHADER0(
 | 
| -      // clang-format on
 | 
| -      float luminance(vec3 color) { return dot(vec3(0.3, 0.59, 0.11), color); }
 | 
| -
 | 
| -      vec3 set_luminance(vec3 hueSat, float alpha, vec3 lumColor) {
 | 
| -        float diff = luminance(lumColor - hueSat);
 | 
| -        vec3 outColor = hueSat + diff;
 | 
| -        float outLum = luminance(outColor);
 | 
| -        float minComp = min(min(outColor.r, outColor.g), outColor.b);
 | 
| -        float maxComp = max(max(outColor.r, outColor.g), outColor.b);
 | 
| -        if (minComp < 0.0 && outLum != minComp) {
 | 
| -          outColor = outLum +
 | 
| -                     ((outColor - vec3(outLum, outLum, outLum)) * outLum) /
 | 
| -                         (outLum - minComp);
 | 
| -        }
 | 
| -        if (maxComp > alpha && maxComp != outLum) {
 | 
| -          outColor =
 | 
| -              outLum +
 | 
| -              ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /
 | 
| -                  (maxComp - outLum);
 | 
| +  static const std::string kFunctionHardLight = SHADER0([]() {
 | 
| +    vec3 hardLight(vec4 src, vec4 dst) {
 | 
| +      vec3 result;
 | 
| +      result.r =
 | 
| +          (2.0 * src.r <= src.a)
 | 
| +              ? (2.0 * src.r * dst.r)
 | 
| +              : (src.a * dst.a - 2.0 * (dst.a - dst.r) * (src.a - src.r));
 | 
| +      result.g =
 | 
| +          (2.0 * src.g <= src.a)
 | 
| +              ? (2.0 * src.g * dst.g)
 | 
| +              : (src.a * dst.a - 2.0 * (dst.a - dst.g) * (src.a - src.g));
 | 
| +      result.b =
 | 
| +          (2.0 * src.b <= src.a)
 | 
| +              ? (2.0 * src.b * dst.b)
 | 
| +              : (src.a * dst.a - 2.0 * (dst.a - dst.b) * (src.a - src.b));
 | 
| +      result.rgb += src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
 | 
| +      return result;
 | 
| +    }
 | 
| +  });
 | 
| +
 | 
| +  static const std::string kFunctionColorDodgeComponent = SHADER0([]() {
 | 
| +    float getColorDodgeComponent(float srcc, float srca, float dstc,
 | 
| +                                 float dsta) {
 | 
| +      if (0.0 == dstc)
 | 
| +        return srcc * (1.0 - dsta);
 | 
| +      float d = srca - srcc;
 | 
| +      if (0.0 == d)
 | 
| +        return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| +      d = min(dsta, dstc * srca / d);
 | 
| +      return d * srca + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| +    }
 | 
| +  });
 | 
| +
 | 
| +  static const std::string kFunctionColorBurnComponent = SHADER0([]() {
 | 
| +    float getColorBurnComponent(float srcc, float srca, float dstc,
 | 
| +                                float dsta) {
 | 
| +      if (dsta == dstc)
 | 
| +        return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| +      if (0.0 == srcc)
 | 
| +        return dstc * (1.0 - srca);
 | 
| +      float d = max(0.0, dsta - (dsta - dstc) * srca / srcc);
 | 
| +      return srca * d + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
 | 
| +    }
 | 
| +  });
 | 
| +
 | 
| +  static const std::string kFunctionSoftLightComponentPosDstAlpha =
 | 
| +      SHADER0([]() {
 | 
| +        float getSoftLightComponent(float srcc, float srca, float dstc,
 | 
| +                                    float dsta) {
 | 
| +          if (2.0 * srcc <= srca) {
 | 
| +            return (dstc * dstc * (srca - 2.0 * srcc)) / dsta +
 | 
| +                   (1.0 - dsta) * srcc + dstc * (-srca + 2.0 * srcc + 1.0);
 | 
| +          } else if (4.0 * dstc <= dsta) {
 | 
| +            float DSqd = dstc * dstc;
 | 
| +            float DCub = DSqd * dstc;
 | 
| +            float DaSqd = dsta * dsta;
 | 
| +            float DaCub = DaSqd * dsta;
 | 
| +            return (-DaCub * srcc +
 | 
| +                    DaSqd * (srcc - dstc * (3.0 * srca - 6.0 * srcc - 1.0)) +
 | 
| +                    12.0 * dsta * DSqd * (srca - 2.0 * srcc) -
 | 
| +                    16.0 * DCub * (srca - 2.0 * srcc)) /
 | 
| +                   DaSqd;
 | 
| +          } else {
 | 
| +            return -sqrt(dsta * dstc) * (srca - 2.0 * srcc) - dsta * srcc +
 | 
| +                   dstc * (srca - 2.0 * srcc + 1.0) + srcc;
 | 
| +          }
 | 
|          }
 | 
| -        return outColor;
 | 
| +      });
 | 
| +
 | 
| +  static const std::string kFunctionLum = SHADER0([]() {
 | 
| +    float luminance(vec3 color) { return dot(vec3(0.3, 0.59, 0.11), color); }
 | 
| +
 | 
| +    vec3 set_luminance(vec3 hueSat, float alpha, vec3 lumColor) {
 | 
| +      float diff = luminance(lumColor - hueSat);
 | 
| +      vec3 outColor = hueSat + diff;
 | 
| +      float outLum = luminance(outColor);
 | 
| +      float minComp = min(min(outColor.r, outColor.g), outColor.b);
 | 
| +      float maxComp = max(max(outColor.r, outColor.g), outColor.b);
 | 
| +      if (minComp < 0.0 && outLum != minComp) {
 | 
| +        outColor = outLum +
 | 
| +                   ((outColor - vec3(outLum, outLum, outLum)) * outLum) /
 | 
| +                       (outLum - minComp);
 | 
|        }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -
 | 
| -  static const std::string kFunctionSat = SHADER0(
 | 
| -      // clang-format on
 | 
| -      float saturation(vec3 color) {
 | 
| -        return max(max(color.r, color.g), color.b) -
 | 
| -               min(min(color.r, color.g), color.b);
 | 
| +      if (maxComp > alpha && maxComp != outLum) {
 | 
| +        outColor =
 | 
| +            outLum +
 | 
| +            ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /
 | 
| +                (maxComp - outLum);
 | 
|        }
 | 
| -
 | 
| -      vec3 set_saturation_helper(
 | 
| -          float minComp, float midComp, float maxComp, float sat) {
 | 
| -        if (minComp < maxComp) {
 | 
| -          vec3 result;
 | 
| -          result.r = 0.0;
 | 
| -          result.g = sat * (midComp - minComp) / (maxComp - minComp);
 | 
| -          result.b = sat;
 | 
| -          return result;
 | 
| -        } else {
 | 
| -          return vec3(0, 0, 0);
 | 
| -        }
 | 
| +      return outColor;
 | 
| +    }
 | 
| +  });
 | 
| +
 | 
| +  static const std::string kFunctionSat = SHADER0([]() {
 | 
| +    float saturation(vec3 color) {
 | 
| +      return max(max(color.r, color.g), color.b) -
 | 
| +             min(min(color.r, color.g), color.b);
 | 
| +    }
 | 
| +
 | 
| +    vec3 set_saturation_helper(float minComp, float midComp, float maxComp,
 | 
| +                               float sat) {
 | 
| +      if (minComp < maxComp) {
 | 
| +        vec3 result;
 | 
| +        result.r = 0.0;
 | 
| +        result.g = sat * (midComp - minComp) / (maxComp - minComp);
 | 
| +        result.b = sat;
 | 
| +        return result;
 | 
| +      } else {
 | 
| +        return vec3(0, 0, 0);
 | 
|        }
 | 
| -
 | 
| -      vec3 set_saturation(vec3 hueLumColor, vec3 satColor) {
 | 
| -        float sat = saturation(satColor);
 | 
| -        if (hueLumColor.r <= hueLumColor.g) {
 | 
| -          if (hueLumColor.g <= hueLumColor.b) {
 | 
| -            hueLumColor.rgb = set_saturation_helper(
 | 
| -                hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);
 | 
| -          } else if (hueLumColor.r <= hueLumColor.b) {
 | 
| -            hueLumColor.rbg = set_saturation_helper(
 | 
| -                hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);
 | 
| -          } else {
 | 
| -            hueLumColor.brg = set_saturation_helper(
 | 
| -                hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);
 | 
| -          }
 | 
| +    }
 | 
| +
 | 
| +    vec3 set_saturation(vec3 hueLumColor, vec3 satColor) {
 | 
| +      float sat = saturation(satColor);
 | 
| +      if (hueLumColor.r <= hueLumColor.g) {
 | 
| +        if (hueLumColor.g <= hueLumColor.b) {
 | 
| +          hueLumColor.rgb = set_saturation_helper(hueLumColor.r, hueLumColor.g,
 | 
| +                                                  hueLumColor.b, sat);
 | 
|          } else if (hueLumColor.r <= hueLumColor.b) {
 | 
| -          hueLumColor.grb = set_saturation_helper(
 | 
| -              hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);
 | 
| -        } else if (hueLumColor.g <= hueLumColor.b) {
 | 
| -          hueLumColor.gbr = set_saturation_helper(
 | 
| -              hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);
 | 
| +          hueLumColor.rbg = set_saturation_helper(hueLumColor.r, hueLumColor.b,
 | 
| +                                                  hueLumColor.g, sat);
 | 
|          } else {
 | 
| -          hueLumColor.bgr = set_saturation_helper(
 | 
| -              hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);
 | 
| +          hueLumColor.brg = set_saturation_helper(hueLumColor.b, hueLumColor.r,
 | 
| +                                                  hueLumColor.g, sat);
 | 
|          }
 | 
| -        return hueLumColor;
 | 
| +      } else if (hueLumColor.r <= hueLumColor.b) {
 | 
| +        hueLumColor.grb = set_saturation_helper(hueLumColor.g, hueLumColor.r,
 | 
| +                                                hueLumColor.b, sat);
 | 
| +      } else if (hueLumColor.g <= hueLumColor.b) {
 | 
| +        hueLumColor.gbr = set_saturation_helper(hueLumColor.g, hueLumColor.b,
 | 
| +                                                hueLumColor.r, sat);
 | 
| +      } else {
 | 
| +        hueLumColor.bgr = set_saturation_helper(hueLumColor.b, hueLumColor.g,
 | 
| +                                                hueLumColor.r, sat);
 | 
|        }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +      return hueLumColor;
 | 
| +    }
 | 
| +  });
 | 
|  
 | 
|    switch (blend_mode_) {
 | 
|      case BlendModeOverlay:
 | 
| @@ -1048,85 +1085,105 @@ void FragmentTexOpaqueBinding::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      uniform mat4 colorMatrix;
 | 
| -      uniform vec4 colorOffset;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| -        texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| -        texColor = colorMatrix * texColor + colorOffset;
 | 
| -        texColor.rgb *= texColor.a;
 | 
| -        texColor = clamp(texColor, 0.0, 1.0);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +    uniform mat4 colorMatrix;
 | 
| +    uniform vec4 colorOffset;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| +      texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| +      texColor = colorMatrix * texColor + colorOffset;
 | 
| +      texColor.rgb *= texColor.a;
 | 
| +      texColor = clamp(texColor, 0.0, 1.0);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying float v_alpha;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        gl_FragColor = texColor * v_alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexVaryingAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying float v_alpha;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexVaryingAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      gl_FragColor = texColor * v_alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying float v_alpha;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        texColor.rgb *= texColor.a;
 | 
| -        gl_FragColor = texColor * v_alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying float v_alpha;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      texColor.rgb *= texColor.a;
 | 
| +      gl_FragColor = texColor * v_alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
 | 
| @@ -1158,114 +1215,144 @@ void FragmentTexBackgroundBinding::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying float v_alpha;
 | 
| -      uniform vec4 background_color;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        texColor += background_color * (1.0 - texColor.a);
 | 
| -        gl_FragColor = texColor * v_alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying float v_alpha;
 | 
| +    uniform vec4 background_color;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      texColor += background_color * (1.0 - texColor.a);
 | 
| +      gl_FragColor = texColor * v_alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying float v_alpha;
 | 
| -      uniform vec4 background_color;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        texColor.rgb *= texColor.a;
 | 
| -        texColor += background_color * (1.0 - texColor.a);
 | 
| -        gl_FragColor = texColor * v_alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying float v_alpha;
 | 
| +    uniform vec4 background_color;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      texColor.rgb *= texColor.a;
 | 
| +      texColor += background_color * (1.0 - texColor.a);
 | 
| +      gl_FragColor = texColor * v_alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexOpaque::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        gl_FragColor = vec4(texColor.rgb, 1.0);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexOpaque::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexOpaque::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      gl_FragColor = vec4(texColor.rgb, 1.0);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATex::GetShaderString(TexCoordPrecision precision,
 | 
|                                                     SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() { gl_FragColor = TextureLookup(s_texture, v_texCoord); }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATex::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATex::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() { gl_FragColor = TextureLookup(s_texture, v_texCoord); }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        gl_FragColor =
 | 
| -            vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      gl_FragColor =
 | 
| +          vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType s_texture;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA()
 | 
| @@ -1294,25 +1381,29 @@ void FragmentShaderRGBATexAlphaAA::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexAlphaAA::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
 | 
| @@ -1343,58 +1434,66 @@ void FragmentTexClampAlphaAABinding::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      uniform TexCoordPrecision vec4 fragmentTexTransform;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        TexCoordPrecision vec2 texCoord =
 | 
| -            clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
 | 
| -            fragmentTexTransform.xy;
 | 
| -        vec4 texColor = TextureLookup(s_texture, texCoord);
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor = texColor * alpha * aa;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampAlphaAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +    uniform TexCoordPrecision vec4 fragmentTexTransform;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampAlphaAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      TexCoordPrecision vec2 texCoord =
 | 
| +          clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
 | 
| +          fragmentTexTransform.xy;
 | 
| +      vec4 texColor = TextureLookup(s_texture, texCoord);
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor = texColor * alpha * aa;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      uniform TexCoordPrecision vec4 fragmentTexTransform;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        TexCoordPrecision vec2 texCoord =
 | 
| -            clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
 | 
| -            fragmentTexTransform.xy;
 | 
| -        vec4 texColor = TextureLookup(s_texture, texCoord);
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor =
 | 
| -            vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * aa;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +    uniform TexCoordPrecision vec4 fragmentTexTransform;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      TexCoordPrecision vec2 texCoord =
 | 
| +          clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
 | 
| +          fragmentTexTransform.xy;
 | 
| +      vec4 texColor = TextureLookup(s_texture, texCoord);
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor =
 | 
| +          vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * aa;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask()
 | 
| @@ -1434,27 +1533,32 @@ void FragmentShaderRGBATexAlphaMask::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexAlphaMask::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform sampler2D s_texture;
 | 
| -      uniform SamplerType s_mask;
 | 
| -      uniform TexCoordPrecision vec2 maskTexCoordScale;
 | 
| -      uniform TexCoordPrecision vec2 maskTexCoordOffset;
 | 
| -      uniform float alpha;
 | 
| -      void main() {
 | 
| -        vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| -        TexCoordPrecision vec2 maskTexCoord =
 | 
| -            vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| -                 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| -        vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMask::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform sampler2D s_texture;
 | 
| +    uniform SamplerType s_mask;
 | 
| +    uniform TexCoordPrecision vec2 maskTexCoordScale;
 | 
| +    uniform TexCoordPrecision vec2 maskTexCoordOffset;
 | 
| +    uniform float alpha;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMask::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| +      TexCoordPrecision vec2 maskTexCoord =
 | 
| +          vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| +               maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| +      vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA()
 | 
| @@ -1495,32 +1599,36 @@ void FragmentShaderRGBATexAlphaMaskAA::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform sampler2D s_texture;
 | 
| -      uniform SamplerType s_mask;
 | 
| -      uniform TexCoordPrecision vec2 maskTexCoordScale;
 | 
| -      uniform TexCoordPrecision vec2 maskTexCoordOffset;
 | 
| -      uniform float alpha;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| -        TexCoordPrecision vec2 maskTexCoord =
 | 
| -            vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| -                 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| -        vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform sampler2D s_texture;
 | 
| +    uniform SamplerType s_mask;
 | 
| +    uniform TexCoordPrecision vec2 maskTexCoordScale;
 | 
| +    uniform TexCoordPrecision vec2 maskTexCoordOffset;
 | 
| +    uniform float alpha;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| +      TexCoordPrecision vec2 maskTexCoord =
 | 
| +          vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| +               maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| +      vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderRGBATexAlphaMaskColorMatrixAA::
 | 
| @@ -1568,39 +1676,43 @@ void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init(
 | 
|  std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform sampler2D s_texture;
 | 
| -      uniform SamplerType s_mask;
 | 
| -      uniform vec2 maskTexCoordScale;
 | 
| -      uniform vec2 maskTexCoordOffset;
 | 
| -      uniform mat4 colorMatrix;
 | 
| -      uniform vec4 colorOffset;
 | 
| -      uniform float alpha;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| -        float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| -        texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| -        texColor = colorMatrix * texColor + colorOffset;
 | 
| -        texColor.rgb *= texColor.a;
 | 
| -        texColor = clamp(texColor, 0.0, 1.0);
 | 
| -        TexCoordPrecision vec2 maskTexCoord =
 | 
| -            vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| -                 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| -        vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform sampler2D s_texture;
 | 
| +    uniform SamplerType s_mask;
 | 
| +    uniform vec2 maskTexCoordScale;
 | 
| +    uniform vec2 maskTexCoordOffset;
 | 
| +    uniform mat4 colorMatrix;
 | 
| +    uniform vec4 colorOffset;
 | 
| +    uniform float alpha;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| +      float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| +      texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| +      texColor = colorMatrix * texColor + colorOffset;
 | 
| +      texColor.rgb *= texColor.a;
 | 
| +      texColor = clamp(texColor, 0.0, 1.0);
 | 
| +      TexCoordPrecision vec2 maskTexCoord =
 | 
| +          vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| +               maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| +      vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderRGBATexAlphaColorMatrixAA::
 | 
| @@ -1635,32 +1747,36 @@ void FragmentShaderRGBATexAlphaColorMatrixAA::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform SamplerType s_texture;
 | 
| -      uniform float alpha;
 | 
| -      uniform mat4 colorMatrix;
 | 
| -      uniform vec4 colorOffset;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -        float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| -        texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| -        texColor = colorMatrix * texColor + colorOffset;
 | 
| -        texColor.rgb *= texColor.a;
 | 
| -        texColor = clamp(texColor, 0.0, 1.0);
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform SamplerType s_texture;
 | 
| +    uniform float alpha;
 | 
| +    uniform mat4 colorMatrix;
 | 
| +    uniform vec4 colorOffset;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying TexCoordPrecision vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| +      texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| +      texColor = colorMatrix * texColor + colorOffset;
 | 
| +      texColor.rgb *= texColor.a;
 | 
| +      texColor = clamp(texColor, 0.0, 1.0);
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderRGBATexAlphaMaskColorMatrix::
 | 
| @@ -1705,34 +1821,39 @@ void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform sampler2D s_texture;
 | 
| -      uniform SamplerType s_mask;
 | 
| -      uniform vec2 maskTexCoordScale;
 | 
| -      uniform vec2 maskTexCoordOffset;
 | 
| -      uniform mat4 colorMatrix;
 | 
| -      uniform vec4 colorOffset;
 | 
| -      uniform float alpha;
 | 
| -      void main() {
 | 
| -        vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| -        float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| -        texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| -        texColor = colorMatrix * texColor + colorOffset;
 | 
| -        texColor.rgb *= texColor.a;
 | 
| -        texColor = clamp(texColor, 0.0, 1.0);
 | 
| -        TexCoordPrecision vec2 maskTexCoord =
 | 
| -            vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| -                 maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| -        vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| -        gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform sampler2D s_texture;
 | 
| +    uniform SamplerType s_mask;
 | 
| +    uniform vec2 maskTexCoordScale;
 | 
| +    uniform vec2 maskTexCoordOffset;
 | 
| +    uniform mat4 colorMatrix;
 | 
| +    uniform vec4 colorOffset;
 | 
| +    uniform float alpha;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 texColor = texture2D(s_texture, v_texCoord);
 | 
| +      float nonZeroAlpha = max(texColor.a, 0.00001);
 | 
| +      texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
 | 
| +      texColor = colorMatrix * texColor + colorOffset;
 | 
| +      texColor.rgb *= texColor.a;
 | 
| +      texColor = clamp(texColor, 0.0, 1.0);
 | 
| +      TexCoordPrecision vec2 maskTexCoord =
 | 
| +          vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
 | 
| +               maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
 | 
| +      vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
 | 
| +      gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderYUVVideo::FragmentShaderYUVVideo()
 | 
| @@ -1774,31 +1895,36 @@ void FragmentShaderYUVVideo::Init(GLES2Interface* context,
 | 
|  
 | 
|  std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
 | 
|                                                      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      precision mediump int;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType y_texture;
 | 
| -      uniform SamplerType u_texture;
 | 
| -      uniform SamplerType v_texture;
 | 
| -      uniform float alpha;
 | 
| -      uniform vec3 yuv_adj;
 | 
| -      uniform mat3 yuv_matrix;
 | 
| -      uniform vec4 clamp_rect;
 | 
| -      void main() {
 | 
| -        vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
 | 
| -        float y_raw = TextureLookup(y_texture, clamped).x;
 | 
| -        float u_unsigned = TextureLookup(u_texture, clamped).x;
 | 
| -        float v_unsigned = TextureLookup(v_texture, clamped).x;
 | 
| -        vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
 | 
| -        vec3 rgb = yuv_matrix * yuv;
 | 
| -        gl_FragColor = vec4(rgb, 1.0) * alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderYUVVideo::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    precision mediump int;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType y_texture;
 | 
| +    uniform SamplerType u_texture;
 | 
| +    uniform SamplerType v_texture;
 | 
| +    uniform float alpha;
 | 
| +    uniform vec3 yuv_adj;
 | 
| +    uniform mat3 yuv_matrix;
 | 
| +    uniform vec4 clamp_rect;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderYUVVideo::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
 | 
| +      float y_raw = TextureLookup(y_texture, clamped).x;
 | 
| +      float u_unsigned = TextureLookup(u_texture, clamped).x;
 | 
| +      float v_unsigned = TextureLookup(v_texture, clamped).x;
 | 
| +      vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
 | 
| +      vec3 rgb = yuv_matrix * yuv;
 | 
| +      gl_FragColor = vec4(rgb, 1.0) * alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderYUVAVideo::FragmentShaderYUVAVideo()
 | 
| @@ -1845,33 +1971,38 @@ void FragmentShaderYUVAVideo::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderYUVAVideo::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      precision mediump int;
 | 
| -      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -      uniform SamplerType y_texture;
 | 
| -      uniform SamplerType u_texture;
 | 
| -      uniform SamplerType v_texture;
 | 
| -      uniform SamplerType a_texture;
 | 
| -      uniform float alpha;
 | 
| -      uniform vec3 yuv_adj;
 | 
| -      uniform mat3 yuv_matrix;
 | 
| -      uniform vec4 clamp_rect;
 | 
| -      void main() {
 | 
| -        vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
 | 
| -        float y_raw = TextureLookup(y_texture, clamped).x;
 | 
| -        float u_unsigned = TextureLookup(u_texture, clamped).x;
 | 
| -        float v_unsigned = TextureLookup(v_texture, clamped).x;
 | 
| -        float a_raw = TextureLookup(a_texture, clamped).x;
 | 
| -        vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
 | 
| -        vec3 rgb = yuv_matrix * yuv;
 | 
| -        gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderYUVAVideo::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    precision mediump int;
 | 
| +    varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    uniform SamplerType y_texture;
 | 
| +    uniform SamplerType u_texture;
 | 
| +    uniform SamplerType v_texture;
 | 
| +    uniform SamplerType a_texture;
 | 
| +    uniform float alpha;
 | 
| +    uniform vec3 yuv_adj;
 | 
| +    uniform mat3 yuv_matrix;
 | 
| +    uniform vec4 clamp_rect;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderYUVAVideo::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
 | 
| +      float y_raw = TextureLookup(y_texture, clamped).x;
 | 
| +      float u_unsigned = TextureLookup(u_texture, clamped).x;
 | 
| +      float v_unsigned = TextureLookup(v_texture, clamped).x;
 | 
| +      float a_raw = TextureLookup(a_texture, clamped).x;
 | 
| +      vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
 | 
| +      vec3 rgb = yuv_matrix * yuv;
 | 
| +      gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderColor::FragmentShaderColor() : color_location_(-1) {
 | 
| @@ -1896,15 +2027,20 @@ void FragmentShaderColor::Init(GLES2Interface* context,
 | 
|  
 | 
|  std::string FragmentShaderColor::GetShaderString(TexCoordPrecision precision,
 | 
|                                                   SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform vec4 color;
 | 
| -      void main() { gl_FragColor = color; }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderColor::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform vec4 color;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderColor::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() { gl_FragColor = color; }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderColorAA::FragmentShaderColorAA() : color_location_(-1) {
 | 
| @@ -1929,22 +2065,26 @@ void FragmentShaderColorAA::Init(GLES2Interface* context,
 | 
|  
 | 
|  std::string FragmentShaderColorAA::GetShaderString(TexCoordPrecision precision,
 | 
|                                                     SamplerType sampler) const {
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      uniform vec4 color;
 | 
| -      varying vec4 edge_dist[2];  // 8 edge distances.
 | 
| -
 | 
| -      void main() {
 | 
| -        vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| -        vec2 d2 = min(d4.xz, d4.yw);
 | 
| -        float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| -        gl_FragColor = color * aa;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderColorAA::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    uniform vec4 color;
 | 
| +    varying vec4 edge_dist[2];  // 8 edge distances.
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderColorAA::GetShaderBody() {
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 d4 = min(edge_dist[0], edge_dist[1]);
 | 
| +      vec2 d2 = min(d4.xz, d4.yw);
 | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
 | 
| +      gl_FragColor = color * aa;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  FragmentShaderCheckerboard::FragmentShaderCheckerboard()
 | 
| @@ -1976,30 +2116,35 @@ void FragmentShaderCheckerboard::Init(GLES2Interface* context,
 | 
|  std::string FragmentShaderCheckerboard::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderCheckerboard::GetShaderHead() {
 | 
| +  return SHADER0([]() {
 | 
| +    precision mediump float;
 | 
| +    precision mediump int;
 | 
| +    varying vec2 v_texCoord;
 | 
| +    uniform float alpha;
 | 
| +    uniform float frequency;
 | 
| +    uniform vec4 texTransform;
 | 
| +    uniform vec4 color;
 | 
| +  });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderCheckerboard::GetShaderBody() {
 | 
|    // Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
 | 
|    // by Munshi, Ginsburg, Shreiner.
 | 
| -  // clang-format off
 | 
| -  return FRAGMENT_SHADER(
 | 
| -      // clang-format on
 | 
| -      precision mediump float;
 | 
| -      precision mediump int;
 | 
| -      varying vec2 v_texCoord;
 | 
| -      uniform float alpha;
 | 
| -      uniform float frequency;
 | 
| -      uniform vec4 texTransform;
 | 
| -      uniform vec4 color;
 | 
| -      void main() {
 | 
| -        vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
 | 
| -        vec4 color2 = color;
 | 
| -        vec2 texCoord =
 | 
| -            clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
 | 
| -        vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
 | 
| -        float picker = abs(coord.x - coord.y);  // NOLINT
 | 
| -        gl_FragColor = mix(color1, color2, picker) * alpha;
 | 
| -      }
 | 
| -      // clang-format off
 | 
| -  );  // NOLINT(whitespace/parens)
 | 
| -  // clang-format on
 | 
| +  return SHADER0([]() {
 | 
| +    void main() {
 | 
| +      vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
 | 
| +      vec4 color2 = color;
 | 
| +      vec2 texCoord =
 | 
| +          clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
 | 
| +      vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
 | 
| +      float picker = abs(coord.x - coord.y);  // NOLINT
 | 
| +      gl_FragColor = mix(color1, color2, picker) * alpha;
 | 
| +    }
 | 
| +  });
 | 
|  }
 | 
|  
 | 
|  }  // namespace cc
 | 
| 
 |