diff options
author | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-12 05:33:49 +0000 |
---|---|---|
committer | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-12 05:33:49 +0000 |
commit | d18b4d6ed525c87c4126142c22de05d47502fff5 (patch) | |
tree | 544f3ad9bbb7a66045c9716d4dea636adcdf11df /cc | |
parent | 92594aa101db0a68e7c93ee9d5aec78a38403d86 (diff) | |
download | chromium_src-d18b4d6ed525c87c4126142c22de05d47502fff5.zip chromium_src-d18b4d6ed525c87c4126142c22de05d47502fff5.tar.gz chromium_src-d18b4d6ed525c87c4126142c22de05d47502fff5.tar.bz2 |
Blend TextureLayer background-color at draw time.
This enables the following optimization:
1. The compositor will be able to disable GL blending
if the background-color is opaque.
2. For elements that paint directly to a texture layer,
i.e. accelerated canvas, video, etc., there is no need to
allocate an additional layer just to paint the background.
BUG=236982
Review URL: https://chromiumcodereview.appspot.com/18432002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@211339 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/layers/heads_up_display_layer_impl.cc | 1 | ||||
-rw-r--r-- | cc/layers/nine_patch_layer_impl.cc | 14 | ||||
-rw-r--r-- | cc/layers/scrollbar_layer_impl.cc | 2 | ||||
-rw-r--r-- | cc/layers/texture_layer.cc | 9 | ||||
-rw-r--r-- | cc/layers/texture_layer.h | 5 | ||||
-rw-r--r-- | cc/layers/texture_layer_impl.cc | 8 | ||||
-rw-r--r-- | cc/layers/texture_layer_impl.h | 4 | ||||
-rw-r--r-- | cc/layers/texture_layer_unittest.cc | 1 | ||||
-rw-r--r-- | cc/layers/video_layer_impl.cc | 2 | ||||
-rw-r--r-- | cc/output/gl_renderer.cc | 88 | ||||
-rw-r--r-- | cc/output/gl_renderer.h | 16 | ||||
-rw-r--r-- | cc/output/gl_renderer_draw_cache.h | 3 | ||||
-rw-r--r-- | cc/output/gl_renderer_unittest.cc | 3 | ||||
-rw-r--r-- | cc/output/renderer_pixeltest.cc | 169 | ||||
-rw-r--r-- | cc/output/shader.cc | 62 | ||||
-rw-r--r-- | cc/output/shader.h | 33 | ||||
-rw-r--r-- | cc/output/software_renderer.cc | 24 | ||||
-rw-r--r-- | cc/quads/draw_quad_unittest.cc | 21 | ||||
-rw-r--r-- | cc/quads/texture_draw_quad.cc | 11 | ||||
-rw-r--r-- | cc/quads/texture_draw_quad.h | 3 | ||||
-rw-r--r-- | cc/test/render_pass_test_common.cc | 1 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_delegated.cc | 1 |
22 files changed, 461 insertions, 20 deletions
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index ef3e2fd..8728d70 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc @@ -124,6 +124,7 @@ void HeadsUpDisplayLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); diff --git a/cc/layers/nine_patch_layer_impl.cc b/cc/layers/nine_patch_layer_impl.cc index 57723a0..103f765 100644 --- a/cc/layers/nine_patch_layer_impl.cc +++ b/cc/layers/nine_patch_layer_impl.cc @@ -179,7 +179,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_top_left.origin(), uv_top_left.bottom_right(), - vertex_opacity, flipped); + SK_ColorTRANSPARENT, + vertex_opacity, + flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); quad = TextureDrawQuad::Create(); @@ -190,7 +192,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_top_right.origin(), uv_top_right.bottom_right(), - vertex_opacity, flipped); + SK_ColorTRANSPARENT, + vertex_opacity, + flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); quad = TextureDrawQuad::Create(); @@ -201,6 +205,7 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_bottom_left.origin(), uv_bottom_left.bottom_right(), + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); @@ -213,6 +218,7 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_bottom_right.origin(), uv_bottom_right.bottom_right(), + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); @@ -225,6 +231,7 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_top.origin(), uv_top.bottom_right(), + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); @@ -237,6 +244,7 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_left.origin(), uv_left.bottom_right(), + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); @@ -249,6 +257,7 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_right.origin(), uv_right.bottom_right(), + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); @@ -261,6 +270,7 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_bottom.origin(), uv_bottom.bottom_right(), + SK_ColorTRANSPARENT, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); diff --git a/cc/layers/scrollbar_layer_impl.cc b/cc/layers/scrollbar_layer_impl.cc index 4160bf0..26fda8d 100644 --- a/cc/layers/scrollbar_layer_impl.cc +++ b/cc/layers/scrollbar_layer_impl.cc @@ -118,6 +118,7 @@ void ScrollbarLayerImpl::AppendQuads(QuadSink* quad_sink, premultipled_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); @@ -141,6 +142,7 @@ void ScrollbarLayerImpl::AppendQuads(QuadSink* quad_sink, premultipled_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index 304157e..5e68802 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc @@ -31,6 +31,7 @@ TextureLayer::TextureLayer(TextureLayerClient* client, bool uses_mailbox) uv_top_left_(0.f, 0.f), uv_bottom_right_(1.f, 1.f), premultiplied_alpha_(true), + blend_background_color_(false), rate_limit_context_(false), content_committed_(false), texture_id_(0), @@ -101,6 +102,13 @@ void TextureLayer::SetPremultipliedAlpha(bool premultiplied_alpha) { SetNeedsCommit(); } +void TextureLayer::SetBlendBackgroundColor(bool blend) { + if (blend_background_color_ == blend) + return; + blend_background_color_ = blend; + SetNeedsCommit(); +} + void TextureLayer::SetRateLimitContext(bool rate_limit) { if (!rate_limit && rate_limit_context_ && client_ && layer_tree_host()) layer_tree_host()->StopRateLimiter(client_->Context3d()); @@ -207,6 +215,7 @@ void TextureLayer::PushPropertiesTo(LayerImpl* layer) { texture_layer->set_uv_bottom_right(uv_bottom_right_); texture_layer->set_vertex_opacity(vertex_opacity_); texture_layer->set_premultiplied_alpha(premultiplied_alpha_); + texture_layer->set_blend_background_color(blend_background_color_); if (uses_mailbox_ && needs_set_mailbox_) { TextureMailbox texture_mailbox; if (holder_ref_) { diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index 928f05f..d87a9d3 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h @@ -57,6 +57,10 @@ class CC_EXPORT TextureLayer : public Layer { // Defaults to true. void SetPremultipliedAlpha(bool premultiplied_alpha); + // Sets whether the texture should be blended with the background color + // at draw time. Defaults to false. + void SetBlendBackgroundColor(bool blend); + // Sets whether this context should rate limit on damage to prevent too many // frames from being queued up before the compositor gets a chance to run. // Requires a non-nil client. Defaults to false. @@ -140,6 +144,7 @@ class CC_EXPORT TextureLayer : public Layer { // [bottom left, top left, top right, bottom right] float vertex_opacity_[4]; bool premultiplied_alpha_; + bool blend_background_color_; bool rate_limit_context_; bool content_committed_; diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index ce5251d..5d1f4f4 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc @@ -19,6 +19,7 @@ TextureLayerImpl::TextureLayerImpl(LayerTreeImpl* tree_impl, texture_id_(0), external_texture_resource_(0), premultiplied_alpha_(true), + blend_background_color_(false), flipped_(true), uv_top_left_(0.f, 0.f), uv_bottom_right_(1.f, 1.f), @@ -104,8 +105,12 @@ void TextureLayerImpl::AppendQuads(QuadSink* quad_sink, quad_sink->UseSharedQuadState(CreateSharedQuadState()); AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); + SkColor bg_color = blend_background_color_ ? + background_color() : SK_ColorTRANSPARENT; + bool opaque = contents_opaque() || (SkColorGetA(bg_color) == 0xFF); + gfx::Rect quad_rect(content_bounds()); - gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect()); + gfx::Rect opaque_rect = opaque ? quad_rect : gfx::Rect(); scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, quad_rect, @@ -114,6 +119,7 @@ void TextureLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha_, uv_top_left_, uv_bottom_right_, + bg_color, vertex_opacity_, flipped_); diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h index 63a9c0f..4cd2492 100644 --- a/cc/layers/texture_layer_impl.h +++ b/cc/layers/texture_layer_impl.h @@ -39,6 +39,9 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { void set_premultiplied_alpha(bool premultiplied_alpha) { premultiplied_alpha_ = premultiplied_alpha; } + void set_blend_background_color(bool blend) { + blend_background_color_ = blend; + } void set_flipped(bool flipped) { flipped_ = flipped; } void set_uv_top_left(gfx::PointF top_left) { uv_top_left_ = top_left; } void set_uv_bottom_right(gfx::PointF bottom_right) { @@ -68,6 +71,7 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { unsigned texture_id_; ResourceProvider::ResourceId external_texture_resource_; bool premultiplied_alpha_; + bool blend_background_color_; bool flipped_; gfx::PointF uv_top_left_; gfx::PointF uv_bottom_right_; diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index f50edda..fac9a98 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc @@ -196,6 +196,7 @@ TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity( 0.5f, 0.5f, 0.5f, 0.5f)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false)); + EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTextureId(1)); // Calling SetTextureId can call AcquireLayerTextures. diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index dc55ba2..4b5671f 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc @@ -156,6 +156,7 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, opacity, flipped); quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data); @@ -196,6 +197,7 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, opacity, flipped); quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data); diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index f1ac9d7..0133b27 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -96,6 +96,19 @@ Float4 UVTransform(const TextureDrawQuad* quad) { return xform; } +Float4 PremultipliedColor(SkColor color) { + const float factor = 1.0f / 255.0f; + const float alpha = SkColorGetA(color) * factor; + + Float4 result = { { + SkColorGetR(color) * factor * alpha, + SkColorGetG(color) * factor * alpha, + SkColorGetB(color) * factor * alpha, + alpha + } }; + return result; +} + // Smallest unit that impact anti-aliasing output. We use this to // determine when anti-aliasing is unnecessary. const float kAntiAliasingEpsilon = 1.0f / 1024.0f; @@ -1685,12 +1698,13 @@ struct TextureProgramBinding { program_id = program->program(); sampler_location = program->fragment_shader().sampler_location(); matrix_location = program->vertex_shader().matrix_location(); - alpha_location = program->fragment_shader().alpha_location(); + background_color_location = + program->fragment_shader().background_color_location(); } int program_id; int sampler_location; int matrix_location; - int alpha_location; + int background_color_location; }; struct TexTransformTextureProgramBinding : TextureProgramBinding { @@ -1744,6 +1758,14 @@ void GLRenderer::FlushTextureQuadCache() { static_cast<int>(draw_cache_.uv_xform_location), static_cast<int>(draw_cache_.uv_xform_data.size()), reinterpret_cast<float*>(&draw_cache_.uv_xform_data.front()))); + + if (draw_cache_.background_color != SK_ColorTRANSPARENT) { + Float4 background_color = PremultipliedColor(draw_cache_.background_color); + GLC(context_, + context_->uniform4fv( + draw_cache_.background_color_location, 1, background_color.data)); + } + GLC(context_, context_->uniform1fv( static_cast<int>(draw_cache_.vertex_opacity_location), @@ -1773,10 +1795,20 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, // Choose the correct texture program binding TexTransformTextureProgramBinding binding; if (quad->premultiplied_alpha) { - binding.Set(GetTextureProgram(tex_coord_precision), Context()); + if (quad->background_color == SK_ColorTRANSPARENT) { + binding.Set(GetTextureProgram(tex_coord_precision), Context()); + } else { + binding.Set(GetTextureBackgroundProgram(tex_coord_precision), Context()); + } } else { - binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision), - Context()); + if (quad->background_color == SK_ColorTRANSPARENT) { + binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision), + Context()); + } else { + binding.Set( + GetNonPremultipliedTextureBackgroundProgram(tex_coord_precision), + Context()); + } } int resource_id = quad->resource_id; @@ -1784,13 +1816,16 @@ void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, if (draw_cache_.program_id != binding.program_id || draw_cache_.resource_id != resource_id || draw_cache_.needs_blending != quad->ShouldDrawWithBlending() || + draw_cache_.background_color != quad->background_color || draw_cache_.matrix_data.size() >= 8) { FlushTextureQuadCache(); draw_cache_.program_id = binding.program_id; draw_cache_.resource_id = resource_id; draw_cache_.needs_blending = quad->ShouldDrawWithBlending(); + draw_cache_.background_color = quad->background_color; draw_cache_.uv_xform_location = binding.tex_transform_location; + draw_cache_.background_color_location = binding.background_color_location; draw_cache_.vertex_opacity_location = binding.vertex_opacity_location; draw_cache_.matrix_location = binding.matrix_location; draw_cache_.sampler_location = binding.sampler_location; @@ -2783,6 +2818,41 @@ const GLRenderer::NonPremultipliedTextureProgram* return program.get(); } +const GLRenderer::TextureBackgroundProgram* +GLRenderer::GetTextureBackgroundProgram(TexCoordPrecision precision) { + scoped_ptr<TextureBackgroundProgram>& program = + (precision == TexCoordPrecisionHigh) ? texture_background_program_highp_ + : texture_background_program_; + if (!program) { + program = make_scoped_ptr( + new TextureBackgroundProgram(context_, precision)); + } + if (!program->initialized()) { + TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize"); + program->Initialize(context_, is_using_bind_uniform_); + } + return program.get(); +} + +const GLRenderer::NonPremultipliedTextureBackgroundProgram* +GLRenderer::GetNonPremultipliedTextureBackgroundProgram( + TexCoordPrecision precision) { + scoped_ptr<NonPremultipliedTextureBackgroundProgram>& program = + (precision == TexCoordPrecisionHigh) ? + nonpremultiplied_texture_background_program_highp_ : + nonpremultiplied_texture_background_program_; + if (!program) { + program = make_scoped_ptr( + new NonPremultipliedTextureBackgroundProgram(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 = @@ -2914,6 +2984,10 @@ void GLRenderer::CleanupSharedObjects() { texture_program_->Cleanup(context_); if (nonpremultiplied_texture_program_) nonpremultiplied_texture_program_->Cleanup(context_); + if (texture_background_program_) + texture_background_program_->Cleanup(context_); + if (nonpremultiplied_texture_background_program_) + nonpremultiplied_texture_background_program_->Cleanup(context_); if (texture_io_surface_program_) texture_io_surface_program_->Cleanup(context_); @@ -2921,6 +2995,10 @@ void GLRenderer::CleanupSharedObjects() { texture_program_highp_->Cleanup(context_); if (nonpremultiplied_texture_program_highp_) nonpremultiplied_texture_program_highp_->Cleanup(context_); + if (texture_background_program_highp_) + texture_background_program_highp_->Cleanup(context_); + if (nonpremultiplied_texture_background_program_highp_) + nonpremultiplied_texture_background_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 bde4d71..c6ad8b1 100644 --- a/cc/output/gl_renderer.h +++ b/cc/output/gl_renderer.h @@ -259,6 +259,12 @@ class CC_EXPORT GLRenderer : public DirectRenderer { FragmentShaderRGBATexPremultiplyAlpha> NonPremultipliedTextureProgram; typedef ProgramBinding<VertexShaderPosTexTransform, + FragmentShaderTexBackgroundVaryingAlpha> + TextureBackgroundProgram; + typedef ProgramBinding<VertexShaderPosTexTransform, + FragmentShaderTexBackgroundVaryingAlpha> + NonPremultipliedTextureBackgroundProgram; + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectVaryingAlpha> TextureIOSurfaceProgram; @@ -333,6 +339,10 @@ class CC_EXPORT GLRenderer : public DirectRenderer { TexCoordPrecision precision); const NonPremultipliedTextureProgram* GetNonPremultipliedTextureProgram( TexCoordPrecision precision); + const TextureBackgroundProgram* GetTextureBackgroundProgram( + TexCoordPrecision precision); + const NonPremultipliedTextureBackgroundProgram* + GetNonPremultipliedTextureBackgroundProgram(TexCoordPrecision precision); const TextureIOSurfaceProgram* GetTextureIOSurfaceProgram( TexCoordPrecision precision); @@ -364,11 +374,17 @@ class CC_EXPORT GLRenderer : public DirectRenderer { scoped_ptr<TextureProgram> texture_program_; scoped_ptr<NonPremultipliedTextureProgram> nonpremultiplied_texture_program_; + scoped_ptr<TextureBackgroundProgram> texture_background_program_; + scoped_ptr<NonPremultipliedTextureBackgroundProgram> + nonpremultiplied_texture_background_program_; scoped_ptr<TextureIOSurfaceProgram> texture_io_surface_program_; scoped_ptr<TextureProgram> texture_program_highp_; scoped_ptr<NonPremultipliedTextureProgram> nonpremultiplied_texture_program_highp_; + scoped_ptr<TextureBackgroundProgram> texture_background_program_highp_; + scoped_ptr<NonPremultipliedTextureBackgroundProgram> + nonpremultiplied_texture_background_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 85369ef..f828418 100644 --- a/cc/output/gl_renderer_draw_cache.h +++ b/cc/output/gl_renderer_draw_cache.h @@ -8,6 +8,7 @@ #include <vector> #include "base/basictypes.h" +#include "third_party/skia/include/core/SkColor.h" namespace cc { @@ -32,9 +33,11 @@ struct TexturedQuadDrawCache { int program_id; int resource_id; bool needs_blending; + SkColor background_color; // Information about the program binding that is required to draw. int uv_xform_location; + int background_color_location; int vertex_opacity_location; int matrix_location; int sampler_location; diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index 3bea409..dd4e5f3 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc @@ -94,6 +94,9 @@ class GLRendererShaderPixelTest : public GLRendererPixelTest { EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision)); EXPECT_PROGRAM_VALID( renderer()->GetNonPremultipliedTextureProgram(precision)); + EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision)); + EXPECT_PROGRAM_VALID( + renderer()->GetNonPremultipliedTextureBackgroundProgram(precision)); EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision)); EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision)); EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision)); diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index d7149e5..42f5be1 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -7,6 +7,7 @@ #include "cc/output/gl_renderer.h" #include "cc/quads/draw_quad.h" #include "cc/quads/picture_draw_quad.h" +#include "cc/quads/texture_draw_quad.h" #include "cc/resources/platform_color.h" #include "cc/resources/sync_point_helper.h" #include "cc/test/fake_picture_pile_impl.h" @@ -94,6 +95,42 @@ scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad( return quad.PassAs<DrawQuad>(); } +scoped_ptr<TextureDrawQuad> CreateTestTextureDrawQuad( + gfx::Rect rect, + SkColor texel_color, + SkColor background_color, + bool premultiplied_alpha, + SharedQuadState* shared_state, + ResourceProvider* resource_provider) { + uint32_t pixel_color = premultiplied_alpha ? + SkPreMultiplyColor(texel_color) : texel_color; + std::vector<uint32_t> pixels(rect.size().GetArea(), pixel_color); + + ResourceProvider::ResourceId resource = resource_provider->CreateResource( + rect.size(), GL_RGBA, ResourceProvider::TextureUsageAny); + resource_provider->SetPixels( + resource, + reinterpret_cast<uint8_t*>(&pixels.front()), + rect, + rect, + gfx::Vector2d()); + + float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + + scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create(); + quad->SetNew(shared_state, + rect, + gfx::Rect(), + resource, + premultiplied_alpha, + gfx::PointF(0.0f, 0.0f), // uv_top_left + gfx::PointF(1.0f, 1.0f), // uv_bottom_right + background_color, + vertex_opacity, + false); // flipped + return quad.Pass(); +} + typedef ::testing::Types<GLRenderer, SoftwareRenderer, GLRendererWithExpandedViewport, @@ -218,6 +255,138 @@ TYPED_TEST(RendererPixelTest, SimpleGreenRect_NonRootRenderPass) { ExactPixelComparator(true))); } +TYPED_TEST(RendererPixelTest, PremultipliedTextureWithoutBackground) { + gfx::Rect rect(this->device_viewport_size_); + + RenderPass::Id id(1, 1); + scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); + + scoped_ptr<SharedQuadState> shared_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + + scoped_ptr<TextureDrawQuad> texture_quad = CreateTestTextureDrawQuad( + gfx::Rect(this->device_viewport_size_), + SkColorSetARGB(128, 0, 255, 0), // Texel color. + SK_ColorTRANSPARENT, // Background color. + true, // Premultiplied alpha. + shared_state.get(), + this->resource_provider_.get()); + pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>()); + + scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create(); + color_quad->SetNew(shared_state.get(), rect, SK_ColorWHITE, false); + pass->quad_list.push_back(color_quad.PassAs<DrawQuad>()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("green_alpha.png")), + FuzzyPixelOffByOneComparator(true))); +} + +TYPED_TEST(RendererPixelTest, PremultipliedTextureWithBackground) { + gfx::Rect rect(this->device_viewport_size_); + + RenderPass::Id id(1, 1); + scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); + + scoped_ptr<SharedQuadState> texture_quad_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + texture_quad_state->opacity = 0.5f; + + scoped_ptr<TextureDrawQuad> texture_quad = CreateTestTextureDrawQuad( + gfx::Rect(this->device_viewport_size_), + SK_ColorTRANSPARENT, // Texel color. + SK_ColorGREEN, // Background color. + true, // Premultiplied alpha. + texture_quad_state.get(), + this->resource_provider_.get()); + pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>()); + + scoped_ptr<SharedQuadState> color_quad_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create(); + color_quad->SetNew(color_quad_state.get(), rect, SK_ColorWHITE, false); + pass->quad_list.push_back(color_quad.PassAs<DrawQuad>()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("green_alpha.png")), + FuzzyPixelOffByOneComparator(true))); +} + +// TODO(skaslev): The software renderer does not support non-premultplied alpha. +TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithoutBackground) { + gfx::Rect rect(this->device_viewport_size_); + + RenderPass::Id id(1, 1); + scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); + + scoped_ptr<SharedQuadState> shared_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + + scoped_ptr<TextureDrawQuad> texture_quad = CreateTestTextureDrawQuad( + gfx::Rect(this->device_viewport_size_), + SkColorSetARGB(128, 0, 255, 0), // Texel color. + SK_ColorTRANSPARENT, // Background color. + false, // Premultiplied alpha. + shared_state.get(), + this->resource_provider_.get()); + pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>()); + + scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create(); + color_quad->SetNew(shared_state.get(), rect, SK_ColorWHITE, false); + pass->quad_list.push_back(color_quad.PassAs<DrawQuad>()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("green_alpha.png")), + FuzzyPixelOffByOneComparator(true))); +} + +// TODO(skaslev): The software renderer does not support non-premultplied alpha. +TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) { + gfx::Rect rect(this->device_viewport_size_); + + RenderPass::Id id(1, 1); + scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect); + + scoped_ptr<SharedQuadState> texture_quad_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + texture_quad_state->opacity = 0.5f; + + scoped_ptr<TextureDrawQuad> texture_quad = CreateTestTextureDrawQuad( + gfx::Rect(this->device_viewport_size_), + SK_ColorTRANSPARENT, // Texel color. + SK_ColorGREEN, // Background color. + false, // Premultiplied alpha. + texture_quad_state.get(), + this->resource_provider_.get()); + pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>()); + + scoped_ptr<SharedQuadState> color_quad_state = + CreateTestSharedQuadState(gfx::Transform(), rect); + scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create(); + color_quad->SetNew(color_quad_state.get(), rect, SK_ColorWHITE, false); + pass->quad_list.push_back(color_quad.PassAs<DrawQuad>()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("green_alpha.png")), + FuzzyPixelOffByOneComparator(true))); +} + class VideoGLRendererPixelTest : public GLRendererPixelTest { protected: scoped_ptr<YUVVideoDrawQuad> CreateTestYUVVideoDrawQuad( diff --git a/cc/output/shader.cc b/cc/output/shader.cc index a1637a1..df2c5dc 100644 --- a/cc/output/shader.cc +++ b/cc/output/shader.cc @@ -788,6 +788,68 @@ std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString( ); // NOLINT(whitespace/parens) } +FragmentTexBackgroundBinding::FragmentTexBackgroundBinding() + : background_color_location_(-1), + sampler_location_(-1) { +} + +void FragmentTexBackgroundBinding::Init(WebGraphicsContext3D* context, + unsigned program, + bool using_bind_uniform, + int* base_uniform_index) { + static const char* uniforms[] = { + "s_texture", + "background_color", + }; + int locations[arraysize(uniforms)]; + + GetProgramUniformLocations(context, + program, + arraysize(uniforms), + uniforms, + locations, + using_bind_uniform, + base_uniform_index); + + sampler_location_ = locations[0]; + DCHECK_NE(sampler_location_, -1); + + background_color_location_ = locations[1]; + DCHECK_NE(background_color_location_, -1); +} + +std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString( + TexCoordPrecision precision) const { + return FRAGMENT_SHADER( + precision mediump float; + varying TexCoordPrecision vec2 v_texCoord; + varying float v_alpha; + uniform vec4 background_color; + uniform sampler2D s_texture; + void main() { + vec4 texColor = texture2D(s_texture, v_texCoord); + texColor += background_color * (1.0 - texColor.a); + gl_FragColor = texColor * v_alpha; + } + ); // NOLINT(whitespace/parens) +} + +std::string FragmentShaderTexBackgroundPremultiplyAlpha::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; + texColor += background_color * (1.0 - 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 1037a83..7135bef 100644 --- a/cc/output/shader.h +++ b/cc/output/shader.h @@ -326,6 +326,7 @@ class FragmentTexOpaqueBinding { int* base_uniform_index); int alpha_location() const { return -1; } int fragment_tex_transform_location() const { return -1; } + int background_color_location() const { return -1; } int sampler_location() const { return sampler_location_; } private: @@ -334,6 +335,24 @@ class FragmentTexOpaqueBinding { DISALLOW_COPY_AND_ASSIGN(FragmentTexOpaqueBinding); }; +class FragmentTexBackgroundBinding { + public: + FragmentTexBackgroundBinding(); + + void Init(WebKit::WebGraphicsContext3D* context, + unsigned program, + bool using_bind_uniform, + int* base_uniform_index); + int background_color_location() const { return background_color_location_; } + int sampler_location() const { return sampler_location_; } + + private: + int background_color_location_; + int sampler_location_; + + DISALLOW_COPY_AND_ASSIGN(FragmentTexBackgroundBinding); +}; + class FragmentShaderRGBATexVaryingAlpha : public FragmentTexOpaqueBinding { public: std::string GetShaderString(TexCoordPrecision precision) const; @@ -344,6 +363,18 @@ class FragmentShaderRGBATexPremultiplyAlpha : public FragmentTexOpaqueBinding { std::string GetShaderString(TexCoordPrecision precision) const; }; +class FragmentShaderTexBackgroundVaryingAlpha + : public FragmentTexBackgroundBinding { + public: + std::string GetShaderString(TexCoordPrecision precision) const; +}; + +class FragmentShaderTexBackgroundPremultiplyAlpha + : public FragmentTexBackgroundBinding { + public: + std::string GetShaderString(TexCoordPrecision precision) const; +}; + class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding { public: std::string GetShaderString(TexCoordPrecision precision) const; @@ -355,7 +386,7 @@ class FragmentShaderRGBATexColorMatrixAlpha std::string GetShaderString(TexCoordPrecision precision) const; }; -class FragmentShaderRGBATexRectVaryingAlpha : public FragmentTexAlphaBinding { +class FragmentShaderRGBATexRectVaryingAlpha : public FragmentTexOpaqueBinding { public: std::string GetShaderString(TexCoordPrecision precision) const; }; diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index 817bb67..5c745c0 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc @@ -353,11 +353,31 @@ void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame, bitmap->width(), bitmap->height()); SkRect sk_uv_rect = gfx::RectFToSkRect(uv_rect); + SkRect quad_rect = gfx::RectFToSkRect(QuadVertexRect()); + if (quad->flipped) current_canvas_->scale(1, -1); - current_canvas_->drawBitmapRectToRect(*bitmap, &sk_uv_rect, - gfx::RectFToSkRect(QuadVertexRect()), + + bool blend_background = quad->background_color != SK_ColorTRANSPARENT && + !bitmap->isOpaque(); + bool needs_layer = blend_background && (current_paint_.getAlpha() != 0xFF); + if (needs_layer) { + current_canvas_->saveLayerAlpha(&quad_rect, current_paint_.getAlpha()); + current_paint_.setAlpha(0xFF); + } + if (blend_background) { + SkPaint background_paint; + background_paint.setColor(quad->background_color); + current_canvas_->drawRect(quad_rect, background_paint); + } + + current_canvas_->drawBitmapRectToRect(*bitmap, + &sk_uv_rect, + quad_rect, ¤t_paint_); + + if (needs_layer) + current_canvas_->restore(); } void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame, diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc index 333af3f..0ab0513 100644 --- a/cc/quads/draw_quad_unittest.cc +++ b/cc/quads/draw_quad_unittest.cc @@ -459,12 +459,13 @@ TEST(DrawQuadTest, CopyTextureDrawQuad) { bool flipped = true; CREATE_SHARED_STATE(); - CREATE_QUAD_7_NEW(TextureDrawQuad, + CREATE_QUAD_8_NEW(TextureDrawQuad, opaque_rect, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, copy_quad->material); @@ -476,11 +477,12 @@ TEST(DrawQuadTest, CopyTextureDrawQuad) { EXPECT_FLOAT_ARRAY_EQ(vertex_opacity, copy_quad->vertex_opacity, 4); EXPECT_EQ(flipped, copy_quad->flipped); - CREATE_QUAD_6_ALL(TextureDrawQuad, + CREATE_QUAD_7_ALL(TextureDrawQuad, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, copy_quad->material); @@ -521,19 +523,21 @@ TEST(DrawQuadTest, ClipTextureDrawQuad) { // This the vertex opacity for the vertices 'ABCD'. const float vertex_opacity[] = { 0.3f, 0.4f, 0.7f, 0.8f }; { - CREATE_QUAD_7_NEW(TextureDrawQuad, + CREATE_QUAD_8_NEW(TextureDrawQuad, opaque_rect, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); - CREATE_QUAD_6_ALL(TextureDrawQuad, + CREATE_QUAD_7_ALL(TextureDrawQuad, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); EXPECT_TRUE(quad_all->PerformClipping()); @@ -557,19 +561,21 @@ TEST(DrawQuadTest, ClipTextureDrawQuad) { uv_top_left = gfx::PointF(0.8f, 0.7f); uv_bottom_right = gfx::PointF(0.2f, 0.1f); { - CREATE_QUAD_7_NEW(TextureDrawQuad, + CREATE_QUAD_8_NEW(TextureDrawQuad, opaque_rect, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); - CREATE_QUAD_6_ALL(TextureDrawQuad, + CREATE_QUAD_7_ALL(TextureDrawQuad, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); EXPECT_TRUE(quad_all->PerformClipping()); @@ -821,12 +827,13 @@ TEST_F(DrawQuadIteratorTest, TextureDrawQuad) { bool flipped = true; CREATE_SHARED_STATE(); - CREATE_QUAD_7_NEW(TextureDrawQuad, + CREATE_QUAD_8_NEW(TextureDrawQuad, opaque_rect, resource_id, premultiplied_alpha, uv_top_left, uv_bottom_right, + SK_ColorTRANSPARENT, vertex_opacity, flipped); EXPECT_EQ(resource_id, quad_new->resource_id); diff --git a/cc/quads/texture_draw_quad.cc b/cc/quads/texture_draw_quad.cc index 04c9511..c894985 100644 --- a/cc/quads/texture_draw_quad.cc +++ b/cc/quads/texture_draw_quad.cc @@ -12,6 +12,7 @@ namespace cc { TextureDrawQuad::TextureDrawQuad() : resource_id(0), premultiplied_alpha(false), + background_color(SK_ColorTRANSPARENT), flipped(false) { this->vertex_opacity[0] = 0.f; this->vertex_opacity[1] = 0.f; @@ -28,7 +29,9 @@ void TextureDrawQuad::SetNew(const SharedQuadState* shared_quad_state, unsigned resource_id, bool premultiplied_alpha, gfx::PointF uv_top_left, gfx::PointF uv_bottom_right, - const float vertex_opacity[4], bool flipped) { + SkColor background_color, + const float vertex_opacity[4], + bool flipped) { gfx::Rect visible_rect = rect; bool needs_blending = vertex_opacity[0] != 1.0f || vertex_opacity[1] != 1.0f || vertex_opacity[2] != 1.0f || vertex_opacity[3] != 1.0f; @@ -38,6 +41,7 @@ void TextureDrawQuad::SetNew(const SharedQuadState* shared_quad_state, this->premultiplied_alpha = premultiplied_alpha; this->uv_top_left = uv_top_left; this->uv_bottom_right = uv_bottom_right; + this->background_color = background_color; this->vertex_opacity[0] = vertex_opacity[0]; this->vertex_opacity[1] = vertex_opacity[1]; this->vertex_opacity[2] = vertex_opacity[2]; @@ -51,13 +55,16 @@ void TextureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, unsigned resource_id, bool premultiplied_alpha, gfx::PointF uv_top_left, gfx::PointF uv_bottom_right, - const float vertex_opacity[4], bool flipped) { + SkColor background_color, + const float vertex_opacity[4], + bool flipped) { DrawQuad::SetAll(shared_quad_state, DrawQuad::TEXTURE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); this->resource_id = resource_id; this->premultiplied_alpha = premultiplied_alpha; this->uv_top_left = uv_top_left; this->uv_bottom_right = uv_bottom_right; + this->background_color = background_color; this->vertex_opacity[0] = vertex_opacity[0]; this->vertex_opacity[1] = vertex_opacity[1]; this->vertex_opacity[2] = vertex_opacity[2]; diff --git a/cc/quads/texture_draw_quad.h b/cc/quads/texture_draw_quad.h index 0b35568..3db10c6 100644 --- a/cc/quads/texture_draw_quad.h +++ b/cc/quads/texture_draw_quad.h @@ -23,6 +23,7 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad { bool premultiplied_alpha, gfx::PointF uv_top_left, gfx::PointF uv_bottom_right, + SkColor background_color, const float vertex_opacity[4], bool flipped); @@ -35,6 +36,7 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad { bool premultiplied_alpha, gfx::PointF uv_top_left, gfx::PointF uv_bottom_right, + SkColor background_color, const float vertex_opacity[4], bool flipped); @@ -42,6 +44,7 @@ class CC_EXPORT TextureDrawQuad : public DrawQuad { bool premultiplied_alpha; gfx::PointF uv_top_left; gfx::PointF uv_bottom_right; + SkColor background_color; float vertex_opacity[4]; bool flipped; diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc index 238c499..1807467 100644 --- a/cc/test/render_pass_test_common.cc +++ b/cc/test/render_pass_test_common.cc @@ -165,6 +165,7 @@ void TestRenderPass::AppendOneOfEveryQuadType( false, gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f), + SK_ColorTRANSPARENT, vertex_opacity, false); AppendQuad(texture_quad.PassAs<DrawQuad>()); diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc index 5ab3211..141f3af 100644 --- a/cc/trees/layer_tree_host_unittest_delegated.cc +++ b/cc/trees/layer_tree_host_unittest_delegated.cc @@ -54,6 +54,7 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { false, gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f), + SK_ColorTRANSPARENT, vertex_opacity, false); frame->render_pass_list[0]->shared_quad_state_list.push_back(sqs.Pass()); |