OLD | NEW |
| (Empty) |
1 // Copyright 2012 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. | |
4 | |
5 #include "cc/resources/picture_layer_tiling_set.h" | |
6 | |
7 #include <limits> | |
8 #include <set> | |
9 #include <vector> | |
10 | |
11 #include "cc/resources/raster_source.h" | |
12 | |
13 namespace cc { | |
14 | |
15 namespace { | |
16 | |
17 class LargestToSmallestScaleFunctor { | |
18 public: | |
19 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) { | |
20 return left->contents_scale() > right->contents_scale(); | |
21 } | |
22 }; | |
23 | |
24 inline float LargerRatio(float float1, float float2) { | |
25 DCHECK_GT(float1, 0.f); | |
26 DCHECK_GT(float2, 0.f); | |
27 return float1 > float2 ? float1 / float2 : float2 / float1; | |
28 } | |
29 | |
30 } // namespace | |
31 | |
32 // static | |
33 scoped_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create( | |
34 WhichTree tree, | |
35 PictureLayerTilingClient* client, | |
36 float tiling_interest_area_viewport_multiplier, | |
37 float skewport_target_time_in_seconds, | |
38 int skewport_extrapolation_limit_in_content_pixels) { | |
39 return make_scoped_ptr(new PictureLayerTilingSet( | |
40 tree, client, tiling_interest_area_viewport_multiplier, | |
41 skewport_target_time_in_seconds, | |
42 skewport_extrapolation_limit_in_content_pixels)); | |
43 } | |
44 | |
45 PictureLayerTilingSet::PictureLayerTilingSet( | |
46 WhichTree tree, | |
47 PictureLayerTilingClient* client, | |
48 float tiling_interest_area_viewport_multiplier, | |
49 float skewport_target_time_in_seconds, | |
50 int skewport_extrapolation_limit_in_content_pixels) | |
51 : tiling_interest_area_viewport_multiplier_( | |
52 tiling_interest_area_viewport_multiplier), | |
53 skewport_target_time_in_seconds_(skewport_target_time_in_seconds), | |
54 skewport_extrapolation_limit_in_content_pixels_( | |
55 skewport_extrapolation_limit_in_content_pixels), | |
56 tree_(tree), | |
57 client_(client) { | |
58 } | |
59 | |
60 PictureLayerTilingSet::~PictureLayerTilingSet() { | |
61 } | |
62 | |
63 void PictureLayerTilingSet::CopyTilingsAndPropertiesFromPendingTwin( | |
64 const PictureLayerTilingSet* pending_twin_set, | |
65 const scoped_refptr<RasterSource>& raster_source, | |
66 const Region& layer_invalidation) { | |
67 if (pending_twin_set->tilings_.empty()) { | |
68 // If the twin (pending) tiling set is empty, it was not updated for the | |
69 // current frame. So we drop tilings from our set as well, instead of | |
70 // leaving behind unshared tilings that are all non-ideal. | |
71 RemoveAllTilings(); | |
72 return; | |
73 } | |
74 | |
75 bool tiling_sort_required = false; | |
76 for (PictureLayerTiling* pending_twin_tiling : pending_twin_set->tilings_) { | |
77 float contents_scale = pending_twin_tiling->contents_scale(); | |
78 PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale); | |
79 if (!this_tiling) { | |
80 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create( | |
81 tree_, contents_scale, raster_source, client_, | |
82 tiling_interest_area_viewport_multiplier_, | |
83 skewport_target_time_in_seconds_, | |
84 skewport_extrapolation_limit_in_content_pixels_); | |
85 tilings_.push_back(new_tiling.Pass()); | |
86 this_tiling = tilings_.back(); | |
87 tiling_sort_required = true; | |
88 } | |
89 this_tiling->TakeTilesAndPropertiesFrom(pending_twin_tiling, | |
90 layer_invalidation); | |
91 } | |
92 | |
93 if (tiling_sort_required) | |
94 tilings_.sort(LargestToSmallestScaleFunctor()); | |
95 } | |
96 | |
97 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation( | |
98 scoped_refptr<RasterSource> raster_source, | |
99 const PictureLayerTilingSet* pending_twin_set, | |
100 const Region& layer_invalidation, | |
101 float minimum_contents_scale, | |
102 float maximum_contents_scale) { | |
103 RemoveTilingsBelowScale(minimum_contents_scale); | |
104 RemoveTilingsAboveScale(maximum_contents_scale); | |
105 | |
106 // Copy over tilings that are shared with the |pending_twin_set| tiling set. | |
107 // Also, copy all of the properties from twin tilings. | |
108 CopyTilingsAndPropertiesFromPendingTwin(pending_twin_set, raster_source, | |
109 layer_invalidation); | |
110 | |
111 // If the tiling is not shared (FindTilingWithScale returns nullptr), then | |
112 // invalidate tiles and update them to the new raster source. | |
113 for (PictureLayerTiling* tiling : tilings_) { | |
114 if (pending_twin_set->FindTilingWithScale(tiling->contents_scale())) | |
115 continue; | |
116 | |
117 tiling->SetRasterSourceAndResize(raster_source); | |
118 tiling->Invalidate(layer_invalidation); | |
119 // This is needed for cases where the live tiles rect didn't change but | |
120 // recordings exist in the raster source that did not exist on the last | |
121 // raster source. | |
122 tiling->CreateMissingTilesInLiveTilesRect(); | |
123 | |
124 // |this| is active set and |tiling| is not in the pending set, which means | |
125 // it is now NON_IDEAL_RESOLUTION. | |
126 tiling->set_resolution(NON_IDEAL_RESOLUTION); | |
127 } | |
128 | |
129 VerifyTilings(pending_twin_set); | |
130 } | |
131 | |
132 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit( | |
133 scoped_refptr<RasterSource> raster_source, | |
134 const Region& layer_invalidation, | |
135 float minimum_contents_scale, | |
136 float maximum_contents_scale) { | |
137 RemoveTilingsBelowScale(minimum_contents_scale); | |
138 RemoveTilingsAboveScale(maximum_contents_scale); | |
139 | |
140 // Invalidate tiles and update them to the new raster source. | |
141 for (PictureLayerTiling* tiling : tilings_) { | |
142 tiling->SetRasterSourceAndResize(raster_source); | |
143 tiling->Invalidate(layer_invalidation); | |
144 // This is needed for cases where the live tiles rect didn't change but | |
145 // recordings exist in the raster source that did not exist on the last | |
146 // raster source. | |
147 tiling->CreateMissingTilesInLiveTilesRect(); | |
148 } | |
149 VerifyTilings(nullptr /* pending_twin_set */); | |
150 } | |
151 | |
152 void PictureLayerTilingSet::UpdateRasterSourceDueToLCDChange( | |
153 const scoped_refptr<RasterSource>& raster_source, | |
154 const Region& layer_invalidation) { | |
155 for (PictureLayerTiling* tiling : tilings_) { | |
156 tiling->SetRasterSourceAndResize(raster_source); | |
157 tiling->Invalidate(layer_invalidation); | |
158 // Since the invalidation changed, we need to create any missing tiles in | |
159 // the live tiles rect again. | |
160 tiling->CreateMissingTilesInLiveTilesRect(); | |
161 } | |
162 } | |
163 | |
164 void PictureLayerTilingSet::VerifyTilings( | |
165 const PictureLayerTilingSet* pending_twin_set) const { | |
166 #if DCHECK_IS_ON() | |
167 for (PictureLayerTiling* tiling : tilings_) { | |
168 DCHECK(tiling->tile_size() == | |
169 client_->CalculateTileSize(tiling->tiling_size())) | |
170 << "tile_size: " << tiling->tile_size().ToString() | |
171 << " tiling_size: " << tiling->tiling_size().ToString() | |
172 << " CalculateTileSize: " | |
173 << client_->CalculateTileSize(tiling->tiling_size()).ToString(); | |
174 } | |
175 | |
176 if (!tilings_.empty()) { | |
177 DCHECK_LE(NumHighResTilings(), 1); | |
178 // When commiting from the main thread the high res tiling may get dropped, | |
179 // but when cloning to the active tree, there should always be one. | |
180 if (pending_twin_set) { | |
181 DCHECK_EQ(1, NumHighResTilings()) | |
182 << " num tilings on active: " << tilings_.size() | |
183 << " num tilings on pending: " << pending_twin_set->tilings_.size() | |
184 << " num high res on pending: " | |
185 << pending_twin_set->NumHighResTilings() | |
186 << " are on active tree: " << (tree_ == ACTIVE_TREE); | |
187 } | |
188 } | |
189 #endif | |
190 } | |
191 | |
192 void PictureLayerTilingSet::CleanUpTilings( | |
193 float min_acceptable_high_res_scale, | |
194 float max_acceptable_high_res_scale, | |
195 const std::vector<PictureLayerTiling*>& needed_tilings, | |
196 bool should_have_low_res, | |
197 PictureLayerTilingSet* twin_set, | |
198 PictureLayerTilingSet* recycled_twin_set) { | |
199 float twin_low_res_scale = 0.f; | |
200 if (twin_set) { | |
201 PictureLayerTiling* tiling = | |
202 twin_set->FindTilingWithResolution(LOW_RESOLUTION); | |
203 if (tiling) | |
204 twin_low_res_scale = tiling->contents_scale(); | |
205 } | |
206 | |
207 std::vector<PictureLayerTiling*> to_remove; | |
208 for (auto* tiling : tilings_) { | |
209 // Keep all tilings within the min/max scales. | |
210 if (tiling->contents_scale() >= min_acceptable_high_res_scale && | |
211 tiling->contents_scale() <= max_acceptable_high_res_scale) { | |
212 continue; | |
213 } | |
214 | |
215 // Keep low resolution tilings, if the tiling set should have them. | |
216 if (should_have_low_res && | |
217 (tiling->resolution() == LOW_RESOLUTION || | |
218 tiling->contents_scale() == twin_low_res_scale)) { | |
219 continue; | |
220 } | |
221 | |
222 // Don't remove tilings that are required. | |
223 if (std::find(needed_tilings.begin(), needed_tilings.end(), tiling) != | |
224 needed_tilings.end()) { | |
225 continue; | |
226 } | |
227 | |
228 to_remove.push_back(tiling); | |
229 } | |
230 | |
231 for (auto* tiling : to_remove) { | |
232 PictureLayerTiling* recycled_twin_tiling = | |
233 recycled_twin_set | |
234 ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale()) | |
235 : nullptr; | |
236 // Remove the tiling from the recycle tree. Note that we ignore resolution, | |
237 // since we don't need to maintain high/low res on the recycle set. | |
238 if (recycled_twin_tiling) | |
239 recycled_twin_set->Remove(recycled_twin_tiling); | |
240 | |
241 DCHECK_NE(HIGH_RESOLUTION, tiling->resolution()); | |
242 Remove(tiling); | |
243 } | |
244 } | |
245 | |
246 void PictureLayerTilingSet::RemoveNonIdealTilings() { | |
247 auto to_remove = tilings_.remove_if([](PictureLayerTiling* t) { | |
248 return t->resolution() == NON_IDEAL_RESOLUTION; | |
249 }); | |
250 tilings_.erase(to_remove, tilings_.end()); | |
251 } | |
252 | |
253 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() { | |
254 for (auto* tiling : tilings_) | |
255 tiling->set_resolution(NON_IDEAL_RESOLUTION); | |
256 } | |
257 | |
258 PictureLayerTiling* PictureLayerTilingSet::AddTiling( | |
259 float contents_scale, | |
260 scoped_refptr<RasterSource> raster_source) { | |
261 for (size_t i = 0; i < tilings_.size(); ++i) { | |
262 DCHECK_NE(tilings_[i]->contents_scale(), contents_scale); | |
263 DCHECK_EQ(tilings_[i]->raster_source(), raster_source.get()); | |
264 } | |
265 | |
266 tilings_.push_back(PictureLayerTiling::Create( | |
267 tree_, contents_scale, raster_source, client_, | |
268 tiling_interest_area_viewport_multiplier_, | |
269 skewport_target_time_in_seconds_, | |
270 skewport_extrapolation_limit_in_content_pixels_)); | |
271 PictureLayerTiling* appended = tilings_.back(); | |
272 | |
273 tilings_.sort(LargestToSmallestScaleFunctor()); | |
274 return appended; | |
275 } | |
276 | |
277 int PictureLayerTilingSet::NumHighResTilings() const { | |
278 return std::count_if(tilings_.begin(), tilings_.end(), | |
279 [](PictureLayerTiling* tiling) { | |
280 return tiling->resolution() == HIGH_RESOLUTION; | |
281 }); | |
282 } | |
283 | |
284 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScale( | |
285 float scale) const { | |
286 for (size_t i = 0; i < tilings_.size(); ++i) { | |
287 if (tilings_[i]->contents_scale() == scale) | |
288 return tilings_[i]; | |
289 } | |
290 return NULL; | |
291 } | |
292 | |
293 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithResolution( | |
294 TileResolution resolution) const { | |
295 auto iter = std::find_if(tilings_.begin(), tilings_.end(), | |
296 [resolution](const PictureLayerTiling* tiling) { | |
297 return tiling->resolution() == resolution; | |
298 }); | |
299 if (iter == tilings_.end()) | |
300 return NULL; | |
301 return *iter; | |
302 } | |
303 | |
304 void PictureLayerTilingSet::RemoveTilingsBelowScale(float minimum_scale) { | |
305 auto to_remove = | |
306 tilings_.remove_if([minimum_scale](PictureLayerTiling* tiling) { | |
307 return tiling->contents_scale() < minimum_scale; | |
308 }); | |
309 tilings_.erase(to_remove, tilings_.end()); | |
310 } | |
311 | |
312 void PictureLayerTilingSet::RemoveTilingsAboveScale(float maximum_scale) { | |
313 auto to_remove = | |
314 tilings_.remove_if([maximum_scale](PictureLayerTiling* tiling) { | |
315 return tiling->contents_scale() > maximum_scale; | |
316 }); | |
317 tilings_.erase(to_remove, tilings_.end()); | |
318 } | |
319 | |
320 void PictureLayerTilingSet::RemoveAllTilings() { | |
321 tilings_.clear(); | |
322 } | |
323 | |
324 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) { | |
325 ScopedPtrVector<PictureLayerTiling>::iterator iter = | |
326 std::find(tilings_.begin(), tilings_.end(), tiling); | |
327 if (iter == tilings_.end()) | |
328 return; | |
329 tilings_.erase(iter); | |
330 } | |
331 | |
332 void PictureLayerTilingSet::RemoveAllTiles() { | |
333 for (size_t i = 0; i < tilings_.size(); ++i) | |
334 tilings_[i]->Reset(); | |
335 } | |
336 | |
337 float PictureLayerTilingSet::GetSnappedContentsScale( | |
338 float start_scale, | |
339 float snap_to_existing_tiling_ratio) const { | |
340 // If a tiling exists within the max snapping ratio, snap to its scale. | |
341 float snapped_contents_scale = start_scale; | |
342 float snapped_ratio = snap_to_existing_tiling_ratio; | |
343 for (const auto* tiling : tilings_) { | |
344 float tiling_contents_scale = tiling->contents_scale(); | |
345 float ratio = LargerRatio(tiling_contents_scale, start_scale); | |
346 if (ratio < snapped_ratio) { | |
347 snapped_contents_scale = tiling_contents_scale; | |
348 snapped_ratio = ratio; | |
349 } | |
350 } | |
351 return snapped_contents_scale; | |
352 } | |
353 | |
354 float PictureLayerTilingSet::GetMaximumContentsScale() const { | |
355 if (tilings_.empty()) | |
356 return 0.f; | |
357 // The first tiling has the largest contents scale. | |
358 return tilings_[0]->contents_scale(); | |
359 } | |
360 | |
361 bool PictureLayerTilingSet::UpdateTilePriorities( | |
362 const gfx::Rect& required_rect_in_layer_space, | |
363 float ideal_contents_scale, | |
364 double current_frame_time_in_seconds, | |
365 const Occlusion& occlusion_in_layer_space, | |
366 bool can_require_tiles_for_activation) { | |
367 bool updated = false; | |
368 for (auto* tiling : tilings_) { | |
369 tiling->set_can_require_tiles_for_activation( | |
370 can_require_tiles_for_activation); | |
371 updated |= tiling->ComputeTilePriorityRects( | |
372 required_rect_in_layer_space, ideal_contents_scale, | |
373 current_frame_time_in_seconds, occlusion_in_layer_space); | |
374 } | |
375 return updated; | |
376 } | |
377 | |
378 void PictureLayerTilingSet::GetAllPrioritizedTilesForTracing( | |
379 std::vector<PrioritizedTile>* prioritized_tiles) const { | |
380 for (auto* tiling : tilings_) | |
381 tiling->GetAllPrioritizedTilesForTracing(prioritized_tiles); | |
382 } | |
383 | |
384 PictureLayerTilingSet::CoverageIterator::CoverageIterator( | |
385 const PictureLayerTilingSet* set, | |
386 float contents_scale, | |
387 const gfx::Rect& content_rect, | |
388 float ideal_contents_scale) | |
389 : set_(set), | |
390 contents_scale_(contents_scale), | |
391 ideal_contents_scale_(ideal_contents_scale), | |
392 current_tiling_(-1) { | |
393 missing_region_.Union(content_rect); | |
394 | |
395 for (ideal_tiling_ = 0; | |
396 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size(); | |
397 ++ideal_tiling_) { | |
398 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_]; | |
399 if (tiling->contents_scale() < ideal_contents_scale_) { | |
400 if (ideal_tiling_ > 0) | |
401 ideal_tiling_--; | |
402 break; | |
403 } | |
404 } | |
405 | |
406 DCHECK_LE(set_->tilings_.size(), | |
407 static_cast<size_t>(std::numeric_limits<int>::max())); | |
408 | |
409 int num_tilings = set_->tilings_.size(); | |
410 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0) | |
411 ideal_tiling_--; | |
412 | |
413 ++(*this); | |
414 } | |
415 | |
416 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { | |
417 } | |
418 | |
419 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const { | |
420 if (!tiling_iter_) { | |
421 if (!region_iter_.has_rect()) | |
422 return gfx::Rect(); | |
423 return region_iter_.rect(); | |
424 } | |
425 return tiling_iter_.geometry_rect(); | |
426 } | |
427 | |
428 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { | |
429 if (!tiling_iter_) | |
430 return gfx::RectF(); | |
431 return tiling_iter_.texture_rect(); | |
432 } | |
433 | |
434 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const { | |
435 if (!tiling_iter_) | |
436 return NULL; | |
437 return *tiling_iter_; | |
438 } | |
439 | |
440 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const { | |
441 if (!tiling_iter_) | |
442 return NULL; | |
443 return *tiling_iter_; | |
444 } | |
445 | |
446 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const { | |
447 const PictureLayerTiling* tiling = CurrentTiling(); | |
448 DCHECK(tiling); | |
449 return tiling->resolution(); | |
450 } | |
451 | |
452 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() | |
453 const { | |
454 if (current_tiling_ < 0) | |
455 return NULL; | |
456 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size()) | |
457 return NULL; | |
458 return set_->tilings_[current_tiling_]; | |
459 } | |
460 | |
461 int PictureLayerTilingSet::CoverageIterator::NextTiling() const { | |
462 // Order returned by this method is: | |
463 // 1. Ideal tiling index | |
464 // 2. Tiling index < Ideal in decreasing order (higher res than ideal) | |
465 // 3. Tiling index > Ideal in increasing order (lower res than ideal) | |
466 // 4. Tiling index > tilings.size() (invalid index) | |
467 if (current_tiling_ < 0) | |
468 return ideal_tiling_; | |
469 else if (current_tiling_ > ideal_tiling_) | |
470 return current_tiling_ + 1; | |
471 else if (current_tiling_) | |
472 return current_tiling_ - 1; | |
473 else | |
474 return ideal_tiling_ + 1; | |
475 } | |
476 | |
477 PictureLayerTilingSet::CoverageIterator& | |
478 PictureLayerTilingSet::CoverageIterator::operator++() { | |
479 bool first_time = current_tiling_ < 0; | |
480 | |
481 if (!*this && !first_time) | |
482 return *this; | |
483 | |
484 if (tiling_iter_) | |
485 ++tiling_iter_; | |
486 | |
487 // Loop until we find a valid place to stop. | |
488 while (true) { | |
489 while (tiling_iter_ && | |
490 (!*tiling_iter_ || !tiling_iter_->draw_info().IsReadyToDraw())) { | |
491 missing_region_.Union(tiling_iter_.geometry_rect()); | |
492 ++tiling_iter_; | |
493 } | |
494 if (tiling_iter_) | |
495 return *this; | |
496 | |
497 // If the set of current rects for this tiling is done, go to the next | |
498 // tiling and set up to iterate through all of the remaining holes. | |
499 // This will also happen the first time through the loop. | |
500 if (!region_iter_.has_rect()) { | |
501 current_tiling_ = NextTiling(); | |
502 current_region_.Swap(&missing_region_); | |
503 missing_region_.Clear(); | |
504 region_iter_ = Region::Iterator(current_region_); | |
505 | |
506 // All done and all filled. | |
507 if (!region_iter_.has_rect()) { | |
508 current_tiling_ = set_->tilings_.size(); | |
509 return *this; | |
510 } | |
511 | |
512 // No more valid tiles, return this checkerboard rect. | |
513 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) | |
514 return *this; | |
515 } | |
516 | |
517 // Pop a rect off. If there are no more tilings, then these will be | |
518 // treated as geometry with null tiles that the caller can checkerboard. | |
519 gfx::Rect last_rect = region_iter_.rect(); | |
520 region_iter_.next(); | |
521 | |
522 // Done, found next checkerboard rect to return. | |
523 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) | |
524 return *this; | |
525 | |
526 // Construct a new iterator for the next tiling, but we need to loop | |
527 // again until we get to a valid one. | |
528 tiling_iter_ = PictureLayerTiling::CoverageIterator( | |
529 set_->tilings_[current_tiling_], | |
530 contents_scale_, | |
531 last_rect); | |
532 } | |
533 | |
534 return *this; | |
535 } | |
536 | |
537 PictureLayerTilingSet::CoverageIterator::operator bool() const { | |
538 return current_tiling_ < static_cast<int>(set_->tilings_.size()) || | |
539 region_iter_.has_rect(); | |
540 } | |
541 | |
542 void PictureLayerTilingSet::AsValueInto( | |
543 base::trace_event::TracedValue* state) const { | |
544 for (size_t i = 0; i < tilings_.size(); ++i) { | |
545 state->BeginDictionary(); | |
546 tilings_[i]->AsValueInto(state); | |
547 state->EndDictionary(); | |
548 } | |
549 } | |
550 | |
551 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const { | |
552 size_t amount = 0; | |
553 for (size_t i = 0; i < tilings_.size(); ++i) | |
554 amount += tilings_[i]->GPUMemoryUsageInBytes(); | |
555 return amount; | |
556 } | |
557 | |
558 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange( | |
559 TilingRangeType type) const { | |
560 // Doesn't seem to be the case right now but if it ever becomes a performance | |
561 // problem to compute these ranges each time this function is called, we can | |
562 // compute them only when the tiling set has changed instead. | |
563 TilingRange high_res_range(0, 0); | |
564 TilingRange low_res_range(tilings_.size(), tilings_.size()); | |
565 for (size_t i = 0; i < tilings_.size(); ++i) { | |
566 const PictureLayerTiling* tiling = tilings_[i]; | |
567 if (tiling->resolution() == HIGH_RESOLUTION) | |
568 high_res_range = TilingRange(i, i + 1); | |
569 if (tiling->resolution() == LOW_RESOLUTION) | |
570 low_res_range = TilingRange(i, i + 1); | |
571 } | |
572 | |
573 TilingRange range(0, 0); | |
574 switch (type) { | |
575 case HIGHER_THAN_HIGH_RES: | |
576 range = TilingRange(0, high_res_range.start); | |
577 break; | |
578 case HIGH_RES: | |
579 range = high_res_range; | |
580 break; | |
581 case BETWEEN_HIGH_AND_LOW_RES: | |
582 // TODO(vmpstr): This code assumes that high res tiling will come before | |
583 // low res tiling, however there are cases where this assumption is | |
584 // violated. As a result, it's better to be safe in these situations, | |
585 // since otherwise we can end up accessing a tiling that doesn't exist. | |
586 // See crbug.com/429397 for high res tiling appearing after low res | |
587 // tiling discussion/fixes. | |
588 if (high_res_range.start <= low_res_range.start) | |
589 range = TilingRange(high_res_range.end, low_res_range.start); | |
590 else | |
591 range = TilingRange(low_res_range.end, high_res_range.start); | |
592 break; | |
593 case LOW_RES: | |
594 range = low_res_range; | |
595 break; | |
596 case LOWER_THAN_LOW_RES: | |
597 range = TilingRange(low_res_range.end, tilings_.size()); | |
598 break; | |
599 } | |
600 | |
601 DCHECK_LE(range.start, range.end); | |
602 return range; | |
603 } | |
604 | |
605 } // namespace cc | |
OLD | NEW |