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/tiles/picture_layer_tiling_set.h"
6 
7 #include <stddef.h>
8 
9 #include <algorithm>
10 #include <limits>
11 #include <memory>
12 #include <set>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/memory/ptr_util.h"
17 #include "base/stl_util.h"
18 #include "base/trace_event/trace_event.h"
19 #include "cc/raster/raster_source.h"
20 #include "ui/gfx/geometry/rect_conversions.h"
21 
22 namespace cc {
23 
24 namespace {
25 
26 class LargestToSmallestScaleFunctor {
27  public:
operator ()(const std::unique_ptr<PictureLayerTiling> & left,const std::unique_ptr<PictureLayerTiling> & right)28   bool operator()(const std::unique_ptr<PictureLayerTiling>& left,
29                   const std::unique_ptr<PictureLayerTiling>& right) {
30     return left->contents_scale_key() > right->contents_scale_key();
31   }
32 };
33 
LargerRatio(float float1,float float2)34 inline float LargerRatio(float float1, float float2) {
35   DCHECK_GT(float1, 0.f);
36   DCHECK_GT(float2, 0.f);
37   return float1 > float2 ? float1 / float2 : float2 / float1;
38 }
39 
40 const float kSoonBorderDistanceViewportPercentage = 0.15f;
41 const float kMaxSoonBorderDistanceInScreenPixels = 312.f;
42 
43 }  // namespace
44 
45 // static
Create(WhichTree tree,PictureLayerTilingClient * client,int tiling_interest_area_padding,float skewport_target_time_in_seconds,int skewport_extrapolation_limit_in_screen_pixels,float max_preraster_distance)46 std::unique_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create(
47     WhichTree tree,
48     PictureLayerTilingClient* client,
49     int tiling_interest_area_padding,
50     float skewport_target_time_in_seconds,
51     int skewport_extrapolation_limit_in_screen_pixels,
52     float max_preraster_distance) {
53   return base::WrapUnique(new PictureLayerTilingSet(
54       tree, client, tiling_interest_area_padding,
55       skewport_target_time_in_seconds,
56       skewport_extrapolation_limit_in_screen_pixels, max_preraster_distance));
57 }
58 
PictureLayerTilingSet(WhichTree tree,PictureLayerTilingClient * client,int tiling_interest_area_padding,float skewport_target_time_in_seconds,int skewport_extrapolation_limit_in_screen_pixels,float max_preraster_distance)59 PictureLayerTilingSet::PictureLayerTilingSet(
60     WhichTree tree,
61     PictureLayerTilingClient* client,
62     int tiling_interest_area_padding,
63     float skewport_target_time_in_seconds,
64     int skewport_extrapolation_limit_in_screen_pixels,
65     float max_preraster_distance)
66     : tiling_interest_area_padding_(tiling_interest_area_padding),
67       skewport_target_time_in_seconds_(skewport_target_time_in_seconds),
68       skewport_extrapolation_limit_in_screen_pixels_(
69           skewport_extrapolation_limit_in_screen_pixels),
70       tree_(tree),
71       client_(client),
72       max_preraster_distance_(max_preraster_distance) {}
73 
74 PictureLayerTilingSet::~PictureLayerTilingSet() = default;
75 
CopyTilingsAndPropertiesFromPendingTwin(const PictureLayerTilingSet * pending_twin_set,scoped_refptr<RasterSource> raster_source,const Region & layer_invalidation)76 void PictureLayerTilingSet::CopyTilingsAndPropertiesFromPendingTwin(
77     const PictureLayerTilingSet* pending_twin_set,
78     scoped_refptr<RasterSource> raster_source,
79     const Region& layer_invalidation) {
80   if (pending_twin_set->tilings_.empty()) {
81     // If the twin (pending) tiling set is empty, it was not updated for the
82     // current frame. So we drop tilings from our set as well, instead of
83     // leaving behind unshared tilings that are all non-ideal.
84     RemoveAllTilings();
85     return;
86   }
87 
88   bool tiling_sort_required = false;
89   for (const auto& pending_twin_tiling : pending_twin_set->tilings_) {
90     gfx::AxisTransform2d raster_transform =
91         pending_twin_tiling->raster_transform();
92     bool can_use_lcd_text = pending_twin_tiling->can_use_lcd_text();
93     PictureLayerTiling* this_tiling =
94         FindTilingWithScaleKey(pending_twin_tiling->contents_scale_key());
95     if (this_tiling && (this_tiling->raster_transform() != raster_transform ||
96                         this_tiling->can_use_lcd_text() != can_use_lcd_text)) {
97       Remove(this_tiling);
98       this_tiling = nullptr;
99     }
100     if (!this_tiling) {
101       std::unique_ptr<PictureLayerTiling> new_tiling(
102           new PictureLayerTiling(tree_, raster_transform, raster_source_,
103                                  client_, kMaxSoonBorderDistanceInScreenPixels,
104                                  max_preraster_distance_, can_use_lcd_text));
105       tilings_.push_back(std::move(new_tiling));
106       this_tiling = tilings_.back().get();
107       tiling_sort_required = true;
108       state_since_last_tile_priority_update_.added_tilings = true;
109     }
110     this_tiling->TakeTilesAndPropertiesFrom(pending_twin_tiling.get(),
111                                             layer_invalidation);
112   }
113 
114   if (tiling_sort_required) {
115     std::sort(tilings_.begin(), tilings_.end(),
116               LargestToSmallestScaleFunctor());
117   }
118 }
119 
UpdateTilingsToCurrentRasterSourceForActivation(scoped_refptr<RasterSource> raster_source,const PictureLayerTilingSet * pending_twin_set,const Region & layer_invalidation,float minimum_contents_scale,float maximum_contents_scale)120 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForActivation(
121     scoped_refptr<RasterSource> raster_source,
122     const PictureLayerTilingSet* pending_twin_set,
123     const Region& layer_invalidation,
124     float minimum_contents_scale,
125     float maximum_contents_scale) {
126   RemoveTilingsBelowScaleKey(minimum_contents_scale);
127   RemoveTilingsAboveScaleKey(maximum_contents_scale);
128 
129   raster_source_ = raster_source;
130 
131   // Copy over tilings that are shared with the |pending_twin_set| tiling set.
132   // Also, copy all of the properties from twin tilings.
133   CopyTilingsAndPropertiesFromPendingTwin(pending_twin_set, raster_source,
134                                           layer_invalidation);
135 
136   // If the tiling is not shared (FindTilingWithScale returns nullptr), then
137   // invalidate tiles and update them to the new raster source.
138   for (const auto& tiling : tilings_) {
139     if (pending_twin_set->FindTilingWithScaleKey(tiling->contents_scale_key()))
140       continue;
141 
142     tiling->SetRasterSourceAndResize(raster_source);
143     tiling->Invalidate(layer_invalidation);
144     state_since_last_tile_priority_update_.invalidated = true;
145     // This is needed for cases where the live tiles rect didn't change but
146     // recordings exist in the raster source that did not exist on the last
147     // raster source.
148     tiling->CreateMissingTilesInLiveTilesRect();
149 
150     // |this| is active set and |tiling| is not in the pending set, which means
151     // it is now NON_IDEAL_RESOLUTION. The exception is for LOW_RESOLUTION
152     // tilings, which are computed and created entirely on the active tree.
153     // Since the pending tree does not have them, we should just leave them as
154     // low resolution to not lose them.
155     if (tiling->resolution() != LOW_RESOLUTION)
156       tiling->set_resolution(NON_IDEAL_RESOLUTION);
157   }
158 
159   VerifyTilings(pending_twin_set);
160 }
161 
UpdateTilingsToCurrentRasterSourceForCommit(scoped_refptr<RasterSource> raster_source,const Region & layer_invalidation,float minimum_contents_scale,float maximum_contents_scale)162 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSourceForCommit(
163     scoped_refptr<RasterSource> raster_source,
164     const Region& layer_invalidation,
165     float minimum_contents_scale,
166     float maximum_contents_scale) {
167   RemoveTilingsBelowScaleKey(minimum_contents_scale);
168   RemoveTilingsAboveScaleKey(maximum_contents_scale);
169 
170   raster_source_ = raster_source;
171 
172   // Invalidate tiles and update them to the new raster source.
173   for (const std::unique_ptr<PictureLayerTiling>& tiling : tilings_) {
174     DCHECK(tree_ != PENDING_TREE || !tiling->has_tiles());
175     tiling->SetRasterSourceAndResize(raster_source);
176 
177     // Force |UpdateTilePriorities| on commit for cases where the compositor is
178     // heavily pipelined resulting in back to back draw and commit. This
179     // prevents the early out from |UpdateTilePriorities| because frame time
180     // didn't change. That in turn causes an early out from PrepareTiles which
181     // can cause checkerboarding.
182     state_since_last_tile_priority_update_.invalidated = true;
183 
184     // We can commit on either active or pending trees, but only active one can
185     // have tiles at this point.
186     if (tree_ == ACTIVE_TREE)
187       tiling->Invalidate(layer_invalidation);
188 
189     // This is needed for cases where the live tiles rect didn't change but
190     // recordings exist in the raster source that did not exist on the last
191     // raster source.
192     tiling->CreateMissingTilesInLiveTilesRect();
193   }
194   VerifyTilings(nullptr /* pending_twin_set */);
195 }
196 
Invalidate(const Region & layer_invalidation)197 void PictureLayerTilingSet::Invalidate(const Region& layer_invalidation) {
198   for (const auto& tiling : tilings_) {
199     tiling->Invalidate(layer_invalidation);
200     tiling->CreateMissingTilesInLiveTilesRect();
201   }
202   state_since_last_tile_priority_update_.invalidated = true;
203 }
204 
VerifyTilings(const PictureLayerTilingSet * pending_twin_set) const205 void PictureLayerTilingSet::VerifyTilings(
206     const PictureLayerTilingSet* pending_twin_set) const {
207 #if DCHECK_IS_ON()
208   for (const auto& tiling : tilings_) {
209     DCHECK(tiling->tile_size() ==
210            client_->CalculateTileSize(tiling->tiling_size()))
211         << "tile_size: " << tiling->tile_size().ToString()
212         << " tiling_size: " << tiling->tiling_size().ToString()
213         << " CalculateTileSize: "
214         << client_->CalculateTileSize(tiling->tiling_size()).ToString();
215   }
216 
217   if (!tilings_.empty()) {
218     DCHECK_LE(NumHighResTilings(), 1);
219     // When commiting from the main thread the high res tiling may get dropped,
220     // but when cloning to the active tree, there should always be one.
221     if (pending_twin_set) {
222       DCHECK_EQ(1, NumHighResTilings())
223           << " num tilings on active: " << tilings_.size()
224           << " num tilings on pending: " << pending_twin_set->tilings_.size()
225           << " num high res on pending: "
226           << pending_twin_set->NumHighResTilings()
227           << " are on active tree: " << (tree_ == ACTIVE_TREE);
228     }
229   }
230 #endif
231 }
232 
CleanUpTilings(float min_acceptable_high_res_scale_key,float max_acceptable_high_res_scale_key,const std::vector<PictureLayerTiling * > & needed_tilings,PictureLayerTilingSet * twin_set)233 void PictureLayerTilingSet::CleanUpTilings(
234     float min_acceptable_high_res_scale_key,
235     float max_acceptable_high_res_scale_key,
236     const std::vector<PictureLayerTiling*>& needed_tilings,
237     PictureLayerTilingSet* twin_set) {
238   std::vector<PictureLayerTiling*> to_remove;
239   for (const auto& tiling : tilings_) {
240     // Keep all tilings within the min/max scales.
241     if (tiling->contents_scale_key() >= min_acceptable_high_res_scale_key &&
242         tiling->contents_scale_key() <= max_acceptable_high_res_scale_key) {
243       continue;
244     }
245 
246     // Keep low resolution tilings.
247     if (tiling->resolution() == LOW_RESOLUTION)
248       continue;
249 
250     // Don't remove tilings that are required.
251     if (base::Contains(needed_tilings, tiling.get())) {
252       continue;
253     }
254 
255     to_remove.push_back(tiling.get());
256   }
257 
258   for (auto* tiling : to_remove) {
259     DCHECK_NE(HIGH_RESOLUTION, tiling->resolution());
260     Remove(tiling);
261   }
262 }
263 
RemoveNonIdealTilings()264 void PictureLayerTilingSet::RemoveNonIdealTilings() {
265   base::EraseIf(tilings_, [](const std::unique_ptr<PictureLayerTiling>& t) {
266     return t->resolution() == NON_IDEAL_RESOLUTION;
267   });
268 }
269 
MarkAllTilingsNonIdeal()270 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() {
271   for (const auto& tiling : tilings_)
272     tiling->set_resolution(NON_IDEAL_RESOLUTION);
273 }
274 
AddTiling(const gfx::AxisTransform2d & raster_transform,scoped_refptr<RasterSource> raster_source,bool can_use_lcd_text)275 PictureLayerTiling* PictureLayerTilingSet::AddTiling(
276     const gfx::AxisTransform2d& raster_transform,
277     scoped_refptr<RasterSource> raster_source,
278     bool can_use_lcd_text) {
279   if (!raster_source_)
280     raster_source_ = raster_source;
281 
282 #if DCHECK_IS_ON()
283   for (size_t i = 0; i < tilings_.size(); ++i) {
284     DCHECK_NE(tilings_[i]->contents_scale_key(), raster_transform.scale());
285     DCHECK_EQ(tilings_[i]->raster_source(), raster_source.get());
286   }
287 #endif  // DCHECK_IS_ON()
288 
289   tilings_.push_back(std::make_unique<PictureLayerTiling>(
290       tree_, raster_transform, raster_source, client_,
291       kMaxSoonBorderDistanceInScreenPixels, max_preraster_distance_,
292       can_use_lcd_text));
293   PictureLayerTiling* appended = tilings_.back().get();
294   state_since_last_tile_priority_update_.added_tilings = true;
295 
296   std::sort(tilings_.begin(), tilings_.end(), LargestToSmallestScaleFunctor());
297   return appended;
298 }
299 
NumHighResTilings() const300 int PictureLayerTilingSet::NumHighResTilings() const {
301   return std::count_if(tilings_.begin(), tilings_.end(),
302                        [](const std::unique_ptr<PictureLayerTiling>& tiling) {
303                          return tiling->resolution() == HIGH_RESOLUTION;
304                        });
305 }
306 
FindTilingWithScaleKey(float scale_key) const307 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScaleKey(
308     float scale_key) const {
309   for (size_t i = 0; i < tilings_.size(); ++i) {
310     if (tilings_[i]->contents_scale_key() == scale_key)
311       return tilings_[i].get();
312   }
313   return nullptr;
314 }
315 
FindTilingWithResolution(TileResolution resolution) const316 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithResolution(
317     TileResolution resolution) const {
318   auto iter = std::find_if(
319       tilings_.begin(), tilings_.end(),
320       [resolution](const std::unique_ptr<PictureLayerTiling>& tiling) {
321         return tiling->resolution() == resolution;
322       });
323   if (iter == tilings_.end())
324     return nullptr;
325   return iter->get();
326 }
327 
RemoveTilingsBelowScaleKey(float minimum_scale_key)328 void PictureLayerTilingSet::RemoveTilingsBelowScaleKey(
329     float minimum_scale_key) {
330   base::EraseIf(
331       tilings_,
332       [minimum_scale_key](const std::unique_ptr<PictureLayerTiling>& tiling) {
333         return tiling->contents_scale_key() < minimum_scale_key;
334       });
335 }
336 
RemoveTilingsAboveScaleKey(float maximum_scale_key)337 void PictureLayerTilingSet::RemoveTilingsAboveScaleKey(
338     float maximum_scale_key) {
339   base::EraseIf(
340       tilings_,
341       [maximum_scale_key](const std::unique_ptr<PictureLayerTiling>& tiling) {
342         return tiling->contents_scale_key() > maximum_scale_key;
343       });
344 }
345 
ReleaseAllResources()346 void PictureLayerTilingSet::ReleaseAllResources() {
347   RemoveAllTilings();
348   raster_source_ = nullptr;
349 }
350 
RemoveAllTilings()351 void PictureLayerTilingSet::RemoveAllTilings() {
352   tilings_.clear();
353 }
354 
Remove(PictureLayerTiling * tiling)355 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
356   auto iter = std::find_if(
357       tilings_.begin(), tilings_.end(),
358       [tiling](const std::unique_ptr<PictureLayerTiling>& candidate) {
359         return candidate.get() == tiling;
360       });
361   if (iter == tilings_.end())
362     return;
363   tilings_.erase(iter);
364 }
365 
RemoveAllTiles()366 void PictureLayerTilingSet::RemoveAllTiles() {
367   for (size_t i = 0; i < tilings_.size(); ++i)
368     tilings_[i]->Reset();
369 }
370 
GetSnappedContentsScaleKey(float start_scale,float snap_to_existing_tiling_ratio) const371 float PictureLayerTilingSet::GetSnappedContentsScaleKey(
372     float start_scale,
373     float snap_to_existing_tiling_ratio) const {
374   // If a tiling exists within the max snapping ratio, snap to its scale.
375   float snapped_contents_scale = start_scale;
376   float snapped_ratio = snap_to_existing_tiling_ratio;
377   for (const auto& tiling : tilings_) {
378     float tiling_contents_scale = tiling->contents_scale_key();
379     float ratio = LargerRatio(tiling_contents_scale, start_scale);
380     if (ratio < snapped_ratio) {
381       snapped_contents_scale = tiling_contents_scale;
382       snapped_ratio = ratio;
383     }
384   }
385   return snapped_contents_scale;
386 }
387 
GetMaximumContentsScale() const388 float PictureLayerTilingSet::GetMaximumContentsScale() const {
389   if (tilings_.empty())
390     return 0.f;
391   // The first tiling has the largest contents scale.
392   return tilings_[0]->raster_transform().scale();
393 }
394 
TilingsNeedUpdate(const gfx::Rect & visible_rect_in_layer_space,double current_frame_time_in_seconds)395 bool PictureLayerTilingSet::TilingsNeedUpdate(
396     const gfx::Rect& visible_rect_in_layer_space,
397     double current_frame_time_in_seconds) {
398   // If we don't have any tilings, we don't need an update.
399   if (num_tilings() == 0)
400     return false;
401 
402   // If we never updated the tiling set, then our history is empty. We should
403   // update tilings.
404   if (visible_rect_history_.empty())
405     return true;
406 
407   // If we've added new tilings since the last update, then we have to update at
408   // least that one tiling.
409   if (state_since_last_tile_priority_update_.added_tilings)
410     return true;
411 
412   // Finally, if some state changed (either frame time or visible rect), then we
413   // need to inform the tilings of the change.
414   const auto& last_frame = visible_rect_history_.front();
415   if (current_frame_time_in_seconds != last_frame.frame_time_in_seconds)
416     return true;
417 
418   if (visible_rect_in_layer_space != last_frame.visible_rect_in_layer_space)
419     return true;
420   return false;
421 }
422 
ComputeSkewport(const gfx::Rect & visible_rect_in_layer_space,double current_frame_time_in_seconds,float ideal_contents_scale)423 gfx::Rect PictureLayerTilingSet::ComputeSkewport(
424     const gfx::Rect& visible_rect_in_layer_space,
425     double current_frame_time_in_seconds,
426     float ideal_contents_scale) {
427   gfx::Rect skewport = visible_rect_in_layer_space;
428   if (skewport.IsEmpty() || visible_rect_history_.empty())
429     return skewport;
430 
431   // Use the oldest recorded history to get a stable skewport.
432   const auto& historical_frame = visible_rect_history_.back();
433   double time_delta =
434       current_frame_time_in_seconds - historical_frame.frame_time_in_seconds;
435   if (time_delta == 0.)
436     return skewport;
437 
438   double extrapolation_multiplier =
439       skewport_target_time_in_seconds_ / time_delta;
440   int old_x = historical_frame.visible_rect_in_layer_space.x();
441   int old_y = historical_frame.visible_rect_in_layer_space.y();
442   int old_right = historical_frame.visible_rect_in_layer_space.right();
443   int old_bottom = historical_frame.visible_rect_in_layer_space.bottom();
444 
445   int new_x = visible_rect_in_layer_space.x();
446   int new_y = visible_rect_in_layer_space.y();
447   int new_right = visible_rect_in_layer_space.right();
448   int new_bottom = visible_rect_in_layer_space.bottom();
449 
450   int inset_x = (new_x - old_x) * extrapolation_multiplier;
451   int inset_y = (new_y - old_y) * extrapolation_multiplier;
452   int inset_right = (old_right - new_right) * extrapolation_multiplier;
453   int inset_bottom = (old_bottom - new_bottom) * extrapolation_multiplier;
454 
455   int skewport_extrapolation_limit_in_layer_pixels =
456       skewport_extrapolation_limit_in_screen_pixels_ / ideal_contents_scale;
457   gfx::Rect max_skewport = skewport;
458   max_skewport.Inset(-skewport_extrapolation_limit_in_layer_pixels,
459                      -skewport_extrapolation_limit_in_layer_pixels);
460 
461   skewport.Inset(inset_x, inset_y, inset_right, inset_bottom);
462   skewport.Union(visible_rect_in_layer_space);
463   skewport.Intersect(max_skewport);
464 
465   // Due to limits in int's representation, it is possible that the two
466   // operations above (union and intersect) result in an empty skewport. To
467   // avoid any unpleasant situations like that, union the visible rect again to
468   // ensure that skewport.Contains(visible_rect_in_layer_space) is always
469   // true.
470   skewport.Union(visible_rect_in_layer_space);
471   skewport.Intersect(eventually_rect_in_layer_space_);
472   return skewport;
473 }
474 
ComputeSoonBorderRect(const gfx::Rect & visible_rect,float ideal_contents_scale)475 gfx::Rect PictureLayerTilingSet::ComputeSoonBorderRect(
476     const gfx::Rect& visible_rect,
477     float ideal_contents_scale) {
478   int max_dimension = std::max(visible_rect.width(), visible_rect.height());
479   int distance =
480       std::min<int>(kMaxSoonBorderDistanceInScreenPixels * ideal_contents_scale,
481                     max_dimension * kSoonBorderDistanceViewportPercentage);
482 
483   gfx::Rect soon_border_rect = visible_rect;
484   soon_border_rect.Inset(-distance, -distance);
485   soon_border_rect.Intersect(eventually_rect_in_layer_space_);
486   return soon_border_rect;
487 }
488 
UpdatePriorityRects(const gfx::Rect & visible_rect_in_layer_space,double current_frame_time_in_seconds,float ideal_contents_scale)489 void PictureLayerTilingSet::UpdatePriorityRects(
490     const gfx::Rect& visible_rect_in_layer_space,
491     double current_frame_time_in_seconds,
492     float ideal_contents_scale) {
493   visible_rect_in_layer_space_ = gfx::Rect();
494   eventually_rect_in_layer_space_ = gfx::Rect();
495 
496   // We keep things as floats in here.
497   if (!visible_rect_in_layer_space.IsEmpty()) {
498     gfx::RectF eventually_rectf(visible_rect_in_layer_space);
499     eventually_rectf.Inset(
500         -tiling_interest_area_padding_ / ideal_contents_scale,
501         -tiling_interest_area_padding_ / ideal_contents_scale);
502     if (eventually_rectf.Intersects(
503             gfx::RectF(gfx::SizeF(raster_source_->GetSize())))) {
504       visible_rect_in_layer_space_ = visible_rect_in_layer_space;
505       eventually_rect_in_layer_space_ = gfx::ToEnclosingRect(eventually_rectf);
506     }
507   }
508 
509   skewport_in_layer_space_ =
510       ComputeSkewport(visible_rect_in_layer_space_,
511                       current_frame_time_in_seconds, ideal_contents_scale);
512   DCHECK(skewport_in_layer_space_.Contains(visible_rect_in_layer_space_));
513   DCHECK(eventually_rect_in_layer_space_.Contains(skewport_in_layer_space_));
514 
515   soon_border_rect_in_layer_space_ =
516       ComputeSoonBorderRect(visible_rect_in_layer_space_, ideal_contents_scale);
517   DCHECK(
518       soon_border_rect_in_layer_space_.Contains(visible_rect_in_layer_space_));
519   DCHECK(eventually_rect_in_layer_space_.Contains(
520       soon_border_rect_in_layer_space_));
521 
522   // Finally, update our visible rect history. Note that we use the original
523   // visible rect here, since we want as accurate of a history as possible for
524   // stable skewports.
525   if (visible_rect_history_.size() == 2)
526     visible_rect_history_.pop_back();
527   visible_rect_history_.push_front(FrameVisibleRect(
528       visible_rect_in_layer_space_, current_frame_time_in_seconds));
529 }
530 
UpdateTilePriorities(const gfx::Rect & visible_rect_in_layer_space,float ideal_contents_scale,double current_frame_time_in_seconds,const Occlusion & occlusion_in_layer_space,bool can_require_tiles_for_activation)531 bool PictureLayerTilingSet::UpdateTilePriorities(
532     const gfx::Rect& visible_rect_in_layer_space,
533     float ideal_contents_scale,
534     double current_frame_time_in_seconds,
535     const Occlusion& occlusion_in_layer_space,
536     bool can_require_tiles_for_activation) {
537   StateSinceLastTilePriorityUpdate::AutoClear auto_clear_state(
538       &state_since_last_tile_priority_update_);
539 
540   if (!TilingsNeedUpdate(visible_rect_in_layer_space,
541                          current_frame_time_in_seconds)) {
542     return state_since_last_tile_priority_update_.invalidated;
543   }
544 
545   UpdatePriorityRects(visible_rect_in_layer_space,
546                       current_frame_time_in_seconds, ideal_contents_scale);
547 
548   for (const auto& tiling : tilings_) {
549     tiling->set_can_require_tiles_for_activation(
550         can_require_tiles_for_activation);
551     tiling->ComputeTilePriorityRects(
552         visible_rect_in_layer_space_, skewport_in_layer_space_,
553         soon_border_rect_in_layer_space_, eventually_rect_in_layer_space_,
554         ideal_contents_scale, occlusion_in_layer_space);
555   }
556   return true;
557 }
558 
GetAllPrioritizedTilesForTracing(std::vector<PrioritizedTile> * prioritized_tiles) const559 void PictureLayerTilingSet::GetAllPrioritizedTilesForTracing(
560     std::vector<PrioritizedTile>* prioritized_tiles) const {
561   for (const auto& tiling : tilings_)
562     tiling->GetAllPrioritizedTilesForTracing(prioritized_tiles);
563 }
564 
CoverageIterator(const PictureLayerTilingSet * set,float coverage_scale,const gfx::Rect & coverage_rect,float ideal_contents_scale)565 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
566     const PictureLayerTilingSet* set,
567     float coverage_scale,
568     const gfx::Rect& coverage_rect,
569     float ideal_contents_scale)
570     : set_(set),
571       coverage_scale_(coverage_scale),
572       current_tiling_(std::numeric_limits<size_t>::max()) {
573   missing_region_.Union(coverage_rect);
574 
575   // Determine the smallest content_scale tiling which a scale higher than the
576   // ideal (or the first tiling if all tilings have a scale less than ideal).
577   size_t tilings_size = set_->tilings_.size();
578   for (ideal_tiling_ = 0; ideal_tiling_ < tilings_size; ++ideal_tiling_) {
579     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_].get();
580     if (tiling->contents_scale_key() < ideal_contents_scale) {
581       if (ideal_tiling_ > 0)
582         ideal_tiling_--;
583       break;
584     }
585   }
586 
587   // If all tilings have a scale larger than the ideal, then use the smallest
588   // scale (which is the last one).
589   if (ideal_tiling_ == tilings_size && ideal_tiling_ > 0)
590     ideal_tiling_--;
591 
592   ++(*this);
593 }
594 
595 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() = default;
596 
geometry_rect() const597 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
598   // If we don't have any more tilings to process, then return the region
599   // iterator rect that we need to fill, so that the caller can checkerboard it.
600   if (!tiling_iter_) {
601     if (region_iter_ == current_region_.end())
602       return gfx::Rect();
603     return *region_iter_;
604   }
605   return tiling_iter_.geometry_rect();
606 }
607 
texture_rect() const608 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
609   // Texture rects are only valid if we have a tiling.
610   if (!tiling_iter_)
611     return gfx::RectF();
612   return tiling_iter_.texture_rect();
613 }
614 
operator ->() const615 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
616   if (!tiling_iter_)
617     return nullptr;
618   return *tiling_iter_;
619 }
620 
operator *() const621 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
622   if (!tiling_iter_)
623     return nullptr;
624   return *tiling_iter_;
625 }
626 
resolution() const627 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
628   const PictureLayerTiling* tiling = CurrentTiling();
629   DCHECK(tiling);
630   return tiling->resolution();
631 }
632 
CurrentTiling() const633 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling()
634     const {
635   if (current_tiling_ == std::numeric_limits<size_t>::max())
636     return nullptr;
637   if (current_tiling_ >= set_->tilings_.size())
638     return nullptr;
639   return set_->tilings_[current_tiling_].get();
640 }
641 
NextTiling() const642 size_t PictureLayerTilingSet::CoverageIterator::NextTiling() const {
643   // Order returned by this method is:
644   // 1. Ideal tiling index
645   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
646   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
647   // 4. Tiling index > tilings.size() (invalid index)
648   if (current_tiling_ == std::numeric_limits<size_t>::max())
649     return ideal_tiling_;
650   else if (current_tiling_ > ideal_tiling_)
651     return current_tiling_ + 1;
652   else if (current_tiling_)
653     return current_tiling_ - 1;
654   else
655     return ideal_tiling_ + 1;
656 }
657 
658 PictureLayerTilingSet::CoverageIterator&
operator ++()659 PictureLayerTilingSet::CoverageIterator::operator++() {
660   bool first_time = current_tiling_ == std::numeric_limits<size_t>::max();
661 
662   if (!*this && !first_time)
663     return *this;
664 
665   if (tiling_iter_)
666     ++tiling_iter_;
667 
668   // Loop until we find a valid place to stop.
669   while (true) {
670     // While we don't have a ready to draw tile, accumulate the geometry rects
671     // back into the missing region, which will be iterated after this tiling is
672     // processed.
673     while (tiling_iter_ &&
674            (!*tiling_iter_ || !tiling_iter_->draw_info().IsReadyToDraw())) {
675       missing_region_.Union(tiling_iter_.geometry_rect());
676       ++tiling_iter_;
677     }
678     // We found a ready tile, yield it!
679     if (tiling_iter_)
680       return *this;
681 
682     // If the set of current rects for this tiling is done, go to the next
683     // tiling and set up to iterate through all of the remaining holes.
684     // This will also happen the first time through the loop.
685     if (region_iter_ == current_region_.end()) {
686       current_tiling_ = NextTiling();
687       current_region_.Swap(&missing_region_);
688       missing_region_.Clear();
689       region_iter_ = current_region_.begin();
690 
691       // All done and all filled.
692       if (region_iter_ == current_region_.end()) {
693         current_tiling_ = set_->tilings_.size();
694         return *this;
695       }
696 
697       // No more valid tiles, return this checkerboard rect.
698       if (current_tiling_ >= set_->tilings_.size())
699         return *this;
700     }
701 
702     // Pop a rect off.  If there are no more tilings, then these will be
703     // treated as geometry with null tiles that the caller can checkerboard.
704     gfx::Rect last_rect = *region_iter_;
705     ++region_iter_;
706 
707     // Done, found next checkerboard rect to return.
708     if (current_tiling_ >= set_->tilings_.size())
709       return *this;
710 
711     // Construct a new iterator for the next tiling, but we need to loop
712     // again until we get to a valid one.
713     tiling_iter_ = PictureLayerTiling::CoverageIterator(
714         set_->tilings_[current_tiling_].get(), coverage_scale_, last_rect);
715   }
716 
717   return *this;
718 }
719 
operator bool() const720 PictureLayerTilingSet::CoverageIterator::operator bool() const {
721   return current_tiling_ < set_->tilings_.size() ||
722          region_iter_ != current_region_.end();
723 }
724 
AsValueInto(base::trace_event::TracedValue * state) const725 void PictureLayerTilingSet::AsValueInto(
726     base::trace_event::TracedValue* state) const {
727   for (size_t i = 0; i < tilings_.size(); ++i) {
728     state->BeginDictionary();
729     tilings_[i]->AsValueInto(state);
730     state->EndDictionary();
731   }
732 }
733 
GPUMemoryUsageInBytes() const734 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
735   size_t amount = 0;
736   for (size_t i = 0; i < tilings_.size(); ++i)
737     amount += tilings_[i]->GPUMemoryUsageInBytes();
738   return amount;
739 }
740 
GetTilingRange(TilingRangeType type) const741 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
742     TilingRangeType type) const {
743   // Doesn't seem to be the case right now but if it ever becomes a performance
744   // problem to compute these ranges each time this function is called, we can
745   // compute them only when the tiling set has changed instead.
746   size_t tilings_size = tilings_.size();
747   TilingRange high_res_range(0, 0);
748   TilingRange low_res_range(tilings_.size(), tilings_.size());
749   for (size_t i = 0; i < tilings_size; ++i) {
750     const PictureLayerTiling* tiling = tilings_[i].get();
751     if (tiling->resolution() == HIGH_RESOLUTION)
752       high_res_range = TilingRange(i, i + 1);
753     if (tiling->resolution() == LOW_RESOLUTION)
754       low_res_range = TilingRange(i, i + 1);
755   }
756 
757   TilingRange range(0, 0);
758   switch (type) {
759     case HIGHER_THAN_HIGH_RES:
760       range = TilingRange(0, high_res_range.start);
761       break;
762     case HIGH_RES:
763       range = high_res_range;
764       break;
765     case BETWEEN_HIGH_AND_LOW_RES:
766       // TODO(vmpstr): This code assumes that high res tiling will come before
767       // low res tiling, however there are cases where this assumption is
768       // violated. As a result, it's better to be safe in these situations,
769       // since otherwise we can end up accessing a tiling that doesn't exist.
770       // See crbug.com/429397 for high res tiling appearing after low res
771       // tiling discussion/fixes.
772       if (high_res_range.start <= low_res_range.start)
773         range = TilingRange(high_res_range.end, low_res_range.start);
774       else
775         range = TilingRange(low_res_range.end, high_res_range.start);
776       break;
777     case LOW_RES:
778       range = low_res_range;
779       break;
780     case LOWER_THAN_LOW_RES:
781       range = TilingRange(low_res_range.end, tilings_size);
782       break;
783   }
784 
785   DCHECK_LE(range.start, range.end);
786   return range;
787 }
788 
789 }  // namespace cc
790