summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-18 07:12:36 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-18 07:12:36 +0000
commit86ad492770a6a72130affe24b982e57bca9da7b0 (patch)
tree29bef7fda7e4fa060e1631303b0d1f4c5143ad64 /cc
parente08ba1b9e4b34142bd116639dc4fd08a50fd8051 (diff)
downloadchromium_src-86ad492770a6a72130affe24b982e57bca9da7b0.zip
chromium_src-86ad492770a6a72130affe24b982e57bca9da7b0.tar.gz
chromium_src-86ad492770a6a72130affe24b982e57bca9da7b0.tar.bz2
cc: In SyncFromActiveLayer, drop all tiles not in the recorded_viewport.
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 Review URL: https://codereview.chromium.org/294163009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277964 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/base/tiling_data.cc24
-rw-r--r--cc/base/tiling_data.h3
-rw-r--r--cc/base/tiling_data_unittest.cc60
-rw-r--r--cc/layers/picture_layer.cc24
-rw-r--r--cc/layers/picture_layer_impl.cc18
-rw-r--r--cc/resources/picture_pile.cc59
-rw-r--r--cc/resources/picture_pile.h23
-rw-r--r--cc/resources/picture_pile_base.h6
-rw-r--r--cc/resources/picture_pile_unittest.cc124
9 files changed, 244 insertions, 97 deletions
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) {
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 0a6e276..61dce74 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -121,16 +121,22 @@ bool PictureLayer::Update(ResourceUpdateQueue* queue,
// the full page content must always be provided in the picture layer.
visible_layer_rect = gfx::Rect(bounds());
}
+
+ // UpdateAndExpandInvalidation will give us an invalidation that covers
+ // anything not explicitly recorded in this frame. We give this region
+ // to the impl side so that it drops tiles that may not have a recording
+ // for them.
DCHECK(client_);
- updated |= pile_->Update(client_,
- SafeOpaqueBackgroundColor(),
- contents_opaque(),
- client_->FillsBoundsCompletely(),
- pile_invalidation_,
- visible_layer_rect,
- update_source_frame_number_,
- RecordingMode(),
- rendering_stats_instrumentation());
+ updated |=
+ pile_->UpdateAndExpandInvalidation(client_,
+ &pile_invalidation_,
+ SafeOpaqueBackgroundColor(),
+ contents_opaque(),
+ client_->FillsBoundsCompletely(),
+ visible_layer_rect,
+ update_source_frame_number_,
+ RecordingMode(),
+ rendering_stats_instrumentation());
last_updated_visible_content_rect_ = visible_content_rect();
if (updated) {
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index eabfdc6..0ebd0e4 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -626,6 +626,7 @@ gfx::Size PictureLayerImpl::CalculateTileSize(
}
void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
+ TRACE_EVENT0("cc", "SyncFromActiveLayer");
DCHECK(!other->needs_post_commit_initialization_);
DCHECK(other->tilings_);
@@ -640,23 +641,6 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
raster_contents_scale_ = other->raster_contents_scale_;
low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
- // Add synthetic invalidations for any recordings that were dropped. As
- // tiles are updated to point to this new pile, this will force the dropping
- // of tiles that can no longer be rastered. This is not ideal, but is a
- // trade-off for memory (use the same pile as much as possible, by switching
- // during DidBecomeActive) and for time (don't bother checking every tile
- // during activation to see if the new pile can still raster it).
- for (int x = 0; x < pile_->num_tiles_x(); ++x) {
- for (int y = 0; y < pile_->num_tiles_y(); ++y) {
- bool previously_had = other->pile_->HasRecordingAt(x, y);
- bool now_has = pile_->HasRecordingAt(x, y);
- if (now_has || !previously_had)
- continue;
- gfx::Rect layer_rect = pile_->tile_bounds(x, y);
- invalidation_.Union(layer_rect);
- }
- }
-
// Union in the other newly exposed regions as invalid.
Region difference_region = Region(gfx::Rect(bounds()));
difference_region.Subtract(gfx::Rect(other->bounds()));
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index 27c58a1..7b300b3 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -146,15 +146,16 @@ PicturePile::PicturePile() : is_suitable_for_gpu_rasterization_(true) {}
PicturePile::~PicturePile() {
}
-bool PicturePile::Update(ContentLayerClient* painter,
- SkColor background_color,
- bool contents_opaque,
- bool contents_fill_bounds_completely,
- const Region& invalidation,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- Picture::RecordingMode recording_mode,
- RenderingStatsInstrumentation* stats_instrumentation) {
+bool PicturePile::UpdateAndExpandInvalidation(
+ ContentLayerClient* painter,
+ Region* invalidation,
+ SkColor background_color,
+ bool contents_opaque,
+ bool contents_fill_bounds_completely,
+ const gfx::Rect& visible_layer_rect,
+ int frame_number,
+ Picture::RecordingMode recording_mode,
+ RenderingStatsInstrumentation* stats_instrumentation) {
background_color_ = background_color;
contents_opaque_ = contents_opaque;
contents_fill_bounds_completely_ = contents_fill_bounds_completely;
@@ -168,13 +169,16 @@ bool PicturePile::Update(ContentLayerClient* painter,
recorded_viewport_ = interest_rect;
recorded_viewport_.Intersect(tiling_rect());
+ gfx::Rect interest_rect_over_tiles =
+ tiling_.ExpandRectToTileBounds(interest_rect);
+
bool invalidated = false;
- for (Region::Iterator i(invalidation); i.has_rect(); i.next()) {
- gfx::Rect invalidation = i.rect();
+ for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) {
+ gfx::Rect invalid_rect = i.rect();
// Split this inflated invalidation across tile boundaries and apply it
// to all tiles that it touches.
bool include_borders = true;
- for (TilingData::Iterator iter(&tiling_, invalidation, include_borders);
+ for (TilingData::Iterator iter(&tiling_, invalid_rect, include_borders);
iter;
++iter) {
const PictureMapKey& key = iter.index();
@@ -186,6 +190,18 @@ bool PicturePile::Update(ContentLayerClient* painter,
// Inform the grid cell that it has been invalidated in this frame.
invalidated = picture_it->second.Invalidate(frame_number) || invalidated;
}
+
+ // Expand invalidation that is outside tiles that intersect the interest
+ // rect. These tiles are no longer valid and should be considerered fully
+ // invalid, so we can know to not keep around raster tiles that intersect
+ // with these recording tiles.
+ gfx::Rect invalid_rect_outside_interest_rect_tiles = invalid_rect;
+ // TODO(danakj): We should have a Rect-subtract-Rect-to-2-rects operator
+ // instead of using Rect::Subtract which gives you the bounding box of the
+ // subtraction.
+ invalid_rect_outside_interest_rect_tiles.Subtract(interest_rect_over_tiles);
+ invalidation->Union(tiling_.ExpandRectToTileBounds(
+ invalid_rect_outside_interest_rect_tiles));
}
// Make a list of all invalid tiles; we will attempt to
@@ -204,12 +220,19 @@ bool PicturePile::Update(ContentLayerClient* painter,
if (info.NeedsRecording(frame_number, distance_to_visible)) {
gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
invalid_tiles.push_back(tile);
- } else if (!info.GetPicture() && recorded_viewport_.Intersects(rect)) {
- // Recorded viewport is just an optimization for a fully recorded
- // interest rect. In this case, a tile in that rect has declined
- // to be recorded (probably due to frequent invalidations).
- // TODO(enne): Shrink the recorded_viewport_ rather than clearing.
- recorded_viewport_ = gfx::Rect();
+ } else if (!info.GetPicture()) {
+ if (recorded_viewport_.Intersects(rect)) {
+ // Recorded viewport is just an optimization for a fully recorded
+ // interest rect. In this case, a tile in that rect has declined
+ // to be recorded (probably due to frequent invalidations).
+ // TODO(enne): Shrink the recorded_viewport_ rather than clearing.
+ recorded_viewport_ = gfx::Rect();
+ }
+
+ // If a tile in the interest rect is not recorded, the entire tile needs
+ // to be considered invalid, so that we know not to keep around raster
+ // tiles that intersect this recording tile.
+ invalidation->Union(tiling_.TileBounds(it.index_x(), it.index_y()));
}
}
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index 415bbdfe..86ef32f 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -18,17 +18,20 @@ class CC_EXPORT PicturePile : public PicturePileBase {
PicturePile();
// Re-record parts of the picture that are invalid.
- // Invalidations are in layer space.
+ // Invalidations are in layer space, and will be expanded to cover everything
+ // that was either recorded/changed or that has no recording, leaving out only
+ // pieces that we had a recording for and it was not changed.
// Return true iff the pile was modified.
- bool Update(ContentLayerClient* painter,
- SkColor background_color,
- bool contents_opaque,
- bool contents_fill_bounds_completely,
- const Region& invalidation,
- const gfx::Rect& visible_layer_rect,
- int frame_number,
- Picture::RecordingMode recording_mode,
- RenderingStatsInstrumentation* stats_instrumentation);
+ bool UpdateAndExpandInvalidation(
+ ContentLayerClient* painter,
+ Region* invalidation,
+ SkColor background_color,
+ bool contents_opaque,
+ bool contents_fill_bounds_completely,
+ const gfx::Rect& visible_layer_rect,
+ int frame_number,
+ Picture::RecordingMode recording_mode,
+ RenderingStatsInstrumentation* stats_instrumentation);
void set_slow_down_raster_scale_factor(int factor) {
slow_down_raster_scale_factor_for_debug_ = factor;
diff --git a/cc/resources/picture_pile_base.h b/cc/resources/picture_pile_base.h
index dd5f883..9f8acff 100644
--- a/cc/resources/picture_pile_base.h
+++ b/cc/resources/picture_pile_base.h
@@ -33,6 +33,11 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
gfx::Rect tiling_rect() const { return tiling_.tiling_rect(); }
void SetMinContentsScale(float min_contents_scale);
+ // If non-empty, all pictures tiles inside this rect are recorded. There may
+ // be recordings outside this rect, but everything inside the rect is
+ // recorded.
+ gfx::Rect recorded_viewport() const { return recorded_viewport_; }
+
int num_tiles_x() const { return tiling_.num_tiles_x(); }
int num_tiles_y() const { return tiling_.num_tiles_y(); }
gfx::Rect tile_bounds(int x, int y) const { return tiling_.TileBounds(x, y); }
@@ -98,7 +103,6 @@ class CC_EXPORT PicturePileBase : public base::RefCounted<PicturePileBase> {
// indices to picture infos.
PictureMap picture_map_;
TilingData tiling_;
- // If non-empty, all pictures tiles inside this rect are recorded.
gfx::Rect recorded_viewport_;
float min_contents_scale_;
SkTileGridFactory::TileGridInfo tile_grid_info_;
diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc
index 0387863..681166e 100644
--- a/cc/resources/picture_pile_unittest.cc
+++ b/cc/resources/picture_pile_unittest.cc
@@ -51,20 +51,26 @@ class PicturePileTest : public testing::Test {
gfx::Rect tiling_rect() const { return pile_->tiling_rect(); }
- bool Update(const Region& invalidation, const gfx::Rect& visible_layer_rect) {
+ bool UpdateAndExpandInvalidation(Region* invalidation,
+ const gfx::Rect& visible_layer_rect) {
frame_number_++;
- return pile_->Update(&client_,
- background_color_,
- contents_opaque_,
- false,
- invalidation,
- visible_layer_rect,
- frame_number_,
- Picture::RECORD_NORMALLY,
- &stats_instrumentation_);
+ return pile_->UpdateAndExpandInvalidation(&client_,
+ invalidation,
+ background_color_,
+ contents_opaque_,
+ false,
+ visible_layer_rect,
+ frame_number_,
+ Picture::RECORD_NORMALLY,
+ &stats_instrumentation_);
}
- bool UpdateWholePile() { return Update(tiling_rect(), tiling_rect()); }
+ bool UpdateWholePile() {
+ Region invalidation = tiling_rect();
+ bool result = UpdateAndExpandInvalidation(&invalidation, tiling_rect());
+ EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
+ return result;
+ }
FakeContentLayerClient client_;
FakeRenderingStatsInstrumentation stats_instrumentation_;
@@ -79,8 +85,9 @@ TEST_F(PicturePileTest, SmallInvalidateInflated) {
UpdateWholePile();
// Invalidate something inside a tile.
- gfx::Rect invalidate_rect(50, 50, 1, 1);
- Update(invalidate_rect, tiling_rect());
+ Region invalidate_rect(gfx::Rect(50, 50, 1, 1));
+ UpdateAndExpandInvalidation(&invalidate_rect, tiling_rect());
+ EXPECT_EQ(gfx::Rect(50, 50, 1, 1).ToString(), invalidate_rect.ToString());
EXPECT_EQ(1, pile_->tiling().num_tiles_x());
EXPECT_EQ(1, pile_->tiling().num_tiles_y());
@@ -102,8 +109,9 @@ TEST_F(PicturePileTest, LargeInvalidateInflated) {
UpdateWholePile();
// Invalidate something inside a tile.
- gfx::Rect invalidate_rect(50, 50, 100, 100);
- Update(invalidate_rect, tiling_rect());
+ Region invalidate_rect(gfx::Rect(50, 50, 100, 100));
+ UpdateAndExpandInvalidation(&invalidate_rect, tiling_rect());
+ EXPECT_EQ(gfx::Rect(50, 50, 100, 100).ToString(), invalidate_rect.ToString());
EXPECT_EQ(1, pile_->tiling().num_tiles_x());
EXPECT_EQ(1, pile_->tiling().num_tiles_y());
@@ -143,12 +151,14 @@ TEST_F(PicturePileTest, InvalidateOnTileBoundaryInflated) {
// Invalidate something just over a tile boundary by a single pixel.
// This will invalidate the tile (1, 1), as well as 1 row of pixels in (1, 0).
- gfx::Rect invalidate_rect(
- pile_->tiling().TileBoundsWithBorder(0, 0).right(),
- pile_->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
- 50,
- 50);
- Update(invalidate_rect, tiling_rect());
+ Region invalidate_rect(
+ gfx::Rect(pile_->tiling().TileBoundsWithBorder(0, 0).right(),
+ pile_->tiling().TileBoundsWithBorder(0, 0).bottom() - 1,
+ 50,
+ 50));
+ Region expected_invalidation = invalidate_rect;
+ UpdateAndExpandInvalidation(&invalidate_rect, tiling_rect());
+ EXPECT_EQ(expected_invalidation.ToString(), invalidate_rect.ToString());
for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
@@ -197,9 +207,10 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
}
}
- // Update once more with a small viewport tiilng_rect.x(), tiilng_rect.y(),
- // tiling_rect.width() by 1
- Update(tiling_rect(), viewport);
+ // Update once more with a small viewport.
+ Region invalidation = tiling_rect();
+ UpdateAndExpandInvalidation(&invalidation, viewport);
+ EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
@@ -218,8 +229,22 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
}
}
+ // Update a partial tile that doesn't get recorded. We should expand the
+ // invalidation to the entire tiles that overlap it.
+ Region small_invalidation =
+ gfx::Rect(pile_->tiling().TileBounds(3, 4).x(),
+ pile_->tiling().TileBounds(3, 4).y() + 10,
+ 1,
+ 1);
+ UpdateAndExpandInvalidation(&small_invalidation, viewport);
+ EXPECT_TRUE(small_invalidation.Contains(gfx::UnionRects(
+ pile_->tiling().TileBounds(2, 4), pile_->tiling().TileBounds(3, 4))))
+ << small_invalidation.ToString();
+
// Now update with no invalidation and full viewport
- Update(gfx::Rect(), tiling_rect());
+ Region empty_invalidation;
+ UpdateAndExpandInvalidation(&empty_invalidation, tiling_rect());
+ EXPECT_EQ(Region().ToString(), empty_invalidation.ToString());
for (int i = 0; i < pile_->tiling().num_tiles_x(); ++i) {
for (int j = 0; j < pile_->tiling().num_tiles_y(); ++j) {
@@ -229,12 +254,7 @@ TEST_F(PicturePileTest, StopRecordingOffscreenInvalidations) {
->second;
// Expect the invalidation frequency to be less than 1, since we just
// updated with no invalidations.
- float expected_frequency =
- 1.0f -
- 1.0f / TestPicturePile::PictureInfo::INVALIDATION_FRAMES_TRACKED;
-
- EXPECT_FLOAT_EQ(expected_frequency,
- picture_info.GetInvalidationFrequencyForTesting());
+ EXPECT_LT(picture_info.GetInvalidationFrequencyForTesting(), 1.f);
// We expect that there are pictures everywhere now.
EXPECT_TRUE(picture_info.GetPicture()) << "i " << i << " j " << j;
@@ -291,7 +311,9 @@ TEST_F(PicturePileTest, FrequentInvalidationCanRaster) {
// Update once more with a small viewport.
gfx::Rect viewport(0, 0, tiling_rect().width(), 1);
- Update(tiling_rect(), viewport);
+ Region invalidation(tiling_rect());
+ UpdateAndExpandInvalidation(&invalidation, viewport);
+ EXPECT_EQ(tiling_rect().ToString(), invalidation.ToString());
// Sanity check some pictures exist and others don't.
EXPECT_TRUE(pile_->picture_map()
@@ -315,16 +337,48 @@ TEST_F(PicturePileTest, NoInvalidationValidViewport) {
EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
// No invalidation, same viewport.
- Update(gfx::Rect(), tiling_rect());
+ Region invalidation;
+ UpdateAndExpandInvalidation(&invalidation, tiling_rect());
EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ EXPECT_EQ(Region().ToString(), invalidation.ToString());
// Partial invalidation, same viewport.
- Update(gfx::Rect(gfx::Rect(0, 0, 1, 1)), tiling_rect());
+ invalidation = gfx::Rect(0, 0, 1, 1);
+ UpdateAndExpandInvalidation(&invalidation, tiling_rect());
EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ EXPECT_EQ(gfx::Rect(0, 0, 1, 1).ToString(), invalidation.ToString());
// No invalidation, changing viewport.
- Update(gfx::Rect(), gfx::Rect(5, 5, 5, 5));
+ invalidation = Region();
+ UpdateAndExpandInvalidation(&invalidation, gfx::Rect(5, 5, 5, 5));
EXPECT_TRUE(!pile_->recorded_viewport().IsEmpty());
+ EXPECT_EQ(Region().ToString(), invalidation.ToString());
+}
+
+TEST_F(PicturePileTest, InvalidationOutsideRecordingRect) {
+ gfx::Rect huge_layer_rect(10000000, 20000000);
+ gfx::Rect viewport(300000, 400000, 5000, 6000);
+
+ pile_->SetTilingRect(huge_layer_rect);
+
+ // Invalidation inside the recording rect does not need to be expanded.
+ Region invalidation = viewport;
+ UpdateAndExpandInvalidation(&invalidation, viewport);
+ EXPECT_EQ(viewport.ToString(), invalidation.ToString());
+
+ // Invalidation outside the recording rect should expand to the tiles it
+ // covers.
+ gfx::Rect recorded_over_tiles =
+ pile_->tiling().ExpandRectToTileBounds(pile_->recorded_viewport());
+ gfx::Rect invalidation_outside(
+ recorded_over_tiles.right(), recorded_over_tiles.y(), 30, 30);
+ invalidation = invalidation_outside;
+ UpdateAndExpandInvalidation(&invalidation, viewport);
+ gfx::Rect expanded_recorded_viewport =
+ pile_->tiling().ExpandRectToTileBounds(pile_->recorded_viewport());
+ Region expected_invalidation =
+ pile_->tiling().ExpandRectToTileBounds(invalidation_outside);
+ EXPECT_EQ(expected_invalidation.ToString(), invalidation.ToString());
}
} // namespace