summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-19 21:42:16 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-19 21:42:16 +0000
commit1786fddacd96f93155fd08b8fe66ef6dccc6af03 (patch)
tree6df38d314e7ac430e9aa02f83cfc9a0276bc6ece /cc
parenta7f63260af23675ada6610db2bd77fabe662643e (diff)
downloadchromium_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.cc48
-rw-r--r--cc/resources/picture_pile_impl_unittest.cc65
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