Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / cc / resources / picture_layer_tiling_set.cc
blob7c482bd7d30f4980562300bdf893a4a760326eec
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 const Region& layer_invalidation) {
60 if (pending_twin_set->tilings_.empty()) {
61 // If the twin (pending) tiling set is empty, it was not updated for the
62 // current frame. So we drop tilings from our set as well, instead of
63 // leaving behind unshared tilings that are all non-ideal.
64 RemoveAllTilings();
65 return;
68 bool tiling_sort_required = false;
69 for (PictureLayerTiling* pending_twin_tiling : pending_twin_set->tilings_) {
70 float contents_scale = pending_twin_tiling->contents_scale();
71 PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale);
72 if (!this_tiling) {
73 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
74 contents_scale, raster_source, client_, max_tiles_for_interest_area_,
75 skewport_target_time_in_seconds_,
76 skewport_extrapolation_limit_in_content_pixels_);
77 tilings_.push_back(new_tiling.Pass());
78 this_tiling = tilings_.back();
79 tiling_sort_required = true;
81 this_tiling->TakeTilesAndPropertiesFrom(pending_twin_tiling,
82 layer_invalidation);
85 if (tiling_sort_required)
86 tilings_.sort(LargestToSmallestScaleFunctor());
89 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation(
90 scoped_refptr<RasterSource> raster_source,
91 const PictureLayerTilingSet* pending_twin_set,
92 const Region& layer_invalidation,
93 float minimum_contents_scale,
94 float maximum_contents_scale) {
95 RemoveTilingsBelowScale(minimum_contents_scale);
96 RemoveTilingsAboveScale(maximum_contents_scale);
98 // Copy over tilings that are shared with the |pending_twin_set| tiling set.
99 // Also, copy all of the properties from twin tilings.
100 CopyTilingsAndPropertiesFromPendingTwin(pending_twin_set, raster_source,
101 layer_invalidation);
103 // If the tiling is not shared (FindTilingWithScale returns nullptr), then
104 // invalidate tiles and update them to the new raster source.
105 for (PictureLayerTiling* tiling : tilings_) {
106 if (pending_twin_set->FindTilingWithScale(tiling->contents_scale()))
107 continue;
109 tiling->SetRasterSourceAndResize(raster_source);
110 tiling->Invalidate(layer_invalidation);
111 tiling->SetRasterSourceOnTiles();
112 // This is needed for cases where the live tiles rect didn't change but
113 // recordings exist in the raster source that did not exist on the last
114 // raster source.
115 tiling->CreateMissingTilesInLiveTilesRect();
117 // |this| is active set and |tiling| is not in the pending set, which means
118 // it is now NON_IDEAL_RESOLUTION.
119 tiling->set_resolution(NON_IDEAL_RESOLUTION);
122 VerifyTilings(pending_twin_set);
125 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit(
126 scoped_refptr<RasterSource> raster_source,
127 const Region& layer_invalidation,
128 float minimum_contents_scale,
129 float maximum_contents_scale) {
130 RemoveTilingsBelowScale(minimum_contents_scale);
131 RemoveTilingsAboveScale(maximum_contents_scale);
133 // Invalidate tiles and update them to the new raster source.
134 for (PictureLayerTiling* tiling : tilings_) {
135 tiling->SetRasterSourceAndResize(raster_source);
136 tiling->Invalidate(layer_invalidation);
137 tiling->SetRasterSourceOnTiles();
138 // This is needed for cases where the live tiles rect didn't change but
139 // recordings exist in the raster source that did not exist on the last
140 // raster source.
141 tiling->CreateMissingTilesInLiveTilesRect();
143 VerifyTilings(nullptr /* pending_twin_set */);
146 void PictureLayerTilingSet::UpdateRasterSourceDueToLCDChange(
147 const scoped_refptr<RasterSource>& raster_source,
148 const Region& layer_invalidation) {
149 for (PictureLayerTiling* tiling : tilings_) {
150 tiling->SetRasterSourceAndResize(raster_source);
151 tiling->Invalidate(layer_invalidation);
152 // Since the invalidation changed, we need to create any missing tiles in
153 // the live tiles rect again.
154 tiling->CreateMissingTilesInLiveTilesRect();
155 tiling->VerifyAllTilesHaveCurrentRasterSource();
159 void PictureLayerTilingSet::VerifyTilings(
160 const PictureLayerTilingSet* pending_twin_set) const {
161 #if DCHECK_IS_ON()
162 for (PictureLayerTiling* tiling : tilings_) {
163 DCHECK(tiling->tile_size() ==
164 client_->CalculateTileSize(tiling->tiling_size()))
165 << "tile_size: " << tiling->tile_size().ToString()
166 << " tiling_size: " << tiling->tiling_size().ToString()
167 << " CalculateTileSize: "
168 << client_->CalculateTileSize(tiling->tiling_size()).ToString();
171 if (!tilings_.empty()) {
172 DCHECK_LE(NumHighResTilings(), 1);
173 // When commiting from the main thread the high res tiling may get dropped,
174 // but when cloning to the active tree, there should always be one.
175 if (pending_twin_set) {
176 DCHECK_EQ(1, NumHighResTilings())
177 << " num tilings on active: " << tilings_.size()
178 << " num tilings on pending: " << pending_twin_set->tilings_.size()
179 << " num high res on pending: "
180 << pending_twin_set->NumHighResTilings()
181 << " are on active tree: " << (client_->GetTree() == ACTIVE_TREE);
184 #endif
187 void PictureLayerTilingSet::CleanUpTilings(
188 float min_acceptable_high_res_scale,
189 float max_acceptable_high_res_scale,
190 const std::vector<PictureLayerTiling*>& needed_tilings,
191 bool should_have_low_res,
192 PictureLayerTilingSet* twin_set,
193 PictureLayerTilingSet* recycled_twin_set) {
194 float twin_low_res_scale = 0.f;
195 if (twin_set) {
196 PictureLayerTiling* tiling =
197 twin_set->FindTilingWithResolution(LOW_RESOLUTION);
198 if (tiling)
199 twin_low_res_scale = tiling->contents_scale();
202 std::vector<PictureLayerTiling*> to_remove;
203 for (auto* tiling : tilings_) {
204 // Keep all tilings within the min/max scales.
205 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
206 tiling->contents_scale() <= max_acceptable_high_res_scale) {
207 continue;
210 // Keep low resolution tilings, if the tiling set should have them.
211 if (should_have_low_res &&
212 (tiling->resolution() == LOW_RESOLUTION ||
213 tiling->contents_scale() == twin_low_res_scale)) {
214 continue;
217 // Don't remove tilings that are required.
218 if (std::find(needed_tilings.begin(), needed_tilings.end(), tiling) !=
219 needed_tilings.end()) {
220 continue;
223 to_remove.push_back(tiling);
226 for (auto* tiling : to_remove) {
227 PictureLayerTiling* recycled_twin_tiling =
228 recycled_twin_set
229 ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale())
230 : nullptr;
231 // Remove the tiling from the recycle tree. Note that we ignore resolution,
232 // since we don't need to maintain high/low res on the recycle set.
233 if (recycled_twin_tiling)
234 recycled_twin_set->Remove(recycled_twin_tiling);
236 DCHECK_NE(HIGH_RESOLUTION, tiling->resolution());
237 Remove(tiling);
241 void PictureLayerTilingSet::RemoveNonIdealTilings() {
242 auto to_remove = tilings_.remove_if([](PictureLayerTiling* t) {
243 return t->resolution() == NON_IDEAL_RESOLUTION;
245 tilings_.erase(to_remove, tilings_.end());
248 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() {
249 for (auto* tiling : tilings_)
250 tiling->set_resolution(NON_IDEAL_RESOLUTION);
253 PictureLayerTiling* PictureLayerTilingSet::AddTiling(
254 float contents_scale,
255 scoped_refptr<RasterSource> raster_source) {
256 for (size_t i = 0; i < tilings_.size(); ++i) {
257 DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
258 DCHECK_EQ(tilings_[i]->raster_source(), raster_source.get());
261 tilings_.push_back(PictureLayerTiling::Create(
262 contents_scale, raster_source, client_, max_tiles_for_interest_area_,
263 skewport_target_time_in_seconds_,
264 skewport_extrapolation_limit_in_content_pixels_));
265 PictureLayerTiling* appended = tilings_.back();
267 tilings_.sort(LargestToSmallestScaleFunctor());
268 return appended;
271 int PictureLayerTilingSet::NumHighResTilings() const {
272 return std::count_if(tilings_.begin(), tilings_.end(),
273 [](PictureLayerTiling* tiling) {
274 return tiling->resolution() == HIGH_RESOLUTION;
278 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScale(
279 float scale) const {
280 for (size_t i = 0; i < tilings_.size(); ++i) {
281 if (tilings_[i]->contents_scale() == scale)
282 return tilings_[i];
284 return NULL;
287 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithResolution(
288 TileResolution resolution) const {
289 auto iter = std::find_if(tilings_.begin(), tilings_.end(),
290 [resolution](const PictureLayerTiling* tiling) {
291 return tiling->resolution() == resolution;
293 if (iter == tilings_.end())
294 return NULL;
295 return *iter;
298 void PictureLayerTilingSet::RemoveTilingsBelowScale(float minimum_scale) {
299 auto to_remove =
300 tilings_.remove_if([minimum_scale](PictureLayerTiling* tiling) {
301 return tiling->contents_scale() < minimum_scale;
303 tilings_.erase(to_remove, tilings_.end());
306 void PictureLayerTilingSet::RemoveTilingsAboveScale(float maximum_scale) {
307 auto to_remove =
308 tilings_.remove_if([maximum_scale](PictureLayerTiling* tiling) {
309 return tiling->contents_scale() > maximum_scale;
311 tilings_.erase(to_remove, tilings_.end());
314 void PictureLayerTilingSet::RemoveAllTilings() {
315 tilings_.clear();
318 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
319 ScopedPtrVector<PictureLayerTiling>::iterator iter =
320 std::find(tilings_.begin(), tilings_.end(), tiling);
321 if (iter == tilings_.end())
322 return;
323 tilings_.erase(iter);
326 void PictureLayerTilingSet::RemoveAllTiles() {
327 for (size_t i = 0; i < tilings_.size(); ++i)
328 tilings_[i]->Reset();
331 float PictureLayerTilingSet::GetSnappedContentsScale(
332 float start_scale,
333 float snap_to_existing_tiling_ratio) const {
334 // If a tiling exists within the max snapping ratio, snap to its scale.
335 float snapped_contents_scale = start_scale;
336 float snapped_ratio = snap_to_existing_tiling_ratio;
337 for (const auto* tiling : tilings_) {
338 float tiling_contents_scale = tiling->contents_scale();
339 float ratio = LargerRatio(tiling_contents_scale, start_scale);
340 if (ratio < snapped_ratio) {
341 snapped_contents_scale = tiling_contents_scale;
342 snapped_ratio = ratio;
345 return snapped_contents_scale;
348 float PictureLayerTilingSet::GetMaximumContentsScale() const {
349 if (tilings_.empty())
350 return 0.f;
351 // The first tiling has the largest contents scale.
352 return tilings_[0]->contents_scale();
355 bool PictureLayerTilingSet::UpdateTilePriorities(
356 const gfx::Rect& required_rect_in_layer_space,
357 float ideal_contents_scale,
358 double current_frame_time_in_seconds,
359 const Occlusion& occlusion_in_layer_space,
360 bool can_require_tiles_for_activation) {
361 bool updated = false;
362 for (auto* tiling : tilings_) {
363 tiling->set_can_require_tiles_for_activation(
364 can_require_tiles_for_activation);
365 updated |= tiling->ComputeTilePriorityRects(
366 required_rect_in_layer_space, ideal_contents_scale,
367 current_frame_time_in_seconds, occlusion_in_layer_space);
369 return updated;
372 void PictureLayerTilingSet::GetAllTilesAndPrioritiesForTracing(
373 std::map<const Tile*, TilePriority>* tile_map) const {
374 for (auto* tiling : tilings_)
375 tiling->GetAllTilesAndPrioritiesForTracing(tile_map);
378 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
379 const PictureLayerTilingSet* set,
380 float contents_scale,
381 const gfx::Rect& content_rect,
382 float ideal_contents_scale)
383 : set_(set),
384 contents_scale_(contents_scale),
385 ideal_contents_scale_(ideal_contents_scale),
386 current_tiling_(-1) {
387 missing_region_.Union(content_rect);
389 for (ideal_tiling_ = 0;
390 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
391 ++ideal_tiling_) {
392 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
393 if (tiling->contents_scale() < ideal_contents_scale_) {
394 if (ideal_tiling_ > 0)
395 ideal_tiling_--;
396 break;
400 DCHECK_LE(set_->tilings_.size(),
401 static_cast<size_t>(std::numeric_limits<int>::max()));
403 int num_tilings = set_->tilings_.size();
404 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
405 ideal_tiling_--;
407 ++(*this);
410 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
413 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
414 if (!tiling_iter_) {
415 if (!region_iter_.has_rect())
416 return gfx::Rect();
417 return region_iter_.rect();
419 return tiling_iter_.geometry_rect();
422 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
423 if (!tiling_iter_)
424 return gfx::RectF();
425 return tiling_iter_.texture_rect();
428 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
429 if (!tiling_iter_)
430 return NULL;
431 return *tiling_iter_;
434 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
435 if (!tiling_iter_)
436 return NULL;
437 return *tiling_iter_;
440 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
441 const PictureLayerTiling* tiling = CurrentTiling();
442 DCHECK(tiling);
443 return tiling->resolution();
446 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling()
447 const {
448 if (current_tiling_ < 0)
449 return NULL;
450 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
451 return NULL;
452 return set_->tilings_[current_tiling_];
455 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
456 // Order returned by this method is:
457 // 1. Ideal tiling index
458 // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
459 // 3. Tiling index > Ideal in increasing order (lower res than ideal)
460 // 4. Tiling index > tilings.size() (invalid index)
461 if (current_tiling_ < 0)
462 return ideal_tiling_;
463 else if (current_tiling_ > ideal_tiling_)
464 return current_tiling_ + 1;
465 else if (current_tiling_)
466 return current_tiling_ - 1;
467 else
468 return ideal_tiling_ + 1;
471 PictureLayerTilingSet::CoverageIterator&
472 PictureLayerTilingSet::CoverageIterator::operator++() {
473 bool first_time = current_tiling_ < 0;
475 if (!*this && !first_time)
476 return *this;
478 if (tiling_iter_)
479 ++tiling_iter_;
481 // Loop until we find a valid place to stop.
482 while (true) {
483 while (tiling_iter_ &&
484 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
485 missing_region_.Union(tiling_iter_.geometry_rect());
486 ++tiling_iter_;
488 if (tiling_iter_)
489 return *this;
491 // If the set of current rects for this tiling is done, go to the next
492 // tiling and set up to iterate through all of the remaining holes.
493 // This will also happen the first time through the loop.
494 if (!region_iter_.has_rect()) {
495 current_tiling_ = NextTiling();
496 current_region_.Swap(&missing_region_);
497 missing_region_.Clear();
498 region_iter_ = Region::Iterator(current_region_);
500 // All done and all filled.
501 if (!region_iter_.has_rect()) {
502 current_tiling_ = set_->tilings_.size();
503 return *this;
506 // No more valid tiles, return this checkerboard rect.
507 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
508 return *this;
511 // Pop a rect off. If there are no more tilings, then these will be
512 // treated as geometry with null tiles that the caller can checkerboard.
513 gfx::Rect last_rect = region_iter_.rect();
514 region_iter_.next();
516 // Done, found next checkerboard rect to return.
517 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
518 return *this;
520 // Construct a new iterator for the next tiling, but we need to loop
521 // again until we get to a valid one.
522 tiling_iter_ = PictureLayerTiling::CoverageIterator(
523 set_->tilings_[current_tiling_],
524 contents_scale_,
525 last_rect);
528 return *this;
531 PictureLayerTilingSet::CoverageIterator::operator bool() const {
532 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
533 region_iter_.has_rect();
536 void PictureLayerTilingSet::AsValueInto(
537 base::trace_event::TracedValue* state) const {
538 for (size_t i = 0; i < tilings_.size(); ++i) {
539 state->BeginDictionary();
540 tilings_[i]->AsValueInto(state);
541 state->EndDictionary();
545 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
546 size_t amount = 0;
547 for (size_t i = 0; i < tilings_.size(); ++i)
548 amount += tilings_[i]->GPUMemoryUsageInBytes();
549 return amount;
552 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
553 TilingRangeType type) const {
554 // Doesn't seem to be the case right now but if it ever becomes a performance
555 // problem to compute these ranges each time this function is called, we can
556 // compute them only when the tiling set has changed instead.
557 TilingRange high_res_range(0, 0);
558 TilingRange low_res_range(tilings_.size(), tilings_.size());
559 for (size_t i = 0; i < tilings_.size(); ++i) {
560 const PictureLayerTiling* tiling = tilings_[i];
561 if (tiling->resolution() == HIGH_RESOLUTION)
562 high_res_range = TilingRange(i, i + 1);
563 if (tiling->resolution() == LOW_RESOLUTION)
564 low_res_range = TilingRange(i, i + 1);
567 TilingRange range(0, 0);
568 switch (type) {
569 case HIGHER_THAN_HIGH_RES:
570 range = TilingRange(0, high_res_range.start);
571 break;
572 case HIGH_RES:
573 range = high_res_range;
574 break;
575 case BETWEEN_HIGH_AND_LOW_RES:
576 // TODO(vmpstr): This code assumes that high res tiling will come before
577 // low res tiling, however there are cases where this assumption is
578 // violated. As a result, it's better to be safe in these situations,
579 // since otherwise we can end up accessing a tiling that doesn't exist.
580 // See crbug.com/429397 for high res tiling appearing after low res
581 // tiling discussion/fixes.
582 if (high_res_range.start <= low_res_range.start)
583 range = TilingRange(high_res_range.end, low_res_range.start);
584 else
585 range = TilingRange(low_res_range.end, high_res_range.start);
586 break;
587 case LOW_RES:
588 range = low_res_range;
589 break;
590 case LOWER_THAN_LOW_RES:
591 range = TilingRange(low_res_range.end, tilings_.size());
592 break;
595 DCHECK_LE(range.start, range.end);
596 return range;
599 } // namespace cc