diff options
author | jbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-27 10:41:53 +0000 |
---|---|---|
committer | jbauman@chromium.org <jbauman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-27 10:41:53 +0000 |
commit | 1d5b954b54e147d0b5a205894c1bf3c3e4c0f205 (patch) | |
tree | 039bbc90b9ebb757201e13af22701320efe2f7f9 /cc/output | |
parent | f526d4dc7af3965969aeb02f328a181538c1bf4f (diff) | |
download | chromium_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.cc | 19 | ||||
-rw-r--r-- | cc/output/software_renderer.cc | 36 | ||||
-rw-r--r-- | cc/output/software_renderer_unittest.cc | 138 |
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()), - ¤t_paint_); + current_canvas_->drawBitmapRectToRect( + *lock.sk_bitmap(), + &uv_rect, + gfx::RectFToSkRect(visible_quad_vertex_rect), + ¤t_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 |