| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/resources/tiling_set_raster_queue_all.h" |
| |
| #include <utility> |
| |
| #include "cc/resources/picture_layer_tiling_set.h" |
| #include "cc/resources/tile.h" |
| #include "cc/resources/tile_priority.h" |
| |
| namespace cc { |
| |
| TilingSetRasterQueueAll::TilingSetRasterQueueAll( |
| PictureLayerTilingSet* tiling_set, |
| bool prioritize_low_res) |
| : tiling_set_(tiling_set), current_stage_(0) { |
| DCHECK(tiling_set_); |
| |
| // Early out if the tiling set has no tilings. |
| if (!tiling_set_->num_tilings()) { |
| current_stage_ = arraysize(stages_); |
| return; |
| } |
| |
| // Find high and low res tilings and initialize the iterators. |
| for (size_t i = 0; i < tiling_set_->num_tilings(); ++i) { |
| PictureLayerTiling* tiling = tiling_set_->tiling_at(i); |
| if (tiling->resolution() == HIGH_RESOLUTION) |
| iterators_[HIGH_RES] = TilingIterator(tiling, &tiling->tiling_data_); |
| if (prioritize_low_res && tiling->resolution() == LOW_RESOLUTION) |
| iterators_[LOW_RES] = TilingIterator(tiling, &tiling->tiling_data_); |
| } |
| |
| if (prioritize_low_res) { |
| stages_[0].iterator_type = LOW_RES; |
| stages_[0].tile_type = TilePriority::NOW; |
| |
| stages_[1].iterator_type = HIGH_RES; |
| stages_[1].tile_type = TilePriority::NOW; |
| } else { |
| stages_[0].iterator_type = HIGH_RES; |
| stages_[0].tile_type = TilePriority::NOW; |
| |
| stages_[1].iterator_type = LOW_RES; |
| stages_[1].tile_type = TilePriority::NOW; |
| } |
| |
| stages_[2].iterator_type = HIGH_RES; |
| stages_[2].tile_type = TilePriority::SOON; |
| |
| stages_[3].iterator_type = HIGH_RES; |
| stages_[3].tile_type = TilePriority::EVENTUALLY; |
| |
| IteratorType index = stages_[current_stage_].iterator_type; |
| TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type; |
| if (iterators_[index].done() || iterators_[index].type() != tile_type) |
| AdvanceToNextStage(); |
| } |
| |
| TilingSetRasterQueueAll::~TilingSetRasterQueueAll() { |
| } |
| |
| bool TilingSetRasterQueueAll::IsEmpty() const { |
| return current_stage_ >= arraysize(stages_); |
| } |
| |
| void TilingSetRasterQueueAll::Pop() { |
| IteratorType index = stages_[current_stage_].iterator_type; |
| TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type; |
| |
| // First advance the iterator. |
| DCHECK(!iterators_[index].done()); |
| DCHECK(iterators_[index].type() == tile_type); |
| ++iterators_[index]; |
| |
| if (iterators_[index].done() || iterators_[index].type() != tile_type) |
| AdvanceToNextStage(); |
| } |
| |
| Tile* TilingSetRasterQueueAll::Top() { |
| DCHECK(!IsEmpty()); |
| |
| IteratorType index = stages_[current_stage_].iterator_type; |
| DCHECK(!iterators_[index].done()); |
| DCHECK(iterators_[index].type() == stages_[current_stage_].tile_type); |
| |
| return *iterators_[index]; |
| } |
| |
| const Tile* TilingSetRasterQueueAll::Top() const { |
| DCHECK(!IsEmpty()); |
| |
| IteratorType index = stages_[current_stage_].iterator_type; |
| DCHECK(!iterators_[index].done()); |
| DCHECK(iterators_[index].type() == stages_[current_stage_].tile_type); |
| |
| return *iterators_[index]; |
| } |
| |
| void TilingSetRasterQueueAll::AdvanceToNextStage() { |
| DCHECK_LT(current_stage_, arraysize(stages_)); |
| ++current_stage_; |
| while (current_stage_ < arraysize(stages_)) { |
| IteratorType index = stages_[current_stage_].iterator_type; |
| TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type; |
| |
| if (!iterators_[index].done() && iterators_[index].type() == tile_type) |
| break; |
| ++current_stage_; |
| } |
| } |
| |
| TilingSetRasterQueueAll::TilingIterator::TilingIterator() |
| : tiling_(NULL), current_tile_(NULL) { |
| } |
| |
| TilingSetRasterQueueAll::TilingIterator::TilingIterator( |
| PictureLayerTiling* tiling, |
| TilingData* tiling_data) |
| : tiling_(tiling), |
| tiling_data_(tiling_data), |
| phase_(VISIBLE_RECT), |
| current_tile_(NULL) { |
| if (!tiling_->has_visible_rect_tiles()) { |
| AdvancePhase(); |
| return; |
| } |
| |
| visible_iterator_ = |
| TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(), |
| false /* include_borders */); |
| if (!visible_iterator_) { |
| AdvancePhase(); |
| return; |
| } |
| |
| current_tile_ = |
| tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); |
| if (!current_tile_ || !TileNeedsRaster(current_tile_)) { |
| ++(*this); |
| return; |
| } |
| tiling_->UpdateTileAndTwinPriority(current_tile_); |
| } |
| |
| TilingSetRasterQueueAll::TilingIterator::~TilingIterator() { |
| } |
| |
| void TilingSetRasterQueueAll::TilingIterator::AdvancePhase() { |
| DCHECK_LT(phase_, EVENTUALLY_RECT); |
| |
| do { |
| phase_ = static_cast<Phase>(phase_ + 1); |
| switch (phase_) { |
| case VISIBLE_RECT: |
| NOTREACHED(); |
| return; |
| case SKEWPORT_RECT: |
| if (!tiling_->has_skewport_rect_tiles()) |
| continue; |
| |
| spiral_iterator_ = TilingData::SpiralDifferenceIterator( |
| tiling_data_, tiling_->current_skewport_rect(), |
| tiling_->current_visible_rect(), tiling_->current_visible_rect()); |
| break; |
| case SOON_BORDER_RECT: |
| if (!tiling_->has_soon_border_rect_tiles()) |
| continue; |
| |
| spiral_iterator_ = TilingData::SpiralDifferenceIterator( |
| tiling_data_, tiling_->current_soon_border_rect(), |
| tiling_->current_skewport_rect(), tiling_->current_visible_rect()); |
| break; |
| case EVENTUALLY_RECT: |
| if (!tiling_->has_eventually_rect_tiles()) { |
| current_tile_ = NULL; |
| return; |
| } |
| |
| spiral_iterator_ = TilingData::SpiralDifferenceIterator( |
| tiling_data_, tiling_->current_eventually_rect(), |
| tiling_->current_skewport_rect(), |
| tiling_->current_soon_border_rect()); |
| break; |
| } |
| |
| while (spiral_iterator_) { |
| current_tile_ = tiling_->TileAt(spiral_iterator_.index_x(), |
| spiral_iterator_.index_y()); |
| if (current_tile_ && TileNeedsRaster(current_tile_)) |
| break; |
| ++spiral_iterator_; |
| } |
| |
| if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) { |
| current_tile_ = NULL; |
| break; |
| } |
| } while (!spiral_iterator_); |
| |
| if (current_tile_) |
| tiling_->UpdateTileAndTwinPriority(current_tile_); |
| } |
| |
| TilingSetRasterQueueAll::TilingIterator& |
| TilingSetRasterQueueAll::TilingIterator:: |
| operator++() { |
| current_tile_ = NULL; |
| while (!current_tile_ || !TileNeedsRaster(current_tile_)) { |
| std::pair<int, int> next_index; |
| switch (phase_) { |
| case VISIBLE_RECT: |
| ++visible_iterator_; |
| if (!visible_iterator_) { |
| AdvancePhase(); |
| return *this; |
| } |
| next_index = visible_iterator_.index(); |
| break; |
| case SKEWPORT_RECT: |
| case SOON_BORDER_RECT: |
| ++spiral_iterator_; |
| if (!spiral_iterator_) { |
| AdvancePhase(); |
| return *this; |
| } |
| next_index = spiral_iterator_.index(); |
| break; |
| case EVENTUALLY_RECT: |
| ++spiral_iterator_; |
| if (!spiral_iterator_) { |
| current_tile_ = NULL; |
| return *this; |
| } |
| next_index = spiral_iterator_.index(); |
| break; |
| } |
| current_tile_ = tiling_->TileAt(next_index.first, next_index.second); |
| } |
| |
| if (current_tile_) |
| tiling_->UpdateTileAndTwinPriority(current_tile_); |
| return *this; |
| } |
| |
| } // namespace cc |