1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/notreached.h"
10 #include "cc/tiles/tiling_set_eviction_queue.h"
14 TilingSetEvictionQueue::TilingSetEvictionQueue(
15 PictureLayerTilingSet* tiling_set,
16 bool is_drawing_layer)
17 : tree_(tiling_set->tree()),
18 phase_(EVENTUALLY_RECT),
19 is_drawing_layer_(is_drawing_layer) {
20 // Early out if the layer has no tilings.
21 if (!tiling_set->num_tilings())
23 GenerateTilingOrder(tiling_set);
24 eventually_iterator_ = EventuallyTilingIterator(&tilings_, tree_);
25 if (eventually_iterator_.done()) {
29 current_tile_ = *eventually_iterator_;
32 TilingSetEvictionQueue::~TilingSetEvictionQueue() = default;
34 void TilingSetEvictionQueue::GenerateTilingOrder(
35 PictureLayerTilingSet* tiling_set) {
36 tilings_.reserve(tiling_set->num_tilings());
37 // Generate all of the tilings in the order described in the header comment
39 PictureLayerTilingSet::TilingRange range =
40 tiling_set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES);
41 for (size_t index = range.start; index < range.end; ++index) {
42 PictureLayerTiling* tiling = tiling_set->tiling_at(index);
43 if (tiling->has_tiles())
44 tilings_.push_back(tiling);
47 range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES);
48 for (size_t i = range.start; i < range.end; ++i) {
49 size_t index = range.start + (range.end - 1 - i);
50 PictureLayerTiling* tiling = tiling_set->tiling_at(index);
51 if (tiling->has_tiles())
52 tilings_.push_back(tiling);
55 range = tiling_set->GetTilingRange(
56 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES);
57 for (size_t i = range.start; i < range.end; ++i) {
58 size_t index = range.start + (range.end - 1 - i);
59 PictureLayerTiling* tiling = tiling_set->tiling_at(index);
60 if (tiling->has_tiles())
61 tilings_.push_back(tiling);
64 range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOW_RES);
65 for (size_t index = range.start; index < range.end; ++index) {
66 PictureLayerTiling* tiling = tiling_set->tiling_at(index);
67 if (tiling->has_tiles())
68 tilings_.push_back(tiling);
71 range = tiling_set->GetTilingRange(PictureLayerTilingSet::HIGH_RES);
72 for (size_t index = range.start; index < range.end; ++index) {
73 PictureLayerTiling* tiling = tiling_set->tiling_at(index);
74 if (tiling->has_tiles())
75 tilings_.push_back(tiling);
77 DCHECK_GE(tiling_set->num_tilings(), tilings_.size());
80 void TilingSetEvictionQueue::AdvancePhase() {
81 current_tile_ = PrioritizedTile();
82 while (!current_tile_.tile() &&
83 phase_ != VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED) {
84 phase_ = static_cast<Phase>(phase_ + 1);
89 case SOON_BORDER_RECT:
90 soon_iterator_ = SoonBorderTilingIterator(&tilings_, tree_);
91 if (!soon_iterator_.done())
92 current_tile_ = *soon_iterator_;
95 skewport_iterator_ = SkewportTilingIterator(&tilings_, tree_);
96 if (!skewport_iterator_.done())
97 current_tile_ = *skewport_iterator_;
99 case PENDING_VISIBLE_RECT:
100 pending_visible_iterator_ = PendingVisibleTilingIterator(
101 &tilings_, tree_, false /* return required for activation tiles */);
102 if (!pending_visible_iterator_.done())
103 current_tile_ = *pending_visible_iterator_;
105 case PENDING_VISIBLE_RECT_REQUIRED_FOR_ACTIVATION:
106 pending_visible_iterator_ = PendingVisibleTilingIterator(
107 &tilings_, tree_, true /* return required for activation tiles */);
108 if (!pending_visible_iterator_.done())
109 current_tile_ = *pending_visible_iterator_;
111 case VISIBLE_RECT_OCCLUDED:
112 visible_iterator_ = VisibleTilingIterator(
113 &tilings_, tree_, true /* return occluded tiles */,
114 false /* return required for activation tiles */);
115 if (!visible_iterator_.done())
116 current_tile_ = *visible_iterator_;
118 case VISIBLE_RECT_UNOCCLUDED:
119 visible_iterator_ = VisibleTilingIterator(
120 &tilings_, tree_, false /* return occluded tiles */,
121 false /* return required for activation tiles */);
122 if (!visible_iterator_.done())
123 current_tile_ = *visible_iterator_;
125 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED:
126 visible_iterator_ = VisibleTilingIterator(
127 &tilings_, tree_, true /* return occluded tiles */,
128 true /* return required for activation tiles */);
129 if (!visible_iterator_.done())
130 current_tile_ = *visible_iterator_;
132 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED:
133 visible_iterator_ = VisibleTilingIterator(
134 &tilings_, tree_, false /* return occluded tiles */,
135 true /* return required for activation tiles */);
136 if (!visible_iterator_.done())
137 current_tile_ = *visible_iterator_;
143 bool TilingSetEvictionQueue::IsEmpty() const {
144 return !current_tile_.tile();
147 const PrioritizedTile& TilingSetEvictionQueue::Top() const {
149 return current_tile_;
152 void TilingSetEvictionQueue::Pop() {
154 current_tile_ = PrioritizedTile();
156 case EVENTUALLY_RECT:
157 ++eventually_iterator_;
158 if (!eventually_iterator_.done())
159 current_tile_ = *eventually_iterator_;
161 case SOON_BORDER_RECT:
163 if (!soon_iterator_.done())
164 current_tile_ = *soon_iterator_;
167 ++skewport_iterator_;
168 if (!skewport_iterator_.done())
169 current_tile_ = *skewport_iterator_;
171 case PENDING_VISIBLE_RECT:
172 case PENDING_VISIBLE_RECT_REQUIRED_FOR_ACTIVATION:
173 ++pending_visible_iterator_;
174 if (!pending_visible_iterator_.done())
175 current_tile_ = *pending_visible_iterator_;
177 case VISIBLE_RECT_OCCLUDED:
178 case VISIBLE_RECT_UNOCCLUDED:
179 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED:
180 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED:
182 if (!visible_iterator_.done())
183 current_tile_ = *visible_iterator_;
186 if (!current_tile_.tile())
190 // EvictionRectIterator
191 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator()
192 : tilings_(nullptr), tree_(ACTIVE_TREE), tiling_index_(0) {
195 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator(
196 std::vector<PictureLayerTiling*>* tilings,
198 PictureLayerTiling::PriorityRectType priority_rect_type)
201 priority_rect_type_(priority_rect_type),
205 template <typename TilingIteratorType>
206 bool TilingSetEvictionQueue::EvictionRectIterator::AdvanceToNextTile(
207 TilingIteratorType* iterator) {
208 bool found_tile = false;
209 while (!found_tile) {
212 prioritized_tile_ = PrioritizedTile();
215 found_tile = GetFirstTileAndCheckIfValid(iterator);
220 template <typename TilingIteratorType>
221 bool TilingSetEvictionQueue::EvictionRectIterator::GetFirstTileAndCheckIfValid(
222 TilingIteratorType* iterator) {
223 PictureLayerTiling* tiling = (*tilings_)[tiling_index_];
224 Tile* tile = tiling->TileAt(iterator->index_x(), iterator->index_y());
225 prioritized_tile_ = PrioritizedTile();
226 // If there's nothing to evict, return false.
227 if (!tile || !tile->draw_info().has_resource())
229 // After the pending visible rect has been processed, we must return false
230 // for pending visible rect tiles as tiling iterators do not ignore those
232 if (priority_rect_type_ > PictureLayerTiling::PENDING_VISIBLE_RECT) {
233 gfx::Rect tile_rect = tiling->tiling_data()->TileBounds(
234 tile->tiling_i_index(), tile->tiling_j_index());
235 if (tiling->pending_visible_rect().Intersects(tile_rect))
238 prioritized_tile_ = tiling->MakePrioritizedTile(tile, priority_rect_type_,
239 tiling->IsTileOccluded(tile));
240 // In other cases, the tile we got is a viable candidate, return true.
244 // EventuallyTilingIterator
245 TilingSetEvictionQueue::EventuallyTilingIterator::EventuallyTilingIterator(
246 std::vector<PictureLayerTiling*>* tilings,
248 : EvictionRectIterator(tilings, tree, PictureLayerTiling::EVENTUALLY_RECT) {
249 // Find the first tiling with a tile.
250 while (tiling_index_ < tilings_->size()) {
251 if (!(*tilings_)[tiling_index_]->has_eventually_rect_tiles()) {
255 iterator_ = TilingData::ReverseSpiralDifferenceIterator(
256 (*tilings_)[tiling_index_]->tiling_data(),
257 (*tilings_)[tiling_index_]->current_eventually_rect(),
258 (*tilings_)[tiling_index_]->current_skewport_rect(),
259 (*tilings_)[tiling_index_]->current_soon_border_rect());
266 if (tiling_index_ >= tilings_->size())
268 if (!GetFirstTileAndCheckIfValid(&iterator_))
272 TilingSetEvictionQueue::EventuallyTilingIterator&
273 TilingSetEvictionQueue::EventuallyTilingIterator::
275 bool found_tile = AdvanceToNextTile(&iterator_);
276 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) {
278 if (!(*tilings_)[tiling_index_]->has_eventually_rect_tiles())
280 iterator_ = TilingData::ReverseSpiralDifferenceIterator(
281 (*tilings_)[tiling_index_]->tiling_data(),
282 (*tilings_)[tiling_index_]->current_eventually_rect(),
283 (*tilings_)[tiling_index_]->current_skewport_rect(),
284 (*tilings_)[tiling_index_]->current_soon_border_rect());
287 found_tile = GetFirstTileAndCheckIfValid(&iterator_);
289 found_tile = AdvanceToNextTile(&iterator_);
294 // SoonBorderTilingIterator
295 TilingSetEvictionQueue::SoonBorderTilingIterator::SoonBorderTilingIterator(
296 std::vector<PictureLayerTiling*>* tilings,
298 : EvictionRectIterator(tilings,
300 PictureLayerTiling::SOON_BORDER_RECT) {
301 // Find the first tiling with a tile.
302 while (tiling_index_ < tilings_->size()) {
303 if (!(*tilings_)[tiling_index_]->has_soon_border_rect_tiles()) {
307 iterator_ = TilingData::ReverseSpiralDifferenceIterator(
308 (*tilings_)[tiling_index_]->tiling_data(),
309 (*tilings_)[tiling_index_]->current_soon_border_rect(),
310 (*tilings_)[tiling_index_]->current_skewport_rect(),
311 (*tilings_)[tiling_index_]->current_visible_rect());
318 if (tiling_index_ >= tilings_->size())
320 if (!GetFirstTileAndCheckIfValid(&iterator_))
324 TilingSetEvictionQueue::SoonBorderTilingIterator&
325 TilingSetEvictionQueue::SoonBorderTilingIterator::
327 bool found_tile = AdvanceToNextTile(&iterator_);
328 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) {
330 if (!(*tilings_)[tiling_index_]->has_soon_border_rect_tiles())
332 iterator_ = TilingData::ReverseSpiralDifferenceIterator(
333 (*tilings_)[tiling_index_]->tiling_data(),
334 (*tilings_)[tiling_index_]->current_soon_border_rect(),
335 (*tilings_)[tiling_index_]->current_skewport_rect(),
336 (*tilings_)[tiling_index_]->current_visible_rect());
339 found_tile = GetFirstTileAndCheckIfValid(&iterator_);
341 found_tile = AdvanceToNextTile(&iterator_);
346 // SkewportTilingIterator
347 TilingSetEvictionQueue::SkewportTilingIterator::SkewportTilingIterator(
348 std::vector<PictureLayerTiling*>* tilings,
350 : EvictionRectIterator(tilings, tree, PictureLayerTiling::SKEWPORT_RECT) {
351 // Find the first tiling with a tile.
352 while (tiling_index_ < tilings_->size()) {
353 if (!(*tilings_)[tiling_index_]->has_skewport_rect_tiles()) {
357 iterator_ = TilingData::ReverseSpiralDifferenceIterator(
358 (*tilings_)[tiling_index_]->tiling_data(),
359 (*tilings_)[tiling_index_]->current_skewport_rect(),
360 (*tilings_)[tiling_index_]->current_visible_rect(),
361 (*tilings_)[tiling_index_]->current_visible_rect());
368 if (tiling_index_ >= tilings_->size())
370 if (!GetFirstTileAndCheckIfValid(&iterator_))
374 TilingSetEvictionQueue::SkewportTilingIterator&
375 TilingSetEvictionQueue::SkewportTilingIterator::
377 bool found_tile = AdvanceToNextTile(&iterator_);
378 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) {
380 if (!(*tilings_)[tiling_index_]->has_skewport_rect_tiles())
382 iterator_ = TilingData::ReverseSpiralDifferenceIterator(
383 (*tilings_)[tiling_index_]->tiling_data(),
384 (*tilings_)[tiling_index_]->current_skewport_rect(),
385 (*tilings_)[tiling_index_]->current_visible_rect(),
386 (*tilings_)[tiling_index_]->current_visible_rect());
389 found_tile = GetFirstTileAndCheckIfValid(&iterator_);
391 found_tile = AdvanceToNextTile(&iterator_);
396 // PendingVisibleIterator
397 TilingSetEvictionQueue::PendingVisibleTilingIterator::
398 PendingVisibleTilingIterator(std::vector<PictureLayerTiling*>* tilings,
400 bool return_required_for_activation_tiles)
401 : EvictionRectIterator(tilings,
403 PictureLayerTiling::PENDING_VISIBLE_RECT),
404 return_required_for_activation_tiles_(
405 return_required_for_activation_tiles) {
406 // Find the first tiling with a tile.
407 while (tiling_index_ < tilings_->size()) {
408 iterator_ = TilingData::DifferenceIterator(
409 (*tilings_)[tiling_index_]->tiling_data(),
410 (*tilings_)[tiling_index_]->pending_visible_rect(),
411 (*tilings_)[tiling_index_]->current_visible_rect());
418 if (tiling_index_ >= tilings_->size())
420 if (!GetFirstTileAndCheckIfValid(&iterator_)) {
424 if (!TileMatchesRequiredFlags(prioritized_tile_)) {
430 TilingSetEvictionQueue::PendingVisibleTilingIterator&
431 TilingSetEvictionQueue::PendingVisibleTilingIterator::
433 bool found_tile = AdvanceToNextTile(&iterator_);
434 while (found_tile && !TileMatchesRequiredFlags(prioritized_tile_))
435 found_tile = AdvanceToNextTile(&iterator_);
437 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) {
439 iterator_ = TilingData::DifferenceIterator(
440 (*tilings_)[tiling_index_]->tiling_data(),
441 (*tilings_)[tiling_index_]->pending_visible_rect(),
442 (*tilings_)[tiling_index_]->current_visible_rect());
445 found_tile = GetFirstTileAndCheckIfValid(&iterator_);
447 found_tile = AdvanceToNextTile(&iterator_);
448 while (found_tile && !TileMatchesRequiredFlags(prioritized_tile_))
449 found_tile = AdvanceToNextTile(&iterator_);
454 bool TilingSetEvictionQueue::PendingVisibleTilingIterator::
455 TileMatchesRequiredFlags(const PrioritizedTile& tile) const {
456 bool activation_flag_matches = tile.tile()->required_for_activation() ==
457 return_required_for_activation_tiles_;
458 return activation_flag_matches;
461 // VisibleTilingIterator
462 TilingSetEvictionQueue::VisibleTilingIterator::VisibleTilingIterator(
463 std::vector<PictureLayerTiling*>* tilings,
465 bool return_occluded_tiles,
466 bool return_required_for_activation_tiles)
467 : EvictionRectIterator(tilings, tree, PictureLayerTiling::VISIBLE_RECT),
468 return_occluded_tiles_(return_occluded_tiles),
469 return_required_for_activation_tiles_(
470 return_required_for_activation_tiles) {
471 // Find the first tiling with a tile.
472 while (tiling_index_ < tilings_->size()) {
473 if (!(*tilings_)[tiling_index_]->has_visible_rect_tiles()) {
477 iterator_ = TilingData::Iterator(
478 (*tilings_)[tiling_index_]->tiling_data(),
479 (*tilings_)[tiling_index_]->current_visible_rect(), false);
486 if (tiling_index_ >= tilings_->size())
488 if (!GetFirstTileAndCheckIfValid(&iterator_)) {
492 if (!TileMatchesRequiredFlags(prioritized_tile_)) {
498 TilingSetEvictionQueue::VisibleTilingIterator&
499 TilingSetEvictionQueue::VisibleTilingIterator::
501 bool found_tile = AdvanceToNextTile(&iterator_);
502 while (found_tile && !TileMatchesRequiredFlags(prioritized_tile_))
503 found_tile = AdvanceToNextTile(&iterator_);
505 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) {
507 if (!(*tilings_)[tiling_index_]->has_visible_rect_tiles())
509 iterator_ = TilingData::Iterator(
510 (*tilings_)[tiling_index_]->tiling_data(),
511 (*tilings_)[tiling_index_]->current_visible_rect(), false);
514 found_tile = GetFirstTileAndCheckIfValid(&iterator_);
516 found_tile = AdvanceToNextTile(&iterator_);
517 while (found_tile && !TileMatchesRequiredFlags(prioritized_tile_))
518 found_tile = AdvanceToNextTile(&iterator_);
523 bool TilingSetEvictionQueue::VisibleTilingIterator::TileMatchesRequiredFlags(
524 const PrioritizedTile& tile) const {
525 bool activation_flag_matches = tile.tile()->required_for_activation() ==
526 return_required_for_activation_tiles_;
527 bool occluded_flag_matches = tile.is_occluded() == return_occluded_tiles_;
528 return activation_flag_matches && occluded_flag_matches;