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/resources/tiling_set_eviction_queue.h"
12 bool IsSharedOutOfOrderTile(WhichTree tree
, const Tile
* tile
) {
13 if (!tile
->is_shared())
16 // The priority for tile priority of a shared tile will be a combined
17 // priority thus return shared tiles from a higher priority tree as
18 // it is out of order for a lower priority tree.
19 WhichTree twin_tree
= tree
== ACTIVE_TREE
? PENDING_TREE
: ACTIVE_TREE
;
20 const TilePriority
& priority
= tile
->priority(tree
);
21 const TilePriority
& twin_priority
= tile
->priority(twin_tree
);
22 if (priority
.priority_bin
!= twin_priority
.priority_bin
)
23 return priority
.priority_bin
> twin_priority
.priority_bin
;
24 const bool occluded
= tile
->is_occluded(tree
);
25 const bool twin_occluded
= tile
->is_occluded(twin_tree
);
26 if (occluded
!= twin_occluded
)
28 if (priority
.distance_to_visible
!= twin_priority
.distance_to_visible
)
29 return priority
.distance_to_visible
> twin_priority
.distance_to_visible
;
31 // If priorities are the same, it does not matter which tree returns
32 // the tile. Let's pick the pending tree.
33 return tree
!= PENDING_TREE
;
38 TilingSetEvictionQueue::TilingSetEvictionQueue(
39 PictureLayerTilingSet
* tiling_set
,
40 bool skip_shared_out_of_order_tiles
)
41 : tree_(tiling_set
->client()->GetTree()),
42 skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles
),
43 phase_(EVENTUALLY_RECT
),
44 current_tile_(nullptr) {
45 // Early out if the layer has no tilings.
46 if (!tiling_set
->num_tilings())
48 GenerateTilingOrder(tiling_set
);
49 eventually_iterator_
= EventuallyTilingIterator(
50 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
);
51 if (eventually_iterator_
.done()) {
55 current_tile_
= *eventually_iterator_
;
58 TilingSetEvictionQueue::~TilingSetEvictionQueue() {
61 void TilingSetEvictionQueue::GenerateTilingOrder(
62 PictureLayerTilingSet
* tiling_set
) {
63 tilings_
.reserve(tiling_set
->num_tilings());
64 // Generate all of the tilings in the order described in the header comment
67 tiling_set
->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
);
68 for (int i
= range
.start
; i
< range
.end
; ++i
)
69 tilings_
.push_back(tiling_set
->tiling_at(i
));
71 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES
);
72 for (int i
= range
.end
- 1; i
>= range
.start
; --i
)
73 tilings_
.push_back(tiling_set
->tiling_at(i
));
75 range
= tiling_set
->GetTilingRange(
76 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
);
77 for (int i
= range
.end
- 1; i
>= range
.start
; --i
)
78 tilings_
.push_back(tiling_set
->tiling_at(i
));
80 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::LOW_RES
);
81 for (int i
= range
.start
; i
< range
.end
; ++i
)
82 tilings_
.push_back(tiling_set
->tiling_at(i
));
84 range
= tiling_set
->GetTilingRange(PictureLayerTilingSet::HIGH_RES
);
85 for (int i
= range
.start
; i
< range
.end
; ++i
)
86 tilings_
.push_back(tiling_set
->tiling_at(i
));
87 DCHECK_EQ(tiling_set
->num_tilings(), tilings_
.size());
90 void TilingSetEvictionQueue::AdvancePhase() {
91 current_tile_
= nullptr;
92 while (!current_tile_
&&
93 phase_
!= VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
) {
94 phase_
= static_cast<Phase
>(phase_
+ 1);
99 case SOON_BORDER_RECT
:
100 soon_iterator_
= SoonBorderTilingIterator(
101 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
);
102 if (!soon_iterator_
.done())
103 current_tile_
= *soon_iterator_
;
106 skewport_iterator_
= SkewportTilingIterator(
107 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
);
108 if (!skewport_iterator_
.done())
109 current_tile_
= *skewport_iterator_
;
111 case VISIBLE_RECT_OCCLUDED
:
112 visible_iterator_
= VisibleTilingIterator(
113 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
,
114 true /* return occluded tiles */,
115 false /* return required for activation tiles */);
116 if (!visible_iterator_
.done())
117 current_tile_
= *visible_iterator_
;
119 case VISIBLE_RECT_UNOCCLUDED
:
120 visible_iterator_
= VisibleTilingIterator(
121 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
,
122 false /* return occluded tiles */,
123 false /* return required for activation tiles */);
124 if (!visible_iterator_
.done())
125 current_tile_
= *visible_iterator_
;
127 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED
:
128 visible_iterator_
= VisibleTilingIterator(
129 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
,
130 true /* return occluded tiles */,
131 true /* return required for activation tiles */);
132 if (!visible_iterator_
.done())
133 current_tile_
= *visible_iterator_
;
135 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
:
136 visible_iterator_
= VisibleTilingIterator(
137 &tilings_
, tree_
, skip_shared_out_of_order_tiles_
,
138 false /* return occluded tiles */,
139 true /* return required for activation tiles */);
140 if (!visible_iterator_
.done())
141 current_tile_
= *visible_iterator_
;
147 bool TilingSetEvictionQueue::IsEmpty() const {
148 return !current_tile_
;
151 Tile
* TilingSetEvictionQueue::Top() {
153 return current_tile_
;
156 const Tile
* TilingSetEvictionQueue::Top() const {
158 return current_tile_
;
161 void TilingSetEvictionQueue::Pop() {
163 current_tile_
= nullptr;
165 case EVENTUALLY_RECT
:
166 ++eventually_iterator_
;
167 if (!eventually_iterator_
.done())
168 current_tile_
= *eventually_iterator_
;
170 case SOON_BORDER_RECT
:
172 if (!soon_iterator_
.done())
173 current_tile_
= *soon_iterator_
;
176 ++skewport_iterator_
;
177 if (!skewport_iterator_
.done())
178 current_tile_
= *skewport_iterator_
;
180 case VISIBLE_RECT_OCCLUDED
:
181 case VISIBLE_RECT_UNOCCLUDED
:
182 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED
:
183 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED
:
185 if (!visible_iterator_
.done())
186 current_tile_
= *visible_iterator_
;
193 // EvictionRectIterator
194 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator()
198 skip_shared_out_of_order_tiles_(false),
202 TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator(
203 std::vector
<PictureLayerTiling
*>* tilings
,
205 bool skip_shared_out_of_order_tiles
)
209 skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles
),
213 template <typename TilingIteratorType
>
214 bool TilingSetEvictionQueue::EvictionRectIterator::AdvanceToNextTile(
215 TilingIteratorType
* iterator
) {
216 bool found_tile
= false;
217 while (!found_tile
) {
223 found_tile
= GetFirstTileAndCheckIfValid(iterator
);
228 template <typename TilingIteratorType
>
229 bool TilingSetEvictionQueue::EvictionRectIterator::GetFirstTileAndCheckIfValid(
230 TilingIteratorType
* iterator
) {
231 tile_
= (*tilings_
)[tiling_index_
]->TileAt(iterator
->index_x(),
232 iterator
->index_y());
233 // If there's nothing to evict, return false.
234 if (!tile_
|| !tile_
->HasResource())
236 (*tilings_
)[tiling_index_
]->UpdateTileAndTwinPriority(tile_
);
237 // If the tile is out of order, return false.
238 if (skip_shared_out_of_order_tiles_
&& IsSharedOutOfOrderTile(tree_
, 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 bool skip_shared_out_of_order_tiles
)
249 : EvictionRectIterator(tilings
, tree
, skip_shared_out_of_order_tiles
) {
250 // Find the first tiling with a tile.
251 while (tiling_index_
< tilings_
->size()) {
252 if (!((*tilings_
))[tiling_index_
]->has_eventually_rect_tiles()) {
256 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
257 ((*tilings_
))[tiling_index_
]->tiling_data(),
258 ((*tilings_
))[tiling_index_
]->current_eventually_rect(),
259 ((*tilings_
))[tiling_index_
]->current_skewport_rect(),
260 ((*tilings_
))[tiling_index_
]->current_soon_border_rect());
267 if (tiling_index_
>= tilings_
->size())
269 if (!GetFirstTileAndCheckIfValid(&iterator_
))
273 TilingSetEvictionQueue::EventuallyTilingIterator
&
274 TilingSetEvictionQueue::EventuallyTilingIterator::
276 bool found_tile
= AdvanceToNextTile(&iterator_
);
277 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
279 if (!((*tilings_
))[tiling_index_
]->has_eventually_rect_tiles())
281 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
282 ((*tilings_
))[tiling_index_
]->tiling_data(),
283 ((*tilings_
))[tiling_index_
]->current_eventually_rect(),
284 ((*tilings_
))[tiling_index_
]->current_skewport_rect(),
285 ((*tilings_
))[tiling_index_
]->current_soon_border_rect());
288 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
290 found_tile
= AdvanceToNextTile(&iterator_
);
295 // SoonBorderTilingIterator
296 TilingSetEvictionQueue::SoonBorderTilingIterator::SoonBorderTilingIterator(
297 std::vector
<PictureLayerTiling
*>* tilings
,
299 bool skip_shared_out_of_order_tiles
)
300 : EvictionRectIterator(tilings
, tree
, skip_shared_out_of_order_tiles
) {
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 bool skip_shared_out_of_order_tiles
)
351 : EvictionRectIterator(tilings
, tree
, skip_shared_out_of_order_tiles
) {
352 // Find the first tiling with a tile.
353 while (tiling_index_
< tilings_
->size()) {
354 if (!((*tilings_
))[tiling_index_
]->has_skewport_rect_tiles()) {
358 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
359 ((*tilings_
))[tiling_index_
]->tiling_data(),
360 ((*tilings_
))[tiling_index_
]->current_skewport_rect(),
361 ((*tilings_
))[tiling_index_
]->current_visible_rect(),
362 ((*tilings_
))[tiling_index_
]->current_visible_rect());
369 if (tiling_index_
>= tilings_
->size())
371 if (!GetFirstTileAndCheckIfValid(&iterator_
))
375 TilingSetEvictionQueue::SkewportTilingIterator
&
376 TilingSetEvictionQueue::SkewportTilingIterator::
378 bool found_tile
= AdvanceToNextTile(&iterator_
);
379 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
381 if (!((*tilings_
))[tiling_index_
]->has_skewport_rect_tiles())
383 iterator_
= TilingData::ReverseSpiralDifferenceIterator(
384 ((*tilings_
))[tiling_index_
]->tiling_data(),
385 ((*tilings_
))[tiling_index_
]->current_skewport_rect(),
386 ((*tilings_
))[tiling_index_
]->current_visible_rect(),
387 ((*tilings_
))[tiling_index_
]->current_visible_rect());
390 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
392 found_tile
= AdvanceToNextTile(&iterator_
);
397 // VisibleTilingIterator
398 TilingSetEvictionQueue::VisibleTilingIterator::VisibleTilingIterator(
399 std::vector
<PictureLayerTiling
*>* tilings
,
401 bool skip_shared_out_of_order_tiles
,
402 bool return_occluded_tiles
,
403 bool return_required_for_activation_tiles
)
404 : EvictionRectIterator(tilings
, tree
, skip_shared_out_of_order_tiles
),
405 return_occluded_tiles_(return_occluded_tiles
),
406 return_required_for_activation_tiles_(
407 return_required_for_activation_tiles
) {
408 // Find the first tiling with a tile.
409 while (tiling_index_
< tilings_
->size()) {
410 if (!((*tilings_
))[tiling_index_
]->has_visible_rect_tiles()) {
414 iterator_
= TilingData::Iterator(
415 ((*tilings_
))[tiling_index_
]->tiling_data(),
416 ((*tilings_
))[tiling_index_
]->current_visible_rect(), false);
423 if (tiling_index_
>= tilings_
->size())
425 if (!GetFirstTileAndCheckIfValid(&iterator_
)) {
429 if (!TileMatchesRequiredFlags(tile_
)) {
435 TilingSetEvictionQueue::VisibleTilingIterator
&
436 TilingSetEvictionQueue::VisibleTilingIterator::
438 bool found_tile
= AdvanceToNextTile(&iterator_
);
439 while (found_tile
&& !TileMatchesRequiredFlags(tile_
))
440 found_tile
= AdvanceToNextTile(&iterator_
);
442 while (!found_tile
&& (tiling_index_
+ 1) < tilings_
->size()) {
444 if (!((*tilings_
))[tiling_index_
]->has_visible_rect_tiles())
446 iterator_
= TilingData::Iterator(
447 ((*tilings_
))[tiling_index_
]->tiling_data(),
448 ((*tilings_
))[tiling_index_
]->current_visible_rect(), false);
451 found_tile
= GetFirstTileAndCheckIfValid(&iterator_
);
453 found_tile
= AdvanceToNextTile(&iterator_
);
454 while (found_tile
&& !TileMatchesRequiredFlags(tile_
))
455 found_tile
= AdvanceToNextTile(&iterator_
);
460 bool TilingSetEvictionQueue::VisibleTilingIterator::TileMatchesRequiredFlags(
461 const Tile
* tile
) const {
462 bool activation_flag_matches
=
463 tile
->required_for_activation() == return_required_for_activation_tiles_
;
464 bool occluded_flag_matches
=
465 tile
->is_occluded(tree_
) == return_occluded_tiles_
;
466 return activation_flag_matches
&& occluded_flag_matches
;