blob: adae8a8dfbe8dc14102698fd7fa462c272fce841 [file] [log] [blame]
// 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 <stddef.h>
#include <utility>
#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 or
// LOW_RESOLUTION on the active tree, but HIGH_RESOLUTION on the pending tree.
// These tilings are the only non-high res 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() != HIGH_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)
stages_->push_back(IterationStage(LOW_RES, TilePriority::NOW));
if (use_high_res_tiling)
stages_->push_back(IterationStage(HIGH_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);
// If we've marked the tiling as done, make sure we're actually done.
tiling->VerifyNoTileNeedsRaster();
}
}
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 <typename TilingIteratorType>
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)) {
current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_);
break;
}
}
}
template <typename TilingIteratorType>
bool TilingSetRasterQueueAll::OnePriorityRectIterator::
GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) {
Tile* tile = tiling_->TileAt(iterator->index_x(), iterator->index_y());
if (!IsTileValid(tile)) {
current_tile_ = PrioritizedTile();
return false;
}
current_tile_ = tiling_->MakePrioritizedTile(tile, priority_rect_type_);
return true;
}
bool TilingSetRasterQueueAll::OnePriorityRectIterator::IsTileValid(
const Tile* tile) const {
if (!tile)
return false;
// A tile is valid for raster if it needs raster and is unoccluded.
bool tile_is_valid_for_raster =
tile->draw_info().NeedsRaster() && !tiling_->IsTileOccluded(tile);
// A tile is not valid for the raster queue if it is not valid for raster or
// processing for checker-images.
if (!tile_is_valid_for_raster) {
bool tile_is_valid_for_checker_images =
tile->draw_info().is_checker_imaged() &&
tiling_->ShouldDecodeCheckeredImagesForTile(tile);
if (!tile_is_valid_for_checker_images)
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) {
gfx::Rect tile_bounds = tiling_data_->TileBounds(tile->tiling_i_index(),
tile->tiling_j_index());
if (pending_visible_rect_.Intersects(tile_bounds))
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>(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