summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authoralokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-29 00:35:12 +0000
committeralokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-29 00:35:12 +0000
commitb54beedcc27bea274dba8bdaa55948d4a0447a63 (patch)
tree99ae61ad320b30b66eec65de7544e9301bf828da /cc
parent44a4becb395b09648a40f261a9a91343fe322cad (diff)
downloadchromium_src-b54beedcc27bea274dba8bdaa55948d4a0447a63.zip
chromium_src-b54beedcc27bea274dba8bdaa55948d4a0447a63.tar.gz
chromium_src-b54beedcc27bea274dba8bdaa55948d4a0447a63.tar.bz2
Premultiply alpha in shader for non-premultiplied textures.
Instead of using different blending equations we can perform the pre-multiplication in the shader itself. I am working on improving the performance of compositing canvas elements with opaque background. This requires blending the canvas texture with the background color in the shader. The implementation of this blending equation becomes much easier if we can assume that textures are always premultiplied. BUG=236982 TEST=compositing/webgl/webgl-nonpremultiplied-blend.html Review URL: https://chromiumcodereview.appspot.com/16943021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209246 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/output/gl_renderer.cc78
-rw-r--r--cc/output/gl_renderer.h8
-rw-r--r--cc/output/gl_renderer_draw_cache.h2
-rw-r--r--cc/output/gl_renderer_unittest.cc2
-rw-r--r--cc/output/shader.cc15
-rw-r--r--cc/output/shader.h5
6 files changed, 65 insertions, 45 deletions
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 960198d..901ba9a 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -1686,23 +1686,6 @@ void GLRenderer::FlushTextureQuadCache() {
GLC(Context(),
Context()->bindTexture(GL_TEXTURE_2D, locked_quad.texture_id()));
- // set up premultiplied alpha.
- if (!draw_cache_.use_premultiplied_alpha) {
- // As it turns out, the premultiplied alpha blending function (ONE,
- // ONE_MINUS_SRC_ALPHA) will never cause the alpha channel to be set to
- // anything less than 1.0f if it is initialized to that value! Therefore,
- // premultiplied_alpha being false is the first situation we can generally
- // see an alpha channel less than 1.0f coming out of the compositor. This is
- // causing platform differences in some layout tests (see
- // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use
- // a separate blend function for the alpha channel to avoid modifying it.
- // Don't use colorMask() for this as it has performance implications on some
- // platforms.
- GLC(Context(),
- Context()->blendFuncSeparate(
- GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
- }
-
COMPILE_ASSERT(
sizeof(Float4) == 4 * sizeof(float), // NOLINT(runtime/sizeof)
struct_is_densely_packed);
@@ -1735,10 +1718,6 @@ void GLRenderer::FlushTextureQuadCache() {
GL_UNSIGNED_SHORT,
0));
- // Clean up after ourselves (reset state set above).
- if (!draw_cache_.use_premultiplied_alpha)
- GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
-
// Clear the cache.
draw_cache_.program_id = 0;
draw_cache_.uv_xform_data.resize(0);
@@ -1754,19 +1733,22 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame,
// Choose the correct texture program binding
TexTransformTextureProgramBinding binding;
- binding.Set(GetTextureProgram(tex_coord_precision), Context());
+ if (quad->premultiplied_alpha) {
+ binding.Set(GetTextureProgram(tex_coord_precision), Context());
+ } else {
+ binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision),
+ Context());
+ }
int resource_id = quad->resource_id;
if (draw_cache_.program_id != binding.program_id ||
draw_cache_.resource_id != resource_id ||
- draw_cache_.use_premultiplied_alpha != quad->premultiplied_alpha ||
draw_cache_.needs_blending != quad->ShouldDrawWithBlending() ||
draw_cache_.matrix_data.size() >= 8) {
FlushTextureQuadCache();
draw_cache_.program_id = binding.program_id;
draw_cache_.resource_id = resource_id;
- draw_cache_.use_premultiplied_alpha = quad->premultiplied_alpha;
draw_cache_.needs_blending = quad->ShouldDrawWithBlending();
draw_cache_.uv_xform_location = binding.tex_transform_location;
@@ -1802,7 +1784,12 @@ void GLRenderer::DrawTextureQuad(const DrawingFrame* frame,
quad->shared_quad_state->visible_content_rect.bottom_right());
TexTransformTextureProgramBinding binding;
- binding.Set(GetTextureProgram(tex_coord_precision), Context());
+ if (quad->premultiplied_alpha) {
+ binding.Set(GetTextureProgram(tex_coord_precision), Context());
+ } else {
+ binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision),
+ Context());
+ }
SetUseProgram(binding.program_id);
GLC(Context(), Context()->uniform1i(binding.sampler_location, 0));
Float4 uv_xform = UVTransform(quad);
@@ -1820,27 +1807,8 @@ void GLRenderer::DrawTextureQuad(const DrawingFrame* frame,
ResourceProvider::ScopedSamplerGL quad_resource_lock(
resource_provider_, quad->resource_id, GL_TEXTURE_2D, GL_LINEAR);
- if (!quad->premultiplied_alpha) {
- // As it turns out, the premultiplied alpha blending function (ONE,
- // ONE_MINUS_SRC_ALPHA) will never cause the alpha channel to be set to
- // anything less than 1.0f if it is initialized to that value! Therefore,
- // premultiplied_alpha being false is the first situation we can generally
- // see an alpha channel less than 1.0f coming out of the compositor. This is
- // causing platform differences in some layout tests (see
- // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use
- // a separate blend function for the alpha channel to avoid modifying it.
- // Don't use colorMask() for this as it has performance implications on some
- // platforms.
- GLC(Context(),
- Context()->blendFuncSeparate(
- GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
- }
-
DrawQuadGeometry(
frame, quad->quadTransform(), quad->rect, binding.matrix_location);
-
- if (!quad->premultiplied_alpha)
- GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}
void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
@@ -2824,6 +2792,24 @@ const GLRenderer::TextureProgram* GLRenderer::GetTextureProgram(
return program.get();
}
+const GLRenderer::NonPremultipliedTextureProgram*
+ GLRenderer::GetNonPremultipliedTextureProgram(TexCoordPrecision precision) {
+ scoped_ptr<NonPremultipliedTextureProgram>& program =
+ (precision == TexCoordPrecisionHigh) ?
+ nonpremultiplied_texture_program_highp_ :
+ nonpremultiplied_texture_program_;
+ if (!program) {
+ program = make_scoped_ptr(
+ new NonPremultipliedTextureProgram(context_, precision));
+ }
+ if (!program->initialized()) {
+ TRACE_EVENT0("cc",
+ "GLRenderer::NonPremultipliedTextureProgram::Initialize");
+ program->Initialize(context_, is_using_bind_uniform_);
+ }
+ return program.get();
+}
+
const GLRenderer::TextureIOSurfaceProgram*
GLRenderer::GetTextureIOSurfaceProgram(TexCoordPrecision precision) {
scoped_ptr<TextureIOSurfaceProgram>& program =
@@ -2953,11 +2939,15 @@ void GLRenderer::CleanupSharedObjects() {
if (texture_program_)
texture_program_->Cleanup(context_);
+ if (nonpremultiplied_texture_program_)
+ nonpremultiplied_texture_program_->Cleanup(context_);
if (texture_io_surface_program_)
texture_io_surface_program_->Cleanup(context_);
if (texture_program_highp_)
texture_program_highp_->Cleanup(context_);
+ if (nonpremultiplied_texture_program_highp_)
+ nonpremultiplied_texture_program_highp_->Cleanup(context_);
if (texture_io_surface_program_highp_)
texture_io_surface_program_highp_->Cleanup(context_);
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 32e89d3..db59e5b 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -265,6 +265,9 @@ class CC_EXPORT GLRenderer
typedef ProgramBinding<VertexShaderPosTexTransform,
FragmentShaderRGBATexVaryingAlpha> TextureProgram;
typedef ProgramBinding<VertexShaderPosTexTransform,
+ FragmentShaderRGBATexPremultiplyAlpha>
+ NonPremultipliedTextureProgram;
+ typedef ProgramBinding<VertexShaderPosTexTransform,
FragmentShaderRGBATexRectVaryingAlpha>
TextureIOSurfaceProgram;
@@ -337,6 +340,8 @@ class CC_EXPORT GLRenderer
const TextureProgram* GetTextureProgram(
TexCoordPrecision precision);
+ const NonPremultipliedTextureProgram* GetNonPremultipliedTextureProgram(
+ TexCoordPrecision precision);
const TextureIOSurfaceProgram* GetTextureIOSurfaceProgram(
TexCoordPrecision precision);
@@ -367,9 +372,12 @@ class CC_EXPORT GLRenderer
scoped_ptr<TileProgramSwizzleAA> tile_program_swizzle_aa_highp_;
scoped_ptr<TextureProgram> texture_program_;
+ scoped_ptr<NonPremultipliedTextureProgram> nonpremultiplied_texture_program_;
scoped_ptr<TextureIOSurfaceProgram> texture_io_surface_program_;
scoped_ptr<TextureProgram> texture_program_highp_;
+ scoped_ptr<NonPremultipliedTextureProgram>
+ nonpremultiplied_texture_program_highp_;
scoped_ptr<TextureIOSurfaceProgram> texture_io_surface_program_highp_;
scoped_ptr<RenderPassProgram> render_pass_program_;
diff --git a/cc/output/gl_renderer_draw_cache.h b/cc/output/gl_renderer_draw_cache.h
index e99cc27..85369ef 100644
--- a/cc/output/gl_renderer_draw_cache.h
+++ b/cc/output/gl_renderer_draw_cache.h
@@ -31,7 +31,6 @@ struct TexturedQuadDrawCache {
// Values tracked to determine if textured quads may be coalesced.
int program_id;
int resource_id;
- bool use_premultiplied_alpha;
bool needs_blending;
// Information about the program binding that is required to draw.
@@ -45,6 +44,7 @@ struct TexturedQuadDrawCache {
std::vector<float> vertex_opacity_data;
std::vector<Float16> matrix_data;
+ private:
DISALLOW_COPY_AND_ASSIGN(TexturedQuadDrawCache);
};
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 97c73fa..34443e3 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -93,6 +93,8 @@ class GLRendererShaderPixelTest : public GLRendererPixelTest {
EXPECT_PROGRAM_VALID(
renderer()->GetRenderPassMaskColorMatrixProgram(precision));
EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision));
+ EXPECT_PROGRAM_VALID(
+ renderer()->GetNonPremultipliedTextureProgram(precision));
EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision));
EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision));
EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision));
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index 385c72d..6e1f6c5 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -682,6 +682,21 @@ std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
); // NOLINT(whitespace/parens)
}
+std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
+ TexCoordPrecision precision) const {
+ return FRAGMENT_SHADER(
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying float v_alpha;
+ uniform sampler2D s_texture;
+ void main() {
+ vec4 texColor = texture2D(s_texture, v_texCoord);
+ texColor.rgb *= texColor.a;
+ gl_FragColor = texColor * v_alpha;
+ }
+ ); // NOLINT(whitespace/parens)
+}
+
std::string FragmentShaderRGBATexRectVaryingAlpha::GetShaderString(
TexCoordPrecision precision) const {
return "#extension GL_ARB_texture_rectangle : require\n" +
diff --git a/cc/output/shader.h b/cc/output/shader.h
index 44eedef..7910e59 100644
--- a/cc/output/shader.h
+++ b/cc/output/shader.h
@@ -283,6 +283,11 @@ class FragmentShaderRGBATexVaryingAlpha : public FragmentTexOpaqueBinding {
std::string GetShaderString(TexCoordPrecision precision) const;
};
+class FragmentShaderRGBATexPremultiplyAlpha : public FragmentTexOpaqueBinding {
+ public:
+ std::string GetShaderString(TexCoordPrecision precision) const;
+};
+
class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding {
public:
std::string GetShaderString(TexCoordPrecision precision) const;