// 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/tiles/tiling_set_raster_queue_all.h" #include #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/tile.h" #include "cc/tiles/tile_priority.h" namespace cc { TilingSetRasterQueueAll::IterationStage::IterationStage( IteratorType type, TilePriority::PriorityBin bin) : iterator_type(type), tile_type(bin) { } 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()) return; const PictureLayerTilingClient* client = tiling_set->client(); WhichTree tree = tiling_set->tree(); // Find high and low res tilings and initialize the iterators. PictureLayerTiling* high_res_tiling = nullptr; PictureLayerTiling* low_res_tiling = nullptr; // This variable would point to a tiling that has a NON_IDEAL_RESOLUTION // resolution on the active tree, but HIGH_RESOLUTION on the pending tree. // These tilings are the only non-ideal tilings that could have required for // activation tiles, so they need to be considered for rasterization. PictureLayerTiling* active_non_ideal_pending_high_res_tiling = nullptr; for (size_t i = 0; i < tiling_set_->num_tilings(); ++i) { PictureLayerTiling* tiling = tiling_set_->tiling_at(i); if (tiling->resolution() == HIGH_RESOLUTION) high_res_tiling = tiling; if (prioritize_low_res && tiling->resolution() == LOW_RESOLUTION) low_res_tiling = tiling; if (tree == ACTIVE_TREE && tiling->resolution() == NON_IDEAL_RESOLUTION) { const PictureLayerTiling* twin = client->GetPendingOrActiveTwinTiling(tiling); if (twin && twin->resolution() == HIGH_RESOLUTION) active_non_ideal_pending_high_res_tiling = tiling; } } bool use_low_res_tiling = low_res_tiling && low_res_tiling->has_tiles() && !low_res_tiling->all_tiles_done(); bool use_high_res_tiling = high_res_tiling && high_res_tiling->has_tiles() && !high_res_tiling->all_tiles_done(); bool use_active_non_ideal_pending_high_res_tiling = active_non_ideal_pending_high_res_tiling && active_non_ideal_pending_high_res_tiling->has_tiles() && !active_non_ideal_pending_high_res_tiling->all_tiles_done(); // Make the tiling iterators. if (use_low_res_tiling) MakeTilingIterator(LOW_RES, low_res_tiling); if (use_high_res_tiling) MakeTilingIterator(HIGH_RES, high_res_tiling); if (use_active_non_ideal_pending_high_res_tiling) { MakeTilingIterator(ACTIVE_NON_IDEAL_PENDING_HIGH_RES, active_non_ideal_pending_high_res_tiling); } // Set up the stages. if (use_low_res_tiling && prioritize_low_res) stages_->push_back(IterationStage(LOW_RES, TilePriority::NOW)); if (use_high_res_tiling) stages_->push_back(IterationStage(HIGH_RES, TilePriority::NOW)); if (low_res_tiling && !prioritize_low_res) stages_->push_back(IterationStage(LOW_RES, TilePriority::NOW)); if (use_active_non_ideal_pending_high_res_tiling) { stages_->push_back( IterationStage(ACTIVE_NON_IDEAL_PENDING_HIGH_RES, TilePriority::NOW)); stages_->push_back( IterationStage(ACTIVE_NON_IDEAL_PENDING_HIGH_RES, TilePriority::SOON)); } if (use_high_res_tiling) { stages_->push_back(IterationStage(HIGH_RES, TilePriority::SOON)); stages_->push_back(IterationStage(HIGH_RES, TilePriority::EVENTUALLY)); } if (stages_->empty()) return; 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() { } void TilingSetRasterQueueAll::MakeTilingIterator(IteratorType type, PictureLayerTiling* tiling) { iterators_[type] = TilingIterator(tiling, &tiling->tiling_data_); if (iterators_[type].done()) tiling->set_all_tiles_done(true); } bool TilingSetRasterQueueAll::IsEmpty() const { return current_stage_ >= stages_->size(); } 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(); } const PrioritizedTile& 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_, stages_->size()); ++current_stage_; while (current_stage_ < stages_->size()) { 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_; } } // OnePriorityRectIterator TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator() : tiling_(nullptr), tiling_data_(nullptr) { } TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator( PictureLayerTiling* tiling, TilingData* tiling_data, PictureLayerTiling::PriorityRectType priority_rect_type) : tiling_(tiling), tiling_data_(tiling_data), priority_rect_type_(priority_rect_type), pending_visible_rect_(tiling->pending_visible_rect()) { } template void TilingSetRasterQueueAll::OnePriorityRectIterator::AdvanceToNextTile( TilingIteratorType* iterator) { for (;;) { ++(*iterator); if (!(*iterator)) { current_tile_ = PrioritizedTile(); break; } Tile* tile = tiling_->TileAt(iterator->index_x(), iterator->index_y()); if (IsTileValid(tile)) { tiling_->UpdateRequiredStatesOnTile(tile); current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_); break; } } } template bool TilingSetRasterQueueAll::OnePriorityRectIterator:: GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) { Tile* tile = tiling_->TileAt(iterator->index_x(), iterator->index_y()); if (!IsTileValid(tile)) { current_tile_ = PrioritizedTile(); return false; } tiling_->UpdateRequiredStatesOnTile(tile); current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_); return true; } bool TilingSetRasterQueueAll::OnePriorityRectIterator::IsTileValid( const Tile* tile) const { if (!tile || !TileNeedsRaster(tile)) return false; // After the pending visible rect has been processed, we must return false // for pending visible rect tiles as tiling iterators do not ignore those // tiles. if (priority_rect_type_ > PictureLayerTiling::PENDING_VISIBLE_RECT && pending_visible_rect_.Intersects(tile->content_rect())) { return false; } return true; } // VisibleTilingIterator. TilingSetRasterQueueAll::VisibleTilingIterator::VisibleTilingIterator( PictureLayerTiling* tiling, TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, PictureLayerTiling::VISIBLE_RECT) { if (!tiling_->has_visible_rect_tiles()) return; iterator_ = TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(), false /* include_borders */); if (!iterator_) return; if (!GetFirstTileAndCheckIfValid(&iterator_)) ++(*this); } TilingSetRasterQueueAll::VisibleTilingIterator& TilingSetRasterQueueAll::VisibleTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); return *this; } // PendingVisibleTilingIterator. TilingSetRasterQueueAll::PendingVisibleTilingIterator:: PendingVisibleTilingIterator(PictureLayerTiling* tiling, TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, PictureLayerTiling::PENDING_VISIBLE_RECT) { iterator_ = TilingData::DifferenceIterator( tiling_data_, pending_visible_rect_, tiling_->current_visible_rect()); if (!iterator_) return; if (!GetFirstTileAndCheckIfValid(&iterator_)) ++(*this); } TilingSetRasterQueueAll::PendingVisibleTilingIterator& TilingSetRasterQueueAll::PendingVisibleTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); return *this; } // SkewportTilingIterator. TilingSetRasterQueueAll::SkewportTilingIterator::SkewportTilingIterator( PictureLayerTiling* tiling, TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, PictureLayerTiling::SKEWPORT_RECT) { if (!tiling_->has_skewport_rect_tiles()) return; iterator_ = TilingData::SpiralDifferenceIterator( tiling_data_, tiling_->current_skewport_rect(), tiling_->current_visible_rect(), tiling_->current_visible_rect()); if (!iterator_) return; if (!GetFirstTileAndCheckIfValid(&iterator_)) { ++(*this); return; } } TilingSetRasterQueueAll::SkewportTilingIterator& TilingSetRasterQueueAll::SkewportTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); return *this; } // SoonBorderTilingIterator. TilingSetRasterQueueAll::SoonBorderTilingIterator::SoonBorderTilingIterator( PictureLayerTiling* tiling, TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, PictureLayerTiling::SOON_BORDER_RECT) { if (!tiling_->has_soon_border_rect_tiles()) return; iterator_ = TilingData::SpiralDifferenceIterator( tiling_data_, tiling_->current_soon_border_rect(), tiling_->current_skewport_rect(), tiling_->current_visible_rect()); if (!iterator_) return; if (!GetFirstTileAndCheckIfValid(&iterator_)) { ++(*this); return; } } TilingSetRasterQueueAll::SoonBorderTilingIterator& TilingSetRasterQueueAll::SoonBorderTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); return *this; } // EventuallyTilingIterator. TilingSetRasterQueueAll::EventuallyTilingIterator::EventuallyTilingIterator( PictureLayerTiling* tiling, TilingData* tiling_data) : OnePriorityRectIterator(tiling, tiling_data, PictureLayerTiling::EVENTUALLY_RECT) { if (!tiling_->has_eventually_rect_tiles()) return; iterator_ = TilingData::SpiralDifferenceIterator( tiling_data_, tiling_->current_eventually_rect(), tiling_->current_skewport_rect(), tiling_->current_soon_border_rect()); if (!iterator_) return; if (!GetFirstTileAndCheckIfValid(&iterator_)) { ++(*this); return; } } TilingSetRasterQueueAll::EventuallyTilingIterator& TilingSetRasterQueueAll::EventuallyTilingIterator:: operator++() { AdvanceToNextTile(&iterator_); return *this; } // TilingIterator TilingSetRasterQueueAll::TilingIterator::TilingIterator() : tiling_(nullptr) { } TilingSetRasterQueueAll::TilingIterator::TilingIterator( PictureLayerTiling* tiling, TilingData* tiling_data) : tiling_(tiling), tiling_data_(tiling_data), phase_(Phase::VISIBLE_RECT) { visible_iterator_ = VisibleTilingIterator(tiling_, tiling_data_); if (visible_iterator_.done()) { AdvancePhase(); return; } current_tile_ = *visible_iterator_; } TilingSetRasterQueueAll::TilingIterator::~TilingIterator() { } void TilingSetRasterQueueAll::TilingIterator::AdvancePhase() { DCHECK_LT(phase_, Phase::EVENTUALLY_RECT); current_tile_ = PrioritizedTile(); while (!current_tile_.tile() && phase_ < Phase::EVENTUALLY_RECT) { phase_ = static_cast(phase_ + 1); switch (phase_) { case Phase::VISIBLE_RECT: NOTREACHED(); return; case Phase::PENDING_VISIBLE_RECT: pending_visible_iterator_ = PendingVisibleTilingIterator(tiling_, tiling_data_); if (!pending_visible_iterator_.done()) current_tile_ = *pending_visible_iterator_; break; case Phase::SKEWPORT_RECT: skewport_iterator_ = SkewportTilingIterator(tiling_, tiling_data_); if (!skewport_iterator_.done()) current_tile_ = *skewport_iterator_; break; case Phase::SOON_BORDER_RECT: soon_border_iterator_ = SoonBorderTilingIterator(tiling_, tiling_data_); if (!soon_border_iterator_.done()) current_tile_ = *soon_border_iterator_; break; case Phase::EVENTUALLY_RECT: eventually_iterator_ = EventuallyTilingIterator(tiling_, tiling_data_); if (!eventually_iterator_.done()) current_tile_ = *eventually_iterator_; break; } } } TilingSetRasterQueueAll::TilingIterator& TilingSetRasterQueueAll::TilingIterator:: operator++() { switch (phase_) { case Phase::VISIBLE_RECT: ++visible_iterator_; if (visible_iterator_.done()) { AdvancePhase(); return *this; } current_tile_ = *visible_iterator_; break; case Phase::PENDING_VISIBLE_RECT: ++pending_visible_iterator_; if (pending_visible_iterator_.done()) { AdvancePhase(); return *this; } current_tile_ = *pending_visible_iterator_; break; case Phase::SKEWPORT_RECT: ++skewport_iterator_; if (skewport_iterator_.done()) { AdvancePhase(); return *this; } current_tile_ = *skewport_iterator_; break; case Phase::SOON_BORDER_RECT: ++soon_border_iterator_; if (soon_border_iterator_.done()) { AdvancePhase(); return *this; } current_tile_ = *soon_border_iterator_; break; case Phase::EVENTUALLY_RECT: ++eventually_iterator_; if (eventually_iterator_.done()) { current_tile_ = PrioritizedTile(); return *this; } current_tile_ = *eventually_iterator_; break; } return *this; } } // namespace cc