| Index: cc/output/shader.cc
 | 
| diff --git a/cc/output/shader.cc b/cc/output/shader.cc
 | 
| index b5d163862d14e010aa19d5bcd083278366ed34b4..c80ec27c9e5f5b826172c588b05a13afb142c371 100644
 | 
| --- a/cc/output/shader.cc
 | 
| +++ b/cc/output/shader.cc
 | 
| @@ -351,6 +351,7 @@ std::string VertexShaderPosTexTransform::GetShaderHead() {
 | 
|      uniform TexCoordPrecision vec4 texTransform[NUM_STATIC_QUADS];
 | 
|      uniform float opacity[NUM_STATIC_QUADS * 4];
 | 
|      varying TexCoordPrecision vec2 v_texCoord;
 | 
| +    varying float v_index;
 | 
|      varying float v_alpha;
 | 
|    });
 | 
|  }
 | 
| @@ -359,6 +360,7 @@ std::string VertexShaderPosTexTransform::GetShaderBody() {
 | 
|    return SHADER0([]() {
 | 
|      void main() {
 | 
|        int quad_index = int(a_index * 0.25);  // NOLINT
 | 
| +      v_index = float(quad_index);
 | 
|        gl_Position = matrix[quad_index] * a_position;
 | 
|        TexCoordPrecision vec4 texTrans = texTransform[quad_index];
 | 
|        v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
 | 
| @@ -1216,58 +1218,124 @@ void FragmentShaderRGBATexColorMatrixAlpha::FillLocations(
 | 
|    locations->backdrop_rect = backdrop_rect_location();
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
 | 
| +int FragmentTexQuadBase::background_color_location() const {
 | 
| +  return -1;
 | 
| +}
 | 
| +
 | 
| +int FragmentTexQuadBase::tex_clamp_rect_location() const {
 | 
| +  return -1;
 | 
| +}
 | 
| +
 | 
| +void FragmentTexClampBinding::Init(GLES2Interface* context,
 | 
| +                                   unsigned program,
 | 
| +                                   int* base_uniform_index) {
 | 
| +  static const char* uniforms[] = {
 | 
| +      "s_texture", "tex_clamp_rect",
 | 
| +  };
 | 
| +  int locations[arraysize(uniforms)];
 | 
| +
 | 
| +  GetProgramUniformLocations(context, program, arraysize(uniforms), uniforms,
 | 
| +                             locations, base_uniform_index);
 | 
| +
 | 
| +  sampler_location_ = locations[0];
 | 
| +  DCHECK_NE(sampler_location_, -1);
 | 
| +
 | 
| +  tex_clamp_rect_location_ = locations[1];
 | 
| +  DCHECK_NE(tex_clamp_rect_location_, -1);
 | 
| +}
 | 
| +
 | 
| +int FragmentTexClampBinding::tex_clamp_rect_location() const {
 | 
| +  return tex_clamp_rect_location_;
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampVaryingAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
|    return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATexVaryingAlpha::GetShaderHead() {
 | 
| +std::string FragmentShaderRGBATexClampVaryingAlpha::GetShaderHead() {
 | 
| +  return base::StringPrintf("#define NUM_STATIC_QUADS %d\n",
 | 
| +                            StaticGeometryBinding::NUM_QUADS) +
 | 
| +         SHADER0([]() {
 | 
| +           precision mediump float;
 | 
| +           varying TexCoordPrecision vec2 v_texCoord;
 | 
| +           varying float v_index;
 | 
| +           varying float v_alpha;
 | 
| +           uniform SamplerType s_texture;
 | 
| +           uniform vec4 tex_clamp_rect[NUM_STATIC_QUADS];
 | 
| +         });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampVaryingAlpha::GetShaderBody() {
 | 
|    return SHADER0([]() {
 | 
| -    precision mediump float;
 | 
| -    varying TexCoordPrecision vec2 v_texCoord;
 | 
| -    varying float v_alpha;
 | 
| -    uniform SamplerType s_texture;
 | 
| +    void main() {
 | 
| +      vec2 tex_clamped = max(tex_clamp_rect[int(v_index)].xy,
 | 
| +                             min(tex_clamp_rect[int(v_index)].zw, v_texCoord));
 | 
| +      vec4 texColor = TextureLookup(s_texture, tex_clamped);
 | 
| +      gl_FragColor = texColor * v_alpha;
 | 
| +    }
 | 
|    });
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATexVaryingAlpha::GetShaderBody() {
 | 
| +std::string FragmentShaderRGBATexClampPremultiplyAlpha::GetShaderString(
 | 
| +    TexCoordPrecision precision,
 | 
| +    SamplerType sampler) const {
 | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampPremultiplyAlpha::GetShaderHead() {
 | 
| +  return base::StringPrintf("#define NUM_STATIC_QUADS %d\n",
 | 
| +                            StaticGeometryBinding::NUM_QUADS) +
 | 
| +         SHADER0([]() {
 | 
| +           precision mediump float;
 | 
| +           varying TexCoordPrecision vec2 v_texCoord;
 | 
| +           varying float v_index;
 | 
| +           varying float v_alpha;
 | 
| +           uniform SamplerType s_texture;
 | 
| +           uniform vec4 tex_clamp_rect[NUM_STATIC_QUADS];
 | 
| +         });
 | 
| +}
 | 
| +
 | 
| +std::string FragmentShaderRGBATexClampPremultiplyAlpha::GetShaderBody() {
 | 
|    return SHADER0([]() {
 | 
|      void main() {
 | 
| -      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| +      vec2 tex_clamped = max(tex_clamp_rect[int(v_index)].xy,
 | 
| +                             min(tex_clamp_rect[int(v_index)].zw, v_texCoord));
 | 
| +      vec4 texColor = TextureLookup(s_texture, tex_clamped);
 | 
| +      texColor.rgb *= texColor.a;
 | 
|        gl_FragColor = texColor * v_alpha;
 | 
|      }
 | 
|    });
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
 | 
| +std::string FragmentShaderRGBATexClamp::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
|    return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderHead() {
 | 
| +std::string FragmentShaderRGBATexClamp::GetShaderHead() {
 | 
|    return SHADER0([]() {
 | 
|      precision mediump float;
 | 
|      varying TexCoordPrecision vec2 v_texCoord;
 | 
| -    varying float v_alpha;
 | 
|      uniform SamplerType s_texture;
 | 
| +    uniform vec4 tex_clamp_rect;
 | 
|    });
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderBody() {
 | 
| +std::string FragmentShaderRGBATexClamp::GetShaderBody() {
 | 
|    return SHADER0([]() {
 | 
|      void main() {
 | 
| -      vec4 texColor = TextureLookup(s_texture, v_texCoord);
 | 
| -      texColor.rgb *= texColor.a;
 | 
| -      gl_FragColor = texColor * v_alpha;
 | 
| +      vec2 tex_clamped =
 | 
| +          max(tex_clamp_rect.xy, min(tex_clamp_rect.zw, v_texCoord));
 | 
| +      gl_FragColor = TextureLookup(s_texture, tex_clamped);
 | 
|      }
 | 
|    });
 | 
|  }
 | 
|  
 | 
|  FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
 | 
| -    : background_color_location_(-1), sampler_location_(-1) {
 | 
| -}
 | 
| +    : background_color_location_(-1) {}
 | 
|  
 | 
|  void FragmentTexBackgroundBinding::Init(GLES2Interface* context,
 | 
|                                          unsigned program,
 | 
| @@ -1291,6 +1359,10 @@ void FragmentTexBackgroundBinding::Init(GLES2Interface* context,
 | 
|    DCHECK_NE(background_color_location_, -1);
 | 
|  }
 | 
|  
 | 
| +int FragmentTexBackgroundBinding::background_color_location() const {
 | 
| +  return background_color_location_;
 | 
| +}
 | 
| +
 | 
|  std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
 | 
|      TexCoordPrecision precision,
 | 
|      SamplerType sampler) const {
 | 
| @@ -1367,25 +1439,6 @@ std::string FragmentShaderRGBATexOpaque::GetShaderBody() {
 | 
|    });
 | 
|  }
 | 
|  
 | 
| -std::string FragmentShaderRGBATex::GetShaderString(TexCoordPrecision precision,
 | 
| -                                                   SamplerType sampler) const {
 | 
| -  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 {
 | 
| 
 |