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