1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "cc/tiles/tiling_set_eviction_queue.h"
11 TilingSetEvictionQueue::TilingSetEvictionQueue(
12 PictureLayerTilingSet
* tiling_set
)
13 : tree_(tiling_set
->tree()), phase_(EVENTUALLY_RECT
) {
14 // Early out if the layer has no tilings.
15 if (!tiling_set
->num_tilings())
17 GenerateTilingOrder(tiling_set
);
18 eventually_iterator_
= EventuallyTilingIterator(&tilings_
, tree_
);
19 if (eventually_iterator_
.done()) {
23 current_tile_
= *eventually_iterator_
;
26 TilingSetEvictionQueue::~TilingSetEvictionQueue() {
29 void TilingSetEvictionQueue::GenerateTilingOrder(
30 PictureLayerTilingSet
* tiling_set
) {
31 tilings_
.reserve(tiling_set
->num_tilings());
32 // Generate all of the tilings in the order described in the header comment
34 PictureLayerTilingSet::TilingRange range
=
35 tiling_set
->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
);
36 for (int i
= range
.start
; i
< range
.end
; ++i
) {
37 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(i
);
38 if (tiling
->has_tiles())
39 tilings_
.push_back(tiling
);
42 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES
);
43 for (int i
= range
.end
- 1; i
>= range
.start
; --i
) {
44 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(i
);
45 if (tiling
->has_tiles())
46 tilings_
.push_back(tiling
);
49 range
= tiling_set
->GetTilingRange(
50 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
);
51 for (int i
= range
.end
- 1; i
>= range
.start
; --i
) {
52 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(i
);
53 if (tiling
->has_tiles())
54 tilings_
.push_back(tiling
);
57 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::LOW_RES
);
58 for (int i
= range
.start
; i
< range
.end
; ++i
) {
59 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(i
);
60 if (tiling
->has_tiles())
61 tilings_
.push_back(tiling
);
64 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::HIGH_RES
);
65 for (int i
= range
.start
; i
< range
.end
; ++i
) {
66 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(i
);
67 if (tiling
->has_tiles())
68 tilings_
.push_back(tiling
);
70 DCHECK_GE(tiling_set
->num_tilings(), tilings_
.size());
73 void TilingSetEvictionQueue::AdvancePhase() {
74 current_tile_
= PrioritizedTile();
75 while (!current_tile_
.tile() &&
76 phase_
!= VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
) {
77 phase_
= static_cast<Phase
>(phase_
+ 1);
82 case SOON_BORDER_RECT
:
83 soon_iterator_
= SoonBorderTilingIterator(&tilings_
, tree_
);
84 if (!soon_iterator_
.done())
85 current_tile_
= *soon_iterator_
;
88 skewport_iterator_
= SkewportTilingIterator(&tilings_
, tree_
);
89 if (!skewport_iterator_
.done())
90 current_tile_
= *skewport_iterator_
;
92 case PENDING_VISIBLE_RECT
:
93 pending_visible_iterator_
= PendingVisibleTilingIterator(
94 &tilings_
, tree_
, false /* return required for activation tiles */);
95 if (!pending_visible_iterator_
.done())
96 current_tile_
= *pending_visible_iterator_
;
98 case PENDING_VISIBLE_RECT_REQUIRED_FOR_ACTIVATION
:
99 pending_visible_iterator_
= PendingVisibleTilingIterator(
100 &tilings_
, tree_
, true /* return required for activation tiles */);
101 if (!pending_visible_iterator_
.done())
102 current_tile_
= *pending_visible_iterator_
;
104 case VISIBLE_RECT_OCCLUDED
:
105 visible_iterator_
= VisibleTilingIterator(
106 &tilings_
, tree_
, true /* return occluded tiles */,
107 false /* return required for activation tiles */);
108 if (!visible_iterator_
.done())
109 current_tile_
= *visible_iterator_
;
111 case VISIBLE_RECT_UNOCCLUDED
:
112 visible_iterator_
= VisibleTilingIterator(
113 &tilings_
, tree_
, false /* return occluded tiles */,
114 false /* return required for activation tiles */);
115 if (!visible_iterator_
.done())
116 current_tile_
= *visible_iterator_
;
118 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED
:
119 visible_iterator_
= VisibleTilingIterator(
120 &tilings_
, tree_
, true /* return occluded tiles */,
121 true /* return required for activation tiles */);
122 if (!visible_iterator_
.done())
123 current_tile_
= *visible_iterator_
;
125 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
:
126 visible_iterator_
= VisibleTilingIterator(
127 &tilings_
, tree_
, false /* return occluded tiles */,
128 true /* return required for activation tiles */);
129 if (!visible_iterator_
.done())
130 current_tile_
= *visible_iterator_
;
136 bool TilingSetEvictionQueue::IsEmpty() const {
137 return !current_tile_
.tile();
140 const PrioritizedTile
& TilingSetEvictionQueue::Top() const {
142 return current_tile_
;
145 void TilingSetEvictionQueue::Pop() {
147 current_tile_
= PrioritizedTile();
149 case EVENTUALLY_RECT
:
150 ++eventually_iterator_
;
151 if (!eventually_iterator_
.done())
152 current_tile_
= *eventually_iterator_
;
154 case SOON_BORDER_RECT
:
156 if (!soon_iterator_
.done())
157 current_tile_
= *soon_iterator_
;
160 ++skewport_iterator_
;
161 if (!skewport_iterator_
.done())
162 current_tile_
= *skewport_iterator_
;
164 case PENDING_VISIBLE_RECT
:
165 case PENDING_VISIBLE_RECT_REQUIRED_FOR_ACTIVATION
:
166 ++pending_visible_iterator_
;
167 if (!pending_visible_iterator_
.done())
168 current_tile_
= *pending_visible_iterator_
;
170 case VISIBLE_RECT_OCCLUDED
:
171 case VISIBLE_RECT_UNOCCLUDED
:
172 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED
:
173 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
:
175 if (!visible_iterator_
.done())
176 current_tile_
= *visible_iterator_
;
179 if (!current_tile_
.tile())
183 // EvictionRectIterator
184 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator()
185 : tilings_(nullptr), tree_(ACTIVE_TREE
), tiling_index_(0) {
188 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator(
189 std::vector
<PictureLayerTiling
*>* tilings
,
191 PictureLayerTiling::PriorityRectType priority_rect_type
)
194 priority_rect_type_(priority_rect_type
),
198 template <typename TilingIteratorType
>
199 bool TilingSetEvictionQueue::EvictionRectIterator::AdvanceToNextTile(
200 TilingIteratorType
* iterator
) {
201 bool found_tile
= false;
202 while (!found_tile
) {
205 prioritized_tile_
= PrioritizedTile();
208 found_tile
= GetFirstTileAndCheckIfValid(iterator
);
213 template <typename TilingIteratorType
>
214 bool TilingSetEvictionQueue::EvictionRectIterator::GetFirstTileAndCheckIfValid(
215 TilingIteratorType
* iterator
) {
216 PictureLayerTiling
* tiling
= (*tilings_
)[tiling_index_
];
217 Tile
* tile
= tiling
->TileAt(iterator
->index_x(), iterator
->index_y());
218 prioritized_tile_
= PrioritizedTile();
219 // If there's nothing to evict, return false.
220 if (!tile
|| !tile
->draw_info().has_resource())
222 // After the pending visible rect has been processed, we must return false
223 // for pending visible rect tiles as tiling iterators do not ignore those
225 if (priority_rect_type_
> PictureLayerTiling::PENDING_VISIBLE_RECT
&&
226 tiling
->pending_visible_rect().Intersects(tile
->content_rect())) {
229 (*tilings_
)[tiling_index_
]->UpdateRequiredStatesOnTile(tile
);
230 prioritized_tile_
= (*tilings_
)[tiling_index_
]->MakePrioritizedTile(
231 tile
, priority_rect_type_
);
232 // In other cases, the tile we got is a viable candidate, return true.
236 // EventuallyTilingIterator
237 TilingSetEvictionQueue::EventuallyTilingIterator::EventuallyTilingIterator(
238 std::vector
<PictureLayerTiling
*>* tilings
,
240 : EvictionRectIterator(tilings
, tree
, PictureLayerTiling::EVENTUALLY_RECT
) {
241 // Find the first tiling with a tile.
242 while (tiling_index_
< tilings_
->size()) {
243 if (!(*tilings_
)[tiling_index_
]->has_eventually_rect_tiles()) {
247 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
248 (*tilings_
)[tiling_index_
]->tiling_data(),
249 (*tilings_
)[tiling_index_
]->current_eventually_rect(),
250 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
251 (*tilings_
)[tiling_index_
]->current_soon_border_rect());
258 if (tiling_index_
>= tilings_
->size())
260 if (!GetFirstTileAndCheckIfValid(&iterator_
))
264 TilingSetEvictionQueue::EventuallyTilingIterator
&
265 TilingSetEvictionQueue::EventuallyTilingIterator::
267 bool found_tile
= AdvanceToNextTile(&iterator_
);
268 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
270 if (!(*tilings_
)[tiling_index_
]->has_eventually_rect_tiles())
272 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
273 (*tilings_
)[tiling_index_
]->tiling_data(),
274 (*tilings_
)[tiling_index_
]->current_eventually_rect(),
275 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
276 (*tilings_
)[tiling_index_
]->current_soon_border_rect());
279 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
281 found_tile
= AdvanceToNextTile(&iterator_
);
286 // SoonBorderTilingIterator
287 TilingSetEvictionQueue::SoonBorderTilingIterator::SoonBorderTilingIterator(
288 std::vector
<PictureLayerTiling
*>* tilings
,
290 : EvictionRectIterator(tilings
,
292 PictureLayerTiling::SOON_BORDER_RECT
) {
293 // Find the first tiling with a tile.
294 while (tiling_index_
< tilings_
->size()) {
295 if (!(*tilings_
)[tiling_index_
]->has_soon_border_rect_tiles()) {
299 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
300 (*tilings_
)[tiling_index_
]->tiling_data(),
301 (*tilings_
)[tiling_index_
]->current_soon_border_rect(),
302 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
303 (*tilings_
)[tiling_index_
]->current_visible_rect());
310 if (tiling_index_
>= tilings_
->size())
312 if (!GetFirstTileAndCheckIfValid(&iterator_
))
316 TilingSetEvictionQueue::SoonBorderTilingIterator
&
317 TilingSetEvictionQueue::SoonBorderTilingIterator::
319 bool found_tile
= AdvanceToNextTile(&iterator_
);
320 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
322 if (!(*tilings_
)[tiling_index_
]->has_soon_border_rect_tiles())
324 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
325 (*tilings_
)[tiling_index_
]->tiling_data(),
326 (*tilings_
)[tiling_index_
]->current_soon_border_rect(),
327 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
328 (*tilings_
)[tiling_index_
]->current_visible_rect());
331 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
333 found_tile
= AdvanceToNextTile(&iterator_
);
338 // SkewportTilingIterator
339 TilingSetEvictionQueue::SkewportTilingIterator::SkewportTilingIterator(
340 std::vector
<PictureLayerTiling
*>* tilings
,
342 : EvictionRectIterator(tilings
, tree
, PictureLayerTiling::SKEWPORT_RECT
) {
343 // Find the first tiling with a tile.
344 while (tiling_index_
< tilings_
->size()) {
345 if (!(*tilings_
)[tiling_index_
]->has_skewport_rect_tiles()) {
349 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
350 (*tilings_
)[tiling_index_
]->tiling_data(),
351 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
352 (*tilings_
)[tiling_index_
]->current_visible_rect(),
353 (*tilings_
)[tiling_index_
]->current_visible_rect());
360 if (tiling_index_
>= tilings_
->size())
362 if (!GetFirstTileAndCheckIfValid(&iterator_
))
366 TilingSetEvictionQueue::SkewportTilingIterator
&
367 TilingSetEvictionQueue::SkewportTilingIterator::
369 bool found_tile
= AdvanceToNextTile(&iterator_
);
370 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
372 if (!(*tilings_
)[tiling_index_
]->has_skewport_rect_tiles())
374 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
375 (*tilings_
)[tiling_index_
]->tiling_data(),
376 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
377 (*tilings_
)[tiling_index_
]->current_visible_rect(),
378 (*tilings_
)[tiling_index_
]->current_visible_rect());
381 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
383 found_tile
= AdvanceToNextTile(&iterator_
);
388 // PendingVisibleIterator
389 TilingSetEvictionQueue::PendingVisibleTilingIterator::
390 PendingVisibleTilingIterator(std::vector
<PictureLayerTiling
*>* tilings
,
392 bool return_required_for_activation_tiles
)
393 : EvictionRectIterator(tilings
,
395 PictureLayerTiling::PENDING_VISIBLE_RECT
),
396 return_required_for_activation_tiles_(
397 return_required_for_activation_tiles
) {
398 // Find the first tiling with a tile.
399 while (tiling_index_
< tilings_
->size()) {
400 iterator_
= TilingData::DifferenceIterator(
401 (*tilings_
)[tiling_index_
]->tiling_data(),
402 (*tilings_
)[tiling_index_
]->pending_visible_rect(),
403 (*tilings_
)[tiling_index_
]->current_visible_rect());
410 if (tiling_index_
>= tilings_
->size())
412 if (!GetFirstTileAndCheckIfValid(&iterator_
)) {
416 if (!TileMatchesRequiredFlags(prioritized_tile_
)) {
422 TilingSetEvictionQueue::PendingVisibleTilingIterator
&
423 TilingSetEvictionQueue::PendingVisibleTilingIterator::
425 bool found_tile
= AdvanceToNextTile(&iterator_
);
426 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
427 found_tile
= AdvanceToNextTile(&iterator_
);
429 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
431 iterator_
= TilingData::DifferenceIterator(
432 (*tilings_
)[tiling_index_
]->tiling_data(),
433 (*tilings_
)[tiling_index_
]->pending_visible_rect(),
434 (*tilings_
)[tiling_index_
]->current_visible_rect());
437 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
439 found_tile
= AdvanceToNextTile(&iterator_
);
440 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
441 found_tile
= AdvanceToNextTile(&iterator_
);
446 bool TilingSetEvictionQueue::PendingVisibleTilingIterator::
447 TileMatchesRequiredFlags(const PrioritizedTile
& tile
) const {
448 bool activation_flag_matches
= tile
.tile()->required_for_activation() ==
449 return_required_for_activation_tiles_
;
450 return activation_flag_matches
;
453 // VisibleTilingIterator
454 TilingSetEvictionQueue::VisibleTilingIterator::VisibleTilingIterator(
455 std::vector
<PictureLayerTiling
*>* tilings
,
457 bool return_occluded_tiles
,
458 bool return_required_for_activation_tiles
)
459 : EvictionRectIterator(tilings
, tree
, PictureLayerTiling::VISIBLE_RECT
),
460 return_occluded_tiles_(return_occluded_tiles
),
461 return_required_for_activation_tiles_(
462 return_required_for_activation_tiles
) {
463 // Find the first tiling with a tile.
464 while (tiling_index_
< tilings_
->size()) {
465 if (!(*tilings_
)[tiling_index_
]->has_visible_rect_tiles()) {
469 iterator_
= TilingData::Iterator(
470 (*tilings_
)[tiling_index_
]->tiling_data(),
471 (*tilings_
)[tiling_index_
]->current_visible_rect(), false);
478 if (tiling_index_
>= tilings_
->size())
480 if (!GetFirstTileAndCheckIfValid(&iterator_
)) {
484 if (!TileMatchesRequiredFlags(prioritized_tile_
)) {
490 TilingSetEvictionQueue::VisibleTilingIterator
&
491 TilingSetEvictionQueue::VisibleTilingIterator::
493 bool found_tile
= AdvanceToNextTile(&iterator_
);
494 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
495 found_tile
= AdvanceToNextTile(&iterator_
);
497 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
499 if (!(*tilings_
)[tiling_index_
]->has_visible_rect_tiles())
501 iterator_
= TilingData::Iterator(
502 (*tilings_
)[tiling_index_
]->tiling_data(),
503 (*tilings_
)[tiling_index_
]->current_visible_rect(), false);
506 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
508 found_tile
= AdvanceToNextTile(&iterator_
);
509 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
510 found_tile
= AdvanceToNextTile(&iterator_
);
515 bool TilingSetEvictionQueue::VisibleTilingIterator::TileMatchesRequiredFlags(
516 const PrioritizedTile
& tile
) const {
517 bool activation_flag_matches
= tile
.tile()->required_for_activation() ==
518 return_required_for_activation_tiles_
;
519 bool occluded_flag_matches
= tile
.is_occluded() == return_occluded_tiles_
;
520 return activation_flag_matches
&& occluded_flag_matches
;