summaryrefslogtreecommitdiffstats
path: root/cc/output
diff options
context:
space:
mode:
authorjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-27 10:41:53 +0000
committerjbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-27 10:41:53 +0000
commit1d5b954b54e147d0b5a205894c1bf3c3e4c0f205 (patch)
tree039bbc90b9ebb757201e13af22701320efe2f7f9 /cc/output
parentf526d4dc7af3965969aeb02f328a181538c1bf4f (diff)
downloadchromium_src-1d5b954b54e147d0b5a205894c1bf3c3e4c0f205.zip
chromium_src-1d5b954b54e147d0b5a205894c1bf3c3e4c0f205.tar.gz
chromium_src-1d5b954b54e147d0b5a205894c1bf3c3e4c0f205.tar.bz2
Don't draw invisible portions of quads in software renderer.
The software renderer should only try to draw portions of quads that are within visible_rect, which will reduce overdraw in the browser compositor. BUG=276069 Review URL: https://chromiumcodereview.appspot.com/22815022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219763 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/output')
-rw-r--r--cc/output/gl_renderer.cc19
-rw-r--r--cc/output/software_renderer.cc36
-rw-r--r--cc/output/software_renderer_unittest.cc138
3 files changed, 168 insertions, 25 deletions
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 368ae77..c829c16 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -1323,20 +1323,11 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
ResourceProvider::ResourceId resource_id) {
gfx::Rect tile_rect = quad->visible_rect;
- gfx::RectF tex_coord_rect = quad->tex_coord_rect;
- float tex_to_geom_scale_x = quad->rect.width() / tex_coord_rect.width();
- float tex_to_geom_scale_y = quad->rect.height() / tex_coord_rect.height();
-
- // tex_coord_rect corresponds to quad_rect, but quad_visible_rect may be
- // smaller than quad_rect due to occlusion or clipping. Adjust
- // tex_coord_rect to match.
- gfx::Vector2d top_left_diff = tile_rect.origin() - quad->rect.origin();
- gfx::Vector2d bottom_right_diff =
- tile_rect.bottom_right() - quad->rect.bottom_right();
- tex_coord_rect.Inset(top_left_diff.x() / tex_to_geom_scale_x,
- top_left_diff.y() / tex_to_geom_scale_y,
- -bottom_right_diff.x() / tex_to_geom_scale_x,
- -bottom_right_diff.y() / tex_to_geom_scale_y);
+ gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional(
+ quad->tex_coord_rect, quad->rect, tile_rect);
+ float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width();
+ float tex_to_geom_scale_y =
+ quad->rect.height() / quad->tex_coord_rect.height();
gfx::RectF clamp_geom_rect(tile_rect);
gfx::RectF clamp_tex_rect(tex_coord_rect);
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index ed5c18b..7054fd5 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -277,9 +277,11 @@ void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) {
void SoftwareRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
const CheckerboardDrawQuad* quad) {
+ gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
+ QuadVertexRect(), quad->rect, quad->visible_rect);
current_paint_.setColor(quad->color);
current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color));
- current_canvas_->drawRect(gfx::RectFToSkRect(QuadVertexRect()),
+ current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect),
current_paint_);
}
@@ -336,9 +338,11 @@ void SoftwareRenderer::DrawPictureQuad(const DrawingFrame* frame,
void SoftwareRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
const SolidColorDrawQuad* quad) {
+ gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
+ QuadVertexRect(), quad->rect, quad->visible_rect);
current_paint_.setColor(quad->color);
current_paint_.setAlpha(quad->opacity() * SkColorGetA(quad->color));
- current_canvas_->drawRect(gfx::RectFToSkRect(QuadVertexRect()),
+ current_canvas_->drawRect(gfx::RectFToSkRect(visible_quad_vertex_rect),
current_paint_);
}
@@ -357,8 +361,12 @@ void SoftwareRenderer::DrawTextureQuad(const DrawingFrame* frame,
quad->uv_bottom_right),
bitmap->width(),
bitmap->height());
- SkRect sk_uv_rect = gfx::RectFToSkRect(uv_rect);
- SkRect quad_rect = gfx::RectFToSkRect(QuadVertexRect());
+ gfx::RectF visible_uv_rect =
+ MathUtil::ScaleRectProportional(uv_rect, quad->rect, quad->visible_rect);
+ SkRect sk_uv_rect = gfx::RectFToSkRect(visible_uv_rect);
+ gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
+ QuadVertexRect(), quad->rect, quad->visible_rect);
+ SkRect quad_rect = gfx::RectFToSkRect(visible_quad_vertex_rect);
if (quad->flipped)
current_canvas_->scale(1, -1);
@@ -391,12 +399,18 @@ void SoftwareRenderer::DrawTileQuad(const DrawingFrame* frame,
DCHECK(IsSoftwareResource(quad->resource_id));
ResourceProvider::ScopedReadLockSoftware lock(resource_provider_,
quad->resource_id);
+ gfx::RectF visible_tex_coord_rect = MathUtil::ScaleRectProportional(
+ quad->tex_coord_rect, quad->rect, quad->visible_rect);
+ gfx::RectF visible_quad_vertex_rect = MathUtil::ScaleRectProportional(
+ QuadVertexRect(), quad->rect, quad->visible_rect);
- SkRect uv_rect = gfx::RectFToSkRect(quad->tex_coord_rect);
+ SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect);
current_paint_.setFilterBitmap(true);
- current_canvas_->drawBitmapRectToRect(*lock.sk_bitmap(), &uv_rect,
- gfx::RectFToSkRect(QuadVertexRect()),
- &current_paint_);
+ current_canvas_->drawBitmapRectToRect(
+ *lock.sk_bitmap(),
+ &uv_rect,
+ gfx::RectFToSkRect(visible_quad_vertex_rect),
+ &current_paint_);
}
void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
@@ -411,6 +425,8 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
content_texture->id());
SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect());
+ SkRect dest_visible_rect = gfx::RectFToSkRect(MathUtil::ScaleRectProportional(
+ QuadVertexRect(), quad->rect, quad->visible_rect));
SkRect content_rect = SkRect::MakeWH(quad->rect.width(), quad->rect.height());
SkMatrix content_mat;
@@ -458,10 +474,10 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame,
mask_rasterizer->addLayer(mask_paint);
current_paint_.setRasterizer(mask_rasterizer.get());
- current_canvas_->drawRect(dest_rect, current_paint_);
+ current_canvas_->drawRect(dest_visible_rect, current_paint_);
} else {
// TODO(skaslev): Apply background filters and blend with content
- current_canvas_->drawRect(dest_rect, current_paint_);
+ current_canvas_->drawRect(dest_visible_rect, current_paint_);
}
}
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index a3361a9..e85c02a 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -92,6 +92,7 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
gfx::Size inner_size(98, 98);
gfx::Rect outer_rect(outer_size);
gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
+ gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
set_viewport(gfx::Rect(outer_size));
InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
@@ -108,6 +109,7 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
shared_quad_state.get(), outer_rect, SK_ColorYELLOW, false);
scoped_ptr<SolidColorDrawQuad> inner_quad = SolidColorDrawQuad::Create();
inner_quad->SetNew(shared_quad_state.get(), inner_rect, SK_ColorCYAN, false);
+ inner_quad->visible_rect = visible_rect;
root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
@@ -125,7 +127,8 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
EXPECT_EQ(SK_ColorYELLOW,
output.getColor(outer_size.width() - 1, outer_size.height() - 1));
- EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 1));
+ EXPECT_EQ(SK_ColorYELLOW, output.getColor(1, 1));
+ EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 2));
EXPECT_EQ(SK_ColorCYAN,
output.getColor(inner_size.width() - 1, inner_size.height() - 1));
}
@@ -216,6 +219,85 @@ TEST_F(SoftwareRendererTest, TileQuad) {
output.getColor(inner_size.width() - 1, inner_size.height() - 1));
}
+TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
+ gfx::Size tile_size(100, 100);
+ gfx::Rect tile_rect(tile_size);
+ gfx::Rect visible_rect = tile_rect;
+ visible_rect.Inset(1, 2, 3, 4);
+ set_viewport(gfx::Rect(tile_size));
+ InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
+
+ ResourceProvider::ResourceId resource_cyan =
+ resource_provider()->CreateResource(
+ tile_size, GL_RGBA, ResourceProvider::TextureUsageAny);
+
+ SkBitmap cyan_tile; // The lowest five rows are yellow.
+ cyan_tile.setConfig(
+ SkBitmap::kARGB_8888_Config, tile_size.width(), tile_size.height());
+ cyan_tile.allocPixels();
+ cyan_tile.eraseColor(SK_ColorCYAN);
+ cyan_tile.eraseArea(
+ SkIRect::MakeLTRB(
+ 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
+ SK_ColorYELLOW);
+
+ resource_provider()->SetPixels(resource_cyan,
+ static_cast<uint8_t*>(cyan_tile.getPixels()),
+ gfx::Rect(tile_size),
+ gfx::Rect(tile_size),
+ gfx::Vector2d());
+
+ gfx::Rect root_rect = DeviceViewport();
+
+ scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
+ shared_quad_state->SetAll(
+ gfx::Transform(), tile_size, tile_rect, tile_rect, false, 1.0);
+ RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
+ scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
+ root_render_pass->SetNew(
+ root_render_pass_id, root_rect, root_rect, gfx::Transform());
+ scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
+ quad->SetNew(shared_quad_state.get(),
+ tile_rect,
+ tile_rect,
+ resource_cyan,
+ gfx::RectF(tile_size),
+ tile_size,
+ false);
+ quad->visible_rect = visible_rect;
+ root_render_pass->AppendQuad(quad.PassAs<DrawQuad>());
+
+ RenderPassList list;
+ list.push_back(root_render_pass.PassAs<RenderPass>());
+ renderer()->DrawFrame(&list);
+
+ SkBitmap output;
+ output.setConfig(SkBitmap::kARGB_8888_Config,
+ DeviceViewport().width(),
+ DeviceViewport().height());
+ output.allocPixels();
+ renderer()->GetFramebufferPixels(output.getPixels(), tile_rect);
+
+ // Check portion of tile not in visible rect isn't drawn.
+ const unsigned int kTransparent = SK_ColorTRANSPARENT;
+ EXPECT_EQ(kTransparent, output.getColor(0, 0));
+ EXPECT_EQ(kTransparent,
+ output.getColor(tile_rect.width() - 1, tile_rect.height() - 1));
+ EXPECT_EQ(kTransparent,
+ output.getColor(visible_rect.x() - 1, visible_rect.y() - 1));
+ EXPECT_EQ(kTransparent,
+ output.getColor(visible_rect.right(), visible_rect.bottom()));
+ // Ensure visible part is drawn correctly.
+ EXPECT_EQ(SK_ColorCYAN, output.getColor(visible_rect.x(), visible_rect.y()));
+ EXPECT_EQ(
+ SK_ColorCYAN,
+ output.getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
+ // Ensure last visible line is correct.
+ EXPECT_EQ(
+ SK_ColorYELLOW,
+ output.getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
+}
+
TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
gfx::Rect viewport_rect(0, 0, 100, 100);
set_viewport(viewport_rect);
@@ -270,5 +352,59 @@ TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
output.getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
}
+TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
+ gfx::Rect viewport_rect(0, 0, 100, 100);
+ set_viewport(viewport_rect);
+ InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
+
+ RenderPassList list;
+
+ SkBitmap output;
+ output.setConfig(SkBitmap::kARGB_8888_Config,
+ viewport_rect.width(),
+ viewport_rect.height());
+ output.allocPixels();
+
+ // Pass drawn as inner quad is magenta.
+ gfx::Rect smaller_rect(20, 20, 60, 60);
+ RenderPass::Id smaller_pass_id(2, 1);
+ TestRenderPass* smaller_pass =
+ AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
+ AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
+
+ // Root pass is green.
+ RenderPass::Id root_clear_pass_id(1, 0);
+ TestRenderPass* root_clear_pass =
+ AddRenderPass(&list, root_clear_pass_id, viewport_rect, gfx::Transform());
+ AddRenderPassQuad(root_clear_pass, smaller_pass);
+ AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
+
+ // Interior pass quad has smaller visible rect.
+ gfx::Rect interior_visible_rect(30, 30, 40, 40);
+ root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect;
+
+ renderer()->DecideRenderPassAllocationsForFrame(list);
+ renderer()->DrawFrame(&list);
+ renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
+
+ EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
+ EXPECT_EQ(
+ SK_ColorGREEN,
+ output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
+
+ // Part outside visible rect should remain green.
+ EXPECT_EQ(SK_ColorGREEN, output.getColor(smaller_rect.x(), smaller_rect.y()));
+ EXPECT_EQ(
+ SK_ColorGREEN,
+ output.getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
+
+ EXPECT_EQ(
+ SK_ColorMAGENTA,
+ output.getColor(interior_visible_rect.x(), interior_visible_rect.y()));
+ EXPECT_EQ(SK_ColorMAGENTA,
+ output.getColor(interior_visible_rect.right() - 1,
+ interior_visible_rect.bottom() - 1));
+}
+
} // namespace
} // namespace cc