• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/layers/picture_layer_impl.h"
6 
7 #include <algorithm>
8 #include <limits>
9 #include <set>
10 
11 #include "base/time/time.h"
12 #include "cc/base/math_util.h"
13 #include "cc/base/util.h"
14 #include "cc/debug/debug_colors.h"
15 #include "cc/debug/micro_benchmark_impl.h"
16 #include "cc/debug/traced_value.h"
17 #include "cc/layers/append_quads_data.h"
18 #include "cc/layers/quad_sink.h"
19 #include "cc/quads/checkerboard_draw_quad.h"
20 #include "cc/quads/debug_border_draw_quad.h"
21 #include "cc/quads/picture_draw_quad.h"
22 #include "cc/quads/solid_color_draw_quad.h"
23 #include "cc/quads/tile_draw_quad.h"
24 #include "cc/resources/tile_manager.h"
25 #include "cc/trees/layer_tree_impl.h"
26 #include "ui/gfx/quad_f.h"
27 #include "ui/gfx/rect_conversions.h"
28 #include "ui/gfx/size_conversions.h"
29 
30 namespace {
31 const float kMaxScaleRatioDuringPinch = 2.0f;
32 
33 // When creating a new tiling during pinch, snap to an existing
34 // tiling's scale if the desired scale is within this ratio.
35 const float kSnapToExistingTilingRatio = 1.2f;
36 
37 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
38 const float kCpuSkewportTargetTimeInFrames = 60.0f;
39 
40 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
41 // TileManager::BinFromTilePriority).
42 const float kGpuSkewportTargetTimeInFrames = 0.0f;
43 
44 }  // namespace
45 
46 namespace cc {
47 
PictureLayerImpl(LayerTreeImpl * tree_impl,int id)48 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
49     : LayerImpl(tree_impl, id),
50       twin_layer_(NULL),
51       pile_(PicturePileImpl::Create()),
52       is_mask_(false),
53       ideal_page_scale_(0.f),
54       ideal_device_scale_(0.f),
55       ideal_source_scale_(0.f),
56       ideal_contents_scale_(0.f),
57       raster_page_scale_(0.f),
58       raster_device_scale_(0.f),
59       raster_source_scale_(0.f),
60       raster_contents_scale_(0.f),
61       low_res_raster_contents_scale_(0.f),
62       raster_source_scale_is_fixed_(false),
63       was_screen_space_transform_animating_(false),
64       needs_post_commit_initialization_(true),
65       should_update_tile_priorities_(false) {
66   layer_tree_impl()->RegisterPictureLayerImpl(this);
67 }
68 
~PictureLayerImpl()69 PictureLayerImpl::~PictureLayerImpl() {
70   layer_tree_impl()->UnregisterPictureLayerImpl(this);
71 }
72 
LayerTypeAsString() const73 const char* PictureLayerImpl::LayerTypeAsString() const {
74   return "cc::PictureLayerImpl";
75 }
76 
CreateLayerImpl(LayerTreeImpl * tree_impl)77 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
78     LayerTreeImpl* tree_impl) {
79   return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
80 }
81 
PushPropertiesTo(LayerImpl * base_layer)82 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
83   // It's possible this layer was never drawn or updated (e.g. because it was
84   // a descendant of an opacity 0 layer).
85   DoPostCommitInitializationIfNeeded();
86   PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
87 
88   // We have already synced the important bits from the the active layer, and
89   // we will soon swap out its tilings and use them for recycling. However,
90   // there are now tiles in this layer's tilings that were unref'd and replaced
91   // with new tiles (due to invalidation). This resets all active priorities on
92   // the to-be-recycled tiling to ensure replaced tiles don't linger and take
93   // memory (due to a stale 'active' priority).
94   if (layer_impl->tilings_)
95     layer_impl->tilings_->DidBecomeRecycled();
96 
97   LayerImpl::PushPropertiesTo(base_layer);
98 
99   // When the pending tree pushes to the active tree, the pending twin
100   // becomes recycled.
101   layer_impl->twin_layer_ = NULL;
102   twin_layer_ = NULL;
103 
104   layer_impl->SetIsMask(is_mask_);
105   layer_impl->pile_ = pile_;
106 
107   // Tilings would be expensive to push, so we swap.
108   layer_impl->tilings_.swap(tilings_);
109 
110   // Ensure that we don't have any tiles that are out of date.
111   if (tilings_)
112     tilings_->RemoveTilesInRegion(invalidation_);
113 
114   layer_impl->tilings_->SetClient(layer_impl);
115   if (tilings_)
116     tilings_->SetClient(this);
117 
118   layer_impl->raster_page_scale_ = raster_page_scale_;
119   layer_impl->raster_device_scale_ = raster_device_scale_;
120   layer_impl->raster_source_scale_ = raster_source_scale_;
121   layer_impl->raster_contents_scale_ = raster_contents_scale_;
122   layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
123   layer_impl->needs_post_commit_initialization_ = false;
124 
125   // The invalidation on this soon-to-be-recycled layer must be cleared to
126   // mirror clearing the invalidation in PictureLayer's version of this function
127   // in case push properties is skipped.
128   layer_impl->invalidation_.Swap(&invalidation_);
129   invalidation_.Clear();
130   needs_post_commit_initialization_ = true;
131 
132   // We always need to push properties.
133   // See http://crbug.com/303943
134   needs_push_properties_ = true;
135 }
136 
AppendQuads(QuadSink * quad_sink,AppendQuadsData * append_quads_data)137 void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
138                                    AppendQuadsData* append_quads_data) {
139   DCHECK(!needs_post_commit_initialization_);
140 
141   float max_contents_scale = MaximumTilingContentsScale();
142   gfx::Transform scaled_draw_transform = draw_transform();
143   scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
144                               SK_MScalar1 / max_contents_scale);
145   gfx::Size scaled_content_bounds =
146       gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale));
147 
148   gfx::Rect scaled_visible_content_rect =
149       gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale);
150   scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
151 
152   SharedQuadState* shared_quad_state = quad_sink->CreateSharedQuadState();
153   shared_quad_state->SetAll(scaled_draw_transform,
154                             scaled_content_bounds,
155                             scaled_visible_content_rect,
156                             draw_properties().clip_rect,
157                             draw_properties().is_clipped,
158                             draw_properties().opacity,
159                             blend_mode(),
160                             sorting_context_id_);
161 
162   gfx::Rect rect = scaled_visible_content_rect;
163 
164   if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
165     AppendDebugBorderQuad(
166         quad_sink,
167         scaled_content_bounds,
168         shared_quad_state,
169         append_quads_data,
170         DebugColors::DirectPictureBorderColor(),
171         DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
172 
173     gfx::Rect geometry_rect = rect;
174     gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
175     gfx::Rect visible_geometry_rect =
176         quad_sink->UnoccludedContentRect(geometry_rect, scaled_draw_transform);
177     if (visible_geometry_rect.IsEmpty())
178       return;
179 
180     gfx::Size texture_size = rect.size();
181     gfx::RectF texture_rect = gfx::RectF(texture_size);
182     gfx::Rect quad_content_rect = rect;
183 
184     scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create();
185     quad->SetNew(shared_quad_state,
186                  geometry_rect,
187                  opaque_rect,
188                  visible_geometry_rect,
189                  texture_rect,
190                  texture_size,
191                  RGBA_8888,
192                  quad_content_rect,
193                  max_contents_scale,
194                  pile_);
195     quad_sink->Append(quad.PassAs<DrawQuad>());
196     append_quads_data->num_missing_tiles++;
197     return;
198   }
199 
200   AppendDebugBorderQuad(
201       quad_sink, scaled_content_bounds, shared_quad_state, append_quads_data);
202 
203   if (ShowDebugBorders()) {
204     for (PictureLayerTilingSet::CoverageIterator iter(
205              tilings_.get(), max_contents_scale, rect, ideal_contents_scale_);
206          iter;
207          ++iter) {
208       SkColor color;
209       float width;
210       if (*iter && iter->IsReadyToDraw()) {
211         ManagedTileState::TileVersion::Mode mode =
212             iter->GetTileVersionForDrawing().mode();
213         if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) {
214           color = DebugColors::SolidColorTileBorderColor();
215           width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
216         } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) {
217           color = DebugColors::PictureTileBorderColor();
218           width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
219         } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) {
220           color = DebugColors::HighResTileBorderColor();
221           width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
222         } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) {
223           color = DebugColors::LowResTileBorderColor();
224           width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
225         } else if (iter->contents_scale() > max_contents_scale) {
226           color = DebugColors::ExtraHighResTileBorderColor();
227           width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
228         } else {
229           color = DebugColors::ExtraLowResTileBorderColor();
230           width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
231         }
232       } else {
233         color = DebugColors::MissingTileBorderColor();
234         width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
235       }
236 
237       scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
238           DebugBorderDrawQuad::Create();
239       gfx::Rect geometry_rect = iter.geometry_rect();
240       gfx::Rect visible_geometry_rect = geometry_rect;
241       debug_border_quad->SetNew(shared_quad_state,
242                                 geometry_rect,
243                                 visible_geometry_rect,
244                                 color,
245                                 width);
246       quad_sink->Append(debug_border_quad.PassAs<DrawQuad>());
247     }
248   }
249 
250   // Keep track of the tilings that were used so that tilings that are
251   // unused can be considered for removal.
252   std::vector<PictureLayerTiling*> seen_tilings;
253 
254   // Ignore missing tiles outside of viewport for tile priority. This is
255   // normally the same as draw viewport but can be independently overridden by
256   // embedders like Android WebView with SetExternalDrawConstraints.
257   gfx::Rect scaled_viewport_for_tile_priority = gfx::ScaleToEnclosingRect(
258       GetViewportForTilePriorityInContentSpace(), max_contents_scale);
259 
260   size_t missing_tile_count = 0u;
261   size_t on_demand_missing_tile_count = 0u;
262   for (PictureLayerTilingSet::CoverageIterator iter(
263            tilings_.get(), max_contents_scale, rect, ideal_contents_scale_);
264        iter;
265        ++iter) {
266     gfx::Rect geometry_rect = iter.geometry_rect();
267     gfx::Rect visible_geometry_rect =
268         quad_sink->UnoccludedContentRect(geometry_rect, scaled_draw_transform);
269     if (visible_geometry_rect.IsEmpty())
270       continue;
271 
272     append_quads_data->visible_content_area +=
273         visible_geometry_rect.width() * visible_geometry_rect.height();
274 
275     scoped_ptr<DrawQuad> draw_quad;
276     if (*iter && iter->IsReadyToDraw()) {
277       const ManagedTileState::TileVersion& tile_version =
278           iter->GetTileVersionForDrawing();
279       switch (tile_version.mode()) {
280         case ManagedTileState::TileVersion::RESOURCE_MODE: {
281           gfx::RectF texture_rect = iter.texture_rect();
282           gfx::Rect opaque_rect = iter->opaque_rect();
283           opaque_rect.Intersect(geometry_rect);
284 
285           if (iter->contents_scale() != ideal_contents_scale_ &&
286               geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
287             append_quads_data->had_incomplete_tile = true;
288           }
289 
290           scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
291           quad->SetNew(shared_quad_state,
292                        geometry_rect,
293                        opaque_rect,
294                        visible_geometry_rect,
295                        tile_version.get_resource_id(),
296                        texture_rect,
297                        iter.texture_size(),
298                        tile_version.contents_swizzled());
299           draw_quad = quad.PassAs<DrawQuad>();
300           break;
301         }
302         case ManagedTileState::TileVersion::PICTURE_PILE_MODE: {
303           if (!layer_tree_impl()
304                    ->GetRendererCapabilities()
305                    .allow_rasterize_on_demand) {
306             ++on_demand_missing_tile_count;
307             break;
308           }
309 
310           gfx::RectF texture_rect = iter.texture_rect();
311           gfx::Rect opaque_rect = iter->opaque_rect();
312           opaque_rect.Intersect(geometry_rect);
313 
314           ResourceProvider* resource_provider =
315               layer_tree_impl()->resource_provider();
316           ResourceFormat format =
317               resource_provider->memory_efficient_texture_format();
318           scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create();
319           quad->SetNew(shared_quad_state,
320                        geometry_rect,
321                        opaque_rect,
322                        visible_geometry_rect,
323                        texture_rect,
324                        iter.texture_size(),
325                        format,
326                        iter->content_rect(),
327                        iter->contents_scale(),
328                        pile_);
329           draw_quad = quad.PassAs<DrawQuad>();
330           break;
331         }
332         case ManagedTileState::TileVersion::SOLID_COLOR_MODE: {
333           scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
334           quad->SetNew(shared_quad_state,
335                        geometry_rect,
336                        visible_geometry_rect,
337                        tile_version.get_solid_color(),
338                        false);
339           draw_quad = quad.PassAs<DrawQuad>();
340           break;
341         }
342       }
343     }
344 
345     if (!draw_quad) {
346       if (draw_checkerboard_for_missing_tiles()) {
347         scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create();
348         SkColor color = DebugColors::DefaultCheckerboardColor();
349         quad->SetNew(
350             shared_quad_state, geometry_rect, visible_geometry_rect, color);
351         quad_sink->Append(quad.PassAs<DrawQuad>());
352       } else {
353         SkColor color = SafeOpaqueBackgroundColor();
354         scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
355         quad->SetNew(shared_quad_state,
356                      geometry_rect,
357                      visible_geometry_rect,
358                      color,
359                      false);
360         quad_sink->Append(quad.PassAs<DrawQuad>());
361       }
362 
363       if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
364         append_quads_data->num_missing_tiles++;
365         append_quads_data->had_incomplete_tile = true;
366         ++missing_tile_count;
367       }
368       append_quads_data->approximated_visible_content_area +=
369           visible_geometry_rect.width() * visible_geometry_rect.height();
370       continue;
371     }
372 
373     quad_sink->Append(draw_quad.Pass());
374 
375     if (iter->priority(ACTIVE_TREE).resolution != HIGH_RESOLUTION) {
376       append_quads_data->approximated_visible_content_area +=
377           visible_geometry_rect.width() * visible_geometry_rect.height();
378     }
379 
380     if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling())
381       seen_tilings.push_back(iter.CurrentTiling());
382   }
383 
384   if (missing_tile_count) {
385     TRACE_EVENT_INSTANT2("cc",
386                          "PictureLayerImpl::AppendQuads checkerboard",
387                          TRACE_EVENT_SCOPE_THREAD,
388                          "missing_tile_count",
389                          missing_tile_count,
390                          "on_demand_missing_tile_count",
391                          on_demand_missing_tile_count);
392   }
393 
394   // Aggressively remove any tilings that are not seen to save memory. Note
395   // that this is at the expense of doing cause more frequent re-painting. A
396   // better scheme would be to maintain a tighter visible_content_rect for the
397   // finer tilings.
398   CleanUpTilingsOnActiveLayer(seen_tilings);
399 }
400 
UpdateTiles()401 void PictureLayerImpl::UpdateTiles() {
402   TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
403 
404   DoPostCommitInitializationIfNeeded();
405 
406   // Transforms and viewport are invalid for tile management inside a
407   // resourceless software draw, so don't update them.
408   if (!layer_tree_impl()->resourceless_software_draw()) {
409     visible_rect_for_tile_priority_ = visible_content_rect();
410     viewport_rect_for_tile_priority_ =
411         layer_tree_impl()->ViewportRectForTilePriority();
412     screen_space_transform_for_tile_priority_ = screen_space_transform();
413   }
414 
415   if (!CanHaveTilings()) {
416     ideal_page_scale_ = 0.f;
417     ideal_device_scale_ = 0.f;
418     ideal_contents_scale_ = 0.f;
419     ideal_source_scale_ = 0.f;
420     SanityCheckTilingState();
421     return;
422   }
423 
424   UpdateIdealScales();
425 
426   DCHECK(tilings_->num_tilings() > 0 || raster_contents_scale_ == 0.f)
427       << "A layer with no tilings shouldn't have valid raster scales";
428   if (!raster_contents_scale_ || ShouldAdjustRasterScale()) {
429     RecalculateRasterScales();
430     AddTilingsForRasterScale();
431   }
432 
433   DCHECK(raster_page_scale_);
434   DCHECK(raster_device_scale_);
435   DCHECK(raster_source_scale_);
436   DCHECK(raster_contents_scale_);
437   DCHECK(low_res_raster_contents_scale_);
438 
439   was_screen_space_transform_animating_ =
440       draw_properties().screen_space_transform_is_animating;
441 
442   // TODO(sohanjg): Avoid needlessly update priorities when syncing to a
443   // non-updated tree which will then be updated immediately afterwards.
444   should_update_tile_priorities_ = true;
445 
446   UpdateTilePriorities();
447 
448   if (layer_tree_impl()->IsPendingTree())
449     MarkVisibleResourcesAsRequired();
450 }
451 
UpdateTilePriorities()452 void PictureLayerImpl::UpdateTilePriorities() {
453   TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
454 
455   double current_frame_time_in_seconds =
456       (layer_tree_impl()->CurrentFrameTimeTicks() -
457        base::TimeTicks()).InSecondsF();
458 
459   bool tiling_needs_update = false;
460   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
461     if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime(
462             current_frame_time_in_seconds)) {
463       tiling_needs_update = true;
464       break;
465     }
466   }
467   if (!tiling_needs_update)
468     return;
469 
470   gfx::Rect visible_rect_in_content_space(
471       GetViewportForTilePriorityInContentSpace());
472   visible_rect_in_content_space.Intersect(visible_rect_for_tile_priority_);
473   gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
474       visible_rect_in_content_space, 1.f / contents_scale_x());
475   WhichTree tree =
476       layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
477   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
478     // TODO(sohanjg): Passing MaximumContentsScale as layer contents scale
479     // in UpdateTilePriorities is wrong and should be ideal contents scale.
480     tilings_->tiling_at(i)->UpdateTilePriorities(tree,
481                                                  visible_layer_rect,
482                                                  MaximumTilingContentsScale(),
483                                                  current_frame_time_in_seconds);
484   }
485 
486   // Tile priorities were modified.
487   layer_tree_impl()->DidModifyTilePriorities();
488 }
489 
GetViewportForTilePriorityInContentSpace() const490 gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
491   // If visible_rect_for_tile_priority_ is empty or
492   // viewport_rect_for_tile_priority_ is set to be different from the device
493   // viewport, try to inverse project the viewport into layer space and use
494   // that. Otherwise just use visible_rect_for_tile_priority_
495   gfx::Rect visible_rect_in_content_space = visible_rect_for_tile_priority_;
496 
497   if (visible_rect_in_content_space.IsEmpty() ||
498       layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority_) {
499     gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
500 
501     if (screen_space_transform_for_tile_priority_.GetInverse(&view_to_layer)) {
502       // Transform from view space to content space.
503       visible_rect_in_content_space =
504           gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
505               view_to_layer, viewport_rect_for_tile_priority_));
506 
507       visible_rect_in_content_space.Intersect(gfx::Rect(content_bounds()));
508     }
509   }
510 
511   return visible_rect_in_content_space;
512 }
513 
GetRecycledTwinLayer()514 PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() {
515   // TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418
516   return static_cast<PictureLayerImpl*>(
517       layer_tree_impl()->FindRecycleTreeLayerById(id()));
518 }
519 
NotifyTileStateChanged(const Tile * tile)520 void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
521   if (layer_tree_impl()->IsActiveTree()) {
522     gfx::RectF layer_damage_rect =
523         gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale());
524     AddDamageRect(layer_damage_rect);
525   }
526 }
527 
DidBecomeActive()528 void PictureLayerImpl::DidBecomeActive() {
529   LayerImpl::DidBecomeActive();
530   tilings_->DidBecomeActive();
531   layer_tree_impl()->DidModifyTilePriorities();
532 }
533 
DidBeginTracing()534 void PictureLayerImpl::DidBeginTracing() {
535   pile_->DidBeginTracing();
536 }
537 
ReleaseResources()538 void PictureLayerImpl::ReleaseResources() {
539   if (tilings_)
540     RemoveAllTilings();
541 
542   ResetRasterScale();
543 
544   // To avoid an edge case after lost context where the tree is up to date but
545   // the tilings have not been managed, request an update draw properties
546   // to force tilings to get managed.
547   layer_tree_impl()->set_needs_update_draw_properties();
548 }
549 
GetPicture()550 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
551   return pile_->GetFlattenedPicture();
552 }
553 
CreateTile(PictureLayerTiling * tiling,const gfx::Rect & content_rect)554 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
555                                                const gfx::Rect& content_rect) {
556   if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
557     return scoped_refptr<Tile>();
558 
559   // TODO(vmpstr): Revisit this. For now, enabling analysis means that we get as
560   // much savings on memory as we can. However, for some cases like ganesh or
561   // small layers, the amount of time we spend analyzing might not justify
562   // memory savings that we can get.
563   // Bugs: crbug.com/397198, crbug.com/396908
564   int flags = Tile::USE_PICTURE_ANALYSIS;
565 
566   return layer_tree_impl()->tile_manager()->CreateTile(
567       pile_.get(),
568       content_rect.size(),
569       content_rect,
570       contents_opaque() ? content_rect : gfx::Rect(),
571       tiling->contents_scale(),
572       id(),
573       layer_tree_impl()->source_frame_number(),
574       flags);
575 }
576 
UpdatePile(Tile * tile)577 void PictureLayerImpl::UpdatePile(Tile* tile) {
578   tile->set_picture_pile(pile_);
579 }
580 
GetInvalidation()581 const Region* PictureLayerImpl::GetInvalidation() {
582   return &invalidation_;
583 }
584 
GetTwinTiling(const PictureLayerTiling * tiling) const585 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
586     const PictureLayerTiling* tiling) const {
587   if (!twin_layer_)
588     return NULL;
589   for (size_t i = 0; i < twin_layer_->tilings_->num_tilings(); ++i)
590     if (twin_layer_->tilings_->tiling_at(i)->contents_scale() ==
591         tiling->contents_scale())
592       return twin_layer_->tilings_->tiling_at(i);
593   return NULL;
594 }
595 
GetRecycledTwinTiling(const PictureLayerTiling * tiling)596 PictureLayerTiling* PictureLayerImpl::GetRecycledTwinTiling(
597     const PictureLayerTiling* tiling) {
598   PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
599   if (!recycled_twin || !recycled_twin->tilings_)
600     return NULL;
601   return recycled_twin->tilings_->TilingAtScale(tiling->contents_scale());
602 }
603 
GetMaxTilesForInterestArea() const604 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
605   return layer_tree_impl()->settings().max_tiles_for_interest_area;
606 }
607 
GetSkewportTargetTimeInSeconds() const608 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
609   float skewport_target_time_in_frames =
610       layer_tree_impl()->use_gpu_rasterization()
611           ? kGpuSkewportTargetTimeInFrames
612           : kCpuSkewportTargetTimeInFrames;
613   return skewport_target_time_in_frames *
614          layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
615          layer_tree_impl()->settings().skewport_target_time_multiplier;
616 }
617 
GetSkewportExtrapolationLimitInContentPixels() const618 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
619   return layer_tree_impl()
620       ->settings()
621       .skewport_extrapolation_limit_in_content_pixels;
622 }
623 
CalculateTileSize(const gfx::Size & content_bounds) const624 gfx::Size PictureLayerImpl::CalculateTileSize(
625     const gfx::Size& content_bounds) const {
626   if (is_mask_) {
627     int max_size = layer_tree_impl()->MaxTextureSize();
628     return gfx::Size(
629         std::min(max_size, content_bounds.width()),
630         std::min(max_size, content_bounds.height()));
631   }
632 
633   int max_texture_size =
634       layer_tree_impl()->resource_provider()->max_texture_size();
635 
636   gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size;
637   if (layer_tree_impl()->use_gpu_rasterization()) {
638     // TODO(ernstm) crbug.com/365877: We need a unified way to override the
639     // default-tile-size.
640     default_tile_size =
641         gfx::Size(layer_tree_impl()->device_viewport_size().width(),
642                   layer_tree_impl()->device_viewport_size().height() / 4);
643   }
644   default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size));
645 
646   gfx::Size max_untiled_content_size =
647       layer_tree_impl()->settings().max_untiled_layer_size;
648   max_untiled_content_size.SetToMin(
649       gfx::Size(max_texture_size, max_texture_size));
650 
651   bool any_dimension_too_large =
652       content_bounds.width() > max_untiled_content_size.width() ||
653       content_bounds.height() > max_untiled_content_size.height();
654 
655   bool any_dimension_one_tile =
656       content_bounds.width() <= default_tile_size.width() ||
657       content_bounds.height() <= default_tile_size.height();
658 
659   // If long and skinny, tile at the max untiled content size, and clamp
660   // the smaller dimension to the content size, e.g. 1000x12 layer with
661   // 500x500 max untiled size would get 500x12 tiles.  Also do this
662   // if the layer is small.
663   if (any_dimension_one_tile || !any_dimension_too_large) {
664     int width = std::min(
665         std::max(max_untiled_content_size.width(), default_tile_size.width()),
666         content_bounds.width());
667     int height = std::min(
668         std::max(max_untiled_content_size.height(), default_tile_size.height()),
669         content_bounds.height());
670     // Round width and height up to the closest multiple of 64, or 56 if
671     // we should avoid power-of-two textures. This helps reduce the number
672     // of different textures sizes to help recycling, and also keeps all
673     // textures multiple-of-eight, which is preferred on some drivers (IMG).
674     bool avoid_pow2 =
675         layer_tree_impl()->GetRendererCapabilities().avoid_pow2_textures;
676     int round_up_to = avoid_pow2 ? 56 : 64;
677     width = RoundUp(width, round_up_to);
678     height = RoundUp(height, round_up_to);
679     return gfx::Size(width, height);
680   }
681 
682   return default_tile_size;
683 }
684 
SyncFromActiveLayer(const PictureLayerImpl * other)685 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
686   TRACE_EVENT0("cc", "SyncFromActiveLayer");
687   DCHECK(!other->needs_post_commit_initialization_);
688   DCHECK(other->tilings_);
689 
690   if (!DrawsContent()) {
691     RemoveAllTilings();
692     return;
693   }
694 
695   raster_page_scale_ = other->raster_page_scale_;
696   raster_device_scale_ = other->raster_device_scale_;
697   raster_source_scale_ = other->raster_source_scale_;
698   raster_contents_scale_ = other->raster_contents_scale_;
699   low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
700 
701   // Union in the other newly exposed regions as invalid.
702   Region difference_region = Region(gfx::Rect(bounds()));
703   difference_region.Subtract(gfx::Rect(other->bounds()));
704   invalidation_.Union(difference_region);
705 
706   bool synced_high_res_tiling = false;
707   if (CanHaveTilings()) {
708     synced_high_res_tiling = tilings_->SyncTilings(
709         *other->tilings_, bounds(), invalidation_, MinimumContentsScale());
710   } else {
711     RemoveAllTilings();
712   }
713 
714   // If our MinimumContentsScale has changed to prevent the twin's high res
715   // tiling from being synced, we should reset the raster scale and let it be
716   // recalculated (1) again. This can happen if our bounds shrink to the point
717   // where min contents scale grows.
718   // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
719   // should refactor this code a little bit and actually recalculate this.
720   // However, this is a larger undertaking, so this will work for now.
721   if (!synced_high_res_tiling)
722     ResetRasterScale();
723   else
724     SanityCheckTilingState();
725 }
726 
SyncTiling(const PictureLayerTiling * tiling)727 void PictureLayerImpl::SyncTiling(
728     const PictureLayerTiling* tiling) {
729   if (!CanHaveTilingWithScale(tiling->contents_scale()))
730     return;
731   tilings_->AddTiling(tiling->contents_scale());
732 
733   // If this tree needs update draw properties, then the tiling will
734   // get updated prior to drawing or activation.  If this tree does not
735   // need update draw properties, then its transforms are up to date and
736   // we can create tiles for this tiling immediately.
737   if (!layer_tree_impl()->needs_update_draw_properties() &&
738       should_update_tile_priorities_) {
739     UpdateTilePriorities();
740   }
741 }
742 
SetIsMask(bool is_mask)743 void PictureLayerImpl::SetIsMask(bool is_mask) {
744   if (is_mask_ == is_mask)
745     return;
746   is_mask_ = is_mask;
747   if (tilings_)
748     tilings_->RemoveAllTiles();
749 }
750 
ContentsResourceId() const751 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
752   gfx::Rect content_rect(content_bounds());
753   float scale = MaximumTilingContentsScale();
754   PictureLayerTilingSet::CoverageIterator iter(
755       tilings_.get(), scale, content_rect, ideal_contents_scale_);
756 
757   // Mask resource not ready yet.
758   if (!iter || !*iter)
759     return 0;
760 
761   // Masks only supported if they fit on exactly one tile.
762   if (iter.geometry_rect() != content_rect)
763     return 0;
764 
765   const ManagedTileState::TileVersion& tile_version =
766       iter->GetTileVersionForDrawing();
767   if (!tile_version.IsReadyToDraw() ||
768       tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE)
769     return 0;
770 
771   return tile_version.get_resource_id();
772 }
773 
MarkVisibleResourcesAsRequired() const774 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
775   DCHECK(layer_tree_impl()->IsPendingTree());
776   DCHECK(ideal_contents_scale_);
777   DCHECK_GT(tilings_->num_tilings(), 0u);
778 
779   // The goal of this function is to find the minimum set of tiles that need to
780   // be ready to draw in order to activate without flashing content from a
781   // higher res on the active tree to a lower res on the pending tree.
782 
783   // First, early out for layers with no visible content.
784   if (visible_rect_for_tile_priority_.IsEmpty())
785     return;
786 
787   gfx::Rect rect(visible_rect_for_tile_priority_);
788 
789   // Only mark tiles inside the viewport for tile priority as required for
790   // activation. This viewport is normally the same as the draw viewport but
791   // can be independently overridden by embedders like Android WebView with
792   // SetExternalDrawConstraints.
793   rect.Intersect(GetViewportForTilePriorityInContentSpace());
794 
795   float min_acceptable_scale =
796       std::min(raster_contents_scale_, ideal_contents_scale_);
797 
798   if (PictureLayerImpl* twin = twin_layer_) {
799     float twin_min_acceptable_scale =
800         std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_);
801     // Ignore 0 scale in case CalculateContentsScale() has never been
802     // called for active twin.
803     if (twin_min_acceptable_scale != 0.0f) {
804       min_acceptable_scale =
805           std::min(min_acceptable_scale, twin_min_acceptable_scale);
806     }
807   }
808 
809   PictureLayerTiling* high_res = NULL;
810   PictureLayerTiling* low_res = NULL;
811 
812   // First pass: ready to draw tiles in acceptable but non-ideal tilings are
813   // marked as required for activation so that their textures are not thrown
814   // away; any non-ready tiles are not marked as required.
815   Region missing_region = rect;
816   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
817     PictureLayerTiling* tiling = tilings_->tiling_at(i);
818     DCHECK(tiling->has_ever_been_updated());
819 
820     if (tiling->resolution() == LOW_RESOLUTION) {
821       DCHECK(!low_res) << "There can only be one low res tiling";
822       low_res = tiling;
823     }
824     if (tiling->contents_scale() < min_acceptable_scale)
825       continue;
826     if (tiling->resolution() == HIGH_RESOLUTION) {
827       DCHECK(!high_res) << "There can only be one high res tiling";
828       high_res = tiling;
829       continue;
830     }
831     for (PictureLayerTiling::CoverageIterator iter(tiling,
832                                                    contents_scale_x(),
833                                                    rect);
834          iter;
835          ++iter) {
836       if (!*iter || !iter->IsReadyToDraw())
837         continue;
838 
839       missing_region.Subtract(iter.geometry_rect());
840       iter->MarkRequiredForActivation();
841     }
842   }
843   DCHECK(high_res) << "There must be one high res tiling";
844 
845   // If these pointers are null (because no twin, no matching tiling, or the
846   // simpification just below), then high res tiles will be required to fill any
847   // holes left by the first pass above.  If the pointers are valid, then this
848   // layer is allowed to skip any tiles that are not ready on its twin.
849   const PictureLayerTiling* twin_high_res = NULL;
850   const PictureLayerTiling* twin_low_res = NULL;
851 
852   if (twin_layer_) {
853     // As a simplification, only allow activating to skip twin tiles that the
854     // active layer is also missing when both this layer and its twin have
855     // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high
856     // res tiling. This avoids having to iterate/track coverage of non-ideal
857     // tilings during the last draw call on the active layer.
858     if (tilings_->num_tilings() <= 2 &&
859         twin_layer_->tilings_->num_tilings() <= tilings_->num_tilings()) {
860       twin_low_res = low_res ? GetTwinTiling(low_res) : NULL;
861       twin_high_res = high_res ? GetTwinTiling(high_res) : NULL;
862     }
863 
864     // If this layer and its twin have different transforms, then don't compare
865     // them and only allow activating to high res tiles, since tiles on each
866     // layer will be in different places on screen.
867     if (twin_layer_->layer_tree_impl()->RequiresHighResToDraw() ||
868         bounds() != twin_layer_->bounds() ||
869         draw_properties().screen_space_transform !=
870             twin_layer_->draw_properties().screen_space_transform) {
871       twin_high_res = NULL;
872       twin_low_res = NULL;
873     }
874   }
875 
876   // As a second pass, mark as required any visible high res tiles not filled in
877   // by acceptable non-ideal tiles from the first pass.
878   if (MarkVisibleTilesAsRequired(
879       high_res, twin_high_res, contents_scale_x(), rect, missing_region)) {
880     // As an optional third pass, if a high res tile was skipped because its
881     // twin was also missing, then fall back to mark low res tiles as required
882     // in case the active twin is substituting those for missing high res
883     // content. Only suitable, when low res is enabled.
884     if (low_res) {
885       MarkVisibleTilesAsRequired(
886           low_res, twin_low_res, contents_scale_x(), rect, missing_region);
887     }
888   }
889 }
890 
MarkVisibleTilesAsRequired(PictureLayerTiling * tiling,const PictureLayerTiling * optional_twin_tiling,float contents_scale,const gfx::Rect & rect,const Region & missing_region) const891 bool PictureLayerImpl::MarkVisibleTilesAsRequired(
892     PictureLayerTiling* tiling,
893     const PictureLayerTiling* optional_twin_tiling,
894     float contents_scale,
895     const gfx::Rect& rect,
896     const Region& missing_region) const {
897   bool twin_had_missing_tile = false;
898   for (PictureLayerTiling::CoverageIterator iter(tiling,
899                                                  contents_scale,
900                                                  rect);
901        iter;
902        ++iter) {
903     Tile* tile = *iter;
904     // A null tile (i.e. missing recording) can just be skipped.
905     if (!tile)
906       continue;
907 
908     // If the missing region doesn't cover it, this tile is fully
909     // covered by acceptable tiles at other scales.
910     if (!missing_region.Intersects(iter.geometry_rect()))
911       continue;
912 
913     // If the twin tile doesn't exist (i.e. missing recording or so far away
914     // that it is outside the visible tile rect) or this tile is shared between
915     // with the twin, then this tile isn't required to prevent flashing.
916     if (optional_twin_tiling) {
917       Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j());
918       if (!twin_tile || twin_tile == tile) {
919         twin_had_missing_tile = true;
920         continue;
921       }
922     }
923 
924     tile->MarkRequiredForActivation();
925   }
926   return twin_had_missing_tile;
927 }
928 
DoPostCommitInitialization()929 void PictureLayerImpl::DoPostCommitInitialization() {
930   DCHECK(needs_post_commit_initialization_);
931   DCHECK(layer_tree_impl()->IsPendingTree());
932 
933   if (!tilings_)
934     tilings_.reset(new PictureLayerTilingSet(this, bounds()));
935 
936   DCHECK(!twin_layer_);
937   twin_layer_ = static_cast<PictureLayerImpl*>(
938       layer_tree_impl()->FindActiveTreeLayerById(id()));
939   if (twin_layer_) {
940     DCHECK(!twin_layer_->twin_layer_);
941     twin_layer_->twin_layer_ = this;
942     // If the twin has never been pushed to, do not sync from it.
943     // This can happen if this function is called during activation.
944     if (!twin_layer_->needs_post_commit_initialization_)
945       SyncFromActiveLayer(twin_layer_);
946   }
947 
948   needs_post_commit_initialization_ = false;
949 }
950 
AddTiling(float contents_scale)951 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
952   DCHECK(CanHaveTilingWithScale(contents_scale)) <<
953       "contents_scale: " << contents_scale;
954 
955   PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
956 
957   DCHECK(pile_->HasRecordings());
958 
959   if (twin_layer_)
960     twin_layer_->SyncTiling(tiling);
961 
962   return tiling;
963 }
964 
RemoveTiling(float contents_scale)965 void PictureLayerImpl::RemoveTiling(float contents_scale) {
966   if (!tilings_ || tilings_->num_tilings() == 0)
967     return;
968 
969   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
970     PictureLayerTiling* tiling = tilings_->tiling_at(i);
971     if (tiling->contents_scale() == contents_scale) {
972       tilings_->Remove(tiling);
973       break;
974     }
975   }
976   if (tilings_->num_tilings() == 0)
977     ResetRasterScale();
978   SanityCheckTilingState();
979 }
980 
RemoveAllTilings()981 void PictureLayerImpl::RemoveAllTilings() {
982   if (tilings_)
983     tilings_->RemoveAllTilings();
984   // If there are no tilings, then raster scales are no longer meaningful.
985   ResetRasterScale();
986 }
987 
988 namespace {
989 
PositiveRatio(float float1,float float2)990 inline float PositiveRatio(float float1, float float2) {
991   DCHECK_GT(float1, 0);
992   DCHECK_GT(float2, 0);
993   return float1 > float2 ? float1 / float2 : float2 / float1;
994 }
995 
996 }  // namespace
997 
AddTilingsForRasterScale()998 void PictureLayerImpl::AddTilingsForRasterScale() {
999   PictureLayerTiling* high_res = NULL;
1000   PictureLayerTiling* low_res = NULL;
1001 
1002   PictureLayerTiling* previous_low_res = NULL;
1003   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1004     PictureLayerTiling* tiling = tilings_->tiling_at(i);
1005     if (tiling->contents_scale() == raster_contents_scale_)
1006       high_res = tiling;
1007     if (tiling->contents_scale() == low_res_raster_contents_scale_)
1008       low_res = tiling;
1009     if (tiling->resolution() == LOW_RESOLUTION)
1010       previous_low_res = tiling;
1011 
1012     // Reset all tilings to non-ideal until the end of this function.
1013     tiling->set_resolution(NON_IDEAL_RESOLUTION);
1014   }
1015 
1016   if (!high_res) {
1017     high_res = AddTiling(raster_contents_scale_);
1018     if (raster_contents_scale_ == low_res_raster_contents_scale_)
1019       low_res = high_res;
1020   }
1021 
1022   // Only create new low res tilings when the transform is static.  This
1023   // prevents wastefully creating a paired low res tiling for every new high res
1024   // tiling during a pinch or a CSS animation.
1025   bool is_pinching = layer_tree_impl()->PinchGestureActive();
1026   if (layer_tree_impl()->create_low_res_tiling() && !is_pinching &&
1027       !draw_properties().screen_space_transform_is_animating && !low_res &&
1028       low_res != high_res)
1029     low_res = AddTiling(low_res_raster_contents_scale_);
1030 
1031   // Set low-res if we have one.
1032   if (!low_res)
1033     low_res = previous_low_res;
1034   if (low_res && low_res != high_res)
1035     low_res->set_resolution(LOW_RESOLUTION);
1036 
1037   // Make sure we always have one high-res (even if high == low).
1038   high_res->set_resolution(HIGH_RESOLUTION);
1039 
1040   SanityCheckTilingState();
1041 }
1042 
ShouldAdjustRasterScale() const1043 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
1044   if (was_screen_space_transform_animating_ !=
1045       draw_properties().screen_space_transform_is_animating)
1046     return true;
1047 
1048   bool is_pinching = layer_tree_impl()->PinchGestureActive();
1049   if (is_pinching && raster_page_scale_) {
1050     // We change our raster scale when it is:
1051     // - Higher than ideal (need a lower-res tiling available)
1052     // - Too far from ideal (need a higher-res tiling available)
1053     float ratio = ideal_page_scale_ / raster_page_scale_;
1054     if (raster_page_scale_ > ideal_page_scale_ ||
1055         ratio > kMaxScaleRatioDuringPinch)
1056       return true;
1057   }
1058 
1059   if (!is_pinching) {
1060     // When not pinching, match the ideal page scale factor.
1061     if (raster_page_scale_ != ideal_page_scale_)
1062       return true;
1063   }
1064 
1065   // Always match the ideal device scale factor.
1066   if (raster_device_scale_ != ideal_device_scale_)
1067     return true;
1068 
1069   // When the source scale changes we want to match it, but not when animating
1070   // or when we've fixed the scale in place.
1071   if (!draw_properties().screen_space_transform_is_animating &&
1072       !raster_source_scale_is_fixed_ &&
1073       raster_source_scale_ != ideal_source_scale_)
1074     return true;
1075 
1076   return false;
1077 }
1078 
SnappedContentsScale(float scale)1079 float PictureLayerImpl::SnappedContentsScale(float scale) {
1080   // If a tiling exists within the max snapping ratio, snap to its scale.
1081   float snapped_contents_scale = scale;
1082   float snapped_ratio = kSnapToExistingTilingRatio;
1083   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1084     float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
1085     float ratio = PositiveRatio(tiling_contents_scale, scale);
1086     if (ratio < snapped_ratio) {
1087       snapped_contents_scale = tiling_contents_scale;
1088       snapped_ratio = ratio;
1089     }
1090   }
1091   return snapped_contents_scale;
1092 }
1093 
RecalculateRasterScales()1094 void PictureLayerImpl::RecalculateRasterScales() {
1095   float old_raster_contents_scale = raster_contents_scale_;
1096   float old_raster_page_scale = raster_page_scale_;
1097   float old_raster_source_scale = raster_source_scale_;
1098 
1099   raster_device_scale_ = ideal_device_scale_;
1100   raster_page_scale_ = ideal_page_scale_;
1101   raster_source_scale_ = ideal_source_scale_;
1102   raster_contents_scale_ = ideal_contents_scale_;
1103 
1104   // If we're not animating, or leaving an animation, and the
1105   // ideal_source_scale_ changes, then things are unpredictable, and we fix
1106   // the raster_source_scale_ in place.
1107   if (old_raster_source_scale &&
1108       !draw_properties().screen_space_transform_is_animating &&
1109       !was_screen_space_transform_animating_ &&
1110       old_raster_source_scale != ideal_source_scale_)
1111     raster_source_scale_is_fixed_ = true;
1112 
1113   // TODO(danakj): Adjust raster source scale closer to ideal source scale at
1114   // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
1115   // tree. This will allow CSS scale changes to get re-rastered at an
1116   // appropriate rate.
1117   if (raster_source_scale_is_fixed_) {
1118     raster_contents_scale_ /= raster_source_scale_;
1119     raster_source_scale_ = 1.f;
1120   }
1121 
1122   // During pinch we completely ignore the current ideal scale, and just use
1123   // a multiple of the previous scale.
1124   // TODO(danakj): This seems crazy, we should use the current ideal, no?
1125   bool is_pinching = layer_tree_impl()->PinchGestureActive();
1126   if (is_pinching && old_raster_contents_scale) {
1127     // See ShouldAdjustRasterScale:
1128     // - When zooming out, preemptively create new tiling at lower resolution.
1129     // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1130     bool zooming_out = old_raster_page_scale > ideal_page_scale_;
1131     float desired_contents_scale =
1132         zooming_out ? old_raster_contents_scale / kMaxScaleRatioDuringPinch
1133                     : old_raster_contents_scale * kMaxScaleRatioDuringPinch;
1134     raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
1135     raster_page_scale_ =
1136         raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
1137   }
1138 
1139   raster_contents_scale_ =
1140       std::max(raster_contents_scale_, MinimumContentsScale());
1141 
1142   // Since we're not re-rasterizing during animation, rasterize at the maximum
1143   // scale that will occur during the animation, if the maximum scale is
1144   // known. However, to avoid excessive memory use, don't rasterize at a scale
1145   // at which this layer would become larger than the viewport.
1146   if (draw_properties().screen_space_transform_is_animating) {
1147     bool can_raster_at_maximum_scale = false;
1148     if (draw_properties().maximum_animation_contents_scale > 0.f) {
1149       gfx::Size bounds_at_maximum_scale = gfx::ToCeiledSize(gfx::ScaleSize(
1150           bounds(), draw_properties().maximum_animation_contents_scale));
1151       if (bounds_at_maximum_scale.GetArea() <=
1152           layer_tree_impl()->device_viewport_size().GetArea())
1153         can_raster_at_maximum_scale = true;
1154     }
1155     if (can_raster_at_maximum_scale) {
1156       raster_contents_scale_ =
1157           std::max(raster_contents_scale_,
1158                    draw_properties().maximum_animation_contents_scale);
1159     } else {
1160       raster_contents_scale_ =
1161           std::max(raster_contents_scale_,
1162                    1.f * ideal_page_scale_ * ideal_device_scale_);
1163     }
1164   }
1165 
1166   // If this layer would only create one tile at this content scale,
1167   // don't create a low res tiling.
1168   gfx::Size content_bounds =
1169       gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
1170   gfx::Size tile_size = CalculateTileSize(content_bounds);
1171   if (tile_size.width() >= content_bounds.width() &&
1172       tile_size.height() >= content_bounds.height()) {
1173     low_res_raster_contents_scale_ = raster_contents_scale_;
1174     return;
1175   }
1176 
1177   float low_res_factor =
1178       layer_tree_impl()->settings().low_res_contents_scale_factor;
1179   low_res_raster_contents_scale_ = std::max(
1180       raster_contents_scale_ * low_res_factor,
1181       MinimumContentsScale());
1182 }
1183 
CleanUpTilingsOnActiveLayer(std::vector<PictureLayerTiling * > used_tilings)1184 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1185     std::vector<PictureLayerTiling*> used_tilings) {
1186   DCHECK(layer_tree_impl()->IsActiveTree());
1187   if (tilings_->num_tilings() == 0)
1188     return;
1189 
1190   float min_acceptable_high_res_scale = std::min(
1191       raster_contents_scale_, ideal_contents_scale_);
1192   float max_acceptable_high_res_scale = std::max(
1193       raster_contents_scale_, ideal_contents_scale_);
1194   float twin_low_res_scale = 0.f;
1195 
1196   PictureLayerImpl* twin = twin_layer_;
1197   if (twin && twin->CanHaveTilings()) {
1198     min_acceptable_high_res_scale = std::min(
1199         min_acceptable_high_res_scale,
1200         std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1201     max_acceptable_high_res_scale = std::max(
1202         max_acceptable_high_res_scale,
1203         std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1204 
1205     for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) {
1206       PictureLayerTiling* tiling = twin->tilings_->tiling_at(i);
1207       if (tiling->resolution() == LOW_RESOLUTION)
1208         twin_low_res_scale = tiling->contents_scale();
1209     }
1210   }
1211 
1212   std::vector<PictureLayerTiling*> to_remove;
1213   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1214     PictureLayerTiling* tiling = tilings_->tiling_at(i);
1215 
1216     // Keep multiple high resolution tilings even if not used to help
1217     // activate earlier at non-ideal resolutions.
1218     if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
1219         tiling->contents_scale() <= max_acceptable_high_res_scale)
1220       continue;
1221 
1222     // Keep low resolution tilings, if the layer should have them.
1223     if (layer_tree_impl()->create_low_res_tiling()) {
1224       if (tiling->resolution() == LOW_RESOLUTION ||
1225           tiling->contents_scale() == twin_low_res_scale)
1226         continue;
1227     }
1228 
1229     // Don't remove tilings that are being used (and thus would cause a flash.)
1230     if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
1231         used_tilings.end())
1232       continue;
1233 
1234     to_remove.push_back(tiling);
1235   }
1236 
1237   if (to_remove.empty())
1238     return;
1239 
1240   PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
1241   // Remove tilings on this tree and the twin tree.
1242   for (size_t i = 0; i < to_remove.size(); ++i) {
1243     const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
1244     // Only remove tilings from the twin layer if they have
1245     // NON_IDEAL_RESOLUTION.
1246     if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
1247       twin->RemoveTiling(to_remove[i]->contents_scale());
1248     // Remove the tiling from the recycle tree. Note that we ignore resolution,
1249     // since we don't need to maintain high/low res on the recycle tree.
1250     if (recycled_twin)
1251       recycled_twin->RemoveTiling(to_remove[i]->contents_scale());
1252     // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
1253     CHECK_NE(HIGH_RESOLUTION, to_remove[i]->resolution());
1254     tilings_->Remove(to_remove[i]);
1255   }
1256 
1257   DCHECK_GT(tilings_->num_tilings(), 0u);
1258   SanityCheckTilingState();
1259 }
1260 
MinimumContentsScale() const1261 float PictureLayerImpl::MinimumContentsScale() const {
1262   float setting_min = layer_tree_impl()->settings().minimum_contents_scale;
1263 
1264   // If the contents scale is less than 1 / width (also for height),
1265   // then it will end up having less than one pixel of content in that
1266   // dimension.  Bump the minimum contents scale up in this case to prevent
1267   // this from happening.
1268   int min_dimension = std::min(bounds().width(), bounds().height());
1269   if (!min_dimension)
1270     return setting_min;
1271 
1272   return std::max(1.f / min_dimension, setting_min);
1273 }
1274 
ResetRasterScale()1275 void PictureLayerImpl::ResetRasterScale() {
1276   raster_page_scale_ = 0.f;
1277   raster_device_scale_ = 0.f;
1278   raster_source_scale_ = 0.f;
1279   raster_contents_scale_ = 0.f;
1280   low_res_raster_contents_scale_ = 0.f;
1281   raster_source_scale_is_fixed_ = false;
1282 
1283   // When raster scales aren't valid, don't update tile priorities until
1284   // this layer has been updated via UpdateDrawProperties.
1285   should_update_tile_priorities_ = false;
1286 }
1287 
CanHaveTilings() const1288 bool PictureLayerImpl::CanHaveTilings() const {
1289   if (!DrawsContent())
1290     return false;
1291   if (!pile_->HasRecordings())
1292     return false;
1293   return true;
1294 }
1295 
CanHaveTilingWithScale(float contents_scale) const1296 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const {
1297   if (!CanHaveTilings())
1298     return false;
1299   if (contents_scale < MinimumContentsScale())
1300     return false;
1301   return true;
1302 }
1303 
SanityCheckTilingState() const1304 void PictureLayerImpl::SanityCheckTilingState() const {
1305 #if DCHECK_IS_ON
1306   // Recycle tree doesn't have any restrictions.
1307   if (layer_tree_impl()->IsRecycleTree())
1308     return;
1309 
1310   if (!CanHaveTilings()) {
1311     DCHECK_EQ(0u, tilings_->num_tilings());
1312     return;
1313   }
1314   if (tilings_->num_tilings() == 0)
1315     return;
1316 
1317   // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
1318   // tiling to mark its tiles as being required for activation.
1319   DCHECK_EQ(1, tilings_->NumHighResTilings());
1320 #endif
1321 }
1322 
MaximumTilingContentsScale() const1323 float PictureLayerImpl::MaximumTilingContentsScale() const {
1324   float max_contents_scale = MinimumContentsScale();
1325   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1326     const PictureLayerTiling* tiling = tilings_->tiling_at(i);
1327     max_contents_scale = std::max(max_contents_scale, tiling->contents_scale());
1328   }
1329   return max_contents_scale;
1330 }
1331 
UpdateIdealScales()1332 void PictureLayerImpl::UpdateIdealScales() {
1333   DCHECK(CanHaveTilings());
1334 
1335   float min_contents_scale = MinimumContentsScale();
1336   DCHECK_GT(min_contents_scale, 0.f);
1337   float min_page_scale = layer_tree_impl()->min_page_scale_factor();
1338   DCHECK_GT(min_page_scale, 0.f);
1339   float min_device_scale = 1.f;
1340   float min_source_scale =
1341       min_contents_scale / min_page_scale / min_device_scale;
1342 
1343   float ideal_page_scale = draw_properties().page_scale_factor;
1344   float ideal_device_scale = draw_properties().device_scale_factor;
1345   float ideal_source_scale = draw_properties().ideal_contents_scale /
1346                              ideal_page_scale / ideal_device_scale;
1347   ideal_contents_scale_ =
1348       std::max(draw_properties().ideal_contents_scale, min_contents_scale);
1349   ideal_page_scale_ = draw_properties().page_scale_factor;
1350   ideal_device_scale_ = draw_properties().device_scale_factor;
1351   ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
1352 }
1353 
GetDebugBorderProperties(SkColor * color,float * width) const1354 void PictureLayerImpl::GetDebugBorderProperties(
1355     SkColor* color,
1356     float* width) const {
1357   *color = DebugColors::TiledContentLayerBorderColor();
1358   *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1359 }
1360 
GetAllTilesForTracing(std::set<const Tile * > * tiles) const1361 void PictureLayerImpl::GetAllTilesForTracing(
1362     std::set<const Tile*>* tiles) const {
1363   if (!tilings_)
1364     return;
1365 
1366   for (size_t i = 0; i < tilings_->num_tilings(); ++i)
1367     tilings_->tiling_at(i)->GetAllTilesForTracing(tiles);
1368 }
1369 
AsValueInto(base::DictionaryValue * state) const1370 void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
1371   const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1372   LayerImpl::AsValueInto(state);
1373   state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1374   state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1375   state->Set("tilings", tilings_->AsValue().release());
1376   state->Set("pictures", pile_->AsValue().release());
1377   state->Set("invalidation", invalidation_.AsValue().release());
1378 
1379   scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue);
1380   for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
1381                                                     contents_scale_x(),
1382                                                     gfx::Rect(content_bounds()),
1383                                                     ideal_contents_scale_);
1384        iter;
1385        ++iter) {
1386     scoped_ptr<base::DictionaryValue> tile_data(new base::DictionaryValue);
1387     tile_data->Set("geometry_rect",
1388                    MathUtil::AsValue(iter.geometry_rect()).release());
1389     if (*iter)
1390       tile_data->Set("tile", TracedValue::CreateIDRef(*iter).release());
1391 
1392     coverage_tiles->Append(tile_data.release());
1393   }
1394   state->Set("coverage_tiles", coverage_tiles.release());
1395 }
1396 
GPUMemoryUsageInBytes() const1397 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1398   const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1399   return tilings_->GPUMemoryUsageInBytes();
1400 }
1401 
RunMicroBenchmark(MicroBenchmarkImpl * benchmark)1402 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1403   benchmark->RunOnLayer(this);
1404 }
1405 
GetTree() const1406 WhichTree PictureLayerImpl::GetTree() const {
1407   return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1408 }
1409 
IsOnActiveOrPendingTree() const1410 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1411   return !layer_tree_impl()->IsRecycleTree();
1412 }
1413 
HasValidTilePriorities() const1414 bool PictureLayerImpl::HasValidTilePriorities() const {
1415   return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1416 }
1417 
AllTilesRequiredForActivationAreReadyToDraw() const1418 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1419   if (!layer_tree_impl()->IsPendingTree())
1420     return true;
1421 
1422   if (!HasValidTilePriorities())
1423     return true;
1424 
1425   if (!tilings_)
1426     return true;
1427 
1428   if (visible_rect_for_tile_priority_.IsEmpty())
1429     return true;
1430 
1431   for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1432     PictureLayerTiling* tiling = tilings_->tiling_at(i);
1433     if (tiling->resolution() != HIGH_RESOLUTION &&
1434         tiling->resolution() != LOW_RESOLUTION)
1435       continue;
1436 
1437     gfx::Rect rect(visible_rect_for_tile_priority_);
1438     for (PictureLayerTiling::CoverageIterator iter(
1439              tiling, contents_scale_x(), rect);
1440          iter;
1441          ++iter) {
1442       const Tile* tile = *iter;
1443       // A null tile (i.e. missing recording) can just be skipped.
1444       if (!tile)
1445         continue;
1446 
1447       if (tile->required_for_activation() && !tile->IsReadyToDraw())
1448         return false;
1449     }
1450   }
1451 
1452   return true;
1453 }
1454 
LayerRasterTileIterator()1455 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1456     : layer_(NULL) {}
1457 
LayerRasterTileIterator(PictureLayerImpl * layer,bool prioritize_low_res)1458 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1459     PictureLayerImpl* layer,
1460     bool prioritize_low_res)
1461     : layer_(layer), current_stage_(0) {
1462   DCHECK(layer_);
1463 
1464   // Early out if the layer has no tilings.
1465   if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) {
1466     current_stage_ = arraysize(stages_);
1467     return;
1468   }
1469 
1470   // Tiles without valid priority are treated as having lowest priority and
1471   // never considered for raster.
1472   if (!layer_->HasValidTilePriorities()) {
1473     current_stage_ = arraysize(stages_);
1474     return;
1475   }
1476 
1477   WhichTree tree =
1478       layer_->layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1479 
1480   // Find high and low res tilings and initialize the iterators.
1481   for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
1482     PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1483     if (tiling->resolution() == HIGH_RESOLUTION) {
1484       iterators_[HIGH_RES] =
1485           PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
1486     }
1487 
1488     if (tiling->resolution() == LOW_RESOLUTION) {
1489       iterators_[LOW_RES] =
1490           PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
1491     }
1492   }
1493 
1494   if (prioritize_low_res) {
1495     stages_[0].iterator_type = LOW_RES;
1496     stages_[0].tile_type = TilePriority::NOW;
1497 
1498     stages_[1].iterator_type = HIGH_RES;
1499     stages_[1].tile_type = TilePriority::NOW;
1500   } else {
1501     stages_[0].iterator_type = HIGH_RES;
1502     stages_[0].tile_type = TilePriority::NOW;
1503 
1504     stages_[1].iterator_type = LOW_RES;
1505     stages_[1].tile_type = TilePriority::NOW;
1506   }
1507 
1508   stages_[2].iterator_type = HIGH_RES;
1509   stages_[2].tile_type = TilePriority::SOON;
1510 
1511   stages_[3].iterator_type = HIGH_RES;
1512   stages_[3].tile_type = TilePriority::EVENTUALLY;
1513 
1514   IteratorType index = stages_[current_stage_].iterator_type;
1515   TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1516   if (!iterators_[index] || iterators_[index].get_type() != tile_type)
1517     ++(*this);
1518 }
1519 
~LayerRasterTileIterator()1520 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1521 
operator bool() const1522 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1523   return layer_ && static_cast<size_t>(current_stage_) < arraysize(stages_);
1524 }
1525 
1526 PictureLayerImpl::LayerRasterTileIterator&
1527 PictureLayerImpl::LayerRasterTileIterator::
operator ++()1528 operator++() {
1529   IteratorType index = stages_[current_stage_].iterator_type;
1530   TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1531 
1532   // First advance the iterator.
1533   if (iterators_[index])
1534     ++iterators_[index];
1535 
1536   if (iterators_[index] && iterators_[index].get_type() == tile_type)
1537     return *this;
1538 
1539   // Next, advance the stage.
1540   int stage_count = arraysize(stages_);
1541   ++current_stage_;
1542   while (current_stage_ < stage_count) {
1543     index = stages_[current_stage_].iterator_type;
1544     tile_type = stages_[current_stage_].tile_type;
1545 
1546     if (iterators_[index] && iterators_[index].get_type() == tile_type)
1547       break;
1548     ++current_stage_;
1549   }
1550   return *this;
1551 }
1552 
operator *()1553 Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1554   DCHECK(*this);
1555 
1556   IteratorType index = stages_[current_stage_].iterator_type;
1557   DCHECK(iterators_[index]);
1558   DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type);
1559 
1560   return *iterators_[index];
1561 }
1562 
LayerEvictionTileIterator()1563 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1564     : iterator_index_(0),
1565       iteration_stage_(TilePriority::EVENTUALLY),
1566       required_for_activation_(false),
1567       layer_(NULL) {}
1568 
LayerEvictionTileIterator(PictureLayerImpl * layer,TreePriority tree_priority)1569 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1570     PictureLayerImpl* layer,
1571     TreePriority tree_priority)
1572     : iterator_index_(0),
1573       iteration_stage_(TilePriority::EVENTUALLY),
1574       required_for_activation_(false),
1575       layer_(layer) {
1576   // Early out if the layer has no tilings.
1577   // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure
1578   // that layers that don't have valid tile priorities have lowest priorities so
1579   // they evict their tiles first (crbug.com/381704)
1580   if (!layer_->tilings_ || !layer_->tilings_->num_tilings())
1581     return;
1582 
1583   size_t high_res_tiling_index = layer_->tilings_->num_tilings();
1584   size_t low_res_tiling_index = layer_->tilings_->num_tilings();
1585   for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
1586     PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1587     if (tiling->resolution() == HIGH_RESOLUTION)
1588       high_res_tiling_index = i;
1589     else if (tiling->resolution() == LOW_RESOLUTION)
1590       low_res_tiling_index = i;
1591   }
1592 
1593   iterators_.reserve(layer_->tilings_->num_tilings());
1594 
1595   // Higher resolution non-ideal goes first.
1596   for (size_t i = 0; i < high_res_tiling_index; ++i) {
1597     iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1598         layer_->tilings_->tiling_at(i), tree_priority));
1599   }
1600 
1601   // Lower resolution non-ideal goes next.
1602   for (size_t i = layer_->tilings_->num_tilings() - 1;
1603        i > high_res_tiling_index;
1604        --i) {
1605     PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1606     if (tiling->resolution() == LOW_RESOLUTION)
1607       continue;
1608 
1609     iterators_.push_back(
1610         PictureLayerTiling::TilingEvictionTileIterator(tiling, tree_priority));
1611   }
1612 
1613   // Now, put the low res tiling if we have one.
1614   if (low_res_tiling_index < layer_->tilings_->num_tilings()) {
1615     iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1616         layer_->tilings_->tiling_at(low_res_tiling_index), tree_priority));
1617   }
1618 
1619   // Finally, put the high res tiling if we have one.
1620   if (high_res_tiling_index < layer_->tilings_->num_tilings()) {
1621     iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1622         layer_->tilings_->tiling_at(high_res_tiling_index), tree_priority));
1623   }
1624 
1625   DCHECK_GT(iterators_.size(), 0u);
1626 
1627   if (!iterators_[iterator_index_] ||
1628       !IsCorrectType(&iterators_[iterator_index_])) {
1629     AdvanceToNextIterator();
1630   }
1631 }
1632 
~LayerEvictionTileIterator()1633 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {}
1634 
operator *()1635 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1636   DCHECK(*this);
1637   return *iterators_[iterator_index_];
1638 }
1639 
1640 PictureLayerImpl::LayerEvictionTileIterator&
1641 PictureLayerImpl::LayerEvictionTileIterator::
operator ++()1642 operator++() {
1643   DCHECK(*this);
1644   ++iterators_[iterator_index_];
1645   if (!iterators_[iterator_index_] ||
1646       !IsCorrectType(&iterators_[iterator_index_])) {
1647     AdvanceToNextIterator();
1648   }
1649   return *this;
1650 }
1651 
AdvanceToNextIterator()1652 void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() {
1653   ++iterator_index_;
1654 
1655   while (true) {
1656     while (iterator_index_ < iterators_.size()) {
1657       if (iterators_[iterator_index_] &&
1658           IsCorrectType(&iterators_[iterator_index_])) {
1659         return;
1660       }
1661       ++iterator_index_;
1662     }
1663 
1664     // If we're NOW and required_for_activation, then this was the last pass
1665     // through the iterators.
1666     if (iteration_stage_ == TilePriority::NOW && required_for_activation_)
1667       break;
1668 
1669     if (!required_for_activation_) {
1670       required_for_activation_ = true;
1671     } else {
1672       required_for_activation_ = false;
1673       iteration_stage_ =
1674           static_cast<TilePriority::PriorityBin>(iteration_stage_ - 1);
1675     }
1676     iterator_index_ = 0;
1677   }
1678 }
1679 
operator bool() const1680 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1681   return iterator_index_ < iterators_.size();
1682 }
1683 
IsCorrectType(PictureLayerTiling::TilingEvictionTileIterator * it) const1684 bool PictureLayerImpl::LayerEvictionTileIterator::IsCorrectType(
1685     PictureLayerTiling::TilingEvictionTileIterator* it) const {
1686   return it->get_type() == iteration_stage_ &&
1687          (**it)->required_for_activation() == required_for_activation_;
1688 }
1689 
1690 }  // namespace cc
1691