From 8f322ba0e048d54343148cbaa1e0626063e67d65 Mon Sep 17 00:00:00 2001 From: "danakj@chromium.org" Date: Wed, 18 Jun 2014 23:48:18 +0000 Subject: cc: Expand invalidation to full tile when recording is missing for the tile. Currently we do a walk over all tiles in the pending tree's pile, but there can be 1 million x 1 million tiles on some pages, which makes this method take multiple _seconds_ to complete. These loops were added in r184525 which gave the tradeoffs that led to them, which are that we want to only use a single pile for all the tiles on this layer, but we don't want raster tiles on the active layer (when this activates) that can't be rastered by the pile they are attached to. Instead of walking every pile-tile, to find the tiles that are not present in the current recording and invalidate them, we expand invalidations outside the interest rect to cover the full recording tiles, and we expand invalidation inside the interest rect to include any raster tiles that don't have a recording (such as in the offscreen animating gif case). We give this expanded invalidation to the pending layer, causing it to drop rastered tiles from the active tree that intersect with an unrecorded area. R=enne BUG=371839 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=277964 Review URL: https://codereview.chromium.org/294163009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278196 0039d316-1c4b-4281-b951-d872f2087c98 --- cc/base/tiling_data.cc | 24 ++++++++++++----- cc/base/tiling_data.h | 3 ++- cc/base/tiling_data_unittest.cc | 60 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 7 deletions(-) (limited to 'cc/base') diff --git a/cc/base/tiling_data.cc b/cc/base/tiling_data.cc index a52c940..185bbed 100644 --- a/cc/base/tiling_data.cc +++ b/cc/base/tiling_data.cc @@ -139,20 +139,32 @@ int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const { } gfx::Rect TilingData::ExpandRectToTileBoundsWithBorders( - const gfx::Rect rect) const { + 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()); + int index_right = LastBorderTileXIndexFromSrcCoord(rect.right() - 1); + int index_bottom = LastBorderTileYIndexFromSrcCoord(rect.bottom() - 1); 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; + return gfx::UnionRects(rect_top_left, rect_bottom_right); +} + +gfx::Rect TilingData::ExpandRectToTileBounds(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() - 1); + int index_bottom = LastBorderTileYIndexFromSrcCoord(rect.bottom() - 1); + + gfx::Rect rect_top_left(TileBounds(index_x, index_y)); + gfx::Rect rect_bottom_right(TileBounds(index_right, index_bottom)); + + return gfx::UnionRects(rect_top_left, rect_bottom_right); } gfx::Rect TilingData::TileBounds(int i, int j) const { diff --git a/cc/base/tiling_data.h b/cc/base/tiling_data.h index 3059c21..8550e5f 100644 --- a/cc/base/tiling_data.h +++ b/cc/base/tiling_data.h @@ -52,7 +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 ExpandRectToTileBoundsWithBorders(const gfx::Rect& rect) const; + gfx::Rect ExpandRectToTileBounds(const gfx::Rect& rect) const; gfx::Rect TileBounds(int i, int j) const; gfx::Rect TileBoundsWithBorder(int i, int j) const; diff --git a/cc/base/tiling_data_unittest.cc b/cc/base/tiling_data_unittest.cc index fd0809d..84d9e79 100644 --- a/cc/base/tiling_data_unittest.cc +++ b/cc/base/tiling_data_unittest.cc @@ -2202,6 +2202,66 @@ TEST_P(TilingDataTest, ExpandRectToTileBoundsWithBorders) { EXPECT_FALSE(non_intersect.Intersects(data.tiling_rect())); EXPECT_RECT_EQ(gfx::Rect(), data.ExpandRectToTileBoundsWithBorders(non_intersect)); + + TilingData data2(gfx::Size(8, 8), gfx::Rect(origin, gfx::Size(32, 64)), true); + + // Inside other tile border texels doesn't include other tiles. + gfx::Rect inner_rect_src(data2.TileBounds(1, 1)); + inner_rect_src.Inset(data2.border_texels(), data.border_texels()); + gfx::Rect inner_rect_result(data2.TileBoundsWithBorder(1, 1)); + gfx::Rect expanded = data2.ExpandRectToTileBoundsWithBorders(inner_rect_src); + EXPECT_EQ(inner_rect_result.ToString(), expanded.ToString()); +} + +TEST_P(TilingDataTest, ExpandRectToTileBounds) { + 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.TileBounds(0, 0)); + EXPECT_NE(at_origin_src, at_origin_result); + EXPECT_RECT_EQ(at_origin_result, data.ExpandRectToTileBounds(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.TileBounds(2, 2), data.TileBounds(3, 4))); + EXPECT_NE(rect_src, rect_result); + EXPECT_RECT_EQ(rect_result, data.ExpandRectToTileBounds(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.TileBounds(0, 1), data.TileBounds(4, 5))); + EXPECT_RECT_EQ(border_rect_result, + data.ExpandRectToTileBounds(border_rect_src)); + + // Equal to tiling rect. + EXPECT_RECT_EQ(data.tiling_rect(), + data.ExpandRectToTileBounds(data.tiling_rect())); + + // Containing, but larger than tiling rect. + EXPECT_RECT_EQ( + data.tiling_rect(), + data.ExpandRectToTileBounds(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.ExpandRectToTileBounds(non_intersect)); + + TilingData data2(gfx::Size(8, 8), gfx::Rect(origin, gfx::Size(32, 64)), true); + + // Inside other tile border texels doesn't include other tiles. + gfx::Rect inner_rect_src(data2.TileBounds(1, 1)); + inner_rect_src.Inset(data2.border_texels(), data.border_texels()); + gfx::Rect inner_rect_result(data2.TileBounds(1, 1)); + gfx::Rect expanded = data2.ExpandRectToTileBounds(inner_rect_src); + EXPECT_EQ(inner_rect_result.ToString(), expanded.ToString()); } TEST_P(TilingDataTest, Assignment) { -- cgit v1.1