Index: cc/resources/picture_pile.cc |
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc |
index 5756a66c53abb63053194af0f59d9a88950cd8e4..b915dca257ad0d8cf5256e51bbc450eb6facc000 100644 |
--- a/cc/resources/picture_pile.cc |
+++ b/cc/resources/picture_pile.cc |
@@ -157,6 +157,7 @@ bool PicturePile::UpdateAndExpandInvalidation( |
SkColor background_color, |
bool contents_opaque, |
bool contents_fill_bounds_completely, |
+ const gfx::Rect& layer_bounds_rect, |
const gfx::Rect& visible_layer_rect, |
int frame_number, |
Picture::RecordingMode recording_mode, |
@@ -165,6 +166,15 @@ bool PicturePile::UpdateAndExpandInvalidation( |
contents_opaque_ = contents_opaque; |
contents_fill_bounds_completely_ = contents_fill_bounds_completely; |
+ bool updated = false; |
+ |
+ Region resize_invalidation; |
+ gfx::Rect old_tiling_rect = tiling_rect(); |
+ if (old_tiling_rect != layer_bounds_rect) { |
+ tiling_.SetTilingRect(layer_bounds_rect); |
+ updated = true; |
+ } |
+ |
gfx::Rect interest_rect = visible_layer_rect; |
interest_rect.Inset( |
-kPixelDistanceToRecord, |
@@ -177,11 +187,99 @@ bool PicturePile::UpdateAndExpandInvalidation( |
gfx::Rect interest_rect_over_tiles = |
tiling_.ExpandRectToTileBounds(interest_rect); |
- Region invalidation_expanded_to_full_tiles; |
+ if (old_tiling_rect != layer_bounds_rect) { |
+ has_any_recordings_ = false; |
- bool invalidated = false; |
+ if (tiling_rect().origin() != old_tiling_rect.origin()) { |
+ // If the origin changes we just do something simple. |
+ picture_map_.clear(); |
+ invalidation->Union(old_tiling_rect); |
+ invalidation->Union(tiling_rect()); |
+ } else { |
+ // Drop recordings that are outside the new layer bounds or that changed |
+ // size. |
+ std::vector<PictureMapKey> to_erase; |
+ int min_toss_x = tiling_.num_tiles_x(); |
+ if (tiling_rect().right() > old_tiling_rect.right()) { |
+ min_toss_x = |
+ tiling_.FirstBorderTileXIndexFromSrcCoord(old_tiling_rect.right()); |
+ } |
+ int min_toss_y = tiling_.num_tiles_y(); |
+ if (tiling_rect().bottom() > old_tiling_rect.bottom()) { |
+ min_toss_y = |
+ tiling_.FirstBorderTileYIndexFromSrcCoord(old_tiling_rect.bottom()); |
+ } |
+ for (PictureMap::const_iterator it = picture_map_.begin(); |
+ it != picture_map_.end(); |
+ ++it) { |
+ const PictureMapKey& key = it->first; |
+ if (key.first < min_toss_x && key.second < min_toss_y) { |
+ has_any_recordings_ |= !!it->second.GetPicture(); |
+ continue; |
+ } |
+ to_erase.push_back(key); |
+ } |
+ |
+ for (size_t i = 0; i < to_erase.size(); ++i) |
+ picture_map_.erase(to_erase[i]); |
+ |
+ // If a recording is dropped and not re-recorded below, invalidate that |
+ // full recording to cause any raster tiles that would use it to be |
+ // dropped. |
+ // If the recording will be replaced below, just invalidate newly exposed |
+ // areas to force raster tiles that include the old recording to know |
+ // there is new recording to display. |
+ gfx::Rect old_tiling_rect_over_tiles = |
+ tiling_.ExpandRectToTileBounds(old_tiling_rect); |
+ if (min_toss_x < tiling_.num_tiles_x()) { |
+ int unrecorded_left = std::max(tiling_.TilePositionX(min_toss_x), |
+ interest_rect_over_tiles.right()); |
+ int exposed_left = old_tiling_rect.right(); |
+ int left = std::min(unrecorded_left, exposed_left); |
+ int tile_right = |
+ tiling_.TilePositionX(min_toss_x) + tiling_.TileSizeX(min_toss_x); |
+ int exposed_right = tiling_rect().right(); |
+ int right = std::min(tile_right, exposed_right); |
+ gfx::Rect right_side(left, |
+ old_tiling_rect_over_tiles.y(), |
+ right - left, |
+ old_tiling_rect_over_tiles.height()); |
+ resize_invalidation.Union(right_side); |
+ } |
+ if (min_toss_y < tiling_.num_tiles_y()) { |
+ int unrecorded_top = std::max(tiling_.TilePositionY(min_toss_y), |
+ interest_rect_over_tiles.bottom()); |
+ int exposed_top = old_tiling_rect.bottom(); |
+ int top = std::min(unrecorded_top, exposed_top); |
+ int tile_bottom = |
+ tiling_.TilePositionY(min_toss_y) + tiling_.TileSizeY(min_toss_y); |
+ int exposed_bottom = tiling_rect().bottom(); |
+ int bottom = std::min(tile_bottom, exposed_bottom); |
+ gfx::Rect bottom_side(old_tiling_rect_over_tiles.x(), |
+ top, |
+ old_tiling_rect_over_tiles.width(), |
+ bottom - top); |
+ resize_invalidation.Union(bottom_side); |
+ } |
+ } |
+ } |
+ |
+ Region invalidation_expanded_to_full_tiles; |
for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { |
gfx::Rect invalid_rect = i.rect(); |
+ |
+ // 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_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds( |
+ invalid_rect_outside_interest_rect_tiles)); |
+ |
// Split this inflated invalidation across tile boundaries and apply it |
// to all tiles that it touches. |
bool include_borders = true; |
@@ -195,23 +293,18 @@ bool PicturePile::UpdateAndExpandInvalidation( |
continue; |
// Inform the grid cell that it has been invalidated in this frame. |
- invalidated = picture_it->second.Invalidate(frame_number) || invalidated; |
+ updated = picture_it->second.Invalidate(frame_number) || updated; |
+ // Invalidate drops the picture so the whole tile better be invalidated if |
+ // it won't be re-recorded below. |
+ DCHECK( |
+ tiling_.TileBounds(key.first, key.second).Intersects(interest_rect) || |
+ invalidation_expanded_to_full_tiles.Contains( |
+ tiling_.TileBounds(key.first, key.second))); |
} |
- |
- // 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_expanded_to_full_tiles.Union(tiling_.ExpandRectToTileBounds( |
- invalid_rect_outside_interest_rect_tiles)); |
} |
invalidation->Union(invalidation_expanded_to_full_tiles); |
+ invalidation->Union(resize_invalidation); |
// Make a list of all invalid tiles; we will attempt to |
// cluster these into multiple invalidation regions. |
@@ -249,7 +342,7 @@ bool PicturePile::UpdateAndExpandInvalidation( |
ClusterTiles(invalid_tiles, &record_rects); |
if (record_rects.empty()) |
- return invalidated; |
+ return updated; |
for (std::vector<gfx::Rect>::iterator it = record_rects.begin(); |
it != record_rects.end(); |
@@ -315,4 +408,11 @@ bool PicturePile::UpdateAndExpandInvalidation( |
return true; |
} |
+void PicturePile::SetEmptyBounds() { |
+ tiling_.SetTilingRect(gfx::Rect()); |
+ picture_map_.clear(); |
+ has_any_recordings_ = false; |
+ recorded_viewport_ = gfx::Rect(); |
+} |
+ |
} // namespace cc |