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