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 (size_t index
= range
.start
; index
< range
.end
; ++index
) {
37 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(index
);
38 if (tiling
->has_tiles())
39 tilings_
.push_back(tiling
);
42 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES
);
43 for (size_t i
= range
.start
; i
< range
.end
; ++i
) {
44 size_t index
= range
.start
+ (range
.end
- 1 - i
);
45 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(index
);
46 if (tiling
->has_tiles())
47 tilings_
.push_back(tiling
);
50 range
= tiling_set
->GetTilingRange(
51 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
);
52 for (size_t i
= range
.start
; i
< range
.end
; ++i
) {
53 size_t index
= range
.start
+ (range
.end
- 1 - i
);
54 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(index
);
55 if (tiling
->has_tiles())
56 tilings_
.push_back(tiling
);
59 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::LOW_RES
);
60 for (size_t index
= range
.start
; index
< range
.end
; ++index
) {
61 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(index
);
62 if (tiling
->has_tiles())
63 tilings_
.push_back(tiling
);
66 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::HIGH_RES
);
67 for (size_t index
= range
.start
; index
< range
.end
; ++index
) {
68 PictureLayerTiling
* tiling
= tiling_set
->tiling_at(index
);
69 if (tiling
->has_tiles())
70 tilings_
.push_back(tiling
);
72 DCHECK_GE(tiling_set
->num_tilings(), tilings_
.size());
75 void TilingSetEvictionQueue::AdvancePhase() {
76 current_tile_
= PrioritizedTile();
77 while (!current_tile_
.tile() &&
78 phase_
!= VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
) {
79 phase_
= static_cast<Phase
>(phase_
+ 1);
84 case SOON_BORDER_RECT
:
85 soon_iterator_
= SoonBorderTilingIterator(&tilings_
, tree_
);
86 if (!soon_iterator_
.done())
87 current_tile_
= *soon_iterator_
;
90 skewport_iterator_
= SkewportTilingIterator(&tilings_
, tree_
);
91 if (!skewport_iterator_
.done())
92 current_tile_
= *skewport_iterator_
;
94 case PENDING_VISIBLE_RECT
:
95 pending_visible_iterator_
= PendingVisibleTilingIterator(
96 &tilings_
, tree_
, false /* return required for activation tiles */);
97 if (!pending_visible_iterator_
.done())
98 current_tile_
= *pending_visible_iterator_
;
100 case PENDING_VISIBLE_RECT_REQUIRED_FOR_ACTIVATION
:
101 pending_visible_iterator_
= PendingVisibleTilingIterator(
102 &tilings_
, tree_
, true /* return required for activation tiles */);
103 if (!pending_visible_iterator_
.done())
104 current_tile_
= *pending_visible_iterator_
;
106 case VISIBLE_RECT_OCCLUDED
:
107 visible_iterator_
= VisibleTilingIterator(
108 &tilings_
, tree_
, true /* return occluded tiles */,
109 false /* return required for activation tiles */);
110 if (!visible_iterator_
.done())
111 current_tile_
= *visible_iterator_
;
113 case VISIBLE_RECT_UNOCCLUDED
:
114 visible_iterator_
= VisibleTilingIterator(
115 &tilings_
, tree_
, false /* return occluded tiles */,
116 false /* return required for activation tiles */);
117 if (!visible_iterator_
.done())
118 current_tile_
= *visible_iterator_
;
120 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED
:
121 visible_iterator_
= VisibleTilingIterator(
122 &tilings_
, tree_
, true /* return occluded tiles */,
123 true /* return required for activation tiles */);
124 if (!visible_iterator_
.done())
125 current_tile_
= *visible_iterator_
;
127 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
:
128 visible_iterator_
= VisibleTilingIterator(
129 &tilings_
, tree_
, false /* return occluded tiles */,
130 true /* return required for activation tiles */);
131 if (!visible_iterator_
.done())
132 current_tile_
= *visible_iterator_
;
138 bool TilingSetEvictionQueue::IsEmpty() const {
139 return !current_tile_
.tile();
142 const PrioritizedTile
& TilingSetEvictionQueue::Top() const {
144 return current_tile_
;
147 void TilingSetEvictionQueue::Pop() {
149 current_tile_
= PrioritizedTile();
151 case EVENTUALLY_RECT
:
152 ++eventually_iterator_
;
153 if (!eventually_iterator_
.done())
154 current_tile_
= *eventually_iterator_
;
156 case SOON_BORDER_RECT
:
158 if (!soon_iterator_
.done())
159 current_tile_
= *soon_iterator_
;
162 ++skewport_iterator_
;
163 if (!skewport_iterator_
.done())
164 current_tile_
= *skewport_iterator_
;
166 case PENDING_VISIBLE_RECT
:
167 case PENDING_VISIBLE_RECT_REQUIRED_FOR_ACTIVATION
:
168 ++pending_visible_iterator_
;
169 if (!pending_visible_iterator_
.done())
170 current_tile_
= *pending_visible_iterator_
;
172 case VISIBLE_RECT_OCCLUDED
:
173 case VISIBLE_RECT_UNOCCLUDED
:
174 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED
:
175 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
:
177 if (!visible_iterator_
.done())
178 current_tile_
= *visible_iterator_
;
181 if (!current_tile_
.tile())
185 // EvictionRectIterator
186 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator()
187 : tilings_(nullptr), tree_(ACTIVE_TREE
), tiling_index_(0) {
190 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator(
191 std::vector
<PictureLayerTiling
*>* tilings
,
193 PictureLayerTiling::PriorityRectType priority_rect_type
)
196 priority_rect_type_(priority_rect_type
),
200 template <typename TilingIteratorType
>
201 bool TilingSetEvictionQueue::EvictionRectIterator::AdvanceToNextTile(
202 TilingIteratorType
* iterator
) {
203 bool found_tile
= false;
204 while (!found_tile
) {
207 prioritized_tile_
= PrioritizedTile();
210 found_tile
= GetFirstTileAndCheckIfValid(iterator
);
215 template <typename TilingIteratorType
>
216 bool TilingSetEvictionQueue::EvictionRectIterator::GetFirstTileAndCheckIfValid(
217 TilingIteratorType
* iterator
) {
218 PictureLayerTiling
* tiling
= (*tilings_
)[tiling_index_
];
219 Tile
* tile
= tiling
->TileAt(iterator
->index_x(), iterator
->index_y());
220 prioritized_tile_
= PrioritizedTile();
221 // If there's nothing to evict, return false.
222 if (!tile
|| !tile
->draw_info().has_resource())
224 // After the pending visible rect has been processed, we must return false
225 // for pending visible rect tiles as tiling iterators do not ignore those
227 if (priority_rect_type_
> PictureLayerTiling::PENDING_VISIBLE_RECT
) {
228 gfx::Rect tile_rect
= tiling
->tiling_data()->TileBounds(
229 tile
->tiling_i_index(), tile
->tiling_j_index());
230 if (tiling
->pending_visible_rect().Intersects(tile_rect
))
233 (*tilings_
)[tiling_index_
]->UpdateRequiredStatesOnTile(tile
);
234 prioritized_tile_
= (*tilings_
)[tiling_index_
]->MakePrioritizedTile(
235 tile
, priority_rect_type_
);
236 // In other cases, the tile we got is a viable candidate, return true.
240 // EventuallyTilingIterator
241 TilingSetEvictionQueue::EventuallyTilingIterator::EventuallyTilingIterator(
242 std::vector
<PictureLayerTiling
*>* tilings
,
244 : EvictionRectIterator(tilings
, tree
, PictureLayerTiling::EVENTUALLY_RECT
) {
245 // Find the first tiling with a tile.
246 while (tiling_index_
< tilings_
->size()) {
247 if (!(*tilings_
)[tiling_index_
]->has_eventually_rect_tiles()) {
251 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
252 (*tilings_
)[tiling_index_
]->tiling_data(),
253 (*tilings_
)[tiling_index_
]->current_eventually_rect(),
254 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
255 (*tilings_
)[tiling_index_
]->current_soon_border_rect());
262 if (tiling_index_
>= tilings_
->size())
264 if (!GetFirstTileAndCheckIfValid(&iterator_
))
268 TilingSetEvictionQueue::EventuallyTilingIterator
&
269 TilingSetEvictionQueue::EventuallyTilingIterator::
271 bool found_tile
= AdvanceToNextTile(&iterator_
);
272 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
274 if (!(*tilings_
)[tiling_index_
]->has_eventually_rect_tiles())
276 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
277 (*tilings_
)[tiling_index_
]->tiling_data(),
278 (*tilings_
)[tiling_index_
]->current_eventually_rect(),
279 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
280 (*tilings_
)[tiling_index_
]->current_soon_border_rect());
283 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
285 found_tile
= AdvanceToNextTile(&iterator_
);
290 // SoonBorderTilingIterator
291 TilingSetEvictionQueue::SoonBorderTilingIterator::SoonBorderTilingIterator(
292 std::vector
<PictureLayerTiling
*>* tilings
,
294 : EvictionRectIterator(tilings
,
296 PictureLayerTiling::SOON_BORDER_RECT
) {
297 // Find the first tiling with a tile.
298 while (tiling_index_
< tilings_
->size()) {
299 if (!(*tilings_
)[tiling_index_
]->has_soon_border_rect_tiles()) {
303 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
304 (*tilings_
)[tiling_index_
]->tiling_data(),
305 (*tilings_
)[tiling_index_
]->current_soon_border_rect(),
306 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
307 (*tilings_
)[tiling_index_
]->current_visible_rect());
314 if (tiling_index_
>= tilings_
->size())
316 if (!GetFirstTileAndCheckIfValid(&iterator_
))
320 TilingSetEvictionQueue::SoonBorderTilingIterator
&
321 TilingSetEvictionQueue::SoonBorderTilingIterator::
323 bool found_tile
= AdvanceToNextTile(&iterator_
);
324 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
326 if (!(*tilings_
)[tiling_index_
]->has_soon_border_rect_tiles())
328 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
329 (*tilings_
)[tiling_index_
]->tiling_data(),
330 (*tilings_
)[tiling_index_
]->current_soon_border_rect(),
331 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
332 (*tilings_
)[tiling_index_
]->current_visible_rect());
335 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
337 found_tile
= AdvanceToNextTile(&iterator_
);
342 // SkewportTilingIterator
343 TilingSetEvictionQueue::SkewportTilingIterator::SkewportTilingIterator(
344 std::vector
<PictureLayerTiling
*>* tilings
,
346 : EvictionRectIterator(tilings
, tree
, PictureLayerTiling::SKEWPORT_RECT
) {
347 // Find the first tiling with a tile.
348 while (tiling_index_
< tilings_
->size()) {
349 if (!(*tilings_
)[tiling_index_
]->has_skewport_rect_tiles()) {
353 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
354 (*tilings_
)[tiling_index_
]->tiling_data(),
355 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
356 (*tilings_
)[tiling_index_
]->current_visible_rect(),
357 (*tilings_
)[tiling_index_
]->current_visible_rect());
364 if (tiling_index_
>= tilings_
->size())
366 if (!GetFirstTileAndCheckIfValid(&iterator_
))
370 TilingSetEvictionQueue::SkewportTilingIterator
&
371 TilingSetEvictionQueue::SkewportTilingIterator::
373 bool found_tile
= AdvanceToNextTile(&iterator_
);
374 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
376 if (!(*tilings_
)[tiling_index_
]->has_skewport_rect_tiles())
378 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
379 (*tilings_
)[tiling_index_
]->tiling_data(),
380 (*tilings_
)[tiling_index_
]->current_skewport_rect(),
381 (*tilings_
)[tiling_index_
]->current_visible_rect(),
382 (*tilings_
)[tiling_index_
]->current_visible_rect());
385 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
387 found_tile
= AdvanceToNextTile(&iterator_
);
392 // PendingVisibleIterator
393 TilingSetEvictionQueue::PendingVisibleTilingIterator::
394 PendingVisibleTilingIterator(std::vector
<PictureLayerTiling
*>* tilings
,
396 bool return_required_for_activation_tiles
)
397 : EvictionRectIterator(tilings
,
399 PictureLayerTiling::PENDING_VISIBLE_RECT
),
400 return_required_for_activation_tiles_(
401 return_required_for_activation_tiles
) {
402 // Find the first tiling with a tile.
403 while (tiling_index_
< tilings_
->size()) {
404 iterator_
= TilingData::DifferenceIterator(
405 (*tilings_
)[tiling_index_
]->tiling_data(),
406 (*tilings_
)[tiling_index_
]->pending_visible_rect(),
407 (*tilings_
)[tiling_index_
]->current_visible_rect());
414 if (tiling_index_
>= tilings_
->size())
416 if (!GetFirstTileAndCheckIfValid(&iterator_
)) {
420 if (!TileMatchesRequiredFlags(prioritized_tile_
)) {
426 TilingSetEvictionQueue::PendingVisibleTilingIterator
&
427 TilingSetEvictionQueue::PendingVisibleTilingIterator::
429 bool found_tile
= AdvanceToNextTile(&iterator_
);
430 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
431 found_tile
= AdvanceToNextTile(&iterator_
);
433 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
435 iterator_
= TilingData::DifferenceIterator(
436 (*tilings_
)[tiling_index_
]->tiling_data(),
437 (*tilings_
)[tiling_index_
]->pending_visible_rect(),
438 (*tilings_
)[tiling_index_
]->current_visible_rect());
441 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
443 found_tile
= AdvanceToNextTile(&iterator_
);
444 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
445 found_tile
= AdvanceToNextTile(&iterator_
);
450 bool TilingSetEvictionQueue::PendingVisibleTilingIterator::
451 TileMatchesRequiredFlags(const PrioritizedTile
& tile
) const {
452 bool activation_flag_matches
= tile
.tile()->required_for_activation() ==
453 return_required_for_activation_tiles_
;
454 return activation_flag_matches
;
457 // VisibleTilingIterator
458 TilingSetEvictionQueue::VisibleTilingIterator::VisibleTilingIterator(
459 std::vector
<PictureLayerTiling
*>* tilings
,
461 bool return_occluded_tiles
,
462 bool return_required_for_activation_tiles
)
463 : EvictionRectIterator(tilings
, tree
, PictureLayerTiling::VISIBLE_RECT
),
464 return_occluded_tiles_(return_occluded_tiles
),
465 return_required_for_activation_tiles_(
466 return_required_for_activation_tiles
) {
467 // Find the first tiling with a tile.
468 while (tiling_index_
< tilings_
->size()) {
469 if (!(*tilings_
)[tiling_index_
]->has_visible_rect_tiles()) {
473 iterator_
= TilingData::Iterator(
474 (*tilings_
)[tiling_index_
]->tiling_data(),
475 (*tilings_
)[tiling_index_
]->current_visible_rect(), false);
482 if (tiling_index_
>= tilings_
->size())
484 if (!GetFirstTileAndCheckIfValid(&iterator_
)) {
488 if (!TileMatchesRequiredFlags(prioritized_tile_
)) {
494 TilingSetEvictionQueue::VisibleTilingIterator
&
495 TilingSetEvictionQueue::VisibleTilingIterator::
497 bool found_tile
= AdvanceToNextTile(&iterator_
);
498 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
499 found_tile
= AdvanceToNextTile(&iterator_
);
501 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
503 if (!(*tilings_
)[tiling_index_
]->has_visible_rect_tiles())
505 iterator_
= TilingData::Iterator(
506 (*tilings_
)[tiling_index_
]->tiling_data(),
507 (*tilings_
)[tiling_index_
]->current_visible_rect(), false);
510 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
512 found_tile
= AdvanceToNextTile(&iterator_
);
513 while (found_tile
&& !TileMatchesRequiredFlags(prioritized_tile_
))
514 found_tile
= AdvanceToNextTile(&iterator_
);
519 bool TilingSetEvictionQueue::VisibleTilingIterator::TileMatchesRequiredFlags(
520 const PrioritizedTile
& tile
) const {
521 bool activation_flag_matches
= tile
.tile()->required_for_activation() ==
522 return_required_for_activation_tiles_
;
523 bool occluded_flag_matches
= tile
.is_occluded() == return_occluded_tiles_
;
524 return activation_flag_matches
&& occluded_flag_matches
;