Revert "Remove test result whitespace stripping from blink_gc_plugin test script"
[chromium-blink-merge.git] / cc / resources / picture_layer_tiling_set.cc
blobed97a0577aef93c670f265c1882426390f9aa69d
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 #include "cc/resources/raster_source.h"
13 namespace cc {
15 namespace {
17 class LargestToSmallestScaleFunctor {
18 public:
19 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
20 return left->contents_scale() > right->contents_scale();
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;
30 } // namespace
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));
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) {
60 PictureLayerTilingSet::~PictureLayerTilingSet() {
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;
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;
89 this_tiling->TakeTilesAndPropertiesFrom(pending_twin_tiling,
90 layer_invalidation);
93 if (tiling_sort_required)
94 tilings_.sort(LargestToSmallestScaleFunctor());
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);
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);
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;
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();
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);
129 VerifyTilings(pending_twin_set);
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);
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();
149 VerifyTilings(nullptr /* pending_twin_set */);
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();
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();
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);
189 #endif
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();
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;
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;
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;
228 to_remove.push_back(tiling);
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);
241 DCHECK_NE(HIGH_RESOLUTION, tiling->resolution());
242 Remove(tiling);
246 void PictureLayerTilingSet::RemoveNonIdealTilings() {
247 auto to_remove = tilings_.remove_if([](PictureLayerTiling* t) {
248 return t->resolution() == NON_IDEAL_RESOLUTION;
250 tilings_.erase(to_remove, tilings_.end());
253 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() {
254 for (auto* tiling : tilings_)
255 tiling->set_resolution(NON_IDEAL_RESOLUTION);
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());
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();
273 tilings_.sort(LargestToSmallestScaleFunctor());
274 return appended;
277 int PictureLayerTilingSet::NumHighResTilings() const {
278 return std::count_if(tilings_.begin(), tilings_.end(),
279 [](PictureLayerTiling* tiling) {
280 return tiling->resolution() == HIGH_RESOLUTION;
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];
290 return NULL;
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;
299 if (iter == tilings_.end())
300 return NULL;
301 return *iter;
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;
309 tilings_.erase(to_remove, tilings_.end());
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;
317 tilings_.erase(to_remove, tilings_.end());
320 void PictureLayerTilingSet::RemoveAllTilings() {
321 tilings_.clear();
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);
332 void PictureLayerTilingSet::RemoveAllTiles() {
333 for (size_t i = 0; i < tilings_.size(); ++i)
334 tilings_[i]->Reset();
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;
351 return snapped_contents_scale;
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();
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);
375 return updated;
378 void PictureLayerTilingSet::GetAllPrioritizedTilesForTracing(
379 std::vector<PrioritizedTile>* prioritized_tiles) const {
380 for (auto* tiling : tilings_)
381 tiling->GetAllPrioritizedTilesForTracing(prioritized_tiles);
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);
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;
406 DCHECK_LE(set_->tilings_.size(),
407 static_cast<size_t>(std::numeric_limits<int>::max()));
409 int num_tilings = set_->tilings_.size();
410 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
411 ideal_tiling_--;
413 ++(*this);
416 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
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();
425 return tiling_iter_.geometry_rect();
428 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
429 if (!tiling_iter_)
430 return gfx::RectF();
431 return tiling_iter_.texture_rect();
434 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
435 if (!tiling_iter_)
436 return NULL;
437 return *tiling_iter_;
440 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
441 if (!tiling_iter_)
442 return NULL;
443 return *tiling_iter_;
446 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
447 const PictureLayerTiling* tiling = CurrentTiling();
448 DCHECK(tiling);
449 return tiling->resolution();
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_];
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;
477 PictureLayerTilingSet::CoverageIterator&
478 PictureLayerTilingSet::CoverageIterator::operator++() {
479 bool first_time = current_tiling_ < 0;
481 if (!*this && !first_time)
482 return *this;
484 if (tiling_iter_)
485 ++tiling_iter_;
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_;
494 if (tiling_iter_)
495 return *this;
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_);
506 // All done and all filled.
507 if (!region_iter_.has_rect()) {
508 current_tiling_ = set_->tilings_.size();
509 return *this;
512 // No more valid tiles, return this checkerboard rect.
513 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
514 return *this;
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();
522 // Done, found next checkerboard rect to return.
523 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
524 return *this;
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);
534 return *this;
537 PictureLayerTilingSet::CoverageIterator::operator bool() const {
538 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
539 region_iter_.has_rect();
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();
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;
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);
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;
601 DCHECK_LE(range.start, range.end);
602 return range;
605 } // namespace cc