diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-19 21:42:16 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-19 21:42:16 +0000 |
commit | 1786fddacd96f93155fd08b8fe66ef6dccc6af03 (patch) | |
tree | 6df38d314e7ac430e9aa02f83cfc9a0276bc6ece /cc | |
parent | a7f63260af23675ada6610db2bd77fabe662643e (diff) | |
download | chromium_src-1786fddacd96f93155fd08b8fe66ef6dccc6af03.zip chromium_src-1786fddacd96f93155fd08b8fe66ef6dccc6af03.tar.gz chromium_src-1786fddacd96f93155fd08b8fe66ef6dccc6af03.tar.bz2 |
cc: Prevent overlapping picture playback
BUG=345736
Review URL: https://codereview.chromium.org/189403007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258110 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/resources/picture_pile_impl.cc | 48 | ||||
-rw-r--r-- | cc/resources/picture_pile_impl_unittest.cc | 65 |
2 files changed, 107 insertions, 6 deletions
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index 55a394f..8776895 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc @@ -156,6 +156,13 @@ void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect, gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( content_rect, 1.f / contents_scale); + // Make sure pictures don't overlap by keeping track of previous right/bottom. + int min_content_left = -1; + int min_content_top = -1; + int last_row_index = -1; + int last_col_index = -1; + gfx::Rect last_content_rect; + // Coalesce rasters of the same picture into different rects: // - Compute the clip of each of the pile chunks, // - Subtract it from the canvas rect to get difference region @@ -195,16 +202,43 @@ void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect, << "Contents scale: " << contents_scale; content_clip.Intersect(canvas_rect); + // Make sure iterator goes top->bottom. + DCHECK_GE(tile_iter.index_y(), last_row_index); + if (tile_iter.index_y() > last_row_index) { + // First tile in a new row. + min_content_left = content_clip.x(); + min_content_top = last_content_rect.bottom(); + } else { + // Make sure iterator goes left->right. + DCHECK_GT(tile_iter.index_x(), last_col_index); + min_content_left = last_content_rect.right(); + min_content_top = last_content_rect.y(); + } + + last_col_index = tile_iter.index_x(); + last_row_index = tile_iter.index_y(); + + // Only inset if the content_clip is less than then previous min. + int inset_left = std::max(0, min_content_left - content_clip.x()); + int inset_top = std::max(0, min_content_top - content_clip.y()); + content_clip.Inset(inset_left, inset_top, 0, 0); + PictureRegionMap::iterator it = results->find(picture); + Region* clip_region; if (it == results->end()) { - Region& region = (*results)[picture]; - region = content_rect; - region.Subtract(content_clip); - continue; + // The clip for a set of coalesced pictures starts out clipping the entire + // canvas. Each picture added to the set must subtract its own bounds + // from the clip region, poking a hole so that the picture is unclipped. + clip_region = &(*results)[picture]; + *clip_region = canvas_rect; + } else { + clip_region = &it->second; } - Region& region = it->second; - region.Subtract(content_clip); + DCHECK(clip_region->Contains(content_clip)) + << "Content clips should not overlap."; + clip_region->Subtract(content_clip); + last_content_rect = content_clip; } } @@ -246,6 +280,8 @@ void PicturePileImpl::RasterCommon( #ifndef NDEBUG Region positive_clip = content_rect; positive_clip.Subtract(negated_clip_region); + // Make sure we never rasterize the same region twice. + DCHECK(!total_clip.Intersects(positive_clip)); total_clip.Union(positive_clip); #endif // NDEBUG diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc index 5f144ad..75cb11d 100644 --- a/cc/resources/picture_pile_impl_unittest.cc +++ b/cc/resources/picture_pile_impl_unittest.cc @@ -743,5 +743,70 @@ TEST(PicturePileImpl, RasterContentsTransparent) { } } +class OverlapTest : public ::testing::TestWithParam<float> { + public: + static float MinContentsScale() { return 1.f / 4.f; } +}; + +TEST_P(OverlapTest, NoOverlap) { + gfx::Size tile_size(10, 10); + gfx::Size layer_bounds(30, 30); + gfx::Size bigger_than_layer_bounds(300, 300); + float contents_scale = GetParam(); + // Pick an opaque color to not have to deal with premultiplication off-by-one. + SkColor test_color = SkColorSetARGB(255, 45, 56, 67); + + scoped_refptr<FakePicturePileImpl> pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + pile->set_background_color(SK_ColorTRANSPARENT); + pile->set_contents_opaque(false); + pile->SetMinContentsScale(MinContentsScale()); + pile->set_clear_canvas_with_debug_color(true); + SkPaint color_paint; + color_paint.setColor(test_color); + // Additive paint, so that if two paints overlap, the color will change. + color_paint.setXfermodeMode(SkXfermode::kPlus_Mode); + // Paint outside the layer to make sure that blending works. + pile->add_draw_rect_with_paint(gfx::RectF(bigger_than_layer_bounds), + color_paint); + pile->RerecordPile(); + + gfx::Size content_bounds( + gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale))); + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + content_bounds.width(), + content_bounds.height()); + bitmap.allocPixels(); + SkCanvas canvas(bitmap); + + FakeRenderingStatsInstrumentation rendering_stats_instrumentation; + pile->RasterToBitmap(&canvas, + gfx::Rect(content_bounds), + contents_scale, + &rendering_stats_instrumentation); + + for (int y = 0; y < bitmap.height(); y++) { + for (int x = 0; x < bitmap.width(); x++) { + SkColor color = bitmap.getColor(x, y); + EXPECT_EQ(SkColorGetR(test_color), SkColorGetR(color)) << "x: " << x + << ", y: " << y; + EXPECT_EQ(SkColorGetG(test_color), SkColorGetG(color)) << "x: " << x + << ", y: " << y; + EXPECT_EQ(SkColorGetB(test_color), SkColorGetB(color)) << "x: " << x + << ", y: " << y; + EXPECT_EQ(SkColorGetA(test_color), SkColorGetA(color)) << "x: " << x + << ", y: " << y; + if (test_color != color) + break; + } + } +} + +INSTANTIATE_TEST_CASE_P(PicturePileImpl, + OverlapTest, + ::testing::Values(1.f, 0.873f, 1.f / 4.f, 4.f)); + } // namespace } // namespace cc |