OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 <utility> | 5 #include <utility> |
6 | 6 |
7 #include "cc/resources/tiling_set_eviction_queue.h" | 7 #include "cc/resources/tiling_set_eviction_queue.h" |
8 | 8 |
9 namespace cc { | 9 namespace cc { |
10 namespace { | |
11 | |
12 bool IsSharedOutOfOrderTile(WhichTree tree, | |
13 TreePriority tree_priority, | |
14 const Tile* tile) { | |
15 if (!tile->is_shared()) | |
16 return false; | |
17 | |
18 switch (tree_priority) { | |
19 case SMOOTHNESS_TAKES_PRIORITY: | |
20 DCHECK_EQ(ACTIVE_TREE, tree); | |
21 return false; | |
22 case NEW_CONTENT_TAKES_PRIORITY: | |
23 DCHECK_EQ(PENDING_TREE, tree); | |
24 return false; | |
25 case SAME_PRIORITY_FOR_BOTH_TREES: | |
26 break; | |
27 } | |
28 | |
29 // The priority for tile priority of a shared tile will be a combined | |
30 // priority thus return shared tiles from a higher priority tree as | |
31 // it is out of order for a lower priority tree. | |
32 WhichTree twin_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; | |
33 const TilePriority& priority = tile->priority(tree); | |
34 const TilePriority& twin_priority = tile->priority(twin_tree); | |
35 if (priority.priority_bin != twin_priority.priority_bin) | |
36 return priority.priority_bin > twin_priority.priority_bin; | |
37 const bool occluded = tile->is_occluded(tree); | |
38 const bool twin_occluded = tile->is_occluded(twin_tree); | |
39 if (occluded != twin_occluded) | |
40 return occluded; | |
41 if (priority.distance_to_visible != twin_priority.distance_to_visible) | |
42 return priority.distance_to_visible > twin_priority.distance_to_visible; | |
43 | |
44 // If priorities are the same, it does not matter which tree returns | |
45 // the tile. Let's pick the pending tree. | |
46 return tree != PENDING_TREE; | |
47 } | |
48 | |
49 } // namespace | |
10 | 50 |
11 TilingSetEvictionQueue::TilingSetEvictionQueue( | 51 TilingSetEvictionQueue::TilingSetEvictionQueue( |
12 PictureLayerTilingSet* tiling_set, | 52 PictureLayerTilingSet* tiling_set, |
13 TreePriority tree_priority, | 53 TreePriority tree_priority, |
14 bool skip_shared_out_of_order_tiles) | 54 bool skip_shared_out_of_order_tiles) |
15 : tiling_set_(tiling_set), | 55 : tree_(tiling_set->client()->GetTree()), |
16 tree_(tiling_set->client()->GetTree()), | |
17 tree_priority_(tree_priority), | 56 tree_priority_(tree_priority), |
18 skip_all_shared_tiles_( | 57 skip_all_shared_tiles_( |
19 skip_shared_out_of_order_tiles && | 58 skip_shared_out_of_order_tiles && |
20 tree_priority == (tree_ == ACTIVE_TREE ? NEW_CONTENT_TAKES_PRIORITY | 59 tree_priority == (tree_ == ACTIVE_TREE ? NEW_CONTENT_TAKES_PRIORITY |
21 : SMOOTHNESS_TAKES_PRIORITY)), | 60 : SMOOTHNESS_TAKES_PRIORITY)), |
22 skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles), | 61 skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles), |
23 processing_soon_border_rect_(false), | 62 phase_(EVENTUALLY_RECT), |
24 processing_tiling_with_required_for_activation_tiles_(false), | 63 current_tile_(nullptr) { |
25 tiling_index_with_required_for_activation_tiles_(0u), | |
26 current_priority_bin_(TilePriority::EVENTUALLY), | |
27 current_tiling_index_(0u), | |
28 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES), | |
29 current_eviction_tile_(nullptr) { | |
30 // Early out if the layer has no tilings. | 64 // Early out if the layer has no tilings. |
31 if (!tiling_set_->num_tilings()) | 65 if (!tiling_set->num_tilings()) |
32 return; | 66 return; |
33 | 67 GenerateTilingOrder(tiling_set); |
34 tiling_index_with_required_for_activation_tiles_ = | 68 eventually_iterator_ = EventuallyTilingIterator( |
35 TilingIndexWithRequiredForActivationTiles(); | 69 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, |
36 | 70 skip_all_shared_tiles_); |
37 current_tiling_index_ = CurrentTilingRange().start - 1u; | 71 if (eventually_iterator_.done()) { |
38 AdvanceToNextValidTiling(); | 72 AdvancePhase(); |
73 return; | |
74 } | |
75 current_tile_ = *eventually_iterator_; | |
39 } | 76 } |
40 | 77 |
41 TilingSetEvictionQueue::~TilingSetEvictionQueue() { | 78 TilingSetEvictionQueue::~TilingSetEvictionQueue() { |
42 } | 79 } |
43 | 80 |
81 void TilingSetEvictionQueue::GenerateTilingOrder( | |
82 PictureLayerTilingSet* tiling_set) { | |
83 tilings_.reserve(tiling_set->num_tilings()); | |
84 // Generate all of the tilings in the following order: | |
85 // 1. Higher than high res from higher to lower resolution. | |
enne (OOO)
2015/03/27 19:12:11
This seems like a duplicate comment from some othe
vmpstr
2015/03/27 20:19:27
Done.
| |
86 // 2. Lower than low res from lower to higher resolution. | |
87 // 3. Between high and low res from lower to higher resolution. | |
88 // 4. Low res tiling if one exists. | |
89 // 5. High res tiling if one exists. | |
90 auto range = | |
91 tiling_set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); | |
92 for (int i = range.start; i < range.end; ++i) | |
93 tilings_.push_back(tiling_set->tiling_at(i)); | |
94 | |
95 range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); | |
96 for (int i = range.end - 1; i >= range.start; --i) | |
97 tilings_.push_back(tiling_set->tiling_at(i)); | |
98 | |
99 range = tiling_set->GetTilingRange( | |
100 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); | |
101 for (int i = range.end - 1; i >= range.start; --i) | |
102 tilings_.push_back(tiling_set->tiling_at(i)); | |
103 | |
104 range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOW_RES); | |
105 for (int i = range.start; i < range.end; ++i) | |
106 tilings_.push_back(tiling_set->tiling_at(i)); | |
107 | |
108 range = tiling_set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); | |
109 for (int i = range.start; i < range.end; ++i) | |
110 tilings_.push_back(tiling_set->tiling_at(i)); | |
111 DCHECK_EQ(tiling_set->num_tilings(), tilings_.size()); | |
112 } | |
113 | |
114 void TilingSetEvictionQueue::AdvancePhase() { | |
115 current_tile_ = nullptr; | |
116 while (!current_tile_ && | |
117 phase_ != VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED) { | |
118 phase_ = static_cast<Phase>(phase_ + 1); | |
119 switch (phase_) { | |
120 case EVENTUALLY_RECT: | |
121 NOTREACHED(); | |
122 break; | |
123 case SOON_BORDER_RECT: | |
124 soon_iterator_ = SoonBorderTilingIterator( | |
125 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, | |
126 skip_all_shared_tiles_); | |
127 if (!soon_iterator_.done()) | |
128 current_tile_ = *soon_iterator_; | |
129 break; | |
130 case SKEWPORT_RECT: | |
131 skewport_iterator_ = SkewportTilingIterator( | |
132 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, | |
133 skip_all_shared_tiles_); | |
134 if (!skewport_iterator_.done()) | |
135 current_tile_ = *skewport_iterator_; | |
136 break; | |
137 case VISIBLE_RECT_OCCLUDED: | |
138 visible_iterator_ = VisibleTilingIterator( | |
139 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, | |
140 skip_all_shared_tiles_, true /* return occluded tiles */, | |
141 false /* return required for activation tiles */); | |
142 if (!visible_iterator_.done()) | |
143 current_tile_ = *visible_iterator_; | |
144 break; | |
145 case VISIBLE_RECT_UNOCCLUDED: | |
146 visible_iterator_ = VisibleTilingIterator( | |
147 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, | |
148 skip_all_shared_tiles_, false /* return occluded tiles */, | |
149 false /* return required for activation tiles */); | |
150 if (!visible_iterator_.done()) | |
151 current_tile_ = *visible_iterator_; | |
152 break; | |
153 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED: | |
154 visible_iterator_ = VisibleTilingIterator( | |
155 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, | |
156 skip_all_shared_tiles_, true /* return occluded tiles */, | |
157 true /* return required for activation tiles */); | |
158 if (!visible_iterator_.done()) | |
159 current_tile_ = *visible_iterator_; | |
160 break; | |
161 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED: | |
162 visible_iterator_ = VisibleTilingIterator( | |
163 &tilings_, tree_, tree_priority_, skip_shared_out_of_order_tiles_, | |
164 skip_all_shared_tiles_, false /* return occluded tiles */, | |
165 true /* return required for activation tiles */); | |
166 if (!visible_iterator_.done()) | |
167 current_tile_ = *visible_iterator_; | |
168 break; | |
169 } | |
170 } | |
171 } | |
172 | |
44 bool TilingSetEvictionQueue::IsEmpty() const { | 173 bool TilingSetEvictionQueue::IsEmpty() const { |
45 return !current_eviction_tile_; | 174 return !current_tile_; |
175 } | |
176 | |
177 Tile* TilingSetEvictionQueue::Top() { | |
178 DCHECK(!IsEmpty()); | |
179 return current_tile_; | |
180 } | |
181 | |
182 const Tile* TilingSetEvictionQueue::Top() const { | |
183 DCHECK(!IsEmpty()); | |
184 return current_tile_; | |
46 } | 185 } |
47 | 186 |
48 void TilingSetEvictionQueue::Pop() { | 187 void TilingSetEvictionQueue::Pop() { |
49 DCHECK(!IsEmpty()); | 188 DCHECK(!IsEmpty()); |
50 | 189 current_tile_ = nullptr; |
51 if (!AdvanceToNextEvictionTile()) | 190 switch (phase_) { |
52 AdvanceToNextValidTiling(); | 191 case EVENTUALLY_RECT: |
53 } | 192 ++eventually_iterator_; |
54 | 193 if (!eventually_iterator_.done()) |
55 Tile* TilingSetEvictionQueue::Top() { | 194 current_tile_ = *eventually_iterator_; |
56 DCHECK(!IsEmpty()); | 195 break; |
57 return current_eviction_tile_; | 196 case SOON_BORDER_RECT: |
58 } | 197 ++soon_iterator_; |
59 | 198 if (!soon_iterator_.done()) |
60 const Tile* TilingSetEvictionQueue::Top() const { | 199 current_tile_ = *soon_iterator_; |
61 DCHECK(!IsEmpty()); | 200 break; |
62 return current_eviction_tile_; | 201 case SKEWPORT_RECT: |
63 } | 202 ++skewport_iterator_; |
64 | 203 if (!skewport_iterator_.done()) |
65 bool TilingSetEvictionQueue::AdvanceToNextEvictionTile() { | 204 current_tile_ = *skewport_iterator_; |
66 // Advance to the next eviction tile within the current priority bin and | 205 break; |
67 // tiling. This is done while advancing to a new tiling and while popping | 206 case VISIBLE_RECT_OCCLUDED: |
68 // the current tile. | 207 case VISIBLE_RECT_UNOCCLUDED: |
69 | 208 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED: |
70 bool required_for_activation = | 209 case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED: |
71 processing_tiling_with_required_for_activation_tiles_; | 210 ++visible_iterator_; |
72 | 211 if (!visible_iterator_.done()) |
212 current_tile_ = *visible_iterator_; | |
213 break; | |
214 } | |
215 if (!current_tile_) | |
216 AdvancePhase(); | |
217 } | |
218 | |
219 // OnePriorityRectIterator | |
220 TilingSetEvictionQueue::OnePriorityRectIterator::OnePriorityRectIterator() | |
221 : tile_(nullptr), | |
222 tilings_(nullptr), | |
223 tree_(ACTIVE_TREE), | |
224 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES), | |
225 skip_shared_out_of_order_tiles_(false), | |
226 skip_all_shared_tiles_(false), | |
227 tiling_index_(0) { | |
228 } | |
229 | |
230 TilingSetEvictionQueue::OnePriorityRectIterator::OnePriorityRectIterator( | |
231 std::vector<PictureLayerTiling*>* tilings, | |
232 WhichTree tree, | |
233 TreePriority tree_priority, | |
234 bool skip_shared_out_of_order_tiles, | |
235 bool skip_all_shared_tiles) | |
236 : tile_(nullptr), | |
237 tilings_(tilings), | |
238 tree_(tree), | |
239 tree_priority_(tree_priority), | |
240 skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles), | |
241 skip_all_shared_tiles_(skip_all_shared_tiles), | |
242 tiling_index_(0) { | |
243 } | |
244 | |
245 template <typename TilingIteratorType> | |
246 bool TilingSetEvictionQueue::OnePriorityRectIterator::AdvanceToNextTile( | |
247 TilingIteratorType* iterator) { | |
73 for (;;) { | 248 for (;;) { |
74 while (spiral_iterator_) { | 249 ++(*iterator); |
75 std::pair<int, int> next_index = spiral_iterator_.index(); | 250 if (!(*iterator)) { |
76 Tile* tile = current_tiling_->TileAt(next_index.first, next_index.second); | 251 tile_ = nullptr; |
77 ++spiral_iterator_; | 252 return false; |
78 if (!tile || !tile->HasResource()) | 253 } |
79 continue; | 254 bool have_valid_tile = GetFirstTileAndCheckIfValid(iterator); |
80 if (skip_all_shared_tiles_ && tile->is_shared()) | 255 if (have_valid_tile) |
81 continue; | |
82 current_tiling_->UpdateTileAndTwinPriority(tile); | |
83 if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tile)) | |
84 continue; | |
85 if (tile->required_for_activation() != required_for_activation) | |
86 continue; | |
87 current_eviction_tile_ = tile; | |
88 return true; | 256 return true; |
89 } | |
90 if (processing_soon_border_rect_) { | |
91 // Advance from soon border rect to skewport rect. | |
92 processing_soon_border_rect_ = false; | |
93 if (current_tiling_->has_skewport_rect_tiles_) { | |
94 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
95 ¤t_tiling_->tiling_data_, | |
96 current_tiling_->current_skewport_rect_, | |
97 current_tiling_->current_visible_rect_, | |
98 current_tiling_->current_visible_rect_); | |
99 continue; | |
100 } | |
101 } | |
102 break; | |
103 } | |
104 | |
105 TilePriority::PriorityBin max_tile_priority_bin = | |
106 current_tiling_->client_->GetMaxTilePriorityBin(); | |
107 while (visible_iterator_) { | |
108 std::pair<int, int> next_index = visible_iterator_.index(); | |
109 Tile* tile = current_tiling_->TileAt(next_index.first, next_index.second); | |
110 ++visible_iterator_; | |
111 if (!tile || !tile->HasResource()) | |
112 continue; | |
113 if (skip_all_shared_tiles_ && tile->is_shared()) | |
114 continue; | |
115 // If the max tile priority is not NOW, updated priorities for tiles | |
116 // returned by the visible iterator will not have NOW (but EVENTUALLY) | |
117 // priority bin and cannot therefore be required for activation tiles nor | |
118 // occluded NOW tiles in the current tiling. | |
119 if (max_tile_priority_bin <= TilePriority::NOW) { | |
120 // If the current tiling is a pending tree tiling, required for | |
121 // activation tiles can be detected without updating tile priorities. | |
122 if (tree_ == PENDING_TREE && | |
123 current_tiling_->IsTileRequiredForActivationIfVisible(tile) != | |
124 required_for_activation) { | |
125 continue; | |
126 } | |
127 // Unoccluded NOW tiles should be evicted (and thus returned) only after | |
128 // all occluded NOW tiles. | |
129 if (!current_tiling_->IsTileOccluded(tile)) { | |
130 unoccluded_now_tiles_.push_back(tile); | |
131 continue; | |
132 } | |
133 } | |
134 current_tiling_->UpdateTileAndTwinPriority(tile); | |
135 if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tile)) | |
136 continue; | |
137 if (tile->required_for_activation() != required_for_activation) | |
138 continue; | |
139 current_eviction_tile_ = tile; | |
140 return true; | |
141 } | |
142 | |
143 while (!unoccluded_now_tiles_.empty()) { | |
144 // All (unoccluded) NOW tiles have the same priority bin (NOW) and the same | |
145 // distance to visible (0.0), so it does not matter that tiles are popped | |
146 // in reversed (FILO) order. | |
147 Tile* tile = unoccluded_now_tiles_.back(); | |
148 unoccluded_now_tiles_.pop_back(); | |
149 DCHECK(tile); | |
150 if (!tile->HasResource()) | |
151 continue; | |
152 current_tiling_->UpdateTileAndTwinPriority(tile); | |
153 if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tile)) | |
154 continue; | |
155 if (tile->required_for_activation() != required_for_activation) | |
156 continue; | |
157 current_eviction_tile_ = tile; | |
158 return true; | |
159 } | |
160 | |
161 current_eviction_tile_ = nullptr; | |
162 return false; | |
163 } | |
164 | |
165 bool TilingSetEvictionQueue::AdvanceToNextPriorityBin() { | |
166 // Advance to the next priority bin. This is done only after all tiling range | |
167 // types (including the required for activation tiling) within the previous | |
168 // priority bin have been gone through. | |
169 DCHECK_EQ(current_tiling_range_type_, PictureLayerTilingSet::HIGH_RES); | |
170 | |
171 switch (current_priority_bin_) { | |
172 case TilePriority::EVENTUALLY: | |
173 current_priority_bin_ = TilePriority::SOON; | |
174 return true; | |
175 case TilePriority::SOON: | |
176 current_priority_bin_ = TilePriority::NOW; | |
177 return true; | |
178 case TilePriority::NOW: | |
179 return false; | |
180 } | 257 } |
181 NOTREACHED(); | 258 NOTREACHED(); |
182 return false; | 259 return false; |
183 } | 260 } |
184 | 261 |
185 bool TilingSetEvictionQueue::AdvanceToNextTilingRangeType() { | 262 template <typename TilingIteratorType> |
186 // Advance to the next tiling range type within the current priority bin, to | 263 bool TilingSetEvictionQueue::OnePriorityRectIterator:: |
187 // the required for activation tiling range type within the current priority | 264 GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) { |
188 // bin or to the first tiling range type within the next priority bin. This | 265 tile_ = (*tilings_)[tiling_index_]->TileAt(iterator->index_x(), |
189 // is done only after all tilings within the previous tiling range type have | 266 iterator->index_y()); |
190 // been gone through. | 267 // If there's nothing to evict, return false. |
191 DCHECK_EQ(current_tiling_index_, CurrentTilingRange().end); | 268 if (!tile_ || !tile_->HasResource()) |
192 | |
193 switch (current_tiling_range_type_) { | |
194 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES: | |
195 current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES; | |
196 return true; | |
197 case PictureLayerTilingSet::LOWER_THAN_LOW_RES: | |
198 current_tiling_range_type_ = | |
199 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES; | |
200 return true; | |
201 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES: | |
202 current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES; | |
203 return true; | |
204 case PictureLayerTilingSet::LOW_RES: | |
205 current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES; | |
206 return true; | |
207 case PictureLayerTilingSet::HIGH_RES: | |
208 // Process required for activation tiles (unless that has already been | |
209 // done for the current priority bin) if there is a tiling with required | |
210 // for activation tiles and that tiling may have required for activation | |
211 // tiles having the current priority bin (in the pending tree only NOW | |
212 // tiles may be required for activation). | |
213 if (!processing_tiling_with_required_for_activation_tiles_ && | |
214 tiling_index_with_required_for_activation_tiles_ < | |
215 tiling_set_->num_tilings() && | |
216 (current_priority_bin_ == TilePriority::NOW || | |
217 tree_ == ACTIVE_TREE)) { | |
218 processing_tiling_with_required_for_activation_tiles_ = true; | |
219 return true; | |
220 } | |
221 processing_tiling_with_required_for_activation_tiles_ = false; | |
222 | |
223 if (!AdvanceToNextPriorityBin()) | |
224 return false; | |
225 | |
226 current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES; | |
227 return true; | |
228 } | |
229 NOTREACHED(); | |
230 return false; | |
231 } | |
232 | |
233 bool TilingSetEvictionQueue::AdvanceToNextValidTiling() { | |
234 // Advance to the next tiling within current tiling range type or to | |
235 // the first tiling within the next tiling range type or priority bin until | |
236 // the next eviction tile is found. This is done only after all eviction | |
237 // tiles within the previous tiling within the current priority bin and | |
238 // tiling range type have been gone through. | |
239 DCHECK(!current_eviction_tile_); | |
240 DCHECK_NE(current_tiling_index_, CurrentTilingRange().end); | |
241 | |
242 for (;;) { | |
243 ++current_tiling_index_; | |
244 while (current_tiling_index_ == CurrentTilingRange().end) { | |
245 if (!AdvanceToNextTilingRangeType()) | |
246 return false; | |
247 current_tiling_index_ = CurrentTilingRange().start; | |
248 } | |
249 current_tiling_ = tiling_set_->tiling_at(CurrentTilingIndex()); | |
250 | |
251 switch (current_priority_bin_) { | |
252 case TilePriority::EVENTUALLY: | |
253 if (current_tiling_->has_eventually_rect_tiles_) { | |
254 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
255 ¤t_tiling_->tiling_data_, | |
256 current_tiling_->current_eventually_rect_, | |
257 current_tiling_->current_skewport_rect_, | |
258 current_tiling_->current_soon_border_rect_); | |
259 if (AdvanceToNextEvictionTile()) | |
260 return true; | |
261 } | |
262 break; | |
263 case TilePriority::SOON: | |
264 if (current_tiling_->has_skewport_rect_tiles_ || | |
265 current_tiling_->has_soon_border_rect_tiles_) { | |
266 processing_soon_border_rect_ = true; | |
267 if (current_tiling_->has_soon_border_rect_tiles_) | |
268 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
269 ¤t_tiling_->tiling_data_, | |
270 current_tiling_->current_soon_border_rect_, | |
271 current_tiling_->current_skewport_rect_, | |
272 current_tiling_->current_visible_rect_); | |
273 if (AdvanceToNextEvictionTile()) | |
274 return true; | |
275 } | |
276 break; | |
277 case TilePriority::NOW: | |
278 if (current_tiling_->has_visible_rect_tiles_) { | |
279 visible_iterator_ = | |
280 TilingData::Iterator(¤t_tiling_->tiling_data_, | |
281 current_tiling_->current_visible_rect_, | |
282 false /* include_borders */); | |
283 if (AdvanceToNextEvictionTile()) | |
284 return true; | |
285 } | |
286 break; | |
287 } | |
288 } | |
289 } | |
290 | |
291 PictureLayerTilingSet::TilingRange | |
292 TilingSetEvictionQueue::CurrentTilingRange() const { | |
293 if (processing_tiling_with_required_for_activation_tiles_) | |
294 return PictureLayerTilingSet::TilingRange( | |
295 tiling_index_with_required_for_activation_tiles_, | |
296 tiling_index_with_required_for_activation_tiles_ + 1); | |
297 return tiling_set_->GetTilingRange(current_tiling_range_type_); | |
298 } | |
299 | |
300 size_t TilingSetEvictionQueue::CurrentTilingIndex() const { | |
301 DCHECK_NE(current_tiling_index_, CurrentTilingRange().end); | |
302 switch (current_tiling_range_type_) { | |
303 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES: | |
304 case PictureLayerTilingSet::LOW_RES: | |
305 case PictureLayerTilingSet::HIGH_RES: | |
306 return current_tiling_index_; | |
307 // Tilings in the following ranges are accessed in reverse order. | |
308 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES: | |
309 case PictureLayerTilingSet::LOWER_THAN_LOW_RES: { | |
310 PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange(); | |
311 size_t current_tiling_range_offset = | |
312 current_tiling_index_ - tiling_range.start; | |
313 return tiling_range.end - 1 - current_tiling_range_offset; | |
314 } | |
315 } | |
316 NOTREACHED(); | |
317 return 0; | |
318 } | |
319 | |
320 bool TilingSetEvictionQueue::IsSharedOutOfOrderTile(const Tile* tile) const { | |
321 if (!tile->is_shared()) | |
322 return false; | 269 return false; |
323 | 270 // If the tile is shared while we're skipping shared tiles, return false. |
324 switch (tree_priority_) { | 271 if (skip_all_shared_tiles_ && tile_->is_shared()) |
325 case SMOOTHNESS_TAKES_PRIORITY: | 272 return false; |
326 DCHECK_EQ(ACTIVE_TREE, tree_); | 273 (*tilings_)[tiling_index_]->UpdateTileAndTwinPriority(tile_); |
327 return false; | 274 // If the tile is out of order, return false. |
328 case NEW_CONTENT_TAKES_PRIORITY: | 275 if (skip_shared_out_of_order_tiles_ && |
329 DCHECK_EQ(PENDING_TREE, tree_); | 276 IsSharedOutOfOrderTile(tree_, tree_priority_, tile_)) { |
330 return false; | 277 return false; |
331 case SAME_PRIORITY_FOR_BOTH_TREES: | 278 } |
332 break; | 279 // In other cases, the tile we got is a viable candidate, return true. |
333 } | 280 return true; |
334 | 281 } |
335 // The priority for tile priority of a shared tile will be a combined | 282 |
336 // priority thus return shared tiles from a higher priority tree as | 283 // EventuallyTilingIterator |
337 // it is out of order for a lower priority tree. | 284 TilingSetEvictionQueue::EventuallyTilingIterator::EventuallyTilingIterator( |
338 WhichTree twin_tree = tree_ == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; | 285 std::vector<PictureLayerTiling*>* tilings, |
339 const TilePriority& priority = tile->priority(tree_); | 286 WhichTree tree, |
340 const TilePriority& twin_priority = tile->priority(twin_tree); | 287 TreePriority tree_priority, |
341 if (priority.priority_bin != twin_priority.priority_bin) | 288 bool skip_shared_out_of_order_tiles, |
342 return priority.priority_bin > twin_priority.priority_bin; | 289 bool skip_all_shared_tiles) |
343 const bool occluded = tile->is_occluded(tree_); | 290 : OnePriorityRectIterator(tilings, |
344 const bool twin_occluded = tile->is_occluded(twin_tree); | 291 tree, |
345 if (occluded != twin_occluded) | 292 tree_priority, |
346 return occluded; | 293 skip_shared_out_of_order_tiles, |
347 if (priority.distance_to_visible != twin_priority.distance_to_visible) | 294 skip_all_shared_tiles) { |
348 return priority.distance_to_visible > twin_priority.distance_to_visible; | 295 // Find the first tiling with a tile. |
349 | 296 while (tiling_index_ < tilings_->size()) { |
350 // If priorities are the same, it does not matter which tree returns | 297 if (!((*tilings_))[tiling_index_]->has_eventually_rect_tiles()) { |
351 // the tile. Let's pick the pending tree. | 298 ++tiling_index_; |
352 return tree_ != PENDING_TREE; | 299 continue; |
353 } | 300 } |
354 | 301 iterator_ = TilingData::ReverseSpiralDifferenceIterator( |
355 size_t TilingSetEvictionQueue::TilingIndexWithRequiredForActivationTiles() | 302 ((*tilings_))[tiling_index_]->tiling_data(), |
356 const { | 303 ((*tilings_))[tiling_index_]->current_eventually_rect(), |
357 // Returns the tiling index of the tiling with requuired for activation tiles. | 304 ((*tilings_))[tiling_index_]->current_skewport_rect(), |
358 // If no such tiling exists, returns the past-the-last index (num_tilings). | 305 ((*tilings_))[tiling_index_]->current_soon_border_rect()); |
359 size_t num_tilings = tiling_set_->num_tilings(); | 306 if (!iterator_) { |
360 | 307 ++tiling_index_; |
361 if (tree_ == PENDING_TREE) { | 308 continue; |
362 // For the pending tree, the tiling with required for activation tiles is | 309 } |
363 // the high res one. | 310 break; |
364 PictureLayerTilingSet::TilingRange high_res_tiling_range = | 311 } |
365 tiling_set_->GetTilingRange(PictureLayerTilingSet::HIGH_RES); | 312 if (tiling_index_ >= tilings_->size()) |
366 if (high_res_tiling_range.start != high_res_tiling_range.end) | 313 return; |
367 return high_res_tiling_range.start; | 314 if (!GetFirstTileAndCheckIfValid(&iterator_)) |
368 } else { | 315 ++(*this); |
369 DCHECK_EQ(ACTIVE_TREE, tree_); | 316 } |
370 // Only pending tree tiles can be required for activation. They can appear | 317 |
371 // also in the active tree only if they are shared. If we skip all shared | 318 TilingSetEvictionQueue::EventuallyTilingIterator& |
372 // tiles, there is no need to find them as they will not be returned. | 319 TilingSetEvictionQueue::EventuallyTilingIterator:: |
373 if (skip_all_shared_tiles_) | 320 operator++() { |
374 return num_tilings; | 321 bool found_tile = AdvanceToNextTile(&iterator_); |
375 | 322 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { |
376 // For the active tree, the tiling with required for activation tiles is | 323 ++tiling_index_; |
377 // the one whose twin tiling is the high res pending tiling. | 324 if (!((*tilings_))[tiling_index_]->has_eventually_rect_tiles()) |
378 for (size_t i = 0; i < num_tilings; ++i) { | 325 continue; |
379 const PictureLayerTiling* tiling = tiling_set_->tiling_at(i); | 326 iterator_ = TilingData::ReverseSpiralDifferenceIterator( |
380 const PictureLayerTiling* pending_tiling = | 327 ((*tilings_))[tiling_index_]->tiling_data(), |
381 tiling_set_->client()->GetPendingOrActiveTwinTiling(tiling); | 328 ((*tilings_))[tiling_index_]->current_eventually_rect(), |
382 if (pending_tiling && pending_tiling->resolution() == HIGH_RESOLUTION) | 329 ((*tilings_))[tiling_index_]->current_skewport_rect(), |
383 return i; | 330 ((*tilings_))[tiling_index_]->current_soon_border_rect()); |
384 } | 331 if (!iterator_) |
385 } | 332 continue; |
386 | 333 found_tile = GetFirstTileAndCheckIfValid(&iterator_); |
387 return num_tilings; | 334 if (!found_tile) |
335 found_tile = AdvanceToNextTile(&iterator_); | |
336 } | |
337 return *this; | |
338 } | |
339 | |
340 // SoonBorderTilingIterator | |
341 TilingSetEvictionQueue::SoonBorderTilingIterator::SoonBorderTilingIterator( | |
342 std::vector<PictureLayerTiling*>* tilings, | |
343 WhichTree tree, | |
344 TreePriority tree_priority, | |
345 bool skip_shared_out_of_order_tiles, | |
346 bool skip_all_shared_tiles) | |
347 : OnePriorityRectIterator(tilings, | |
348 tree, | |
349 tree_priority, | |
350 skip_shared_out_of_order_tiles, | |
351 skip_all_shared_tiles) { | |
352 // Find the first tiling with a tile. | |
353 while (tiling_index_ < tilings_->size()) { | |
354 if (!((*tilings_))[tiling_index_]->has_soon_border_rect_tiles()) { | |
355 ++tiling_index_; | |
356 continue; | |
357 } | |
358 iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
359 ((*tilings_))[tiling_index_]->tiling_data(), | |
360 ((*tilings_))[tiling_index_]->current_soon_border_rect(), | |
361 ((*tilings_))[tiling_index_]->current_skewport_rect(), | |
362 ((*tilings_))[tiling_index_]->current_visible_rect()); | |
363 if (!iterator_) { | |
364 ++tiling_index_; | |
365 continue; | |
366 } | |
367 break; | |
368 } | |
369 if (tiling_index_ >= tilings_->size()) | |
370 return; | |
371 if (!GetFirstTileAndCheckIfValid(&iterator_)) | |
372 ++(*this); | |
373 } | |
374 | |
375 TilingSetEvictionQueue::SoonBorderTilingIterator& | |
376 TilingSetEvictionQueue::SoonBorderTilingIterator:: | |
377 operator++() { | |
378 bool found_tile = AdvanceToNextTile(&iterator_); | |
379 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { | |
380 ++tiling_index_; | |
381 if (!((*tilings_))[tiling_index_]->has_soon_border_rect_tiles()) | |
382 continue; | |
383 iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
384 ((*tilings_))[tiling_index_]->tiling_data(), | |
385 ((*tilings_))[tiling_index_]->current_soon_border_rect(), | |
386 ((*tilings_))[tiling_index_]->current_skewport_rect(), | |
387 ((*tilings_))[tiling_index_]->current_visible_rect()); | |
388 if (!iterator_) | |
389 continue; | |
390 found_tile = GetFirstTileAndCheckIfValid(&iterator_); | |
391 if (!found_tile) | |
392 found_tile = AdvanceToNextTile(&iterator_); | |
393 } | |
394 return *this; | |
395 } | |
396 | |
397 // SkewportTilingIterator | |
398 TilingSetEvictionQueue::SkewportTilingIterator::SkewportTilingIterator( | |
399 std::vector<PictureLayerTiling*>* tilings, | |
400 WhichTree tree, | |
401 TreePriority tree_priority, | |
402 bool skip_shared_out_of_order_tiles, | |
403 bool skip_all_shared_tiles) | |
404 : OnePriorityRectIterator(tilings, | |
405 tree, | |
406 tree_priority, | |
407 skip_shared_out_of_order_tiles, | |
408 skip_all_shared_tiles) { | |
409 // Find the first tiling with a tile. | |
410 while (tiling_index_ < tilings_->size()) { | |
411 if (!((*tilings_))[tiling_index_]->has_skewport_rect_tiles()) { | |
412 ++tiling_index_; | |
413 continue; | |
enne (OOO)
2015/03/27 19:12:11
This is maybe just a style nit, but these loops ar
vmpstr
2015/03/27 20:19:27
The has skewport rect tiles check is on the tiling
enne (OOO)
2015/03/27 21:48:05
Oh, right. I think I was thinking about the wrong
| |
414 } | |
415 iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
416 ((*tilings_))[tiling_index_]->tiling_data(), | |
417 ((*tilings_))[tiling_index_]->current_skewport_rect(), | |
418 ((*tilings_))[tiling_index_]->current_visible_rect(), | |
419 ((*tilings_))[tiling_index_]->current_visible_rect()); | |
420 if (!iterator_) { | |
421 ++tiling_index_; | |
422 continue; | |
423 } | |
424 break; | |
425 } | |
426 if (tiling_index_ >= tilings_->size()) | |
427 return; | |
428 if (!GetFirstTileAndCheckIfValid(&iterator_)) | |
429 ++(*this); | |
430 } | |
431 | |
432 TilingSetEvictionQueue::SkewportTilingIterator& | |
433 TilingSetEvictionQueue::SkewportTilingIterator:: | |
434 operator++() { | |
435 bool found_tile = AdvanceToNextTile(&iterator_); | |
436 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { | |
437 ++tiling_index_; | |
438 if (!((*tilings_))[tiling_index_]->has_skewport_rect_tiles()) | |
439 continue; | |
440 iterator_ = TilingData::ReverseSpiralDifferenceIterator( | |
441 ((*tilings_))[tiling_index_]->tiling_data(), | |
442 ((*tilings_))[tiling_index_]->current_skewport_rect(), | |
443 ((*tilings_))[tiling_index_]->current_visible_rect(), | |
444 ((*tilings_))[tiling_index_]->current_visible_rect()); | |
445 if (!iterator_) | |
446 continue; | |
447 found_tile = GetFirstTileAndCheckIfValid(&iterator_); | |
448 if (!found_tile) | |
449 found_tile = AdvanceToNextTile(&iterator_); | |
450 } | |
451 return *this; | |
452 } | |
453 | |
454 // VisibleTilingIterator | |
455 TilingSetEvictionQueue::VisibleTilingIterator::VisibleTilingIterator( | |
456 std::vector<PictureLayerTiling*>* tilings, | |
457 WhichTree tree, | |
458 TreePriority tree_priority, | |
459 bool skip_shared_out_of_order_tiles, | |
460 bool skip_all_shared_tiles, | |
461 bool return_occluded_tiles, | |
462 bool return_required_for_activation_tiles) | |
463 : OnePriorityRectIterator(tilings, | |
464 tree, | |
465 tree_priority, | |
466 skip_shared_out_of_order_tiles, | |
467 skip_all_shared_tiles), | |
468 return_occluded_tiles_(return_occluded_tiles), | |
469 return_required_for_activation_tiles_( | |
470 return_required_for_activation_tiles) { | |
471 // Find the first tiling with a tile. | |
472 while (tiling_index_ < tilings_->size()) { | |
473 if (!((*tilings_))[tiling_index_]->has_visible_rect_tiles()) { | |
474 ++tiling_index_; | |
475 continue; | |
476 } | |
477 iterator_ = TilingData::Iterator( | |
478 ((*tilings_))[tiling_index_]->tiling_data(), | |
479 ((*tilings_))[tiling_index_]->current_visible_rect(), false); | |
480 if (!iterator_) { | |
481 ++tiling_index_; | |
482 continue; | |
483 } | |
484 break; | |
485 } | |
486 if (tiling_index_ >= tilings_->size()) | |
487 return; | |
488 if (!GetFirstTileAndCheckIfValid(&iterator_)) { | |
489 ++(*this); | |
490 return; | |
491 } | |
492 if (!TileMatchesRequiredFlags(tile_)) { | |
493 ++(*this); | |
494 return; | |
495 } | |
496 } | |
497 | |
498 TilingSetEvictionQueue::VisibleTilingIterator& | |
499 TilingSetEvictionQueue::VisibleTilingIterator:: | |
500 operator++() { | |
501 bool found_tile = AdvanceToNextTile(&iterator_); | |
502 while (found_tile && !TileMatchesRequiredFlags(tile_)) | |
503 found_tile = AdvanceToNextTile(&iterator_); | |
504 | |
505 while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { | |
506 ++tiling_index_; | |
507 if (!((*tilings_))[tiling_index_]->has_visible_rect_tiles()) | |
508 continue; | |
509 iterator_ = TilingData::Iterator( | |
510 ((*tilings_))[tiling_index_]->tiling_data(), | |
511 ((*tilings_))[tiling_index_]->current_visible_rect(), false); | |
512 if (!iterator_) | |
513 continue; | |
514 found_tile = GetFirstTileAndCheckIfValid(&iterator_); | |
515 if (!found_tile) | |
516 found_tile = AdvanceToNextTile(&iterator_); | |
517 while (found_tile && !TileMatchesRequiredFlags(tile_)) | |
518 found_tile = AdvanceToNextTile(&iterator_); | |
519 } | |
520 return *this; | |
521 } | |
522 | |
523 bool TilingSetEvictionQueue::VisibleTilingIterator::TileMatchesRequiredFlags( | |
524 const Tile* tile) const { | |
525 return (tile->required_for_activation() == | |
enne (OOO)
2015/03/27 19:12:11
style nit: no need for parens. You could also bre
vmpstr
2015/03/27 20:19:27
Eh, I'm not so worried about length, but I did cha
| |
526 return_required_for_activation_tiles_ && | |
527 tile->is_occluded(tree_) == return_occluded_tiles_); | |
388 } | 528 } |
389 | 529 |
390 } // namespace cc | 530 } // namespace cc |
OLD | NEW |