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..d2d54846ad2428685146648203bd60876c1b84db 100644 |
--- a/cc/resources/picture_layer_tiling.cc |
+++ b/cc/resources/picture_layer_tiling.cc |
@@ -25,63 +25,44 @@ namespace { |
const float kSoonBorderDistanceInScreenPixels = 312.f; |
-class TileEvictionOrder { |
- public: |
- explicit TileEvictionOrder(TreePriority tree_priority) |
- : tree_priority_(tree_priority) {} |
- ~TileEvictionOrder() {} |
- |
- bool operator()(const Tile* a, const Tile* b) { |
- const TilePriority& a_priority = |
- a->priority_for_tree_priority(tree_priority_); |
- const TilePriority& b_priority = |
- b->priority_for_tree_priority(tree_priority_); |
- |
- DCHECK(a_priority.priority_bin == b_priority.priority_bin); |
- DCHECK(a->required_for_activation() == b->required_for_activation()); |
- |
- // Or if a is occluded and b is unoccluded. |
- bool a_is_occluded = a->is_occluded_for_tree_priority(tree_priority_); |
- bool b_is_occluded = b->is_occluded_for_tree_priority(tree_priority_); |
- if (a_is_occluded != b_is_occluded) |
- return a_is_occluded; |
- |
- // Or if a is farther away from visible. |
- return a_priority.distance_to_visible > b_priority.distance_to_visible; |
- } |
- |
- private: |
- TreePriority tree_priority_; |
-}; |
- |
} // namespace |
scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
float contents_scale, |
const gfx::Size& layer_bounds, |
- PictureLayerTilingClient* client) { |
- return make_scoped_ptr(new PictureLayerTiling(contents_scale, |
- layer_bounds, |
- client)); |
+ PictureLayerTilingClient* client, |
+ size_t max_tiles_for_interest_area, |
+ float skewport_target_time_in_seconds, |
+ int skewport_extrapolation_limit_in_content_pixels) { |
+ return make_scoped_ptr(new PictureLayerTiling( |
+ contents_scale, layer_bounds, client, max_tiles_for_interest_area, |
+ skewport_target_time_in_seconds, |
+ skewport_extrapolation_limit_in_content_pixels)); |
} |
-PictureLayerTiling::PictureLayerTiling(float contents_scale, |
- const gfx::Size& layer_bounds, |
- PictureLayerTilingClient* client) |
- : contents_scale_(contents_scale), |
+PictureLayerTiling::PictureLayerTiling( |
+ float contents_scale, |
+ const gfx::Size& layer_bounds, |
+ PictureLayerTilingClient* client, |
+ size_t max_tiles_for_interest_area, |
+ float skewport_target_time_in_seconds, |
+ int skewport_extrapolation_limit_in_content_pixels) |
+ : max_tiles_for_interest_area_(max_tiles_for_interest_area), |
+ skewport_target_time_in_seconds_(skewport_target_time_in_seconds), |
+ skewport_extrapolation_limit_in_content_pixels_( |
+ skewport_extrapolation_limit_in_content_pixels), |
+ contents_scale_(contents_scale), |
layer_bounds_(layer_bounds), |
resolution_(NON_IDEAL_RESOLUTION), |
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), |
- has_eventually_rect_tiles_(false), |
- eviction_tiles_cache_valid_(false), |
- eviction_cache_tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES) { |
+ has_eventually_rect_tiles_(false) { |
gfx::Size content_bounds = |
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); |
gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
@@ -105,13 +86,13 @@ 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) { |
+ const PictureLayerTiling* twin_tiling, |
+ PictureLayerTiling* recycled_twin) { |
+ // Can't have both a (pending or active) twin and a recycled twin tiling. |
+ DCHECK_IMPLIES(twin_tiling, !recycled_twin); |
+ DCHECK_IMPLIES(recycled_twin, !twin_tiling); |
TileMapKey key(i, j); |
DCHECK(tiles_.find(key) == tiles_.end()); |
@@ -144,14 +125,24 @@ Tile* PictureLayerTiling::CreateTile(int i, |
DCHECK(!tile->is_shared()); |
tile->set_tiling_index(i, j); |
tiles_[key] = tile; |
+ |
+ if (recycled_twin) { |
+ DCHECK(recycled_twin->tiles_.find(key) == recycled_twin->tiles_.end()); |
+ // Do what recycled_twin->CreateTile() would do. |
+ tile->set_shared(true); |
+ recycled_twin->tiles_[key] = tile; |
+ } |
} |
- eviction_tiles_cache_valid_ = false; |
return tile.get(); |
} |
void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
const PictureLayerTiling* twin_tiling = |
client_->GetPendingOrActiveTwinTiling(this); |
+ // There is no recycled twin during commit from the main thread which is when |
+ // this occurs. |
+ PictureLayerTiling* null_recycled_twin = nullptr; |
+ DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); |
bool include_borders = false; |
for (TilingData::Iterator iter( |
&tiling_data_, live_tiles_rect_, include_borders); |
@@ -161,116 +152,160 @@ void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
TileMap::iterator find = tiles_.find(key); |
if (find != tiles_.end()) |
continue; |
- CreateTile(key.first, key.second, twin_tiling); |
+ CreateTile(key.first, key.second, twin_tiling, null_recycled_twin); |
} |
- VerifyLiveTilesRect(); |
+ VerifyLiveTilesRect(false); |
} |
-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, null_recycled_twin); |
+ } |
- 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); |
- } |
+ // Create any missing tiles from the |twin_tiling|. |
+ for (const auto& tile_map_pair : twin_tiling.tiles_) { |
+ TileMapKey key = tile_map_pair.first; |
+ Tile* tile = tile_map_pair.second.get(); |
+ if (!tile->is_shared()) |
+ CreateTile(key.first, key.second, &twin_tiling, null_recycled_twin); |
+ } |
- // 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()); |
+ 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()); |
+ VerifyLiveTilesRect(false); |
+#endif |
- // 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); |
- } |
+ 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_); |
+} |
- // 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::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 (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* null_recycled_twin = nullptr; |
+ DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); |
-void PictureLayerTiling::Invalidate(const Region& layer_region) { |
- bool recreate_invalidated_tiles = true; |
- DoInvalidate(layer_region, recreate_invalidated_tiles); |
+ // 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, null_recycled_twin); |
+ } |
+ for (int i = before_left; i <= after_right; ++i) { |
+ for (int j = after_bottom + 1; j <= before_bottom; ++j) |
+ RemoveTileAt(i, j, null_recycled_twin); |
+ } |
+ |
+ // 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, null_recycled_twin); |
+ } |
+ 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, null_recycled_twin); |
+ } |
} |
-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 +326,40 @@ 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 = nullptr; |
+ 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. |
+ // And when invalidating an active-tree tiling, it means there was no |
+ // pending tiling to clone from. |
+ const PictureLayerTiling* null_twin_tiling = nullptr; |
+ PictureLayerTiling* null_recycled_twin = nullptr; |
+ DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); |
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); |
+ CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, |
+ null_twin_tiling, null_recycled_twin); |
} |
} |
} |
+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(false); |
+} |
+ |
PictureLayerTiling::CoverageIterator::CoverageIterator() |
: tiling_(NULL), |
current_tile_(NULL), |
@@ -468,10 +518,9 @@ bool PictureLayerTiling::RemoveTileAt(int i, |
return false; |
found->second->set_shared(false); |
tiles_.erase(found); |
- eviction_tiles_cache_valid_ = false; |
if (recycled_twin) { |
- // Recycled twin does not also have a recycled twin, so pass NULL. |
- recycled_twin->RemoveTileAt(i, j, NULL); |
+ // Recycled twin does not also have a recycled twin, so pass null. |
+ recycled_twin->RemoveTileAt(i, j, nullptr); |
} |
return true; |
} |
@@ -482,10 +531,9 @@ void PictureLayerTiling::Reset() { |
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
it->second->set_shared(false); |
if (recycled_twin) |
- recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); |
+ recycled_twin->RemoveTileAt(it->first.first, it->first.second, nullptr); |
} |
tiles_.clear(); |
- eviction_tiles_cache_valid_ = false; |
} |
gfx::Rect PictureLayerTiling::ComputeSkewport( |
@@ -500,10 +548,8 @@ gfx::Rect PictureLayerTiling::ComputeSkewport( |
if (time_delta == 0.0) |
return skewport; |
- float skewport_target_time_in_seconds = |
- client_->GetSkewportTargetTimeInSeconds(); |
double extrapolation_multiplier = |
- skewport_target_time_in_seconds / time_delta; |
+ skewport_target_time_in_seconds_ / time_delta; |
int old_x = last_visible_rect_in_content_space_.x(); |
int old_y = last_visible_rect_in_content_space_.y(); |
@@ -515,12 +561,11 @@ gfx::Rect PictureLayerTiling::ComputeSkewport( |
int new_right = visible_rect_in_content_space.right(); |
int new_bottom = visible_rect_in_content_space.bottom(); |
- int skewport_limit = client_->GetSkewportExtrapolationLimitInContentPixels(); |
- |
- // Compute the maximum skewport based on |skewport_limit|. |
+ // Compute the maximum skewport based on |
+ // |skewport_extrapolation_limit_in_content_pixels_|. |
gfx::Rect max_skewport = skewport; |
- max_skewport.Inset( |
- -skewport_limit, -skewport_limit, -skewport_limit, -skewport_limit); |
+ max_skewport.Inset(-skewport_extrapolation_limit_in_content_pixels_, |
+ -skewport_extrapolation_limit_in_content_pixels_); |
// Inset the skewport by the needed adjustment. |
skewport.Inset(extrapolation_multiplier * (new_x - old_x), |
@@ -564,11 +609,9 @@ void PictureLayerTiling::ComputeTilePriorityRects( |
DCHECK(skewport.Contains(visible_rect_in_content_space)); |
// Calculate the eventually/live tiles rect. |
- size_t max_tiles_for_interest_area = client_->GetMaxTilesForInterestArea(); |
- |
gfx::Size tile_size = tiling_data_.max_texture_size(); |
int64 eventually_rect_area = |
- max_tiles_for_interest_area * tile_size.width() * tile_size.height(); |
+ max_tiles_for_interest_area_ * tile_size.width() * tile_size.height(); |
gfx::Rect eventually_rect = |
ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space, |
@@ -582,29 +625,36 @@ 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_ = |
@@ -621,8 +671,9 @@ void PictureLayerTiling::SetLiveTilesRect( |
if (live_tiles_rect_ == new_live_tiles_rect) |
return; |
- // Iterate to delete all tiles outside of our new live_tiles rect. |
PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); |
+ |
+ // Iterate to delete all tiles outside of our new live_tiles rect. |
for (TilingData::DifferenceIterator iter(&tiling_data_, |
live_tiles_rect_, |
new_live_tiles_rect); |
@@ -641,16 +692,20 @@ void PictureLayerTiling::SetLiveTilesRect( |
iter; |
++iter) { |
TileMapKey key(iter.index()); |
- CreateTile(key.first, key.second, twin_tiling); |
+ CreateTile(key.first, key.second, twin_tiling, recycled_twin); |
} |
live_tiles_rect_ = new_live_tiles_rect; |
- VerifyLiveTilesRect(); |
+ VerifyLiveTilesRect(false); |
+ if (recycled_twin) { |
+ recycled_twin->live_tiles_rect_ = live_tiles_rect_; |
+ recycled_twin->VerifyLiveTilesRect(true); |
+ } |
} |
-void PictureLayerTiling::VerifyLiveTilesRect() { |
+void PictureLayerTiling::VerifyLiveTilesRect(bool is_on_recycle_tree) const { |
#if DCHECK_IS_ON |
- for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
+ for (auto it = tiles_.begin(); it != tiles_.end(); ++it) { |
if (!it->second.get()) |
continue; |
DCHECK(it->first.first < tiling_data_.num_tiles_x()) |
@@ -667,6 +722,7 @@ void PictureLayerTiling::VerifyLiveTilesRect() { |
<< " tile bounds " |
<< tiling_data_.TileBounds(it->first.first, it->first.second).ToString() |
<< " live_tiles_rect " << live_tiles_rect_.ToString(); |
+ DCHECK_IMPLIES(is_on_recycle_tree, it->second->is_shared()); |
} |
#endif |
} |
@@ -805,10 +861,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) || |
@@ -998,92 +1054,6 @@ gfx::Rect PictureLayerTiling::ExpandRectEquallyToAreaBoundedBy( |
return result; |
} |
-void PictureLayerTiling::UpdateEvictionCacheIfNeeded( |
- TreePriority tree_priority) { |
- if (eviction_tiles_cache_valid_ && |
- eviction_cache_tree_priority_ == tree_priority) |
- return; |
- |
- eviction_tiles_now_.clear(); |
- eviction_tiles_now_and_required_for_activation_.clear(); |
- eviction_tiles_soon_.clear(); |
- eviction_tiles_soon_and_required_for_activation_.clear(); |
- eviction_tiles_eventually_.clear(); |
- eviction_tiles_eventually_and_required_for_activation_.clear(); |
- |
- for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
- Tile* tile = it->second.get(); |
- UpdateTileAndTwinPriority(tile); |
- const TilePriority& priority = |
- tile->priority_for_tree_priority(tree_priority); |
- switch (priority.priority_bin) { |
- case TilePriority::EVENTUALLY: |
- if (tile->required_for_activation()) |
- eviction_tiles_eventually_and_required_for_activation_.push_back( |
- tile); |
- else |
- eviction_tiles_eventually_.push_back(tile); |
- break; |
- case TilePriority::SOON: |
- if (tile->required_for_activation()) |
- eviction_tiles_soon_and_required_for_activation_.push_back(tile); |
- else |
- eviction_tiles_soon_.push_back(tile); |
- break; |
- case TilePriority::NOW: |
- if (tile->required_for_activation()) |
- eviction_tiles_now_and_required_for_activation_.push_back(tile); |
- else |
- eviction_tiles_now_.push_back(tile); |
- break; |
- } |
- } |
- |
- // TODO(vmpstr): Do this lazily. One option is to have a "sorted" flag that |
- // can be updated for each of the queues. |
- TileEvictionOrder sort_order(tree_priority); |
- std::sort(eviction_tiles_now_.begin(), eviction_tiles_now_.end(), sort_order); |
- std::sort(eviction_tiles_now_and_required_for_activation_.begin(), |
- eviction_tiles_now_and_required_for_activation_.end(), |
- sort_order); |
- std::sort( |
- eviction_tiles_soon_.begin(), eviction_tiles_soon_.end(), sort_order); |
- std::sort(eviction_tiles_soon_and_required_for_activation_.begin(), |
- eviction_tiles_soon_and_required_for_activation_.end(), |
- sort_order); |
- std::sort(eviction_tiles_eventually_.begin(), |
- eviction_tiles_eventually_.end(), |
- sort_order); |
- std::sort(eviction_tiles_eventually_and_required_for_activation_.begin(), |
- eviction_tiles_eventually_and_required_for_activation_.end(), |
- sort_order); |
- |
- eviction_tiles_cache_valid_ = true; |
- eviction_cache_tree_priority_ = tree_priority; |
-} |
- |
-const std::vector<Tile*>* PictureLayerTiling::GetEvictionTiles( |
- TreePriority tree_priority, |
- EvictionCategory category) { |
- UpdateEvictionCacheIfNeeded(tree_priority); |
- switch (category) { |
- case EVENTUALLY: |
- return &eviction_tiles_eventually_; |
- case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: |
- return &eviction_tiles_eventually_and_required_for_activation_; |
- case SOON: |
- return &eviction_tiles_soon_; |
- case SOON_AND_REQUIRED_FOR_ACTIVATION: |
- return &eviction_tiles_soon_and_required_for_activation_; |
- case NOW: |
- return &eviction_tiles_now_; |
- case NOW_AND_REQUIRED_FOR_ACTIVATION: |
- return &eviction_tiles_now_and_required_for_activation_; |
- } |
- NOTREACHED(); |
- return &eviction_tiles_eventually_; |
-} |
- |
PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() |
: tiling_(NULL), current_tile_(NULL) {} |