Index: cc/resources/picture_layer_tiling.cc |
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc |
index e9e3b86180a0dba8a297dc77235f6f84224fe191..340faa96fec2695ff2142519f3225de730253434 100644 |
--- a/cc/resources/picture_layer_tiling.cc |
+++ b/cc/resources/picture_layer_tiling.cc |
@@ -74,8 +74,8 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale, |
client_(client), |
tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), |
last_impl_frame_time_in_seconds_(0.0), |
- content_to_screen_scale_(0.f), |
can_require_tiles_for_activation_(false), |
+ current_content_to_screen_scale_(0.f), |
has_visible_rect_tiles_(false), |
has_skewport_rect_tiles_(false), |
has_soon_border_rect_tiles_(false), |
@@ -105,10 +105,6 @@ PictureLayerTiling::~PictureLayerTiling() { |
it->second->set_shared(false); |
} |
-void PictureLayerTiling::SetClient(PictureLayerTilingClient* client) { |
- client_ = client; |
-} |
- |
Tile* PictureLayerTiling::CreateTile(int i, |
int j, |
const PictureLayerTiling* twin_tiling) { |
@@ -167,110 +163,145 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
VerifyLiveTilesRect(); |
} |
-void PictureLayerTiling::UpdateTilesToCurrentRasterSource( |
- RasterSource* raster_source, |
- const Region& layer_invalidation, |
- const gfx::Size& new_layer_bounds) { |
- DCHECK(!new_layer_bounds.IsEmpty()); |
+void PictureLayerTiling::CloneTilesAndPropertiesFrom( |
+ const PictureLayerTiling& twin_tiling) { |
+ DCHECK_EQ(&twin_tiling, client_->GetPendingOrActiveTwinTiling(this)); |
- gfx::Size content_bounds = |
- gfx::ToCeiledSize(gfx::ScaleSize(new_layer_bounds, contents_scale_)); |
- gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
+ Resize(twin_tiling.layer_bounds_); |
+ DCHECK_EQ(twin_tiling.contents_scale_, contents_scale_); |
+ DCHECK_EQ(twin_tiling.layer_bounds().ToString(), layer_bounds().ToString()); |
+ DCHECK_EQ(twin_tiling.tile_size().ToString(), tile_size().ToString()); |
- if (new_layer_bounds != layer_bounds_) { |
- if (tile_size.IsEmpty()) { |
- layer_bounds_ = gfx::Size(); |
- content_bounds = gfx::Size(); |
- } else { |
- layer_bounds_ = new_layer_bounds; |
- } |
+ resolution_ = twin_tiling.resolution_; |
- // The SetLiveTilesRect() method would drop tiles outside the new bounds, |
- // but may do so incorrectly if resizing the tiling causes the number of |
- // tiles in the tiling_data_ to change. |
- gfx::Rect content_rect(content_bounds); |
- int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); |
- int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); |
- int before_right = |
- tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
- int before_bottom = |
- tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
+ SetLiveTilesRect(twin_tiling.live_tiles_rect()); |
- // The live_tiles_rect_ is clamped to stay within the tiling size as we |
- // change it. |
- live_tiles_rect_.Intersect(content_rect); |
- tiling_data_.SetTilingSize(content_bounds); |
+ // Recreate unshared tiles. |
+ std::vector<TileMapKey> to_remove; |
+ for (const auto& tile_map_pair : tiles_) { |
+ TileMapKey key = tile_map_pair.first; |
+ Tile* tile = tile_map_pair.second.get(); |
+ if (!tile->is_shared()) |
+ to_remove.push_back(key); |
+ } |
+ // The recycled twin does not exist since there is a pending twin (which is |
+ // |twin_tiling|). |
+ PictureLayerTiling* null_recycled_twin = nullptr; |
+ DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); |
+ for (const auto& key : to_remove) { |
+ RemoveTileAt(key.first, key.second, null_recycled_twin); |
+ CreateTile(key.first, key.second, &twin_tiling); |
+ } |
- int after_right = -1; |
- int after_bottom = -1; |
- if (!live_tiles_rect_.IsEmpty()) { |
- after_right = |
- tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
- after_bottom = |
- tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
- } |
+ DCHECK_EQ(twin_tiling.tiles_.size(), tiles_.size()); |
+#if DCHECK_IS_ON |
+ for (const auto& tile_map_pair : tiles_) |
+ DCHECK(tile_map_pair.second->is_shared()); |
+#endif |
- // There is no recycled twin since this is run on the pending tiling. |
- PictureLayerTiling* recycled_twin = NULL; |
- DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); |
- DCHECK_EQ(PENDING_TREE, client_->GetTree()); |
+ UpdateTilePriorityRects(twin_tiling.current_content_to_screen_scale_, |
+ twin_tiling.current_visible_rect_, |
+ twin_tiling.current_skewport_rect_, |
+ twin_tiling.current_soon_border_rect_, |
+ twin_tiling.current_eventually_rect_, |
+ twin_tiling.current_occlusion_in_layer_space_); |
+} |
- // Drop tiles outside the new layer bounds if the layer shrank. |
- for (int i = after_right + 1; i <= before_right; ++i) { |
- for (int j = before_top; j <= before_bottom; ++j) |
- RemoveTileAt(i, j, recycled_twin); |
- } |
- for (int i = before_left; i <= after_right; ++i) { |
- for (int j = after_bottom + 1; j <= before_bottom; ++j) |
- RemoveTileAt(i, j, recycled_twin); |
- } |
+void PictureLayerTiling::Resize(const gfx::Size& new_layer_bounds) { |
+ gfx::Size layer_bounds = new_layer_bounds; |
+ gfx::Size content_bounds = |
+ gfx::ToCeiledSize(gfx::ScaleSize(new_layer_bounds, contents_scale_)); |
+ gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
- // If the layer grew, the live_tiles_rect_ is not changed, but a new row |
- // and/or column of tiles may now exist inside the same live_tiles_rect_. |
- const PictureLayerTiling* twin_tiling = |
- client_->GetPendingOrActiveTwinTiling(this); |
- if (after_right > before_right) { |
- DCHECK_EQ(after_right, before_right + 1); |
- for (int j = before_top; j <= after_bottom; ++j) |
- CreateTile(after_right, j, twin_tiling); |
- } |
- if (after_bottom > before_bottom) { |
- DCHECK_EQ(after_bottom, before_bottom + 1); |
- for (int i = before_left; i <= before_right; ++i) |
- CreateTile(i, after_bottom, twin_tiling); |
- } |
+ if (tile_size.IsEmpty()) { |
+ layer_bounds = gfx::Size(); |
+ content_bounds = gfx::Size(); |
} |
+ // The layer bounds are only allowed to be empty when the tile size is empty. |
+ // Otherwise we should not have such a tiling in the first place. |
+ DCHECK_IMPLIES(!tile_size.IsEmpty(), !layer_bounds_.IsEmpty()); |
+ |
+ bool resized = layer_bounds != layer_bounds_; |
+ layer_bounds_ = layer_bounds; |
+ |
if (tile_size != tiling_data_.max_texture_size()) { |
+ tiling_data_.SetTilingSize(content_bounds); |
tiling_data_.SetMaxTextureSize(tile_size); |
// When the tile size changes, the TilingData positions no longer work |
- // as valid keys to the TileMap, so just drop all tiles. |
+ // as valid keys to the TileMap, so just drop all tiles and clear the live |
+ // tiles rect. |
Reset(); |
- } else { |
- Invalidate(layer_invalidation); |
+ return; |
} |
- for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
- it->second->set_raster_source(raster_source); |
- VerifyLiveTilesRect(); |
-} |
+ if (!resized) |
+ return; |
-void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) { |
- bool recreate_invalidated_tiles = false; |
- DoInvalidate(layer_region, recreate_invalidated_tiles); |
-} |
+ // The SetLiveTilesRect() method would drop tiles outside the new bounds, |
+ // but may do so incorrectly if resizing the tiling causes the number of |
+ // tiles in the tiling_data_ to change. |
+ gfx::Rect content_rect(content_bounds); |
+ int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); |
+ int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); |
+ int before_right = |
+ tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
+ int before_bottom = |
+ tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
+ |
+ // The live_tiles_rect_ is clamped to stay within the tiling size as we |
+ // change it. |
+ live_tiles_rect_.Intersect(content_rect); |
+ tiling_data_.SetTilingSize(content_bounds); |
+ |
+ int after_right = -1; |
+ int after_bottom = -1; |
+ if (!live_tiles_rect_.IsEmpty()) { |
+ after_right = |
+ tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
+ after_bottom = |
+ tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
+ } |
+ |
+ // There is no recycled twin since this is run on the pending tiling |
+ // during commit, and on the active tree during activate. |
+ PictureLayerTiling* recycled_twin = NULL; |
+ DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); |
+ |
+ // Drop tiles outside the new layer bounds if the layer shrank. |
+ for (int i = after_right + 1; i <= before_right; ++i) { |
+ for (int j = before_top; j <= before_bottom; ++j) |
+ RemoveTileAt(i, j, recycled_twin); |
+ } |
+ for (int i = before_left; i <= after_right; ++i) { |
+ for (int j = after_bottom + 1; j <= before_bottom; ++j) |
+ RemoveTileAt(i, j, recycled_twin); |
+ } |
-void PictureLayerTiling::Invalidate(const Region& layer_region) { |
- bool recreate_invalidated_tiles = true; |
- DoInvalidate(layer_region, recreate_invalidated_tiles); |
+ // If the layer grew, the live_tiles_rect_ is not changed, but a new row |
+ // and/or column of tiles may now exist inside the same live_tiles_rect_. |
+ const PictureLayerTiling* twin_tiling = |
+ client_->GetPendingOrActiveTwinTiling(this); |
+ if (after_right > before_right) { |
+ DCHECK_EQ(after_right, before_right + 1); |
+ for (int j = before_top; j <= after_bottom; ++j) |
+ CreateTile(after_right, j, twin_tiling); |
+ } |
+ if (after_bottom > before_bottom) { |
+ DCHECK_EQ(after_bottom, before_bottom + 1); |
+ for (int i = before_left; i <= before_right; ++i) |
+ CreateTile(i, after_bottom, twin_tiling); |
+ } |
} |
-void PictureLayerTiling::DoInvalidate(const Region& layer_region, |
- bool recreate_invalidated_tiles) { |
+void PictureLayerTiling::Invalidate(const Region& layer_invalidation) { |
+ if (live_tiles_rect_.IsEmpty()) |
+ return; |
std::vector<TileMapKey> new_tile_keys; |
gfx::Rect expanded_live_tiles_rect = |
tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); |
- for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { |
+ for (Region::Iterator iter(layer_invalidation); iter.has_rect(); |
+ iter.next()) { |
gfx::Rect layer_rect = iter.rect(); |
gfx::Rect content_rect = |
gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); |
@@ -291,25 +322,35 @@ void PictureLayerTiling::DoInvalidate(const Region& layer_region, |
&tiling_data_, content_rect, include_borders); |
iter; |
++iter) { |
- // There is no recycled twin since this is run on the pending tiling. |
- PictureLayerTiling* recycled_twin = NULL; |
- DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); |
- DCHECK_EQ(PENDING_TREE, client_->GetTree()); |
- if (RemoveTileAt(iter.index_x(), iter.index_y(), recycled_twin)) |
+ // There is no recycled twin for the pending tree during commit, or for |
+ // the active tree during activation. |
+ PictureLayerTiling* null_recycled_twin = NULL; |
+ DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); |
+ if (RemoveTileAt(iter.index_x(), iter.index_y(), null_recycled_twin)) |
new_tile_keys.push_back(iter.index()); |
} |
} |
- if (recreate_invalidated_tiles && !new_tile_keys.empty()) { |
+ if (!new_tile_keys.empty()) { |
+ // During commit from the main thread, invalidations can never be shared |
+ // with the active tree since the active tree has different content there. |
+ const PictureLayerTiling* twin_tiling = nullptr; |
for (size_t i = 0; i < new_tile_keys.size(); ++i) { |
- // Don't try to share a tile with the twin layer, it's been invalidated so |
- // we have to make our own tile here. |
- const PictureLayerTiling* twin_tiling = NULL; |
CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, twin_tiling); |
} |
} |
} |
+void PictureLayerTiling::SetRasterSource( |
+ scoped_refptr<RasterSource> raster_source) { |
+ // Shared (ie. non-invalidated) tiles on the pending tree are updated to use |
+ // the new raster source. When this raster source is activated, the raster |
+ // source will remain valid for shared tiles in the active tree. |
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
+ it->second->set_raster_source(raster_source); |
+ VerifyLiveTilesRect(); |
+} |
+ |
PictureLayerTiling::CoverageIterator::CoverageIterator() |
: tiling_(NULL), |
current_tile_(NULL), |
@@ -582,34 +623,43 @@ void PictureLayerTiling::ComputeTilePriorityRects( |
<< " eventually_rect: " << eventually_rect.ToString(); |
// Calculate the soon border rect. |
- content_to_screen_scale_ = ideal_contents_scale / contents_scale_; |
+ float content_to_screen_scale = ideal_contents_scale / contents_scale_; |
gfx::Rect soon_border_rect = visible_rect_in_content_space; |
- float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale_; |
+ float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale; |
soon_border_rect.Inset(-border, -border, -border, -border); |
- // Update the tiling state. |
- SetLiveTilesRect(eventually_rect); |
- |
last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
last_viewport_in_layer_space_ = viewport_in_layer_space; |
last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
- eviction_tiles_cache_valid_ = false; |
+ SetLiveTilesRect(eventually_rect); |
+ UpdateTilePriorityRects( |
+ content_to_screen_scale, visible_rect_in_content_space, skewport, |
+ soon_border_rect, eventually_rect, occlusion_in_layer_space); |
+} |
+void PictureLayerTiling::UpdateTilePriorityRects( |
+ float content_to_screen_scale, |
+ const gfx::Rect& visible_rect_in_content_space, |
+ const gfx::Rect& skewport, |
+ const gfx::Rect& soon_border_rect, |
+ const gfx::Rect& eventually_rect, |
+ const Occlusion& occlusion_in_layer_space) { |
current_visible_rect_ = visible_rect_in_content_space; |
current_skewport_rect_ = skewport; |
current_soon_border_rect_ = soon_border_rect; |
current_eventually_rect_ = eventually_rect; |
current_occlusion_in_layer_space_ = occlusion_in_layer_space; |
+ current_content_to_screen_scale_ = content_to_screen_scale; |
- // Update has_*_tiles state. |
gfx::Rect tiling_rect(tiling_size()); |
- |
has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); |
has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_); |
has_soon_border_rect_tiles_ = |
tiling_rect.Intersects(current_soon_border_rect_); |
has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_); |
+ |
+ eviction_tiles_cache_valid_ = false; |
} |
void PictureLayerTiling::SetLiveTilesRect( |
@@ -805,10 +855,10 @@ void PictureLayerTiling::UpdateTilePriority(Tile* tile) const { |
tile->set_required_for_draw(false); |
tile->set_is_occluded(tree, false); |
- DCHECK_GT(content_to_screen_scale_, 0.f); |
+ DCHECK_GT(current_content_to_screen_scale_, 0.f); |
float distance_to_visible = |
current_visible_rect_.ManhattanInternalDistance(tile_bounds) * |
- content_to_screen_scale_; |
+ current_content_to_screen_scale_; |
if (max_tile_priority_bin <= TilePriority::SOON && |
(current_soon_border_rect_.Intersects(tile_bounds) || |