Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / cc / resources / raster_tile_priority_queue_all.cc
blob9baa9b32de7177e67738a675a78dda8f1cf65779
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"
9 namespace cc {
11 namespace {
13 class RasterOrderComparator {
14 public:
15 explicit RasterOrderComparator(TreePriority tree_priority)
16 : tree_priority_(tree_priority) {}
18 bool operator()(
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 =
39 a_tile->priority_for_tree_priority(tree_priority_);
40 const TilePriority& b_priority =
41 b_tile->priority_for_tree_priority(tree_priority_);
42 bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
44 // In smoothness mode, we should return pending NOW tiles before active
45 // EVENTUALLY tiles. So if both priorities here are eventually, we need to
46 // check the pending priority.
47 if (prioritize_low_res &&
48 a_priority.priority_bin == TilePriority::EVENTUALLY &&
49 b_priority.priority_bin == TilePriority::EVENTUALLY) {
50 bool a_is_pending_now =
51 a_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW;
52 bool b_is_pending_now =
53 b_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW;
54 if (a_is_pending_now || b_is_pending_now)
55 return a_is_pending_now < b_is_pending_now;
57 // In case neither one is pending now, fall through.
60 // If the bin is the same but the resolution is not, then the order will be
61 // determined by whether we prioritize low res or not.
62 // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile
63 // class but instead produced by the iterators.
64 if (b_priority.priority_bin == a_priority.priority_bin &&
65 b_priority.resolution != a_priority.resolution) {
66 // Non ideal resolution should be sorted lower than other resolutions.
67 if (a_priority.resolution == NON_IDEAL_RESOLUTION)
68 return true;
70 if (b_priority.resolution == NON_IDEAL_RESOLUTION)
71 return false;
73 if (prioritize_low_res)
74 return b_priority.resolution == LOW_RESOLUTION;
75 return b_priority.resolution == HIGH_RESOLUTION;
78 return b_priority.IsHigherPriorityThan(a_priority);
81 private:
82 TreePriority tree_priority_;
85 WhichTree HigherPriorityTree(TreePriority tree_priority,
86 const TilingSetRasterQueueAll* active_queue,
87 const TilingSetRasterQueueAll* pending_queue,
88 const Tile* shared_tile) {
89 switch (tree_priority) {
90 case SMOOTHNESS_TAKES_PRIORITY: {
91 const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top();
92 const Tile* pending_tile =
93 shared_tile ? shared_tile : pending_queue->Top();
95 const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE);
96 const TilePriority& pending_priority =
97 pending_tile->priority(PENDING_TREE);
99 // If we're down to eventually bin tiles on the active tree, process the
100 // pending tree to allow tiles required for activation to be initialized
101 // when memory policy only allows prepaint.
102 if (active_priority.priority_bin == TilePriority::EVENTUALLY &&
103 pending_priority.priority_bin == TilePriority::NOW) {
104 return PENDING_TREE;
106 return ACTIVE_TREE;
108 case NEW_CONTENT_TAKES_PRIORITY:
109 return PENDING_TREE;
110 case SAME_PRIORITY_FOR_BOTH_TREES: {
111 const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top();
112 const Tile* pending_tile =
113 shared_tile ? shared_tile : pending_queue->Top();
115 const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE);
116 const TilePriority& pending_priority =
117 pending_tile->priority(PENDING_TREE);
119 if (active_priority.IsHigherPriorityThan(pending_priority))
120 return ACTIVE_TREE;
121 return PENDING_TREE;
123 default:
124 NOTREACHED();
125 return ACTIVE_TREE;
129 scoped_ptr<TilingSetRasterQueueAll> CreateTilingSetRasterQueue(
130 PictureLayerImpl* layer,
131 TreePriority tree_priority) {
132 if (!layer)
133 return nullptr;
134 PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set();
135 bool prioritize_low_res = tree_priority == SMOOTHNESS_TAKES_PRIORITY;
136 return make_scoped_ptr(
137 new TilingSetRasterQueueAll(tiling_set, prioritize_low_res));
140 } // namespace
142 RasterTilePriorityQueueAll::RasterTilePriorityQueueAll() {
145 RasterTilePriorityQueueAll::~RasterTilePriorityQueueAll() {
148 void RasterTilePriorityQueueAll::Build(
149 const std::vector<PictureLayerImpl::Pair>& paired_layers,
150 TreePriority tree_priority) {
151 tree_priority_ = tree_priority;
152 for (std::vector<PictureLayerImpl::Pair>::const_iterator it =
153 paired_layers.begin();
154 it != paired_layers.end(); ++it) {
155 paired_queues_.push_back(
156 make_scoped_ptr(new PairedTilingSetQueue(*it, tree_priority_)));
158 paired_queues_.make_heap(RasterOrderComparator(tree_priority_));
161 bool RasterTilePriorityQueueAll::IsEmpty() const {
162 return paired_queues_.empty() || paired_queues_.front()->IsEmpty();
165 Tile* RasterTilePriorityQueueAll::Top() {
166 DCHECK(!IsEmpty());
167 return paired_queues_.front()->Top(tree_priority_);
170 void RasterTilePriorityQueueAll::Pop() {
171 DCHECK(!IsEmpty());
173 paired_queues_.pop_heap(RasterOrderComparator(tree_priority_));
174 PairedTilingSetQueue* paired_queue = paired_queues_.back();
175 paired_queue->Pop(tree_priority_);
176 paired_queues_.push_heap(RasterOrderComparator(tree_priority_));
179 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue() {
182 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue(
183 const PictureLayerImpl::Pair& layer_pair,
184 TreePriority tree_priority)
185 : active_queue_(
186 CreateTilingSetRasterQueue(layer_pair.active, tree_priority)),
187 pending_queue_(
188 CreateTilingSetRasterQueue(layer_pair.pending, tree_priority)),
189 has_both_layers_(layer_pair.active && layer_pair.pending) {
190 SkipTilesReturnedByTwin(tree_priority);
192 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
193 "PairedTilingSetQueue::PairedTilingSetQueue",
194 TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue());
197 RasterTilePriorityQueueAll::PairedTilingSetQueue::~PairedTilingSetQueue() {
198 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
199 "PairedTilingSetQueue::~PairedTilingSetQueue",
200 TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue());
203 bool RasterTilePriorityQueueAll::PairedTilingSetQueue::IsEmpty() const {
204 return (!active_queue_ || active_queue_->IsEmpty()) &&
205 (!pending_queue_ || pending_queue_->IsEmpty());
208 Tile* RasterTilePriorityQueueAll::PairedTilingSetQueue::Top(
209 TreePriority tree_priority) {
210 DCHECK(!IsEmpty());
212 WhichTree next_tree = NextTileIteratorTree(tree_priority);
213 TilingSetRasterQueueAll* next_queue =
214 next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get();
215 DCHECK(next_queue && !next_queue->IsEmpty());
216 Tile* tile = next_queue->Top();
217 DCHECK(returned_tiles_for_debug_.find(tile) ==
218 returned_tiles_for_debug_.end());
219 return tile;
222 void RasterTilePriorityQueueAll::PairedTilingSetQueue::Pop(
223 TreePriority tree_priority) {
224 DCHECK(!IsEmpty());
226 WhichTree next_tree = NextTileIteratorTree(tree_priority);
227 TilingSetRasterQueueAll* next_queue =
228 next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get();
229 DCHECK(next_queue && !next_queue->IsEmpty());
230 DCHECK(returned_tiles_for_debug_.insert(next_queue->Top()).second);
231 next_queue->Pop();
233 SkipTilesReturnedByTwin(tree_priority);
235 // If no empty, use Top to do DCHECK the next iterator.
236 DCHECK(IsEmpty() || Top(tree_priority));
239 void RasterTilePriorityQueueAll::PairedTilingSetQueue::SkipTilesReturnedByTwin(
240 TreePriority tree_priority) {
241 if (!has_both_layers_)
242 return;
244 // We have both layers (active and pending) thus we can encounter shared
245 // tiles twice (from the active iterator and from the pending iterator).
246 while (!IsEmpty()) {
247 WhichTree next_tree = NextTileIteratorTree(tree_priority);
248 TilingSetRasterQueueAll* next_queue =
249 next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get();
250 DCHECK(next_queue && !next_queue->IsEmpty());
252 // Accept all non-shared tiles.
253 const Tile* tile = next_queue->Top();
254 if (!tile->is_shared())
255 break;
257 // Accept a shared tile if the next tree is the higher priority one
258 // corresponding the iterator (active or pending) which usually (but due
259 // to spiral iterators not always) returns the shared tile first.
260 if (next_tree == HigherPriorityTree(tree_priority, nullptr, nullptr, tile))
261 break;
263 next_queue->Pop();
267 WhichTree
268 RasterTilePriorityQueueAll::PairedTilingSetQueue::NextTileIteratorTree(
269 TreePriority tree_priority) const {
270 DCHECK(!IsEmpty());
272 // If we only have one queue with tiles, return it.
273 if (!active_queue_ || active_queue_->IsEmpty())
274 return PENDING_TREE;
275 if (!pending_queue_ || pending_queue_->IsEmpty())
276 return ACTIVE_TREE;
278 // Now both iterators have tiles, so we have to decide based on tree priority.
279 return HigherPriorityTree(tree_priority, active_queue_.get(),
280 pending_queue_.get(), nullptr);
283 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
284 RasterTilePriorityQueueAll::PairedTilingSetQueue::StateAsValue() const {
285 scoped_refptr<base::trace_event::TracedValue> state =
286 new base::trace_event::TracedValue();
288 bool active_queue_has_tile = active_queue_ && !active_queue_->IsEmpty();
289 TilePriority::PriorityBin active_priority_bin = TilePriority::EVENTUALLY;
290 TilePriority::PriorityBin pending_priority_bin = TilePriority::EVENTUALLY;
291 if (active_queue_has_tile) {
292 active_priority_bin =
293 active_queue_->Top()->priority(ACTIVE_TREE).priority_bin;
294 pending_priority_bin =
295 active_queue_->Top()->priority(PENDING_TREE).priority_bin;
298 state->BeginDictionary("active_queue");
299 state->SetBoolean("has_tile", active_queue_has_tile);
300 state->SetInteger("active_priority_bin", active_priority_bin);
301 state->SetInteger("pending_priority_bin", pending_priority_bin);
302 state->EndDictionary();
304 bool pending_queue_has_tile = pending_queue_ && !pending_queue_->IsEmpty();
305 active_priority_bin = TilePriority::EVENTUALLY;
306 pending_priority_bin = TilePriority::EVENTUALLY;
307 if (pending_queue_has_tile) {
308 active_priority_bin =
309 pending_queue_->Top()->priority(ACTIVE_TREE).priority_bin;
310 pending_priority_bin =
311 pending_queue_->Top()->priority(PENDING_TREE).priority_bin;
314 state->BeginDictionary("pending_queue");
315 state->SetBoolean("has_tile", active_queue_has_tile);
316 state->SetInteger("active_priority_bin", active_priority_bin);
317 state->SetInteger("pending_priority_bin", pending_priority_bin);
318 state->EndDictionary();
319 return state;
322 } // namespace cc