Chromium Code Reviews| 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..8f010227a4c878222078d2a5824f82ae41e34095 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,120 @@ 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_[HIGHER_THAN_HIGH_RES].start_index = 0; |
| + ranges_[HIGHER_THAN_HIGH_RES].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_[LOWER_THAN_LOW_RES].start_index = layer_->tilings_->num_tilings() - 1; |
| + ranges_[LOWER_THAN_LOW_RES].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_[BETWEEN_HIGH_AND_LOW_RES].start_index = low_res_tiling_index - 1; |
| + ranges_[BETWEEN_HIGH_AND_LOW_RES].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_[LOW_RES].start_index = low_res_tiling_index; |
| + ranges_[LOW_RES].one_past_end_index = low_res_tiling_index + 1; |
| + } else { |
| + // If there is no LOW_RES tiling, then set an empty range. |
| + ranges_[LOW_RES].start_index = 0; |
| + ranges_[LOW_RES].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_[HIGH_RES].start_index = high_res_tiling_index; |
| + ranges_[HIGH_RES].one_past_end_index = high_res_tiling_index + 1; |
| - DCHECK_GT(iterators_.size(), 0u); |
| + range_index_ = HIGHER_THAN_HIGH_RES; |
| + 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; |
| } |
|
reveman
2014/07/29 21:41:32
I think I'd like to see this function removed and
vmpstr
2014/07/30 00:18:51
I'm still a little bit confused about how we would
reveman
2014/07/30 16:06:47
See my comment about RangeOffsetToTilingSetIndex b
vmpstr
2014/07/30 20:06:39
Acknowledged.
|
| -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; |
|
reveman
2014/07/29 21:41:32
hm, doesn't this need to be a nested loop? ie. we
vmpstr
2014/07/30 00:18:51
AdvanceTiling will advance to the next tiling if o
reveman
2014/07/31 15:32:47
AdvanceTiling doesn't advance until it finds non-e
vmpstr
2014/08/01 06:04:48
Well, this is kind of a weird one. Here's my reaso
reveman
2014/08/01 17:54:46
I feel like there's a lack of uniformity in curren
vmpstr
2014/08/01 19:39:50
Done.
|
| -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()) |
|
reveman
2014/07/29 21:41:33
Seems odd that we check this both before and after
vmpstr
2014/07/30 00:18:52
I don't think this was required. I replaced it wit
reveman
2014/07/31 15:32:47
Acknowledged.
|
| + return false; |
| + |
| + int direction = ranges_[range_index_].start_index < |
| + ranges_[range_index_].one_past_end_index |
| + ? 1 |
| + : -1; |
|
reveman
2014/07/29 21:41:32
I think it would be cleaner to adjust the index ba
vmpstr
2014/07/30 00:18:52
I'm not sure I understand what you mean. Would Ran
reveman
2014/07/30 16:06:48
RangeOffsetToTilingSetIndex would simply take an o
vmpstr
2014/07/30 20:06:38
I've done this. To be honest, I find this more con
reveman
2014/07/31 15:32:47
Let's see what it looks like after rebase onto my
vmpstr
2014/08/01 06:04:48
Done.
|
| + 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()); |
| + bool wrapped_around = false; |
|
reveman
2014/07/29 21:41:32
I think this function would be a bit cleaner with
vmpstr
2014/07/30 00:18:52
switch (range_index_) {
case HIGHER_THAN_HIGH_RES
reveman
2014/07/31 15:32:47
Yup, thanks!
|
| + while (!CurrentTilingIndexInRange()) { |
| + range_index_ = static_cast<RangeType>((range_index_ + 1) % NUM_RANGE_TYPES); |
| + tiling_index_ = ranges_[range_index_].start_index; |
| + if (range_index_ == 0) |
| + wrapped_around = true; |
| } |
| - return *this; |
| + // If we wrapped around the ranges, we need to indicate that we should advance |
| + // the stage. |
| + return !wrapped_around; |
| } |
| -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() { |
|
reveman
2014/07/29 21:41:33
Think this function would also be cleaner with a s
vmpstr
2014/07/30 00:18:52
switch over bins? That would end up looking like t
reveman
2014/07/30 16:06:47
Why don't we add an enum for all stages? ie. EVENT
vmpstr
2014/07/30 20:06:38
I don't like that. Either this enum would have to
reveman
2014/07/31 15:32:47
Enum living here and two utility functions that re
vmpstr
2014/08/01 06:04:48
Done.
|
| + // 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_; |
|
reveman
2014/07/29 21:41:32
!!iterator_?
vmpstr
2014/07/30 00:18:51
Done.
|
| } |
| } // namespace cc |