Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Unified Diff: cc/resources/picture_layer_tiling.cc

Issue 674103004: [WIP] cc: Use reverse spiral iterator in tiling eviction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/resources/picture_layer_tiling.h ('k') | cc/resources/picture_layer_tiling_perftest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/resources/picture_layer_tiling.cc
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index 04b18c311835d0b8b26c9bb1c1e035ef6c8c0200..9e83712c07addee2522f250b62fc16e9a451a0ed 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -25,35 +25,6 @@ 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(
@@ -79,9 +50,7 @@ PictureLayerTiling::PictureLayerTiling(float contents_scale,
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);
@@ -145,7 +114,6 @@ Tile* PictureLayerTiling::CreateTile(int i,
tile->set_tiling_index(i, j);
tiles_[key] = tile;
}
- eviction_tiles_cache_valid_ = false;
return tile.get();
}
@@ -468,7 +436,6 @@ 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);
@@ -485,7 +452,6 @@ void PictureLayerTiling::Reset() {
recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL);
}
tiles_.clear();
- eviction_tiles_cache_valid_ = false;
}
gfx::Rect PictureLayerTiling::ComputeSkewport(
@@ -595,8 +561,6 @@ void PictureLayerTiling::ComputeTilePriorityRects(
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;
-
current_visible_rect_ = visible_rect_in_content_space;
current_skewport_rect_ = skewport;
current_soon_border_rect_ = soon_border_rect;
@@ -999,92 +963,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) {}
@@ -1218,48 +1096,285 @@ operator++() {
}
PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator()
- : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) {
+ : tiling_(nullptr),
+ tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES),
+ eviction_category_(EVENTUALLY),
+ processing_soon_border_rect_(false),
+ skip_shared_high_priority_tiles_(false),
+ unoccluded_now_tiles_index_(0u),
+ current_tile_(nullptr) {
}
PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator(
PictureLayerTiling* tiling,
TreePriority tree_priority,
- EvictionCategory category)
- : eviction_tiles_(tiling->GetEvictionTiles(tree_priority, category)),
- // Note: initializing to "0 - 1" works as overflow is well defined for
- // unsigned integers.
- current_eviction_tiles_index_(static_cast<size_t>(0) - 1) {
- DCHECK(eviction_tiles_);
- ++(*this);
+ EvictionCategory category,
+ bool skip_shared_high_priority_tiles)
+ : tiling_(tiling),
+ tree_priority_(tree_priority),
+ eviction_category_(category),
+ processing_soon_border_rect_(true),
+ skip_shared_high_priority_tiles_(skip_shared_high_priority_tiles),
+ unoccluded_now_tiles_index_(0),
+ current_tile_(nullptr) {
+ WhichTree tree = tiling_->client_->GetTree();
+ if (tree == PENDING_TREE) {
+ switch (eviction_category_) {
+ case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
+ case SOON_AND_REQUIRED_FOR_ACTIVATION:
+ // Pending EVENTUALLY and SOON tiles are never required for activation.
+ return;
+ default:
+ break;
+ }
+ } else {
+ switch (eviction_category_) {
+ case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
+ case SOON_AND_REQUIRED_FOR_ACTIVATION:
+ case NOW_AND_REQUIRED_FOR_ACTIVATION: {
+ // Early out if there is no pending twin tiling.
+ if (!skip_shared_high_priority_tiles_)
+ return;
+ const PictureLayerTiling* twin_tiling =
+ tiling_->client_->GetPendingOrActiveTwinTiling(tiling_);
+ if (!twin_tiling)
+ return;
+ // Early out if the pending twin tiling does not have NOW tiles.
+ TilePriority::PriorityBin max_twin_tile_priority_bin =
+ twin_tiling->client_->GetMaxTilePriorityBin();
+ if (max_twin_tile_priority_bin > TilePriority::NOW)
+ return;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ TilePriority::PriorityBin max_tile_priority_bin =
+ tiling_->client_->GetMaxTilePriorityBin();
+ switch (eviction_category_) {
+ case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
+ case EVENTUALLY:
+ if (tiling_->has_eventually_rect_tiles_) {
+ if (max_tile_priority_bin < TilePriority::EVENTUALLY)
+ spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator(
+ &tiling_->tiling_data_, tiling_->current_eventually_rect_,
+ tiling_->current_skewport_rect_,
+ tiling_->current_soon_border_rect_);
+ else
+ spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator(
+ &tiling_->tiling_data_, tiling_->current_eventually_rect_,
+ gfx::Rect(), gfx::Rect());
+ bool skipped_tiles = false;
+ AdvanceEventually(&skipped_tiles);
+ if (!current_tile_ && !skipped_tiles &&
+ max_tile_priority_bin == TilePriority::EVENTUALLY)
+ tiling_->has_eventually_rect_tiles_ = false;
+ }
+ break;
+ case SOON_AND_REQUIRED_FOR_ACTIVATION:
+ case SOON:
+ if (max_tile_priority_bin <= TilePriority::SOON &&
+ (tiling_->has_skewport_rect_tiles_ ||
+ tiling_->has_soon_border_rect_tiles_)) {
+ if (tiling_->has_soon_border_rect_tiles_)
+ spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator(
+ &tiling_->tiling_data_, tiling_->current_soon_border_rect_,
+ tiling_->current_skewport_rect_, tiling_->current_visible_rect_);
+ AdvanceSoon();
+ }
+ break;
+ case NOW_AND_REQUIRED_FOR_ACTIVATION:
+ case NOW:
+ if (max_tile_priority_bin <= TilePriority::NOW &&
+ tiling_->has_visible_rect_tiles_) {
+ visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_,
+ tiling_->current_visible_rect_,
+ false /* include_borders */);
+ AdvanceNow();
+ }
+ break;
+ }
+}
+
+void PictureLayerTiling::TilingEvictionTileIterator::AdvanceEventually(
+ bool* skipped_tiles) {
+ bool required_for_activation =
+ eviction_category_ == EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION;
+ while (spiral_iterator_) {
+ std::pair<int, int> next_index = spiral_iterator_.index();
+ Tile* tile = tiling_->TileAt(next_index.first, next_index.second);
+ ++spiral_iterator_;
+ if (!tile || !tile->HasResources())
+ continue;
+ if (PrepareTileUnlessReturnedByTwin(tile) &&
+ tile->required_for_activation() == required_for_activation) {
+ current_tile_ = tile;
+ return;
+ }
+ if (skipped_tiles)
+ *skipped_tiles = true;
+ }
+
+ current_tile_ = nullptr;
+}
+
+void PictureLayerTiling::TilingEvictionTileIterator::AdvanceSoon() {
+ bool required_for_activation =
+ eviction_category_ == SOON_AND_REQUIRED_FOR_ACTIVATION;
+ while (spiral_iterator_) {
+ std::pair<int, int> next_index = spiral_iterator_.index();
+ Tile* tile = tiling_->TileAt(next_index.first, next_index.second);
+ ++spiral_iterator_;
+ if (tile && tile->HasResources() && PrepareTileUnlessReturnedByTwin(tile) &&
+ tile->required_for_activation() == required_for_activation) {
+ current_tile_ = tile;
+ return;
+ }
+ if (!spiral_iterator_ && processing_soon_border_rect_) {
+ if (tiling_->has_skewport_rect_tiles_) {
+ // Max tile priority bin should never be SOON so there is no need to
+ // create a special case for the inclusion of the visible rect.
+ DCHECK_EQ(tiling_->client_->GetMaxTilePriorityBin(), TilePriority::NOW);
+ DCHECK_LT(tiling_->client_->GetMaxTilePriorityBin(),
+ TilePriority::SOON);
+ spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator(
+ &tiling_->tiling_data_, tiling_->current_skewport_rect_,
+ tiling_->current_visible_rect_, tiling_->current_visible_rect_);
+ }
+ processing_soon_border_rect_ = false;
+ }
+ }
+
+ current_tile_ = nullptr;
+}
+
+void PictureLayerTiling::TilingEvictionTileIterator::AdvanceNow() {
+ bool required_for_activation =
+ eviction_category_ == NOW_AND_REQUIRED_FOR_ACTIVATION;
+ if (visible_iterator_) {
+ WhichTree tree = tiling_->client_->GetTree();
+ bool skip_all_shared_tiles =
+ skip_shared_high_priority_tiles_ &&
+ tree_priority_ == (tree == ACTIVE_TREE ? NEW_CONTENT_TAKES_PRIORITY
+ : SMOOTHNESS_TAKES_PRIORITY);
+ while (visible_iterator_) {
+ std::pair<int, int> next_index = visible_iterator_.index();
+ Tile* tile = tiling_->TileAt(next_index.first, next_index.second);
+ ++visible_iterator_;
+ if (!tile || !tile->HasResources())
+ continue;
+ if (skip_all_shared_tiles && tile->is_shared())
+ continue;
+ if (tree == PENDING_TREE &&
+ tiling_->IsTileRequiredForActivationIfVisible(tile) !=
+ required_for_activation)
+ continue;
+ if (!tiling_->IsTileOccluded(tile)) {
+ unoccluded_now_tiles_.push_back(tile);
+ continue;
+ }
+ if (PrepareTileUnlessReturnedByTwin(tile) &&
+ tile->required_for_activation() == required_for_activation) {
+ current_tile_ = tile;
+ return;
+ }
+ }
+ }
+
+ while (unoccluded_now_tiles_index_ < unoccluded_now_tiles_.size()) {
+ Tile* tile = unoccluded_now_tiles_[unoccluded_now_tiles_index_];
+ ++unoccluded_now_tiles_index_;
+ DCHECK(tile);
+ if (!tile->HasResources())
+ continue;
+ if (PrepareTileUnlessReturnedByTwin(tile) &&
+ tile->required_for_activation() == required_for_activation) {
+ current_tile_ = tile;
+ return;
+ }
+ }
+
+ current_tile_ = nullptr;
+}
+
+bool PictureLayerTiling::TilingEvictionTileIterator::
+ PrepareTileUnlessReturnedByTwin(Tile* tile) const {
+ if (skip_shared_high_priority_tiles_ && tile->is_shared()) {
+ WhichTree tree = tiling_->client_->GetTree();
+ switch (tree_priority_) {
+ case SMOOTHNESS_TAKES_PRIORITY:
+ // The priority for tile priority of a shared tile will be the active
+ // priority thus return shared tiles from the active tree.
+ if (tree != ACTIVE_TREE)
+ return false;
+ break;
+ case NEW_CONTENT_TAKES_PRIORITY:
+ // The priority for tile priority of a shared tile will be the pending
+ // priority thus return shared tiles from the pending tree.
+ if (tree != PENDING_TREE)
+ return false;
+ break;
+ case SAME_PRIORITY_FOR_BOTH_TREES: {
+ // The priority for tile priority of a shared tile will be a combined
+ // priority thus return shared tiles from a higher priority tree.
+ tiling_->UpdateTileAndTwinPriority(tile);
+ WhichTree other_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE;
+ const TilePriority& priority = tile->priority(tree);
+ const TilePriority& other_priority = tile->priority(other_tree);
+ if (priority.priority_bin != other_priority.priority_bin)
+ return priority.priority_bin < other_priority.priority_bin;
+ const bool occluded = tile->is_occluded(tree);
+ const bool other_occluded = tile->is_occluded(other_tree);
+ if (occluded != other_occluded)
+ return !occluded;
+ if (priority.distance_to_visible != other_priority.distance_to_visible)
+ return priority.distance_to_visible <
+ other_priority.distance_to_visible;
+ return tree == ACTIVE_TREE;
+ }
+ default:
+ NOTREACHED();
+ }
+ }
+ tiling_->UpdateTileAndTwinPriority(tile);
+ return true;
}
PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() {
}
PictureLayerTiling::TilingEvictionTileIterator::operator bool() const {
- return eviction_tiles_ &&
- current_eviction_tiles_index_ != eviction_tiles_->size();
+ return !!current_tile_;
}
Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() {
DCHECK(*this);
- return (*eviction_tiles_)[current_eviction_tiles_index_];
+ return current_tile_;
}
const Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() const {
DCHECK(*this);
- return (*eviction_tiles_)[current_eviction_tiles_index_];
+ return current_tile_;
}
PictureLayerTiling::TilingEvictionTileIterator&
PictureLayerTiling::TilingEvictionTileIterator::
operator++() {
- DCHECK(*this);
- do {
- ++current_eviction_tiles_index_;
- } while (current_eviction_tiles_index_ != eviction_tiles_->size() &&
- !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources());
-
+ switch (eviction_category_) {
+ case EVENTUALLY:
+ case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
+ AdvanceEventually(nullptr);
+ break;
+ case SOON:
+ case SOON_AND_REQUIRED_FOR_ACTIVATION:
+ AdvanceSoon();
+ break;
+ case NOW:
+ case NOW_AND_REQUIRED_FOR_ACTIVATION:
+ AdvanceNow();
+ break;
+ }
return *this;
}
« no previous file with comments | « cc/resources/picture_layer_tiling.h ('k') | cc/resources/picture_layer_tiling_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698