OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/resources/raster_tile_priority_queue_all.h" | 5 #include "cc/resources/raster_tile_priority_queue_all.h" |
6 | 6 |
7 #include "cc/resources/tiling_set_raster_queue_all.h" | 7 #include "cc/resources/tiling_set_raster_queue_all.h" |
8 | 8 |
9 namespace cc { | 9 namespace cc { |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 const TilingSetRasterQueueAll* a_queue = | 28 const TilingSetRasterQueueAll* a_queue = |
29 a_tree == ACTIVE_TREE ? a->active_queue() : a->pending_queue(); | 29 a_tree == ACTIVE_TREE ? a->active_queue() : a->pending_queue(); |
30 | 30 |
31 WhichTree b_tree = b->NextTileIteratorTree(tree_priority_); | 31 WhichTree b_tree = b->NextTileIteratorTree(tree_priority_); |
32 const TilingSetRasterQueueAll* b_queue = | 32 const TilingSetRasterQueueAll* b_queue = |
33 b_tree == ACTIVE_TREE ? b->active_queue() : b->pending_queue(); | 33 b_tree == ACTIVE_TREE ? b->active_queue() : b->pending_queue(); |
34 | 34 |
35 const Tile* a_tile = a_queue->Top(); | 35 const Tile* a_tile = a_queue->Top(); |
36 const Tile* b_tile = b_queue->Top(); | 36 const Tile* b_tile = b_queue->Top(); |
37 | 37 |
38 const TilePriority& a_priority = a_tile->priority(); | 38 const TilePriority& a_priority = |
39 const TilePriority& b_priority = b_tile->priority(); | 39 a_tile->priority_for_tree_priority(tree_priority_); |
| 40 const TilePriority& b_priority = |
| 41 b_tile->priority_for_tree_priority(tree_priority_); |
40 bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY; | 42 bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY; |
41 | 43 |
| 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; |
| 56 |
| 57 // In case neither one is pending now, fall through. |
| 58 } |
| 59 |
42 // If the bin is the same but the resolution is not, then the order will be | 60 // 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. | 61 // determined by whether we prioritize low res or not. |
44 // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile | 62 // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile |
45 // class but instead produced by the iterators. | 63 // class but instead produced by the iterators. |
46 if (b_priority.priority_bin == a_priority.priority_bin && | 64 if (b_priority.priority_bin == a_priority.priority_bin && |
47 b_priority.resolution != a_priority.resolution) { | 65 b_priority.resolution != a_priority.resolution) { |
48 // Non ideal resolution should be sorted lower than other resolutions. | 66 // Non ideal resolution should be sorted lower than other resolutions. |
49 if (a_priority.resolution == NON_IDEAL_RESOLUTION) | 67 if (a_priority.resolution == NON_IDEAL_RESOLUTION) |
50 return true; | 68 return true; |
51 | 69 |
52 if (b_priority.resolution == NON_IDEAL_RESOLUTION) | 70 if (b_priority.resolution == NON_IDEAL_RESOLUTION) |
53 return false; | 71 return false; |
54 | 72 |
55 if (prioritize_low_res) | 73 if (prioritize_low_res) |
56 return b_priority.resolution == LOW_RESOLUTION; | 74 return b_priority.resolution == LOW_RESOLUTION; |
57 return b_priority.resolution == HIGH_RESOLUTION; | 75 return b_priority.resolution == HIGH_RESOLUTION; |
58 } | 76 } |
59 | 77 |
60 return b_priority.IsHigherPriorityThan(a_priority); | 78 return b_priority.IsHigherPriorityThan(a_priority); |
61 } | 79 } |
62 | 80 |
63 private: | 81 private: |
64 TreePriority tree_priority_; | 82 TreePriority tree_priority_; |
65 }; | 83 }; |
66 | 84 |
67 WhichTree HigherPriorityTree(TreePriority tree_priority, | 85 WhichTree HigherPriorityTree(TreePriority tree_priority, |
68 const TilingSetRasterQueueAll* active_queue, | 86 const TilingSetRasterQueueAll* active_queue, |
69 const TilingSetRasterQueueAll* pending_queue) { | 87 const TilingSetRasterQueueAll* pending_queue, |
70 const Tile* active_tile = active_queue->Top(); | 88 const Tile* shared_tile) { |
71 const Tile* pending_tile = pending_queue->Top(); | 89 // In cases when we're given an active tile with a non ideal active resolution |
72 | 90 // (or pending tile with non ideal pending resolution), we should return the |
73 const TilePriority& active_priority = active_tile->priority(); | 91 // other tree. The reason for this is that tiling set iterators will not |
74 const TilePriority& pending_priority = pending_tile->priority(); | 92 // return non ideal tiles and the only way we get here is if we're skipping |
| 93 // twin tiles, but since it's non-ideal on the twin, we shouldn't skip it. |
| 94 // TODO(vmpstr): Remove when tiles aren't shared. |
| 95 const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top(); |
| 96 const Tile* pending_tile = shared_tile ? shared_tile : pending_queue->Top(); |
| 97 if (active_tile->priority(ACTIVE_TREE).resolution == NON_IDEAL_RESOLUTION) |
| 98 return PENDING_TREE; |
| 99 if (pending_tile->priority(PENDING_TREE).resolution == NON_IDEAL_RESOLUTION) |
| 100 return ACTIVE_TREE; |
75 | 101 |
76 switch (tree_priority) { | 102 switch (tree_priority) { |
77 case SMOOTHNESS_TAKES_PRIORITY: { | 103 case SMOOTHNESS_TAKES_PRIORITY: { |
| 104 const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE); |
| 105 const TilePriority& pending_priority = |
| 106 pending_tile->priority(PENDING_TREE); |
| 107 |
78 // If we're down to eventually bin tiles on the active tree, process the | 108 // 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 | 109 // pending tree to allow tiles required for activation to be initialized |
80 // when memory policy only allows prepaint. | 110 // when memory policy only allows prepaint. |
81 if (active_priority.priority_bin == TilePriority::EVENTUALLY && | 111 if (active_priority.priority_bin == TilePriority::EVENTUALLY && |
82 pending_priority.priority_bin == TilePriority::NOW) { | 112 pending_priority.priority_bin == TilePriority::NOW) { |
83 return PENDING_TREE; | 113 return PENDING_TREE; |
84 } | 114 } |
85 return ACTIVE_TREE; | 115 return ACTIVE_TREE; |
86 } | 116 } |
87 case NEW_CONTENT_TAKES_PRIORITY: { | 117 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) { | |
94 return ACTIVE_TREE; | |
95 } | |
96 return PENDING_TREE; | 118 return PENDING_TREE; |
97 } | |
98 case SAME_PRIORITY_FOR_BOTH_TREES: { | 119 case SAME_PRIORITY_FOR_BOTH_TREES: { |
| 120 const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE); |
| 121 const TilePriority& pending_priority = |
| 122 pending_tile->priority(PENDING_TREE); |
| 123 |
99 if (active_priority.IsHigherPriorityThan(pending_priority)) | 124 if (active_priority.IsHigherPriorityThan(pending_priority)) |
100 return ACTIVE_TREE; | 125 return ACTIVE_TREE; |
101 return PENDING_TREE; | 126 return PENDING_TREE; |
102 } | 127 } |
103 default: | 128 default: |
104 NOTREACHED(); | 129 NOTREACHED(); |
105 return ACTIVE_TREE; | 130 return ACTIVE_TREE; |
106 } | 131 } |
107 } | 132 } |
108 | 133 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 | 183 |
159 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue() { | 184 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue() { |
160 } | 185 } |
161 | 186 |
162 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue( | 187 RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue( |
163 const PictureLayerImpl::Pair& layer_pair, | 188 const PictureLayerImpl::Pair& layer_pair, |
164 TreePriority tree_priority) | 189 TreePriority tree_priority) |
165 : active_queue_( | 190 : active_queue_( |
166 CreateTilingSetRasterQueue(layer_pair.active, tree_priority)), | 191 CreateTilingSetRasterQueue(layer_pair.active, tree_priority)), |
167 pending_queue_( | 192 pending_queue_( |
168 CreateTilingSetRasterQueue(layer_pair.pending, tree_priority)) { | 193 CreateTilingSetRasterQueue(layer_pair.pending, tree_priority)), |
| 194 has_both_layers_(layer_pair.active && layer_pair.pending) { |
| 195 SkipTilesReturnedByTwin(tree_priority); |
| 196 |
169 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 197 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
170 "PairedTilingSetQueue::PairedTilingSetQueue", | 198 "PairedTilingSetQueue::PairedTilingSetQueue", |
171 TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); | 199 TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); |
172 } | 200 } |
173 | 201 |
174 RasterTilePriorityQueueAll::PairedTilingSetQueue::~PairedTilingSetQueue() { | 202 RasterTilePriorityQueueAll::PairedTilingSetQueue::~PairedTilingSetQueue() { |
175 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 203 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
176 "PairedTilingSetQueue::~PairedTilingSetQueue", | 204 "PairedTilingSetQueue::~PairedTilingSetQueue", |
177 TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); | 205 TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); |
178 } | 206 } |
(...skipping 21 matching lines...) Expand all Loading... |
200 TreePriority tree_priority) { | 228 TreePriority tree_priority) { |
201 DCHECK(!IsEmpty()); | 229 DCHECK(!IsEmpty()); |
202 | 230 |
203 WhichTree next_tree = NextTileIteratorTree(tree_priority); | 231 WhichTree next_tree = NextTileIteratorTree(tree_priority); |
204 TilingSetRasterQueueAll* next_queue = | 232 TilingSetRasterQueueAll* next_queue = |
205 next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); | 233 next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); |
206 DCHECK(next_queue && !next_queue->IsEmpty()); | 234 DCHECK(next_queue && !next_queue->IsEmpty()); |
207 DCHECK(returned_tiles_for_debug_.insert(next_queue->Top()).second); | 235 DCHECK(returned_tiles_for_debug_.insert(next_queue->Top()).second); |
208 next_queue->Pop(); | 236 next_queue->Pop(); |
209 | 237 |
| 238 SkipTilesReturnedByTwin(tree_priority); |
| 239 |
210 // If no empty, use Top to do DCHECK the next iterator. | 240 // If no empty, use Top to do DCHECK the next iterator. |
211 DCHECK(IsEmpty() || Top(tree_priority)); | 241 DCHECK(IsEmpty() || Top(tree_priority)); |
212 } | 242 } |
213 | 243 |
| 244 void RasterTilePriorityQueueAll::PairedTilingSetQueue::SkipTilesReturnedByTwin( |
| 245 TreePriority tree_priority) { |
| 246 if (!has_both_layers_) |
| 247 return; |
| 248 |
| 249 // We have both layers (active and pending) thus we can encounter shared |
| 250 // tiles twice (from the active iterator and from the pending iterator). |
| 251 while (!IsEmpty()) { |
| 252 WhichTree next_tree = NextTileIteratorTree(tree_priority); |
| 253 TilingSetRasterQueueAll* next_queue = |
| 254 next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); |
| 255 DCHECK(next_queue && !next_queue->IsEmpty()); |
| 256 |
| 257 // Accept all non-shared tiles. |
| 258 const Tile* tile = next_queue->Top(); |
| 259 if (!tile->is_shared()) |
| 260 break; |
| 261 |
| 262 // Accept a shared tile if the next tree is the higher priority one |
| 263 // corresponding the iterator (active or pending) which usually (but due |
| 264 // to spiral iterators not always) returns the shared tile first. |
| 265 if (next_tree == HigherPriorityTree(tree_priority, nullptr, nullptr, tile)) |
| 266 break; |
| 267 |
| 268 next_queue->Pop(); |
| 269 } |
| 270 } |
| 271 |
214 WhichTree | 272 WhichTree |
215 RasterTilePriorityQueueAll::PairedTilingSetQueue::NextTileIteratorTree( | 273 RasterTilePriorityQueueAll::PairedTilingSetQueue::NextTileIteratorTree( |
216 TreePriority tree_priority) const { | 274 TreePriority tree_priority) const { |
217 DCHECK(!IsEmpty()); | 275 DCHECK(!IsEmpty()); |
218 | 276 |
219 // If we only have one queue with tiles, return it. | 277 // If we only have one queue with tiles, return it. |
220 if (!active_queue_ || active_queue_->IsEmpty()) | 278 if (!active_queue_ || active_queue_->IsEmpty()) |
221 return PENDING_TREE; | 279 return PENDING_TREE; |
222 if (!pending_queue_ || pending_queue_->IsEmpty()) | 280 if (!pending_queue_ || pending_queue_->IsEmpty()) |
223 return ACTIVE_TREE; | 281 return ACTIVE_TREE; |
224 | 282 |
225 // Now both iterators have tiles, so we have to decide based on tree priority. | 283 // Now both iterators have tiles, so we have to decide based on tree priority. |
226 return HigherPriorityTree(tree_priority, active_queue_.get(), | 284 return HigherPriorityTree(tree_priority, active_queue_.get(), |
227 pending_queue_.get()); | 285 pending_queue_.get(), nullptr); |
228 } | 286 } |
229 | 287 |
230 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 288 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
231 RasterTilePriorityQueueAll::PairedTilingSetQueue::StateAsValue() const { | 289 RasterTilePriorityQueueAll::PairedTilingSetQueue::StateAsValue() const { |
232 scoped_refptr<base::trace_event::TracedValue> state = | 290 scoped_refptr<base::trace_event::TracedValue> state = |
233 new base::trace_event::TracedValue(); | 291 new base::trace_event::TracedValue(); |
234 | 292 |
235 bool active_queue_has_tile = active_queue_ && !active_queue_->IsEmpty(); | 293 bool active_queue_has_tile = active_queue_ && !active_queue_->IsEmpty(); |
236 TilePriority::PriorityBin active_priority_bin = TilePriority::EVENTUALLY; | 294 TilePriority::PriorityBin active_priority_bin = TilePriority::EVENTUALLY; |
237 TilePriority::PriorityBin pending_priority_bin = TilePriority::EVENTUALLY; | 295 TilePriority::PriorityBin pending_priority_bin = TilePriority::EVENTUALLY; |
238 if (active_queue_has_tile) { | 296 if (active_queue_has_tile) { |
239 active_priority_bin = active_queue_->Top()->priority().priority_bin; | 297 active_priority_bin = |
240 pending_priority_bin = active_queue_->Top()->priority().priority_bin; | 298 active_queue_->Top()->priority(ACTIVE_TREE).priority_bin; |
| 299 pending_priority_bin = |
| 300 active_queue_->Top()->priority(PENDING_TREE).priority_bin; |
241 } | 301 } |
242 | 302 |
243 state->BeginDictionary("active_queue"); | 303 state->BeginDictionary("active_queue"); |
244 state->SetBoolean("has_tile", active_queue_has_tile); | 304 state->SetBoolean("has_tile", active_queue_has_tile); |
245 state->SetInteger("active_priority_bin", active_priority_bin); | 305 state->SetInteger("active_priority_bin", active_priority_bin); |
246 state->SetInteger("pending_priority_bin", pending_priority_bin); | 306 state->SetInteger("pending_priority_bin", pending_priority_bin); |
247 state->EndDictionary(); | 307 state->EndDictionary(); |
248 | 308 |
249 bool pending_queue_has_tile = pending_queue_ && !pending_queue_->IsEmpty(); | 309 bool pending_queue_has_tile = pending_queue_ && !pending_queue_->IsEmpty(); |
250 active_priority_bin = TilePriority::EVENTUALLY; | 310 active_priority_bin = TilePriority::EVENTUALLY; |
251 pending_priority_bin = TilePriority::EVENTUALLY; | 311 pending_priority_bin = TilePriority::EVENTUALLY; |
252 if (pending_queue_has_tile) { | 312 if (pending_queue_has_tile) { |
253 active_priority_bin = pending_queue_->Top()->priority().priority_bin; | 313 active_priority_bin = |
254 pending_priority_bin = pending_queue_->Top()->priority().priority_bin; | 314 pending_queue_->Top()->priority(ACTIVE_TREE).priority_bin; |
| 315 pending_priority_bin = |
| 316 pending_queue_->Top()->priority(PENDING_TREE).priority_bin; |
255 } | 317 } |
256 | 318 |
257 state->BeginDictionary("pending_queue"); | 319 state->BeginDictionary("pending_queue"); |
258 state->SetBoolean("has_tile", active_queue_has_tile); | 320 state->SetBoolean("has_tile", active_queue_has_tile); |
259 state->SetInteger("active_priority_bin", active_priority_bin); | 321 state->SetInteger("active_priority_bin", active_priority_bin); |
260 state->SetInteger("pending_priority_bin", pending_priority_bin); | 322 state->SetInteger("pending_priority_bin", pending_priority_bin); |
261 state->EndDictionary(); | 323 state->EndDictionary(); |
262 return state; | 324 return state; |
263 } | 325 } |
264 | 326 |
265 } // namespace cc | 327 } // namespace cc |
OLD | NEW |