Skip to content

Commit

Permalink
Blend TextureLayer background-color at draw time.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alokp@chromium.org committed Jul 12, 2013
1 parent 92594aa commit d18b4d6
Show file tree
Hide file tree
Showing 26 changed files with 469 additions and 20 deletions.
1 change: 1 addition & 0 deletions cc/layers/heads_up_display_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 12 additions & 2 deletions cc/layers/nine_patch_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions cc/layers/scrollbar_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions cc/layers/texture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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_) {
Expand Down
5 changes: 5 additions & 0 deletions cc/layers/texture_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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_;

Expand Down
8 changes: 7 additions & 1 deletion cc/layers/texture_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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,
Expand All @@ -114,6 +119,7 @@ void TextureLayerImpl::AppendQuads(QuadSink* quad_sink,
premultiplied_alpha_,
uv_top_left_,
uv_bottom_right_,
bg_color,
vertex_opacity_,
flipped_);

Expand Down
4 changes: 4 additions & 0 deletions cc/layers/texture_layer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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_;
Expand Down
1 change: 1 addition & 0 deletions cc/layers/texture_layer_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions cc/layers/video_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
88 changes: 83 additions & 5 deletions cc/output/gl_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -1773,24 +1795,37 @@ 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;

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;
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -2914,13 +2984,21 @@ 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_);

if (texture_program_highp_)
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_);

Expand Down
Loading

0 comments on commit d18b4d6

Please sign in to comment.