summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-22 18:53:18 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-22 18:53:18 +0000
commitb7d57217eda14c6415522b74bf9c6b6089fb3b61 (patch)
treef94c17347e0415b43e013f4da72a069f5a0894e9
parent66b31f81a284cf3f2936585d43e8d3bcb9ac6119 (diff)
downloadchromium_src-b7d57217eda14c6415522b74bf9c6b6089fb3b61.zip
chromium_src-b7d57217eda14c6415522b74bf9c6b6089fb3b61.tar.gz
chromium_src-b7d57217eda14c6415522b74bf9c6b6089fb3b61.tar.bz2
cc: Fix missing compositor invalidations during resize
In practice, cc is responsible for implicit invalidations on layers, such as the original layer being entirely invalid or new areas being exposed during resize. In this case, these invalidations were being clipped to the live tiles rect, which itself is clipped to the bounds of the tiling. Therefore, when the bounds of a layer grew, the new invalidation intersected with the old bounds was empty. The intersection of invalidations with the live tiles rect is an optimization, to prevent needless work trying to look up invalidations on parts of the layer that don't matter. To fix the bug, rather than intersecting with the live tiles rect, expand the live tiles rect to tile boundaries. This lets implicit invalidation due to resize within a tile not skip rerasterizing that tile. BUG=357120 Review URL: https://codereview.chromium.org/240593004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@265313 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/base/tiling_data.cc17
-rw-r--r--cc/base/tiling_data.h2
-rw-r--r--cc/base/tiling_data_unittest.cc71
-rw-r--r--cc/resources/picture_layer_tiling.cc6
-rw-r--r--cc/resources/picture_layer_tiling_unittest.cc17
5 files changed, 112 insertions, 1 deletions
diff --git a/cc/base/tiling_data.cc b/cc/base/tiling_data.cc
index af581ff..a52c940 100644
--- a/cc/base/tiling_data.cc
+++ b/cc/base/tiling_data.cc
@@ -138,6 +138,23 @@ int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const {
return std::min(std::max(y, 0), num_tiles_y_ - 1);
}
+gfx::Rect TilingData::ExpandRectToTileBoundsWithBorders(
+ const gfx::Rect rect) const {
+ if (!rect.Intersects(tiling_rect_) || has_empty_bounds())
+ return gfx::Rect();
+ int index_x = FirstBorderTileXIndexFromSrcCoord(rect.x());
+ int index_y = FirstBorderTileYIndexFromSrcCoord(rect.y());
+ int index_right = LastBorderTileXIndexFromSrcCoord(rect.right());
+ int index_bottom = LastBorderTileYIndexFromSrcCoord(rect.bottom());
+
+ gfx::Rect rect_top_left(TileBoundsWithBorder(index_x, index_y));
+ gfx::Rect rect_bottom_right(TileBoundsWithBorder(index_right, index_bottom));
+
+ gfx::Rect expanded(rect_top_left);
+ expanded.Union(rect_bottom_right);
+ return expanded;
+}
+
gfx::Rect TilingData::TileBounds(int i, int j) const {
AssertTile(i, j);
int max_texture_size_x = max_texture_size_.width() - 2 * border_texels_;
diff --git a/cc/base/tiling_data.h b/cc/base/tiling_data.h
index 27ec034..3059c21 100644
--- a/cc/base/tiling_data.h
+++ b/cc/base/tiling_data.h
@@ -52,6 +52,8 @@ class CC_EXPORT TilingData {
int LastBorderTileXIndexFromSrcCoord(int src_position) const;
int LastBorderTileYIndexFromSrcCoord(int src_position) const;
+ gfx::Rect ExpandRectToTileBoundsWithBorders(const gfx::Rect rect) const;
+
gfx::Rect TileBounds(int i, int j) const;
gfx::Rect TileBoundsWithBorder(int i, int j) const;
int TilePositionX(int x_index) const;
diff --git a/cc/base/tiling_data_unittest.cc b/cc/base/tiling_data_unittest.cc
index 1563b02..fd0809d 100644
--- a/cc/base/tiling_data_unittest.cc
+++ b/cc/base/tiling_data_unittest.cc
@@ -2133,6 +2133,77 @@ TEST_P(TilingDataTest, SetMaxTextureSizeBorders) {
EXPECT_EQ(10, data.num_tiles_y());
}
+TEST_P(TilingDataTest, ExpandRectToTileBoundsWithBordersEmpty) {
+ gfx::Point origin = GetParam();
+ TilingData empty_total_size(
+ gfx::Size(0, 0), gfx::Rect(origin, gfx::Size(8, 8)), true);
+ EXPECT_RECT_EQ(
+ gfx::Rect(),
+ empty_total_size.ExpandRectToTileBoundsWithBorders(gfx::Rect()));
+ EXPECT_RECT_EQ(gfx::Rect(),
+ empty_total_size.ExpandRectToTileBoundsWithBorders(
+ gfx::Rect(100, 100, 100, 100)));
+ EXPECT_RECT_EQ(gfx::Rect(),
+ empty_total_size.ExpandRectToTileBoundsWithBorders(
+ gfx::Rect(0, 0, 100, 100)));
+
+ TilingData empty_max_texture_size(
+ gfx::Size(8, 8), gfx::Rect(origin, gfx::Size(0, 0)), true);
+ EXPECT_RECT_EQ(
+ gfx::Rect(),
+ empty_max_texture_size.ExpandRectToTileBoundsWithBorders(gfx::Rect()));
+ EXPECT_RECT_EQ(gfx::Rect(),
+ empty_max_texture_size.ExpandRectToTileBoundsWithBorders(
+ gfx::Rect(100, 100, 100, 100)));
+ EXPECT_RECT_EQ(gfx::Rect(),
+ empty_max_texture_size.ExpandRectToTileBoundsWithBorders(
+ gfx::Rect(0, 0, 100, 100)));
+}
+
+TEST_P(TilingDataTest, ExpandRectToTileBoundsWithBorders) {
+ gfx::Point origin = GetParam();
+ TilingData data(gfx::Size(4, 4), gfx::Rect(origin, gfx::Size(16, 32)), true);
+
+ // Small rect at origin rounds up to tile 0, 0.
+ gfx::Rect at_origin_src(origin, gfx::Size(1, 1));
+ gfx::Rect at_origin_result(data.TileBoundsWithBorder(0, 0));
+ EXPECT_NE(at_origin_src, at_origin_result);
+ EXPECT_RECT_EQ(at_origin_result,
+ data.ExpandRectToTileBoundsWithBorders(at_origin_src));
+
+ // Arbitrary internal rect.
+ gfx::Rect rect_src(origin.x() + 6, origin.y() + 6, 1, 3);
+ // Tile 2, 2 => gfx::Rect(4, 4, 4, 4)
+ // Tile 3, 4 => gfx::Rect(6, 8, 4, 4)
+ gfx::Rect rect_result(gfx::UnionRects(data.TileBoundsWithBorder(2, 2),
+ data.TileBoundsWithBorder(3, 4)));
+ EXPECT_NE(rect_src, rect_result);
+ EXPECT_RECT_EQ(rect_result, data.ExpandRectToTileBoundsWithBorders(rect_src));
+
+ // On tile bounds rounds up to next tile (since border overlaps).
+ gfx::Rect border_rect_src(
+ gfx::UnionRects(data.TileBounds(1, 2), data.TileBounds(3, 4)));
+ gfx::Rect border_rect_result(gfx::UnionRects(
+ data.TileBoundsWithBorder(0, 1), data.TileBoundsWithBorder(4, 5)));
+ EXPECT_RECT_EQ(border_rect_result,
+ data.ExpandRectToTileBoundsWithBorders(border_rect_src));
+
+ // Equal to tiling rect.
+ EXPECT_RECT_EQ(data.tiling_rect(),
+ data.ExpandRectToTileBoundsWithBorders(data.tiling_rect()));
+
+ // Containing, but larger than tiling rect.
+ EXPECT_RECT_EQ(data.tiling_rect(),
+ data.ExpandRectToTileBoundsWithBorders(
+ gfx::Rect(origin, gfx::Size(100, 100))));
+
+ // Non-intersecting with tiling rect.
+ gfx::Rect non_intersect(origin.x() + 200, origin.y() + 200, 100, 100);
+ EXPECT_FALSE(non_intersect.Intersects(data.tiling_rect()));
+ EXPECT_RECT_EQ(gfx::Rect(),
+ data.ExpandRectToTileBoundsWithBorders(non_intersect));
+}
+
TEST_P(TilingDataTest, Assignment) {
gfx::Point origin = GetParam();
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index d2a732d..a3664e7 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -189,11 +189,15 @@ void PictureLayerTiling::Invalidate(const Region& layer_region) {
void PictureLayerTiling::DoInvalidate(const Region& layer_region,
bool recreate_tiles) {
std::vector<TileMapKey> new_tile_keys;
+ gfx::Rect expanded_live_tiles_rect(
+ tiling_data_.ExpandRectToTileBoundsWithBorders(live_tiles_rect_));
for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) {
gfx::Rect layer_rect = iter.rect();
gfx::Rect content_rect =
gfx::ScaleToEnclosingRect(layer_rect, contents_scale_);
- content_rect.Intersect(live_tiles_rect_);
+ // Avoid needless work by not bothering to invalidate where there aren't
+ // tiles.
+ content_rect.Intersect(expanded_live_tiles_rect);
if (content_rect.IsEmpty())
continue;
bool include_borders = true;
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc
index 976ed6b..e1eddd7 100644
--- a/cc/resources/picture_layer_tiling_unittest.cc
+++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -173,6 +173,23 @@ class PictureLayerTilingIteratorTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingIteratorTest);
};
+TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) {
+ // Verifies that a resize deletes tiles that used to be on the edge.
+ gfx::Size tile_size(100, 100);
+ gfx::Size original_layer_size(10, 10);
+ Initialize(tile_size, 1.f, original_layer_size);
+ SetLiveRectAndVerifyTiles(gfx::Rect(original_layer_size));
+
+ // Tiling only has one tile, since its total size is less than one.
+ EXPECT_TRUE(tiling_->TileAt(0, 0));
+
+ // Stop creating tiles so that any invalidations are left as holes.
+ client_.set_allow_create_tile(false);
+
+ tiling_->SetLayerBounds(gfx::Size(200, 200));
+ EXPECT_FALSE(tiling_->TileAt(0, 0));
+}
+
TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) {
Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801));
SetLiveRectAndVerifyTiles(gfx::Rect(100, 100));