Index: cc/layers/picture_layer_impl.cc |
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc |
index 181501310760f60df712761baef455a373ebab13..ba9a14fb5134ce9c4c2a4420873f65f5b8645081 100644 |
--- a/cc/layers/picture_layer_impl.cc |
+++ b/cc/layers/picture_layer_impl.cc |
@@ -1556,17 +1556,22 @@ const Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() const { |
} |
PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator() |
- : iterator_index_(0), |
+ : tiling_index_(0), |
iteration_stage_(TilePriority::EVENTUALLY), |
+ range_index_(0), |
required_for_activation_(false), |
- layer_(NULL) {} |
+ tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES), |
+ layer_(NULL) { |
+} |
PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator( |
PictureLayerImpl* layer, |
TreePriority tree_priority) |
- : iterator_index_(0), |
+ : tiling_index_(0), |
iteration_stage_(TilePriority::EVENTUALLY), |
+ range_index_(0), |
required_for_activation_(false), |
+ tree_priority_(tree_priority), |
layer_(layer) { |
// Early out if the layer has no tilings. |
// TODO(vmpstr): Once tile priorities are determined by the iterators, ensure |
@@ -1575,6 +1580,49 @@ PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator( |
if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) |
return; |
+ ConstructRanges(); |
+ if (!CurrentTilingIndexInRange()) |
+ AdvanceRange(); |
+ |
+ // There must be at least one valid range. |
+ DCHECK(CurrentTilingIndexInRange()); |
+ |
+ iterator_ = PictureLayerTiling::TilingEvictionTileIterator( |
+ layer_->tilings_->tiling_at(tiling_index_), |
+ tree_priority, |
+ iteration_stage_, |
+ required_for_activation_); |
+ |
+ if (!iterator_) |
+ AdvanceToNextIterator(); |
+} |
+ |
+PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() { |
+} |
+ |
+Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() { |
+ DCHECK(*this); |
+ return *iterator_; |
+} |
+ |
+const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const { |
+ DCHECK(*this); |
+ return *iterator_; |
+} |
+ |
+PictureLayerImpl::LayerEvictionTileIterator& |
+PictureLayerImpl::LayerEvictionTileIterator:: |
+operator++() { |
+ DCHECK(*this); |
+ ++iterator_; |
+ |
+ if (!iterator_) |
+ AdvanceToNextIterator(); |
+ return *this; |
+} |
+ |
+void PictureLayerImpl::LayerEvictionTileIterator::ConstructRanges() { |
+ // TODO(vmpstr): See if these can be looked up from the tiling set. |
size_t high_res_tiling_index = layer_->tilings_->num_tilings(); |
size_t low_res_tiling_index = layer_->tilings_->num_tilings(); |
for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) { |
@@ -1585,106 +1633,119 @@ PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator( |
low_res_tiling_index = i; |
} |
- iterators_.reserve(layer_->tilings_->num_tilings()); |
+ DCHECK_LT(high_res_tiling_index, layer_->tilings_->num_tilings()); |
- // Higher resolution non-ideal goes first. |
- for (size_t i = 0; i < high_res_tiling_index; ++i) { |
- iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator( |
- layer_->tilings_->tiling_at(i), tree_priority)); |
- } |
+ // First iterate from highest resolution to the HIGH_RES tiling. |
+ ranges_[0].start_index = 0; |
+ ranges_[0].one_past_end_index = high_res_tiling_index; |
- // Lower resolution non-ideal goes next. |
- for (size_t i = layer_->tilings_->num_tilings() - 1; |
- i > high_res_tiling_index; |
- --i) { |
- PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i); |
- if (tiling->resolution() == LOW_RESOLUTION) |
- continue; |
+ // Next, iterate from the lowest resolution to the LOW_RES tiling. Note that |
+ // if we don't have a low res tiling, then the start index will be the same as |
+ // one past the end, which means it is an empty range. |
+ ranges_[1].start_index = layer_->tilings_->num_tilings() - 1; |
+ ranges_[1].one_past_end_index = low_res_tiling_index; |
- iterators_.push_back( |
- PictureLayerTiling::TilingEvictionTileIterator(tiling, tree_priority)); |
- } |
+ // Next, iterate from just after the LOW_RES tiling to the HIGH_RES tiling. |
+ // Note that if there is no low res tiling, then start index will be the last |
+ // tiling. |
+ ranges_[2].start_index = low_res_tiling_index - 1; |
+ ranges_[2].one_past_end_index = high_res_tiling_index; |
- // Now, put the low res tiling if we have one. |
if (low_res_tiling_index < layer_->tilings_->num_tilings()) { |
- iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator( |
- layer_->tilings_->tiling_at(low_res_tiling_index), tree_priority)); |
+ // Next, iterate a range of one element: LOW_RES tiling. |
+ ranges_[3].start_index = low_res_tiling_index; |
+ ranges_[3].one_past_end_index = low_res_tiling_index + 1; |
+ } else { |
+ // If there is no LOW_RES tiling, then set an empty range. |
+ ranges_[3].start_index = 0; |
+ ranges_[3].one_past_end_index = 0; |
} |
- // Finally, put the high res tiling if we have one. |
- if (high_res_tiling_index < layer_->tilings_->num_tilings()) { |
- iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator( |
- layer_->tilings_->tiling_at(high_res_tiling_index), tree_priority)); |
- } |
+ // Finally, iterate a range of one element: HIGH_RES tiling. |
+ ranges_[4].start_index = high_res_tiling_index; |
+ ranges_[4].one_past_end_index = high_res_tiling_index + 1; |
- DCHECK_GT(iterators_.size(), 0u); |
+ range_index_ = 0; |
+ tiling_index_ = ranges_[range_index_].start_index; |
+} |
- if (!iterators_[iterator_index_] || |
- !IsCorrectType(&iterators_[iterator_index_])) { |
- AdvanceToNextIterator(); |
+bool PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndexInRange() { |
+ TilingIterationRange& range = ranges_[range_index_]; |
+ if (range.start_index < range.one_past_end_index) { |
+ return tiling_index_ >= range.start_index && |
+ tiling_index_ < range.one_past_end_index; |
+ } else if (range.start_index > range.one_past_end_index) { |
+ return tiling_index_ <= range.start_index && |
+ tiling_index_ > range.one_past_end_index; |
} |
+ // Empty range means we're not in range. |
+ return false; |
} |
-PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {} |
+void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() { |
+ DCHECK(!iterator_); |
+ while (!iterator_) { |
+ bool success = AdvanceTiling(); |
+ if (!success) |
+ success = AdvanceRange(); |
+ if (!success) |
+ success = AdvanceStage(); |
+ if (!success) |
+ break; |
-Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() { |
- DCHECK(*this); |
- return *iterators_[iterator_index_]; |
+ iterator_ = PictureLayerTiling::TilingEvictionTileIterator( |
+ layer_->tilings_->tiling_at(tiling_index_), |
+ tree_priority_, |
+ iteration_stage_, |
+ required_for_activation_); |
+ } |
} |
-const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const { |
- DCHECK(*this); |
- return *iterators_[iterator_index_]; |
+bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceTiling() { |
+ // We can't advance the tiling if we're already not in range. |
+ if (!CurrentTilingIndexInRange()) |
+ return false; |
+ |
+ int direction = ranges_[range_index_].start_index < |
+ ranges_[range_index_].one_past_end_index |
+ ? 1 |
+ : -1; |
+ tiling_index_ += direction; |
+ |
+ return CurrentTilingIndexInRange(); |
} |
-PictureLayerImpl::LayerEvictionTileIterator& |
-PictureLayerImpl::LayerEvictionTileIterator:: |
-operator++() { |
- DCHECK(*this); |
- ++iterators_[iterator_index_]; |
- if (!iterators_[iterator_index_] || |
- !IsCorrectType(&iterators_[iterator_index_])) { |
- AdvanceToNextIterator(); |
+bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceRange() { |
+ DCHECK(!CurrentTilingIndexInRange()); |
+ while (!CurrentTilingIndexInRange()) { |
+ range_index_ = (range_index_ + 1) % arraysize(ranges_); |
+ tiling_index_ = ranges_[range_index_].start_index; |
+ // If we failed to find a range and cycled back to the start, then we need |
+ // to indicate that we should advance the stage instead. |
+ if (range_index_ == 0) |
+ return false; |
} |
- return *this; |
+ return true; |
} |
-void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() { |
- ++iterator_index_; |
- |
- while (true) { |
- while (iterator_index_ < iterators_.size()) { |
- if (iterators_[iterator_index_] && |
- IsCorrectType(&iterators_[iterator_index_])) { |
- return; |
- } |
- ++iterator_index_; |
- } |
- |
- // If we're NOW and required_for_activation, then this was the last pass |
- // through the iterators. |
- if (iteration_stage_ == TilePriority::NOW && required_for_activation_) |
- break; |
+bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceStage() { |
+ // If we're NOW and required_for_activation, then this was the last pass |
+ // through the iterators. |
+ if (iteration_stage_ == TilePriority::NOW && required_for_activation_) |
+ return false; |
- if (!required_for_activation_) { |
- required_for_activation_ = true; |
- } else { |
- required_for_activation_ = false; |
- iteration_stage_ = |
- static_cast<TilePriority::PriorityBin>(iteration_stage_ - 1); |
- } |
- iterator_index_ = 0; |
+ if (!required_for_activation_) { |
+ required_for_activation_ = true; |
+ } else { |
+ required_for_activation_ = false; |
+ iteration_stage_ = |
+ static_cast<TilePriority::PriorityBin>(iteration_stage_ - 1); |
} |
+ return true; |
} |
PictureLayerImpl::LayerEvictionTileIterator::operator bool() const { |
- return iterator_index_ < iterators_.size(); |
-} |
- |
-bool PictureLayerImpl::LayerEvictionTileIterator::IsCorrectType( |
- PictureLayerTiling::TilingEvictionTileIterator* it) const { |
- return it->get_type() == iteration_stage_ && |
- (**it)->required_for_activation() == required_for_activation_; |
+ return iterator_; |
} |
} // namespace cc |