// 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_required.h" #include #include #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/tile.h" #include "cc/tiles/tile_priority.h" namespace cc { TilingSetRasterQueueRequired::TilingSetRasterQueueRequired( PictureLayerTilingSet* tiling_set, RasterTilePriorityQueue::Type type) : type_(type) { DCHECK_NE(static_cast(type), static_cast(RasterTilePriorityQueue::Type::ALL)); // Required tiles should only come from HIGH_RESOLUTION tilings. However, if // we want required for activation tiles on the active tree, then it will come // from tilings whose pending twin is high resolution. PictureLayerTiling* tiling = nullptr; if (type == RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION && tiling_set->tree() == ACTIVE_TREE) { for (size_t i = 0; i < tiling_set->num_tilings(); ++i) { PictureLayerTiling* active_tiling = tiling_set->tiling_at(i); const PictureLayerTiling* pending_twin = tiling_set->client()->GetPendingOrActiveTwinTiling(active_tiling); if (pending_twin && pending_twin->resolution() == HIGH_RESOLUTION) { tiling = active_tiling; break; } } } else { tiling = tiling_set->FindTilingWithResolution(HIGH_RESOLUTION); } // If we don't have a tiling, then this queue will yield no tiles. See // PictureLayerImpl::CanHaveTilings for examples of when a HIGH_RESOLUTION // tiling would not be generated. if (!tiling || tiling->all_tiles_done()) return; if (type == RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION) { iterator_ = TilingIterator(tiling, &tiling->tiling_data_, tiling->pending_visible_rect()); } else { iterator_ = TilingIterator(tiling, &tiling->tiling_data_, tiling->current_visible_rect()); } while (!iterator_.done() && !IsTileRequired(*iterator_)) ++iterator_; } TilingSetRasterQueueRequired::~TilingSetRasterQueueRequired() { } bool TilingSetRasterQueueRequired::IsEmpty() const { return iterator_.done(); } void TilingSetRasterQueueRequired::Pop() { DCHECK(!IsEmpty()); ++iterator_; while (!iterator_.done() && !IsTileRequired(*iterator_)) ++iterator_; } const PrioritizedTile& TilingSetRasterQueueRequired::Top() const { DCHECK(!IsEmpty()); return *iterator_; } bool TilingSetRasterQueueRequired::IsTileRequired( const PrioritizedTile& prioritized_tile) const { return (type_ == RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION && prioritized_tile.tile()->required_for_activation()) || (type_ == RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW && prioritized_tile.tile()->required_for_draw()); } TilingSetRasterQueueRequired::TilingIterator::TilingIterator() : tiling_(nullptr) { } TilingSetRasterQueueRequired::TilingIterator::TilingIterator( PictureLayerTiling* tiling, TilingData* tiling_data, const gfx::Rect& rect) : tiling_(tiling), tiling_data_(tiling_data) { visible_iterator_ = TilingData::Iterator(tiling_data_, rect, false /* include_borders */); if (!visible_iterator_) return; Tile* tile = tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); // If this is a valid tile, return it. Note that we have to use a tiling check // for occlusion, since the tile's internal state has not yet been updated. if (tile && tile->draw_info().NeedsRaster() && !tiling_->IsTileOccluded(tile)) { tiling_->UpdateRequiredStatesOnTile(tile); current_tile_ = tiling_->MakePrioritizedTile( tile, tiling_->ComputePriorityRectTypeForTile(tile)); return; } ++(*this); } TilingSetRasterQueueRequired::TilingIterator::~TilingIterator() { } TilingSetRasterQueueRequired::TilingIterator& TilingSetRasterQueueRequired::TilingIterator:: operator++() { Tile* tile = nullptr; while (true) { ++visible_iterator_; if (!visible_iterator_) { current_tile_ = PrioritizedTile(); return *this; } std::pair next_index = visible_iterator_.index(); tile = tiling_->TileAt(next_index.first, next_index.second); // If the tile doesn't exist or if it exists but doesn't need raster work, // we can move on to the next tile. if (!tile || !tile->draw_info().NeedsRaster()) continue; // If the tile is occluded, we also can skip it. Note that we use the tiling // check for occlusion, since tile's internal state has not yet been updated // (by UpdateTilePriority). The tiling check does not rely on tile's // internal state (it is, in fact, used to determine the tile's state). if (tiling_->IsTileOccluded(tile)) continue; // If we get here, that means we have a valid tile that needs raster and is // in the NOW bin, which means that it can be required. break; } tiling_->UpdateRequiredStatesOnTile(tile); current_tile_ = tiling_->MakePrioritizedTile( tile, tiling_->ComputePriorityRectTypeForTile(tile)); return *this; } } // namespace cc