| Index: cc/output/shader.cc | 
| diff --git a/cc/output/shader.cc b/cc/output/shader.cc | 
| index 189154637d6ab9bffbecf1244b516762e1f9114e..a50d4a6c5e56a6297fb37c5caf1e5366ff0dd121 100644 | 
| --- a/cc/output/shader.cc | 
| +++ b/cc/output/shader.cc | 
| @@ -347,6 +347,12 @@ std::string VertexShaderPosTexTransform::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| +void VertexShaderPosTexTransform::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->matrix = matrix_location(); | 
| +  locations->tex_transform = tex_transform_location(); | 
| +} | 
| + | 
| std::string VertexShaderPosTexIdentity::GetShaderString() const { | 
| return VERTEX_SHADER(GetShaderHead(), GetShaderBody()); | 
| } | 
| @@ -560,6 +566,16 @@ std::string VertexShaderQuadTexTransformAA::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| +void VertexShaderQuadTexTransformAA::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->quad = quad_location(); | 
| +  locations->edge = edge_location(); | 
| +  locations->viewport = viewport_location(); | 
| +  locations->matrix = matrix_location(); | 
| +  locations->tex_transform = tex_transform_location(); | 
| +} | 
| + | 
| + | 
| VertexShaderTile::VertexShaderTile() | 
| : matrix_location_(-1), | 
| quad_location_(-1), | 
| @@ -722,19 +738,24 @@ std::string VertexShaderVideoTransform::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| -#define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect" | 
| -#define UNUSED_BLEND_MODE_UNIFORMS (!has_blend_mode() ? 2 : 0) | 
| +#define BLEND_MODE_UNIFORMS "s_backdropTexture", \ | 
| +                            "s_originalBackdropTexture", \ | 
| +                            "backdropRect" | 
| +#define UNUSED_BLEND_MODE_UNIFORMS (!has_blend_mode() ? 3 : 0) | 
| #define BLEND_MODE_SET_LOCATIONS(X, POS)                   \ | 
| if (has_blend_mode()) {                                  \ | 
| -    DCHECK_LT(static_cast<size_t>(POS) + 1, arraysize(X)); \ | 
| +    DCHECK_LT(static_cast<size_t>(POS) + 2, arraysize(X)); \ | 
| backdrop_location_ = locations[POS];                   \ | 
| -    backdrop_rect_location_ = locations[POS + 1];          \ | 
| +    original_backdrop_location_ = locations[POS + 1];      \ | 
| +    backdrop_rect_location_ = locations[POS + 2];          \ | 
| } | 
|  | 
| FragmentTexBlendMode::FragmentTexBlendMode() | 
| : backdrop_location_(-1), | 
| +      original_backdrop_location_(-1), | 
| backdrop_rect_location_(-1), | 
| -      blend_mode_(BLEND_MODE_NONE) { | 
| +      blend_mode_(BLEND_MODE_NONE), | 
| +      mask_for_background_(false) { | 
| } | 
|  | 
| std::string FragmentTexBlendMode::SetBlendModeFunctions( | 
| @@ -743,11 +764,14 @@ std::string FragmentTexBlendMode::SetBlendModeFunctions( | 
| return shader_string; | 
|  | 
| if (!has_blend_mode()) { | 
| -    return "#define ApplyBlendMode(X) (X)\n" + shader_string; | 
| +    return "#define ApplyBlendMode(X) (X)\n" | 
| +           "#define ApplyBlendModeWithMask(X, Y) (X)\n" + | 
| +           shader_string; | 
| } | 
|  | 
| static const std::string kFunctionApplyBlendMode = SHADER0([]() { | 
| uniform sampler2D s_backdropTexture; | 
| +    uniform sampler2D s_originalBackdropTexture; | 
| uniform TexCoordPrecision vec4 backdropRect; | 
|  | 
| vec4 GetBackdropColor() { | 
| @@ -761,6 +785,20 @@ std::string FragmentTexBlendMode::SetBlendModeFunctions( | 
| vec4 dst = GetBackdropColor(); | 
| return Blend(src, dst); | 
| } | 
| + | 
| +    vec4 GetBackdropColorWithMask(float mask) { | 
| +      TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy; | 
| +      bgTexCoord.x /= backdropRect.z; | 
| +      bgTexCoord.y /= backdropRect.w; | 
| +      vec4 backdrop = texture2D(s_backdropTexture, bgTexCoord); | 
| +      vec4 original_backdrop = texture2D(s_originalBackdropTexture, bgTexCoord); | 
| +      return mix(original_backdrop, backdrop, mask); | 
| +    } | 
| + | 
| +    vec4 ApplyBlendModeWithMask(vec4 src, float mask) { | 
| +      vec4 dst = GetBackdropColorWithMask(mask); | 
| +      return Blend(src, dst); | 
| +    } | 
| }); | 
|  | 
| return "precision mediump float;" + GetHelperFunctions() + | 
| @@ -1105,6 +1143,13 @@ std::string FragmentShaderRGBATexAlpha::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| +void FragmentShaderRGBATexAlpha::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->alpha = alpha_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +} | 
| + | 
| std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString( | 
| TexCoordPrecision precision, | 
| SamplerType sampler) const { | 
| @@ -1136,6 +1181,15 @@ std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| +void FragmentShaderRGBATexColorMatrixAlpha::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->alpha = alpha_location(); | 
| +  locations->color_matrix = color_matrix_location(); | 
| +  locations->color_offset = color_offset_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +} | 
| + | 
| std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString( | 
| TexCoordPrecision precision, | 
| SamplerType sampler) const { | 
| @@ -1405,6 +1459,13 @@ std::string FragmentShaderRGBATexAlphaAA::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| +void FragmentShaderRGBATexAlphaAA::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->alpha = alpha_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +} | 
| + | 
| FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding() | 
| : sampler_location_(-1), | 
| alpha_location_(-1), | 
| @@ -1532,7 +1593,7 @@ void FragmentShaderRGBATexAlphaMask::Init(GLES2Interface* context, | 
| std::string FragmentShaderRGBATexAlphaMask::GetShaderString( | 
| TexCoordPrecision precision, | 
| SamplerType sampler) const { | 
| -  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody()); | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody(mask_for_background())); | 
| } | 
|  | 
| std::string FragmentShaderRGBATexAlphaMask::GetShaderHead() { | 
| @@ -1547,17 +1608,33 @@ std::string FragmentShaderRGBATexAlphaMask::GetShaderHead() { | 
| }); | 
| } | 
|  | 
| -std::string FragmentShaderRGBATexAlphaMask::GetShaderBody() { | 
| +std::string FragmentShaderRGBATexAlphaMask::GetShaderBody( | 
| +    bool mask_for_background) { | 
| 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); | 
| -    } | 
| -  }); | 
| +                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y); | 
| +      vec4 maskColor = TextureLookup(s_mask, maskTexCoord); }) + | 
| +  (mask_for_background | 
| +  ? SHADER0([]() { gl_FragColor = ApplyBlendModeWithMask( | 
| +                       texColor * alpha * maskColor.w, maskColor.w); }) | 
| +  : SHADER0([]() { gl_FragColor = ApplyBlendMode( | 
| +                       texColor * alpha * maskColor.w); })) + | 
| +  SHADER0([]() {}}); | 
| +} | 
| + | 
| +void FragmentShaderRGBATexAlphaMask::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->mask_sampler = mask_sampler_location(); | 
| +  locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); | 
| +  locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); | 
| +  locations->alpha = alpha_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +  if (mask_for_background()) | 
| +    locations->original_backdrop = original_backdrop_location(); | 
| } | 
|  | 
| FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA() | 
| @@ -1598,7 +1675,7 @@ void FragmentShaderRGBATexAlphaMaskAA::Init(GLES2Interface* context, | 
| std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString( | 
| TexCoordPrecision precision, | 
| SamplerType sampler) const { | 
| -  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody()); | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody(mask_for_background())); | 
| } | 
|  | 
| std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderHead() { | 
| @@ -1614,20 +1691,36 @@ std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderHead() { | 
| }); | 
| } | 
|  | 
| -std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderBody() { | 
| +std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderBody( | 
| +    bool mask_for_background) { | 
| 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); | 
| +                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); | 
| -    } | 
| -  }); | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0); }) + | 
| +  (mask_for_background | 
| +  ? SHADER0([]() { gl_FragColor = ApplyBlendModeWithMask( | 
| +                       texColor * alpha * maskColor.w * aa, maskColor.w); }) | 
| +  : SHADER0([]() { gl_FragColor = ApplyBlendMode( | 
| +                       texColor * alpha * maskColor.w * aa); })) + | 
| +  SHADER0([]() {}}); | 
| +} | 
| + | 
| +void FragmentShaderRGBATexAlphaMaskAA::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->mask_sampler = mask_sampler_location(); | 
| +  locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); | 
| +  locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); | 
| +  locations->alpha = alpha_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +  if (mask_for_background()) | 
| +    locations->original_backdrop = original_backdrop_location(); | 
| } | 
|  | 
| FragmentShaderRGBATexAlphaMaskColorMatrixAA:: | 
| @@ -1675,7 +1768,7 @@ void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init( | 
| std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString( | 
| TexCoordPrecision precision, | 
| SamplerType sampler) const { | 
| -  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody()); | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody(mask_for_background())); | 
| } | 
|  | 
| std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderHead() { | 
| @@ -1693,7 +1786,8 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderHead() { | 
| }); | 
| } | 
|  | 
| -std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderBody() { | 
| +std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderBody( | 
| +    bool mask_for_background) { | 
| return SHADER0([]() { | 
| void main() { | 
| vec4 texColor = texture2D(s_texture, v_texCoord); | 
| @@ -1704,14 +1798,31 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderBody() { | 
| 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); | 
| +                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); | 
| -    } | 
| -  }); | 
| +      float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0); }) + | 
| +  (mask_for_background | 
| +  ? SHADER0([]() { gl_FragColor = ApplyBlendModeWithMask( | 
| +                       texColor * alpha * maskColor.w * aa, maskColor.w); }) | 
| +  : SHADER0([]() { gl_FragColor = ApplyBlendMode( | 
| +                       texColor * alpha * maskColor.w * aa); })) + | 
| +  SHADER0([]() {}}); | 
| +} | 
| + | 
| +void FragmentShaderRGBATexAlphaMaskColorMatrixAA::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->alpha = alpha_location(); | 
| +  locations->mask_sampler = mask_sampler_location(); | 
| +  locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); | 
| +  locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); | 
| +  locations->color_matrix = color_matrix_location(); | 
| +  locations->color_offset = color_offset_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +  if (mask_for_background()) | 
| +    locations->original_backdrop = original_backdrop_location(); | 
| } | 
|  | 
| FragmentShaderRGBATexAlphaColorMatrixAA:: | 
| @@ -1778,6 +1889,15 @@ std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderBody() { | 
| }); | 
| } | 
|  | 
| +void FragmentShaderRGBATexAlphaColorMatrixAA::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->alpha = alpha_location(); | 
| +  locations->color_matrix = color_matrix_location(); | 
| +  locations->color_offset = color_offset_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +} | 
| + | 
| FragmentShaderRGBATexAlphaMaskColorMatrix:: | 
| FragmentShaderRGBATexAlphaMaskColorMatrix() | 
| : sampler_location_(-1), | 
| @@ -1820,7 +1940,7 @@ void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(GLES2Interface* context, | 
| std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString( | 
| TexCoordPrecision precision, | 
| SamplerType sampler) const { | 
| -  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody()); | 
| +  return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody(mask_for_background())); | 
| } | 
|  | 
| std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderHead() { | 
| @@ -1837,7 +1957,8 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderHead() { | 
| }); | 
| } | 
|  | 
| -std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderBody() { | 
| +std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderBody( | 
| +    bool mask_for_background) { | 
| return SHADER0([]() { | 
| void main() { | 
| vec4 texColor = texture2D(s_texture, v_texCoord); | 
| @@ -1848,11 +1969,28 @@ std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderBody() { | 
| 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); | 
| -    } | 
| -  }); | 
| +                maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y); | 
| +      vec4 maskColor = TextureLookup(s_mask, maskTexCoord); }) + | 
| +  (mask_for_background | 
| +  ? SHADER0([]() { gl_FragColor = ApplyBlendModeWithMask( | 
| +                       texColor * alpha * maskColor.w, maskColor.w); }) | 
| +  : SHADER0([]() { gl_FragColor = ApplyBlendMode( | 
| +                       texColor * alpha * maskColor.w); })) + | 
| +  SHADER0([]() {}}); | 
| +} | 
| + | 
| +void FragmentShaderRGBATexAlphaMaskColorMatrix::FillLocations( | 
| +    ShaderLocations* locations) const { | 
| +  locations->mask_sampler = mask_sampler_location(); | 
| +  locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); | 
| +  locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); | 
| +  locations->alpha = alpha_location(); | 
| +  locations->color_matrix = color_matrix_location(); | 
| +  locations->color_offset = color_offset_location(); | 
| +  locations->backdrop = backdrop_location(); | 
| +  locations->backdrop_rect = backdrop_rect_location(); | 
| +  if (mask_for_background()) | 
| +    locations->original_backdrop = original_backdrop_location(); | 
| } | 
|  | 
| FragmentShaderYUVVideo::FragmentShaderYUVVideo() | 
|  |