1 // Copyright 2015 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.
5 #include "cc/resources/raster_tile_priority_queue_all.h"
7 #include "cc/resources/tiling_set_raster_queue_all.h"
13 class RasterOrderComparator
{
15 explicit RasterOrderComparator(TreePriority tree_priority
)
16 : tree_priority_(tree_priority
) {}
19 const RasterTilePriorityQueueAll::PairedTilingSetQueue
* a
,
20 const RasterTilePriorityQueueAll::PairedTilingSetQueue
* b
) const {
21 // Note that in this function, we have to return true if and only if
22 // a is strictly lower priority than b. Note that for the sake of
23 // completeness, empty queue is considered to have lowest priority.
24 if (a
->IsEmpty() || b
->IsEmpty())
25 return b
->IsEmpty() < a
->IsEmpty();
27 WhichTree a_tree
= a
->NextTileIteratorTree(tree_priority_
);
28 const TilingSetRasterQueueAll
* a_queue
=
29 a_tree
== ACTIVE_TREE
? a
->active_queue() : a
->pending_queue();
31 WhichTree b_tree
= b
->NextTileIteratorTree(tree_priority_
);
32 const TilingSetRasterQueueAll
* b_queue
=
33 b_tree
== ACTIVE_TREE
? b
->active_queue() : b
->pending_queue();
35 const Tile
* a_tile
= a_queue
->Top();
36 const Tile
* b_tile
= b_queue
->Top();
38 const TilePriority
& a_priority
= a_tile
->priority();
39 const TilePriority
& b_priority
= b_tile
->priority();
40 bool prioritize_low_res
= tree_priority_
== SMOOTHNESS_TAKES_PRIORITY
;
42 // If the bin is the same but the resolution is not, then the order will be
43 // determined by whether we prioritize low res or not.
44 // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile
45 // class but instead produced by the iterators.
46 if (b_priority
.priority_bin
== a_priority
.priority_bin
&&
47 b_priority
.resolution
!= a_priority
.resolution
) {
48 // Non ideal resolution should be sorted lower than other resolutions.
49 if (a_priority
.resolution
== NON_IDEAL_RESOLUTION
)
52 if (b_priority
.resolution
== NON_IDEAL_RESOLUTION
)
55 if (prioritize_low_res
)
56 return b_priority
.resolution
== LOW_RESOLUTION
;
57 return b_priority
.resolution
== HIGH_RESOLUTION
;
60 return b_priority
.IsHigherPriorityThan(a_priority
);
64 TreePriority tree_priority_
;
67 WhichTree
HigherPriorityTree(TreePriority tree_priority
,
68 const TilingSetRasterQueueAll
* active_queue
,
69 const TilingSetRasterQueueAll
* pending_queue
) {
70 const Tile
* active_tile
= active_queue
->Top();
71 const Tile
* pending_tile
= pending_queue
->Top();
73 const TilePriority
& active_priority
= active_tile
->priority();
74 const TilePriority
& pending_priority
= pending_tile
->priority();
76 switch (tree_priority
) {
77 case SMOOTHNESS_TAKES_PRIORITY
: {
78 // If we're down to eventually bin tiles on the active tree, process the
79 // pending tree to allow tiles required for activation to be initialized
80 // when memory policy only allows prepaint.
81 if (active_priority
.priority_bin
== TilePriority::EVENTUALLY
&&
82 pending_priority
.priority_bin
== TilePriority::NOW
) {
87 case NEW_CONTENT_TAKES_PRIORITY
: {
88 // If we're down to soon bin tiles on the pending tree, process the
89 // active tree to allow tiles required for activation to be initialized
90 // when memory policy only allows prepaint. Note that active required for
91 // activation tiles might come from either now or soon bins.
92 if (pending_priority
.priority_bin
>= TilePriority::SOON
&&
93 active_priority
.priority_bin
<= TilePriority::SOON
) {
98 case SAME_PRIORITY_FOR_BOTH_TREES
: {
99 if (active_priority
.IsHigherPriorityThan(pending_priority
))
109 scoped_ptr
<TilingSetRasterQueueAll
> CreateTilingSetRasterQueue(
110 PictureLayerImpl
* layer
,
111 TreePriority tree_priority
) {
114 PictureLayerTilingSet
* tiling_set
= layer
->picture_layer_tiling_set();
115 bool prioritize_low_res
= tree_priority
== SMOOTHNESS_TAKES_PRIORITY
;
116 return make_scoped_ptr(
117 new TilingSetRasterQueueAll(tiling_set
, prioritize_low_res
));
122 RasterTilePriorityQueueAll::RasterTilePriorityQueueAll() {
125 RasterTilePriorityQueueAll::~RasterTilePriorityQueueAll() {
128 void RasterTilePriorityQueueAll::Build(
129 const std::vector
<PictureLayerImpl::Pair
>& paired_layers
,
130 TreePriority tree_priority
) {
131 tree_priority_
= tree_priority
;
132 for (std::vector
<PictureLayerImpl::Pair
>::const_iterator it
=
133 paired_layers
.begin();
134 it
!= paired_layers
.end(); ++it
) {
135 paired_queues_
.push_back(
136 make_scoped_ptr(new PairedTilingSetQueue(*it
, tree_priority_
)));
138 paired_queues_
.make_heap(RasterOrderComparator(tree_priority_
));
141 bool RasterTilePriorityQueueAll::IsEmpty() const {
142 return paired_queues_
.empty() || paired_queues_
.front()->IsEmpty();
145 Tile
* RasterTilePriorityQueueAll::Top() {
147 return paired_queues_
.front()->Top(tree_priority_
);
150 void RasterTilePriorityQueueAll::Pop() {
153 paired_queues_
.pop_heap(RasterOrderComparator(tree_priority_
));
154 PairedTilingSetQueue
* paired_queue
= paired_queues_
.back();
155 paired_queue
->Pop(tree_priority_
);
156 paired_queues_
.push_heap(RasterOrderComparator(tree_priority_
));
159 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue() {
162 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue(
163 const PictureLayerImpl::Pair
& layer_pair
,
164 TreePriority tree_priority
)
166 CreateTilingSetRasterQueue(layer_pair
.active
, tree_priority
)),
168 CreateTilingSetRasterQueue(layer_pair
.pending
, tree_priority
)) {
169 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
170 "PairedTilingSetQueue::PairedTilingSetQueue",
171 TRACE_EVENT_SCOPE_THREAD
, "state", StateAsValue());
174 RasterTilePriorityQueueAll::PairedTilingSetQueue::~PairedTilingSetQueue() {
175 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
176 "PairedTilingSetQueue::~PairedTilingSetQueue",
177 TRACE_EVENT_SCOPE_THREAD
, "state", StateAsValue());
180 bool RasterTilePriorityQueueAll::PairedTilingSetQueue::IsEmpty() const {
181 return (!active_queue_
|| active_queue_
->IsEmpty()) &&
182 (!pending_queue_
|| pending_queue_
->IsEmpty());
185 Tile
* RasterTilePriorityQueueAll::PairedTilingSetQueue::Top(
186 TreePriority tree_priority
) {
189 WhichTree next_tree
= NextTileIteratorTree(tree_priority
);
190 TilingSetRasterQueueAll
* next_queue
=
191 next_tree
== ACTIVE_TREE
? active_queue_
.get() : pending_queue_
.get();
192 DCHECK(next_queue
&& !next_queue
->IsEmpty());
193 Tile
* tile
= next_queue
->Top();
194 DCHECK(returned_tiles_for_debug_
.find(tile
) ==
195 returned_tiles_for_debug_
.end());
199 void RasterTilePriorityQueueAll::PairedTilingSetQueue::Pop(
200 TreePriority tree_priority
) {
203 WhichTree next_tree
= NextTileIteratorTree(tree_priority
);
204 TilingSetRasterQueueAll
* next_queue
=
205 next_tree
== ACTIVE_TREE
? active_queue_
.get() : pending_queue_
.get();
206 DCHECK(next_queue
&& !next_queue
->IsEmpty());
207 DCHECK(returned_tiles_for_debug_
.insert(next_queue
->Top()).second
);
210 // If no empty, use Top to do DCHECK the next iterator.
211 DCHECK(IsEmpty() || Top(tree_priority
));
215 RasterTilePriorityQueueAll::PairedTilingSetQueue::NextTileIteratorTree(
216 TreePriority tree_priority
) const {
219 // If we only have one queue with tiles, return it.
220 if (!active_queue_
|| active_queue_
->IsEmpty())
222 if (!pending_queue_
|| pending_queue_
->IsEmpty())
225 // Now both iterators have tiles, so we have to decide based on tree priority.
226 return HigherPriorityTree(tree_priority
, active_queue_
.get(),
227 pending_queue_
.get());
230 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>
231 RasterTilePriorityQueueAll::PairedTilingSetQueue::StateAsValue() const {
232 scoped_refptr
<base::trace_event::TracedValue
> state
=
233 new base::trace_event::TracedValue();
235 bool active_queue_has_tile
= active_queue_
&& !active_queue_
->IsEmpty();
236 TilePriority::PriorityBin active_priority_bin
= TilePriority::EVENTUALLY
;
237 TilePriority::PriorityBin pending_priority_bin
= TilePriority::EVENTUALLY
;
238 if (active_queue_has_tile
) {
239 active_priority_bin
= active_queue_
->Top()->priority().priority_bin
;
240 pending_priority_bin
= active_queue_
->Top()->priority().priority_bin
;
243 state
->BeginDictionary("active_queue");
244 state
->SetBoolean("has_tile", active_queue_has_tile
);
245 state
->SetInteger("active_priority_bin", active_priority_bin
);
246 state
->SetInteger("pending_priority_bin", pending_priority_bin
);
247 state
->EndDictionary();
249 bool pending_queue_has_tile
= pending_queue_
&& !pending_queue_
->IsEmpty();
250 active_priority_bin
= TilePriority::EVENTUALLY
;
251 pending_priority_bin
= TilePriority::EVENTUALLY
;
252 if (pending_queue_has_tile
) {
253 active_priority_bin
= pending_queue_
->Top()->priority().priority_bin
;
254 pending_priority_bin
= pending_queue_
->Top()->priority().priority_bin
;
257 state
->BeginDictionary("pending_queue");
258 state
->SetBoolean("has_tile", active_queue_has_tile
);
259 state
->SetInteger("active_priority_bin", active_priority_bin
);
260 state
->SetInteger("pending_priority_bin", pending_priority_bin
);
261 state
->EndDictionary();