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 <stddef.h>
8 #include <stdint.h>
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <limits>
13 #include <memory>
14 #include <set>
15 #include <utility>
16 
17 #include "base/metrics/histogram_macros.h"
18 #include "base/no_destructor.h"
19 #include "base/numerics/ranges.h"
20 #include "base/system/sys_info.h"
21 #include "base/time/time.h"
22 #include "base/trace_event/traced_value.h"
23 #include "build/build_config.h"
24 #include "cc/base/math_util.h"
25 #include "cc/benchmarks/micro_benchmark_impl.h"
26 #include "cc/debug/debug_colors.h"
27 #include "cc/layers/append_quads_data.h"
28 #include "cc/layers/solid_color_layer_impl.h"
29 #include "cc/paint/display_item_list.h"
30 #include "cc/tiles/tile_manager.h"
31 #include "cc/tiles/tiling_set_raster_queue_all.h"
32 #include "cc/trees/effect_node.h"
33 #include "cc/trees/layer_tree_impl.h"
34 #include "cc/trees/occlusion.h"
35 #include "cc/trees/transform_node.h"
36 #include "components/viz/common/frame_sinks/begin_frame_args.h"
37 #include "components/viz/common/quads/debug_border_draw_quad.h"
38 #include "components/viz/common/quads/picture_draw_quad.h"
39 #include "components/viz/common/quads/solid_color_draw_quad.h"
40 #include "components/viz/common/quads/tile_draw_quad.h"
41 #include "components/viz/common/traced_value.h"
42 #include "ui/gfx/geometry/quad_f.h"
43 #include "ui/gfx/geometry/rect_conversions.h"
44 #include "ui/gfx/geometry/size_conversions.h"
45 
46 namespace cc {
47 namespace {
48 // This must be > 1 as we multiply or divide by this to find a new raster
49 // scale during pinch.
50 const float kMaxScaleRatioDuringPinch = 2.0f;
51 
52 // When creating a new tiling during pinch, snap to an existing
53 // tiling's scale if the desired scale is within this ratio.
54 const float kSnapToExistingTilingRatio = 1.2f;
55 
56 // Large contents scale can cause overflow issues. Cap the ideal contents scale
57 // by this constant, since scales larger than this are usually not correct or
58 // their scale doesn't matter as long as it's large. Content scales usually
59 // closely match the default device-scale factor (so it's usually <= 5). See
60 // Renderer4.IdealContentsScale UMA (deprecated) for distribution of content
61 // scales.
62 const float kMaxIdealContentsScale = 10000.f;
63 
64 // We try to avoid raster scale adjustment for will-change:transform for
65 // performance, unless the scale is too small compared to the ideal scale and
66 // the native scale.
67 const float kMinScaleRatioForWillChangeTransform = 0.25f;
68 
69 // Intersect rects which may have right() and bottom() that overflow integer
70 // boundaries. This code is similar to gfx::Rect::Intersect with the exception
71 // that the types are promoted to int64_t when there is a chance of overflow.
SafeIntersectRects(const gfx::Rect & one,const gfx::Rect & two)72 gfx::Rect SafeIntersectRects(const gfx::Rect& one, const gfx::Rect& two) {
73   if (one.IsEmpty() || two.IsEmpty())
74     return gfx::Rect();
75 
76   int rx = std::max(one.x(), two.x());
77   int ry = std::max(one.y(), two.y());
78   int64_t rr = std::min(static_cast<int64_t>(one.x()) + one.width(),
79                         static_cast<int64_t>(two.x()) + two.width());
80   int64_t rb = std::min(static_cast<int64_t>(one.y()) + one.height(),
81                         static_cast<int64_t>(two.y()) + two.height());
82   if (rx > rr || ry > rb)
83     return gfx::Rect();
84   return gfx::Rect(rx, ry, static_cast<int>(rr - rx),
85                    static_cast<int>(rb - ry));
86 }
87 
88 }  // namespace
89 
PictureLayerImpl(LayerTreeImpl * tree_impl,int id)90 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
91     : LayerImpl(tree_impl, id, /*will_always_push_properties=*/true),
92       twin_layer_(nullptr),
93       tilings_(CreatePictureLayerTilingSet()),
94       ideal_page_scale_(0.f),
95       ideal_device_scale_(0.f),
96       ideal_source_scale_(0.f),
97       ideal_contents_scale_(0.f),
98       raster_page_scale_(0.f),
99       raster_device_scale_(0.f),
100       raster_source_scale_(0.f),
101       raster_contents_scale_(0.f),
102       low_res_raster_contents_scale_(0.f),
103       is_backdrop_filter_mask_(false),
104       was_screen_space_transform_animating_(false),
105       only_used_low_res_last_append_quads_(false),
106       nearest_neighbor_(false),
107       lcd_text_disallowed_reason_(LCDTextDisallowedReason::kNone),
108       directly_composited_image_size_(base::nullopt),
109       directly_composited_image_initial_raster_scale_(0.f),
110       tile_size_calculator_(this) {
111   layer_tree_impl()->RegisterPictureLayerImpl(this);
112 }
113 
~PictureLayerImpl()114 PictureLayerImpl::~PictureLayerImpl() {
115   if (twin_layer_)
116     twin_layer_->twin_layer_ = nullptr;
117 
118   // We only track PaintWorklet-containing PictureLayerImpls on the pending
119   // tree. However this deletion may happen outside the commit flow when we are
120   // on the recycle tree instead, so just check !IsActiveTree().
121   if (!paint_worklet_records_.empty() && !layer_tree_impl()->IsActiveTree())
122     layer_tree_impl()->NotifyLayerHasPaintWorkletsChanged(this, false);
123 
124   // Similarly, AnimatedPaintWorkletTracker is only valid on the pending tree.
125   if (!layer_tree_impl()->IsActiveTree()) {
126     layer_tree_impl()
127         ->paint_worklet_tracker()
128         .UpdatePaintWorkletInputProperties({}, this);
129   }
130 
131   layer_tree_impl()->UnregisterPictureLayerImpl(this);
132 
133   // Unregister for all images on the current raster source.
134   UnregisterAnimatedImages();
135 }
136 
LayerTypeAsString() const137 const char* PictureLayerImpl::LayerTypeAsString() const {
138   return "cc::PictureLayerImpl";
139 }
140 
CreateLayerImpl(LayerTreeImpl * tree_impl)141 std::unique_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
142     LayerTreeImpl* tree_impl) {
143   return PictureLayerImpl::Create(tree_impl, id());
144 }
145 
PushPropertiesTo(LayerImpl * base_layer)146 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
147   PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
148 
149   LayerImpl::PushPropertiesTo(base_layer);
150 
151   // Twin relationships should never change once established.
152   DCHECK(!twin_layer_ || twin_layer_ == layer_impl);
153   DCHECK(!twin_layer_ || layer_impl->twin_layer_ == this);
154   // The twin relationship does not need to exist before the first
155   // PushPropertiesTo from pending to active layer since before that the active
156   // layer can not have a pile or tilings, it has only been created and inserted
157   // into the tree at that point.
158   twin_layer_ = layer_impl;
159   layer_impl->twin_layer_ = this;
160 
161   layer_impl->SetNearestNeighbor(nearest_neighbor_);
162   layer_impl->SetDirectlyCompositedImageSize(directly_composited_image_size_);
163   layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask_);
164 
165   // Solid color layers have no tilings.
166   DCHECK(!raster_source_->IsSolidColor() || tilings_->num_tilings() == 0);
167   // The pending tree should only have a high res (and possibly low res) tiling.
168   DCHECK_LE(tilings_->num_tilings(),
169             layer_tree_impl()->create_low_res_tiling() ? 2u : 1u);
170 
171   layer_impl->set_gpu_raster_max_texture_size(gpu_raster_max_texture_size_);
172   layer_impl->UpdateRasterSource(raster_source_, &invalidation_, tilings_.get(),
173                                  &paint_worklet_records_);
174   DCHECK(invalidation_.IsEmpty());
175 
176   // After syncing a solid color layer, the active layer has no tilings.
177   DCHECK(!raster_source_->IsSolidColor() ||
178          layer_impl->tilings_->num_tilings() == 0);
179 
180   layer_impl->raster_page_scale_ = raster_page_scale_;
181   layer_impl->raster_device_scale_ = raster_device_scale_;
182   layer_impl->raster_source_scale_ = raster_source_scale_;
183   layer_impl->raster_contents_scale_ = raster_contents_scale_;
184   layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
185   layer_impl->directly_composited_image_initial_raster_scale_ =
186       directly_composited_image_initial_raster_scale_;
187   // Simply push the value to the active tree without any extra invalidations,
188   // since the pending tree tiles would have this handled. This is here to
189   // ensure the state is consistent for future raster.
190   layer_impl->lcd_text_disallowed_reason_ = lcd_text_disallowed_reason_;
191 
192   layer_impl->SanityCheckTilingState();
193 }
194 
AppendQuads(viz::CompositorRenderPass * render_pass,AppendQuadsData * append_quads_data)195 void PictureLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
196                                    AppendQuadsData* append_quads_data) {
197   // RenderSurfaceImpl::AppendQuads sets mask properties in the DrawQuad for
198   // the masked surface, which will apply to both the backdrop filter and the
199   // contents of the masked surface, so we should not append quads of the mask
200   // layer in DstIn blend mode which would apply the mask in another codepath.
201   if (is_backdrop_filter_mask_)
202     return;
203 
204   // The bounds and the pile size may differ if the pile wasn't updated (ie.
205   // PictureLayer::Update didn't happen). In that case the pile will be empty.
206   DCHECK(raster_source_->GetSize().IsEmpty() ||
207          bounds() == raster_source_->GetSize())
208       << " bounds " << bounds().ToString() << " pile "
209       << raster_source_->GetSize().ToString();
210 
211   viz::SharedQuadState* shared_quad_state =
212       render_pass->CreateAndAppendSharedQuadState();
213 
214   if (raster_source_->IsSolidColor()) {
215     // TODO(979672): This is still hard-coded at 1.0. This has some history:
216     //  - for crbug.com/769319, the contents scale was allowed to change, to
217     //    avoid blurring on high-dpi screens.
218     //  - for crbug.com/796558, the max device scale was hard-coded back to 1.0
219     //    for single-tile masks, to avoid problems with transforms.
220     // To avoid those transform/scale bugs, this is currently left at 1.0. See
221     // crbug.com/979672 for more context and test links.
222     float max_contents_scale = 1;
223 
224     // The downstream CA layers use shared_quad_state to generate resources of
225     // the right size even if it is a solid color picture layer.
226     PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
227                                   contents_opaque());
228 
229     AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
230                           append_quads_data);
231 
232     gfx::Rect scaled_visible_layer_rect =
233         shared_quad_state->visible_quad_layer_rect;
234     Occlusion occlusion = draw_properties().occlusion_in_content_space;
235 
236     EffectNode* effect_node = GetEffectTree().Node(effect_tree_index());
237     SolidColorLayerImpl::AppendSolidQuads(
238         render_pass, occlusion, shared_quad_state, scaled_visible_layer_rect,
239         raster_source_->GetSolidColor(),
240         !layer_tree_impl()->settings().enable_edge_anti_aliasing,
241         effect_node->blend_mode, append_quads_data);
242     return;
243   }
244 
245   float device_scale_factor = layer_tree_impl()->device_scale_factor();
246   // If we don't have tilings, we're likely going to append a checkerboard quad
247   // the size of the layer. In that case, use scale 1 for more stable
248   // to-screen-space mapping.
249   float max_contents_scale =
250       tilings_->num_tilings() ? MaximumTilingContentsScale() : 1.f;
251   PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
252                                 contents_opaque());
253 
254   if (directly_composited_image_size_) {
255     // Directly composited images should be clipped to the layer's content rect.
256     // When a PictureLayerTiling is created for a directly composited image, the
257     // layer bounds are multiplied by the raster scale in order to compute the
258     // tile size. If the aspect ratio of the layer doesn't match that of the
259     // image, it's possible that one of the dimensions of the resulting size
260     // (layer bounds * raster scale) is a fractional number, as raster scale
261     // does not scale x and y independently.
262     // When this happens, the ToEnclosingRect() operation in
263     // |PictureLayerTiling::EnclosingContentsRectFromLayer()| will
264     // create a tiling that, when scaled by |max_contents_scale| above, is
265     // larger than the layer bounds by a fraction of a pixel.
266     gfx::Rect bounds_in_target_space = MathUtil::MapEnclosingClippedRect(
267         draw_properties().target_space_transform, gfx::Rect(bounds()));
268     if (is_clipped())
269       bounds_in_target_space.Intersect(draw_properties().clip_rect);
270 
271     if (shared_quad_state->is_clipped)
272       bounds_in_target_space.Intersect(shared_quad_state->clip_rect);
273 
274     shared_quad_state->is_clipped = true;
275     shared_quad_state->clip_rect = bounds_in_target_space;
276 
277 #if DCHECK_IS_ON()
278     // Validate that the tile and bounds size are always within one pixel.
279     PictureLayerTiling* high_res =
280         tilings_->FindTilingWithResolution(HIGH_RESOLUTION);
281     if (raster_contents_scale_ >= 1.f && high_res) {
282       const float epsilon = 1.f;
283       gfx::SizeF scaled_tiling_size(high_res->tiling_size());
284       scaled_tiling_size.Scale(1 / raster_contents_scale_);
285       DCHECK(std::abs(bounds().width() - scaled_tiling_size.width()) < epsilon);
286       DCHECK(std::abs(bounds().height() - scaled_tiling_size.height()) <
287              epsilon);
288     }
289 #endif
290   }
291 
292   Occlusion scaled_occlusion =
293       draw_properties()
294           .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
295               shared_quad_state->quad_to_target_transform);
296 
297   if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
298     DCHECK(shared_quad_state->quad_layer_rect.origin() == gfx::Point(0, 0));
299     AppendDebugBorderQuad(
300         render_pass, shared_quad_state->quad_layer_rect, shared_quad_state,
301         append_quads_data, DebugColors::DirectPictureBorderColor(),
302         DebugColors::DirectPictureBorderWidth(device_scale_factor));
303 
304     gfx::Rect geometry_rect = shared_quad_state->visible_quad_layer_rect;
305     gfx::Rect visible_geometry_rect =
306         scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
307     bool needs_blending = !contents_opaque();
308 
309     // The raster source may not be valid over the entire visible rect,
310     // and rastering outside of that may cause incorrect pixels.
311     gfx::Rect scaled_recorded_viewport = gfx::ScaleToEnclosingRect(
312         raster_source_->RecordedViewport(), max_contents_scale);
313     geometry_rect.Intersect(scaled_recorded_viewport);
314     visible_geometry_rect.Intersect(scaled_recorded_viewport);
315 
316     if (visible_geometry_rect.IsEmpty())
317       return;
318 
319     DCHECK(raster_source_->HasRecordings());
320     gfx::Rect quad_content_rect = shared_quad_state->visible_quad_layer_rect;
321     gfx::Size texture_size = quad_content_rect.size();
322     gfx::RectF texture_rect = gfx::RectF(gfx::SizeF(texture_size));
323 
324     viz::PictureDrawQuad::ImageAnimationMap image_animation_map;
325     const auto* controller = layer_tree_impl()->image_animation_controller();
326     WhichTree tree = layer_tree_impl()->IsPendingTree()
327                          ? WhichTree::PENDING_TREE
328                          : WhichTree::ACTIVE_TREE;
329     for (const auto& image_data : raster_source_->GetDisplayItemList()
330                                       ->discardable_image_map()
331                                       .animated_images_metadata()) {
332       image_animation_map[image_data.paint_image_id] =
333           controller->GetFrameIndexForImage(image_data.paint_image_id, tree);
334     }
335 
336     auto* quad = render_pass->CreateAndAppendDrawQuad<viz::PictureDrawQuad>();
337     quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
338                  needs_blending, texture_rect, texture_size, nearest_neighbor_,
339                  viz::RGBA_8888, quad_content_rect, max_contents_scale,
340                  std::move(image_animation_map),
341                  raster_source_->GetDisplayItemList());
342     ValidateQuadResources(quad);
343     return;
344   }
345 
346   // If we're doing a regular AppendQuads (ie, not solid color or resourceless
347   // software draw, and if the visible rect is scrolled far enough away, then we
348   // may run into a floating point precision in AA calculations in the renderer.
349   // See crbug.com/765297. In order to avoid this, we shift the quads up from
350   // where they logically reside and adjust the shared_quad_state's transform
351   // instead. We only do this in a scale/translate matrices to ensure the math
352   // is correct.
353   gfx::Vector2d quad_offset;
354   if (shared_quad_state->quad_to_target_transform.IsScaleOrTranslation()) {
355     const auto& visible_rect = shared_quad_state->visible_quad_layer_rect;
356     quad_offset = gfx::Vector2d(-visible_rect.x(), -visible_rect.y());
357   }
358 
359   gfx::Rect debug_border_rect(shared_quad_state->quad_layer_rect);
360   debug_border_rect.Offset(quad_offset);
361   AppendDebugBorderQuad(render_pass, debug_border_rect, shared_quad_state,
362                         append_quads_data);
363 
364   if (ShowDebugBorders(DebugBorderType::LAYER)) {
365     for (PictureLayerTilingSet::CoverageIterator iter(
366              tilings_.get(), max_contents_scale,
367              shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_);
368          iter; ++iter) {
369       SkColor color;
370       float width;
371       if (*iter && iter->draw_info().IsReadyToDraw()) {
372         TileDrawInfo::Mode mode = iter->draw_info().mode();
373         if (mode == TileDrawInfo::SOLID_COLOR_MODE) {
374           color = DebugColors::SolidColorTileBorderColor();
375           width = DebugColors::SolidColorTileBorderWidth(device_scale_factor);
376         } else if (mode == TileDrawInfo::OOM_MODE) {
377           color = DebugColors::OOMTileBorderColor();
378           width = DebugColors::OOMTileBorderWidth(device_scale_factor);
379         } else if (iter.resolution() == HIGH_RESOLUTION) {
380           color = DebugColors::HighResTileBorderColor();
381           width = DebugColors::HighResTileBorderWidth(device_scale_factor);
382         } else if (iter.resolution() == LOW_RESOLUTION) {
383           color = DebugColors::LowResTileBorderColor();
384           width = DebugColors::LowResTileBorderWidth(device_scale_factor);
385         } else if (iter->contents_scale_key() > max_contents_scale) {
386           color = DebugColors::ExtraHighResTileBorderColor();
387           width = DebugColors::ExtraHighResTileBorderWidth(device_scale_factor);
388         } else {
389           color = DebugColors::ExtraLowResTileBorderColor();
390           width = DebugColors::ExtraLowResTileBorderWidth(device_scale_factor);
391         }
392       } else {
393         color = DebugColors::MissingTileBorderColor();
394         width = DebugColors::MissingTileBorderWidth(device_scale_factor);
395       }
396 
397       auto* debug_border_quad =
398           render_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
399       gfx::Rect geometry_rect = iter.geometry_rect();
400       geometry_rect.Offset(quad_offset);
401       gfx::Rect visible_geometry_rect = geometry_rect;
402       debug_border_quad->SetNew(shared_quad_state,
403                                 geometry_rect,
404                                 visible_geometry_rect,
405                                 color,
406                                 width);
407     }
408   }
409 
410   if (layer_tree_impl()->debug_state().highlight_non_lcd_text_layers) {
411     SkColor color =
412         DebugColors::NonLCDTextHighlightColor(lcd_text_disallowed_reason());
413     if (color != SK_ColorTRANSPARENT &&
414         GetRasterSource()->GetDisplayItemList()->AreaOfDrawText(
415             gfx::Rect(bounds()))) {
416       render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>()->SetNew(
417           shared_quad_state, debug_border_rect, debug_border_rect, color,
418           append_quads_data);
419     }
420   }
421 
422   // Keep track of the tilings that were used so that tilings that are
423   // unused can be considered for removal.
424   last_append_quads_tilings_.clear();
425 
426   // Ignore missing tiles outside of viewport for tile priority. This is
427   // normally the same as draw viewport but can be independently overridden by
428   // embedders like Android WebView with SetExternalTilePriorityConstraints.
429   gfx::Rect scaled_viewport_for_tile_priority = gfx::ScaleToEnclosingRect(
430       viewport_rect_for_tile_priority_in_content_space_, max_contents_scale);
431 
432   size_t missing_tile_count = 0u;
433   size_t on_demand_missing_tile_count = 0u;
434   only_used_low_res_last_append_quads_ = true;
435   gfx::Rect scaled_recorded_viewport = gfx::ScaleToEnclosingRect(
436       raster_source_->RecordedViewport(), max_contents_scale);
437   for (PictureLayerTilingSet::CoverageIterator iter(
438            tilings_.get(), max_contents_scale,
439            shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_);
440        iter; ++iter) {
441     gfx::Rect geometry_rect = iter.geometry_rect();
442     gfx::Rect visible_geometry_rect =
443         scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
444 
445     gfx::Rect offset_geometry_rect = geometry_rect;
446     offset_geometry_rect.Offset(quad_offset);
447     gfx::Rect offset_visible_geometry_rect = visible_geometry_rect;
448     offset_visible_geometry_rect.Offset(quad_offset);
449 
450     bool needs_blending = !contents_opaque();
451     if (visible_geometry_rect.IsEmpty())
452       continue;
453 
454     int64_t visible_geometry_area =
455         static_cast<int64_t>(visible_geometry_rect.width()) *
456         visible_geometry_rect.height();
457     append_quads_data->visible_layer_area += visible_geometry_area;
458 
459     bool has_draw_quad = false;
460     if (*iter && iter->draw_info().IsReadyToDraw()) {
461       const TileDrawInfo& draw_info = iter->draw_info();
462 
463       switch (draw_info.mode()) {
464         case TileDrawInfo::RESOURCE_MODE: {
465           gfx::RectF texture_rect = iter.texture_rect();
466 
467           // The raster_contents_scale_ is the best scale that the layer is
468           // trying to produce, even though it may not be ideal. Since that's
469           // the best the layer can promise in the future, consider those as
470           // complete. But if a tile is ideal scale, we don't want to consider
471           // it incomplete and trying to replace it with a tile at a worse
472           // scale.
473           if (iter->contents_scale_key() != raster_contents_scale_ &&
474               iter->contents_scale_key() != ideal_contents_scale_ &&
475               geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
476             append_quads_data->num_incomplete_tiles++;
477           }
478 
479           auto* quad =
480               render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
481           quad->SetNew(
482               shared_quad_state, offset_geometry_rect,
483               offset_visible_geometry_rect, needs_blending,
484               draw_info.resource_id_for_export(), texture_rect,
485               draw_info.resource_size(), draw_info.is_premultiplied(),
486               nearest_neighbor_,
487               !layer_tree_impl()->settings().enable_edge_anti_aliasing);
488           ValidateQuadResources(quad);
489           has_draw_quad = true;
490           break;
491         }
492         case TileDrawInfo::SOLID_COLOR_MODE: {
493           float alpha =
494               (SkColorGetA(draw_info.solid_color()) * (1.0f / 255.0f)) *
495               shared_quad_state->opacity;
496           if (alpha >= std::numeric_limits<float>::epsilon()) {
497             auto* quad =
498                 render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
499             quad->SetNew(
500                 shared_quad_state, offset_geometry_rect,
501                 offset_visible_geometry_rect, draw_info.solid_color(),
502                 !layer_tree_impl()->settings().enable_edge_anti_aliasing);
503             ValidateQuadResources(quad);
504           }
505           has_draw_quad = true;
506           break;
507         }
508         case TileDrawInfo::OOM_MODE:
509           break;  // Checkerboard.
510       }
511     }
512 
513     if (!has_draw_quad) {
514       // Checkerboard.
515       SkColor color = SafeOpaqueBackgroundColor();
516       if (ShowDebugBorders(DebugBorderType::LAYER)) {
517         // Fill the whole tile with the missing tile color.
518         color = DebugColors::DefaultCheckerboardColor();
519       }
520       auto* quad =
521           render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
522       quad->SetNew(shared_quad_state, offset_geometry_rect,
523                    offset_visible_geometry_rect, color, false);
524       ValidateQuadResources(quad);
525 
526       if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
527         append_quads_data->num_missing_tiles++;
528         ++missing_tile_count;
529       }
530       append_quads_data->checkerboarded_visible_content_area +=
531           visible_geometry_area;
532       // Intersect checkerboard rect with interest rect to generate rect where
533       // we checkerboarded and has recording. The area where we don't have
534       // recording is not necessarily a Rect, and its area is calculated using
535       // subtraction.
536       gfx::Rect visible_rect_has_recording = visible_geometry_rect;
537       visible_rect_has_recording.Intersect(scaled_recorded_viewport);
538       int64_t checkerboarded_has_recording_area =
539           static_cast<int64_t>(visible_rect_has_recording.width()) *
540           visible_rect_has_recording.height();
541       append_quads_data->checkerboarded_needs_raster_content_area +=
542           checkerboarded_has_recording_area;
543       append_quads_data->checkerboarded_no_recording_content_area +=
544           visible_geometry_area - checkerboarded_has_recording_area;
545       continue;
546     }
547 
548     if (iter.resolution() != HIGH_RESOLUTION) {
549       append_quads_data->approximated_visible_content_area +=
550           visible_geometry_area;
551     }
552 
553     // If we have a draw quad, but it's not low resolution, then
554     // mark that we've used something other than low res to draw.
555     if (iter.resolution() != LOW_RESOLUTION)
556       only_used_low_res_last_append_quads_ = false;
557 
558     if (last_append_quads_tilings_.empty() ||
559         last_append_quads_tilings_.back() != iter.CurrentTiling()) {
560       last_append_quads_tilings_.push_back(iter.CurrentTiling());
561     }
562   }
563 
564   // Adjust shared_quad_state with the quad_offset, since we've adjusted each
565   // quad we've appended by it.
566   shared_quad_state->quad_to_target_transform.Translate(-quad_offset);
567   shared_quad_state->quad_layer_rect.Offset(quad_offset);
568   shared_quad_state->visible_quad_layer_rect.Offset(quad_offset);
569 
570   if (missing_tile_count) {
571     TRACE_EVENT_INSTANT2("cc",
572                          "PictureLayerImpl::AppendQuads checkerboard",
573                          TRACE_EVENT_SCOPE_THREAD,
574                          "missing_tile_count",
575                          missing_tile_count,
576                          "on_demand_missing_tile_count",
577                          on_demand_missing_tile_count);
578   }
579 
580   // Aggressively remove any tilings that are not seen to save memory. Note
581   // that this is at the expense of doing cause more frequent re-painting. A
582   // better scheme would be to maintain a tighter visible_layer_rect for the
583   // finer tilings.
584   CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);
585 }
586 
UpdateTiles()587 bool PictureLayerImpl::UpdateTiles() {
588   if (!CanHaveTilings()) {
589     ideal_page_scale_ = 0.f;
590     ideal_device_scale_ = 0.f;
591     ideal_contents_scale_ = 0.f;
592     ideal_source_scale_ = 0.f;
593     SanityCheckTilingState();
594     return false;
595   }
596 
597   // Remove any non-ideal tilings that were not used last time we generated
598   // quads to save memory and processing time. Note that pending tree should
599   // only have one or two tilings (high and low res), so only clean up the
600   // active layer. This cleans it up here in case AppendQuads didn't run.
601   // If it did run, this would not remove any additional tilings.
602   if (layer_tree_impl()->IsActiveTree())
603     CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);
604 
605   UpdateIdealScales();
606 
607   const bool should_adjust_raster_scale = ShouldAdjustRasterScale();
608   if (should_adjust_raster_scale)
609     RecalculateRasterScales();
610   UpdateTilingsForRasterScaleAndTranslation(should_adjust_raster_scale);
611 
612   if (layer_tree_impl()->IsActiveTree())
613     AddLowResolutionTilingIfNeeded();
614 
615   DCHECK(raster_page_scale_);
616   DCHECK(raster_device_scale_);
617   DCHECK(raster_source_scale_);
618   DCHECK(raster_contents_scale_);
619   DCHECK(low_res_raster_contents_scale_);
620 
621   was_screen_space_transform_animating_ =
622       draw_properties().screen_space_transform_is_animating;
623 
624   double current_frame_time_in_seconds =
625       (layer_tree_impl()->CurrentBeginFrameArgs().frame_time -
626        base::TimeTicks()).InSecondsF();
627   UpdateViewportRectForTilePriorityInContentSpace();
628 
629   // The tiling set can require tiles for activation any of the following
630   // conditions are true:
631   // - This layer produced a high-res or non-ideal-res tile last frame.
632   // - We're in requires high res to draw mode.
633   // - We're not in smoothness takes priority mode.
634   // To put different, the tiling set can't require tiles for activation if
635   // we're in smoothness mode and only used low-res or checkerboard to draw last
636   // frame and we don't need high res to draw.
637   //
638   // The reason for this is that we should be able to activate sooner and get a
639   // more up to date recording, so we don't run out of recording on the active
640   // tree.
641   // A layer must be a drawing layer for it to require tiles for activation.
642   bool can_require_tiles_for_activation = false;
643   if (contributes_to_drawn_render_surface()) {
644     can_require_tiles_for_activation =
645         !only_used_low_res_last_append_quads_ || RequiresHighResToDraw() ||
646         !layer_tree_impl()->SmoothnessTakesPriority();
647   }
648 
649   static const base::NoDestructor<Occlusion> kEmptyOcclusion;
650   const Occlusion& occlusion_in_content_space =
651       layer_tree_impl()->settings().use_occlusion_for_tile_prioritization
652           ? draw_properties().occlusion_in_content_space
653           : *kEmptyOcclusion;
654 
655   // Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since
656   // they are the same space in picture layer, as contents scale is always 1.
657   bool updated = tilings_->UpdateTilePriorities(
658       viewport_rect_for_tile_priority_in_content_space_, ideal_contents_scale_,
659       current_frame_time_in_seconds, occlusion_in_content_space,
660       can_require_tiles_for_activation);
661   return updated;
662 }
663 
UpdateViewportRectForTilePriorityInContentSpace()664 void PictureLayerImpl::UpdateViewportRectForTilePriorityInContentSpace() {
665   // If visible_layer_rect() is empty or viewport_rect_for_tile_priority is
666   // set to be different from the device viewport, try to inverse project the
667   // viewport into layer space and use that. Otherwise just use
668   // visible_layer_rect().
669   gfx::Rect visible_rect_in_content_space = visible_layer_rect();
670   gfx::Rect viewport_rect_for_tile_priority =
671       layer_tree_impl()->ViewportRectForTilePriority();
672   if (visible_rect_in_content_space.IsEmpty() ||
673       layer_tree_impl()->GetDeviceViewport() !=
674           viewport_rect_for_tile_priority) {
675     gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
676     if (ScreenSpaceTransform().GetInverse(&view_to_layer)) {
677       // Transform from view space to content space.
678       visible_rect_in_content_space = MathUtil::ProjectEnclosingClippedRect(
679           view_to_layer, viewport_rect_for_tile_priority);
680 
681       // We have to allow for a viewport that is outside of the layer bounds in
682       // order to compute tile priorities correctly for offscreen content that
683       // is going to make it on screen. However, we also have to limit the
684       // viewport since it can be very large due to screen_space_transforms. As
685       // a heuristic, we clip to bounds padded by skewport_extrapolation_limit *
686       // maximum tiling scale, since this should allow sufficient room for
687       // skewport calculations.
688       gfx::Rect padded_bounds(bounds());
689       int padding_amount = layer_tree_impl()
690                                ->settings()
691                                .skewport_extrapolation_limit_in_screen_pixels *
692                            MaximumTilingContentsScale();
693       padded_bounds.Inset(-padding_amount, -padding_amount);
694       visible_rect_in_content_space =
695           SafeIntersectRects(visible_rect_in_content_space, padded_bounds);
696     }
697   }
698   viewport_rect_for_tile_priority_in_content_space_ =
699       visible_rect_in_content_space;
700 }
701 
GetPendingOrActiveTwinLayer() const702 PictureLayerImpl* PictureLayerImpl::GetPendingOrActiveTwinLayer() const {
703   if (!twin_layer_ || !twin_layer_->IsOnActiveOrPendingTree())
704     return nullptr;
705   return twin_layer_;
706 }
707 
UpdateRasterSource(scoped_refptr<RasterSource> raster_source,Region * new_invalidation,const PictureLayerTilingSet * pending_set,const PaintWorkletRecordMap * pending_paint_worklet_records)708 void PictureLayerImpl::UpdateRasterSource(
709     scoped_refptr<RasterSource> raster_source,
710     Region* new_invalidation,
711     const PictureLayerTilingSet* pending_set,
712     const PaintWorkletRecordMap* pending_paint_worklet_records) {
713   // The bounds and the pile size may differ if the pile wasn't updated (ie.
714   // PictureLayer::Update didn't happen). In that case the pile will be empty.
715   DCHECK(raster_source->GetSize().IsEmpty() ||
716          bounds() == raster_source->GetSize())
717       << " bounds " << bounds().ToString() << " pile "
718       << raster_source->GetSize().ToString();
719 
720   // We have an updated recording if the DisplayItemList in the new RasterSource
721   // is different.
722   const bool recording_updated =
723       !raster_source_ || raster_source_->GetDisplayItemList() !=
724                              raster_source->GetDisplayItemList();
725 
726   // Unregister for all images on the current raster source, if the recording
727   // was updated.
728   if (recording_updated) {
729     UnregisterAnimatedImages();
730 
731     // When the display list changes, the set of PaintWorklets may also change.
732     if (pending_paint_worklet_records) {
733       paint_worklet_records_ = *pending_paint_worklet_records;
734     } else {
735       if (raster_source->GetDisplayItemList()) {
736         SetPaintWorkletInputs(raster_source->GetDisplayItemList()
737                                   ->discardable_image_map()
738                                   .paint_worklet_inputs());
739       } else {
740         SetPaintWorkletInputs({});
741       }
742     }
743 
744     // If the MSAA sample count has changed, we need to re-raster the complete
745     // layer.
746     if (raster_source_) {
747       const auto& current_display_item_list =
748           raster_source_->GetDisplayItemList();
749       const auto& new_display_item_list = raster_source->GetDisplayItemList();
750       if (current_display_item_list && new_display_item_list) {
751         bool needs_full_invalidation =
752             layer_tree_impl()->GetMSAASampleCountForRaster(
753                 current_display_item_list) !=
754             layer_tree_impl()->GetMSAASampleCountForRaster(
755                 new_display_item_list);
756         needs_full_invalidation |=
757             layer_tree_impl()->GetRasterColorSpace(
758                 current_display_item_list->discardable_image_map()
759                     .content_color_usage()) !=
760             layer_tree_impl()->GetRasterColorSpace(
761                 new_display_item_list->discardable_image_map()
762                     .content_color_usage());
763         if (needs_full_invalidation)
764           new_invalidation->Union(gfx::Rect(raster_source->GetSize()));
765       }
766     }
767   }
768 
769   // The |raster_source_| is initially null, so have to check for that for the
770   // first frame.
771   bool could_have_tilings = CanHaveTilings();
772   raster_source_.swap(raster_source);
773 
774   // Register images from the new raster source, if the recording was updated.
775   // TODO(khushalsagar): UMA the number of animated images in layer?
776   if (recording_updated)
777     RegisterAnimatedImages();
778 
779   // The |new_invalidation| must be cleared before updating tilings since they
780   // access the invalidation through the PictureLayerTilingClient interface.
781   invalidation_.Clear();
782   invalidation_.Swap(new_invalidation);
783 
784   bool can_have_tilings = CanHaveTilings();
785   DCHECK(!pending_set ||
786          can_have_tilings == GetPendingOrActiveTwinLayer()->CanHaveTilings());
787 
788   // Need to call UpdateTiles again if CanHaveTilings changed.
789   if (could_have_tilings != can_have_tilings)
790     layer_tree_impl()->set_needs_update_draw_properties();
791 
792   if (!can_have_tilings) {
793     RemoveAllTilings();
794     return;
795   }
796 
797   // We could do this after doing UpdateTiles, which would avoid doing this for
798   // tilings that are going to disappear on the pending tree (if scale changed).
799   // But that would also be more complicated, so we just do it here for now.
800   //
801   // TODO(crbug.com/843787): If the LayerTreeFrameSink is lost, and we activate,
802   // this ends up running with the old LayerTreeFrameSink, or possibly with a
803   // null LayerTreeFrameSink, which can give incorrect results or maybe crash.
804   if (pending_set) {
805     tilings_->UpdateTilingsToCurrentRasterSourceForActivation(
806         raster_source_, pending_set, invalidation_, MinimumContentsScale(),
807         MaximumContentsScale());
808   } else {
809     tilings_->UpdateTilingsToCurrentRasterSourceForCommit(
810         raster_source_, invalidation_, MinimumContentsScale(),
811         MaximumContentsScale());
812     // We're in a commit, make sure to update the state of the checker image
813     // tracker with the new async attribute data.
814     layer_tree_impl()->UpdateImageDecodingHints(
815         raster_source_->TakeDecodingModeMap());
816   }
817 }
818 
UpdateCanUseLCDText(bool raster_translation_aligns_pixels)819 void PictureLayerImpl::UpdateCanUseLCDText(
820     bool raster_translation_aligns_pixels) {
821   // If we have pending/active trees, the active tree doesn't update lcd text
822   // status but copies it from the pending tree.
823   if (!layer_tree_impl()->IsSyncTree())
824     return;
825 
826   lcd_text_disallowed_reason_ =
827       ComputeLCDTextDisallowedReason(raster_translation_aligns_pixels);
828 }
829 
HasWillChangeTransformHint() const830 bool PictureLayerImpl::HasWillChangeTransformHint() const {
831   TransformNode* transform_node =
832       GetTransformTree().Node(transform_tree_index());
833   return transform_node && transform_node->will_change_transform;
834 }
835 
ComputeLCDTextDisallowedReason(bool raster_translation_aligns_pixels) const836 LCDTextDisallowedReason PictureLayerImpl::ComputeLCDTextDisallowedReason(
837     bool raster_translation_aligns_pixels) const {
838   // No need to use LCD text if there is no text.
839   if (!raster_source_ || !raster_source_->GetDisplayItemList() ||
840       !raster_source_->GetDisplayItemList()->has_draw_text_ops()) {
841     return LCDTextDisallowedReason::kNoText;
842   }
843 
844   if (layer_tree_impl()->settings().layers_always_allowed_lcd_text)
845     return LCDTextDisallowedReason::kNone;
846   if (!layer_tree_impl()->settings().can_use_lcd_text)
847     return LCDTextDisallowedReason::kSetting;
848   if (!contents_opaque_for_text()) {
849     if (SkColorGetA(background_color()) != SK_AlphaOPAQUE)
850       return LCDTextDisallowedReason::kBackgroundColorNotOpaque;
851     return LCDTextDisallowedReason::kContentsNotOpaque;
852   }
853 
854   // If raster translation aligns pixels, we can ignore fractional layer offset
855   // and transform for LCD text.
856   if (!raster_translation_aligns_pixels) {
857     if (static_cast<int>(offset_to_transform_parent().x()) !=
858         offset_to_transform_parent().x())
859       return LCDTextDisallowedReason::kNonIntegralXOffset;
860     if (static_cast<int>(offset_to_transform_parent().y()) !=
861         offset_to_transform_parent().y())
862       return LCDTextDisallowedReason::kNonIntegralYOffset;
863     return LCDTextDisallowedReason::kNonIntegralTranslation;
864   }
865 
866   TransformNode* transform_node =
867       GetTransformTree().Node(transform_tree_index());
868   if (transform_node->node_or_ancestors_will_change_transform)
869     return LCDTextDisallowedReason::kWillChangeTransform;
870 
871   if (screen_space_transform_is_animating())
872     return LCDTextDisallowedReason::kTransformAnimation;
873 
874   EffectNode* effect_node = GetEffectTree().Node(effect_tree_index());
875   if (effect_node->node_or_ancestor_has_filters ||
876       effect_node->affected_by_backdrop_filter)
877     return LCDTextDisallowedReason::kPixelOrColorEffect;
878 
879   return LCDTextDisallowedReason::kNone;
880 }
881 
882 LCDTextDisallowedReason
ComputeLCDTextDisallowedReasonForTesting() const883 PictureLayerImpl::ComputeLCDTextDisallowedReasonForTesting() const {
884   gfx::Vector2dF raster_translation;
885   return ComputeLCDTextDisallowedReason(
886       CalculateRasterTranslation(raster_translation));
887 }
888 
NotifyTileStateChanged(const Tile * tile)889 void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
890   if (layer_tree_impl()->IsActiveTree())
891     damage_rect_.Union(tile->enclosing_layer_rect());
892   if (tile->draw_info().NeedsRaster()) {
893     PictureLayerTiling* tiling =
894         tilings_->FindTilingWithScaleKey(tile->contents_scale_key());
895     if (tiling)
896       tiling->set_all_tiles_done(false);
897   }
898 }
899 
GetDamageRect() const900 gfx::Rect PictureLayerImpl::GetDamageRect() const {
901   return damage_rect_;
902 }
903 
ResetChangeTracking()904 void PictureLayerImpl::ResetChangeTracking() {
905   LayerImpl::ResetChangeTracking();
906   damage_rect_.SetRect(0, 0, 0, 0);
907 }
908 
DidBeginTracing()909 void PictureLayerImpl::DidBeginTracing() {
910   raster_source_->DidBeginTracing();
911 }
912 
ReleaseResources()913 void PictureLayerImpl::ReleaseResources() {
914   tilings_->ReleaseAllResources();
915   ResetRasterScale();
916 }
917 
ReleaseTileResources()918 void PictureLayerImpl::ReleaseTileResources() {
919   // All resources are tile resources.
920   ReleaseResources();
921 }
922 
RecreateTileResources()923 void PictureLayerImpl::RecreateTileResources() {
924   // Recreate tilings with new settings, since some of those might change when
925   // we release resources.
926   tilings_ = CreatePictureLayerTilingSet();
927 }
928 
GetInvalidationRegionForDebugging()929 Region PictureLayerImpl::GetInvalidationRegionForDebugging() {
930   // |invalidation_| gives the invalidation contained in the source frame, but
931   // is not cleared after drawing from the layer. However, update_rect() is
932   // cleared once the invalidation is drawn, which is useful for debugging
933   // visualizations. This method intersects the two to give a more exact
934   // representation of what was invalidated that is cleared after drawing.
935   return IntersectRegions(invalidation_, update_rect());
936 }
937 
CreateTile(const Tile::CreateInfo & info)938 std::unique_ptr<Tile> PictureLayerImpl::CreateTile(
939     const Tile::CreateInfo& info) {
940   int flags = 0;
941 
942   // We don't handle solid color single texture masks for backdrop filters,
943   // so we shouldn't bother analyzing those.
944   // Otherwise, always analyze to maximize memory savings.
945   if (!is_backdrop_filter_mask_)
946     flags = Tile::USE_PICTURE_ANALYSIS;
947 
948   if (contents_opaque())
949     flags |= Tile::IS_OPAQUE;
950 
951   return layer_tree_impl()->tile_manager()->CreateTile(
952       info, id(), layer_tree_impl()->source_frame_number(), flags);
953 }
954 
GetPendingInvalidation()955 const Region* PictureLayerImpl::GetPendingInvalidation() {
956   if (layer_tree_impl()->IsPendingTree())
957     return &invalidation_;
958   if (layer_tree_impl()->IsRecycleTree())
959     return nullptr;
960   DCHECK(layer_tree_impl()->IsActiveTree());
961   if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer())
962     return &twin_layer->invalidation_;
963   return nullptr;
964 }
965 
GetPendingOrActiveTwinTiling(const PictureLayerTiling * tiling) const966 const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling(
967     const PictureLayerTiling* tiling) const {
968   PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer();
969   if (!twin_layer)
970     return nullptr;
971   const PictureLayerTiling* twin_tiling =
972       twin_layer->tilings_->FindTilingWithScaleKey(
973           tiling->contents_scale_key());
974   if (twin_tiling &&
975       twin_tiling->raster_transform() == tiling->raster_transform())
976     return twin_tiling;
977   return nullptr;
978 }
979 
RequiresHighResToDraw() const980 bool PictureLayerImpl::RequiresHighResToDraw() const {
981   return layer_tree_impl()->RequiresHighResToDraw();
982 }
983 
GetPaintWorkletRecords() const984 const PaintWorkletRecordMap& PictureLayerImpl::GetPaintWorkletRecords() const {
985   return paint_worklet_records_;
986 }
987 
IsDirectlyCompositedImage() const988 bool PictureLayerImpl::IsDirectlyCompositedImage() const {
989   return directly_composited_image_size_.has_value();
990 }
991 
GetEnclosingRectInTargetSpace() const992 gfx::Rect PictureLayerImpl::GetEnclosingRectInTargetSpace() const {
993   return GetScaledEnclosingRectInTargetSpace(MaximumTilingContentsScale());
994 }
995 
ShouldAnimate(PaintImage::Id paint_image_id) const996 bool PictureLayerImpl::ShouldAnimate(PaintImage::Id paint_image_id) const {
997   // If we are registered with the animation controller, which queries whether
998   // the image should be animated, then we must have recordings with this image.
999   DCHECK(raster_source_);
1000   DCHECK(raster_source_->GetDisplayItemList());
1001   DCHECK(
1002       !raster_source_->GetDisplayItemList()->discardable_image_map().empty());
1003 
1004   // Only animate images for layers which HasValidTilePriorities. This check is
1005   // important for 2 reasons:
1006   // 1) It avoids doing additional work for layers we don't plan to rasterize
1007   //    and/or draw. The updated state will be pulled by the animation system
1008   //    if the draw properties change.
1009   // 2) It eliminates considering layers on the recycle tree. Once the pending
1010   //    tree is activated, the layers on the recycle tree remain registered as
1011   //    animation drivers, but should not drive animations since they don't have
1012   //    updated draw properties.
1013   //
1014   //  Additionally only animate images which are on-screen, animations are
1015   //  paused once they are not visible.
1016   if (!HasValidTilePriorities())
1017     return false;
1018 
1019   const auto& rects = raster_source_->GetDisplayItemList()
1020                           ->discardable_image_map()
1021                           .GetRectsForImage(paint_image_id);
1022   for (const auto& r : rects.container()) {
1023     if (r.Intersects(visible_layer_rect()))
1024       return true;
1025   }
1026   return false;
1027 }
1028 
CalculateTileSize(const gfx::Size & content_bounds)1029 gfx::Size PictureLayerImpl::CalculateTileSize(const gfx::Size& content_bounds) {
1030   content_bounds_ = content_bounds;
1031   return tile_size_calculator_.CalculateTileSize();
1032 }
1033 
GetContentsResourceId(viz::ResourceId * resource_id,gfx::Size * resource_size,gfx::SizeF * resource_uv_size) const1034 void PictureLayerImpl::GetContentsResourceId(
1035     viz::ResourceId* resource_id,
1036     gfx::Size* resource_size,
1037     gfx::SizeF* resource_uv_size) const {
1038   // We need contents resource for backdrop filter masks only.
1039   if (!is_backdrop_filter_mask()) {
1040     *resource_id = 0;
1041     return;
1042   }
1043 
1044   // The bounds and the pile size may differ if the pile wasn't updated (ie.
1045   // PictureLayer::Update didn't happen). In that case the pile will be empty.
1046   DCHECK(raster_source_->GetSize().IsEmpty() ||
1047          bounds() == raster_source_->GetSize())
1048       << " bounds " << bounds().ToString() << " pile "
1049       << raster_source_->GetSize().ToString();
1050   float dest_scale = MaximumTilingContentsScale();
1051   gfx::Rect content_rect =
1052       gfx::ScaleToEnclosingRect(gfx::Rect(bounds()), dest_scale);
1053   PictureLayerTilingSet::CoverageIterator iter(
1054       tilings_.get(), dest_scale, content_rect, ideal_contents_scale_);
1055 
1056   // Mask resource not ready yet.
1057   if (!iter || !*iter) {
1058     *resource_id = 0;
1059     return;
1060   }
1061 
1062   // Masks only supported if they fit on exactly one tile.
1063   DCHECK(iter.geometry_rect() == content_rect)
1064       << "iter rect " << iter.geometry_rect().ToString() << " content rect "
1065       << content_rect.ToString();
1066 
1067   const TileDrawInfo& draw_info = iter->draw_info();
1068   if (!draw_info.IsReadyToDraw() ||
1069       draw_info.mode() != TileDrawInfo::RESOURCE_MODE) {
1070     *resource_id = 0;
1071     return;
1072   }
1073 
1074   *resource_id = draw_info.resource_id_for_export();
1075   *resource_size = draw_info.resource_size();
1076   // |resource_uv_size| represents the range of UV coordinates that map to the
1077   // content being drawn. Typically, we draw to the entire texture, so these
1078   // coordinates are (1.0f, 1.0f). However, if we are rasterizing to an
1079   // over-large texture, this size will be smaller, mapping to the subset of the
1080   // texture being used.
1081   gfx::SizeF requested_tile_size =
1082       gfx::SizeF(iter->tiling()->tiling_data()->tiling_size());
1083   DCHECK_LE(requested_tile_size.width(), draw_info.resource_size().width());
1084   DCHECK_LE(requested_tile_size.height(), draw_info.resource_size().height());
1085   *resource_uv_size = gfx::SizeF(
1086       requested_tile_size.width() / draw_info.resource_size().width(),
1087       requested_tile_size.height() / draw_info.resource_size().height());
1088 }
1089 
SetNearestNeighbor(bool nearest_neighbor)1090 void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) {
1091   if (nearest_neighbor_ == nearest_neighbor)
1092     return;
1093 
1094   nearest_neighbor_ = nearest_neighbor;
1095   NoteLayerPropertyChanged();
1096 }
1097 
SetDirectlyCompositedImageSize(base::Optional<gfx::Size> size)1098 void PictureLayerImpl::SetDirectlyCompositedImageSize(
1099     base::Optional<gfx::Size> size) {
1100   if (directly_composited_image_size_ == size)
1101     return;
1102 
1103   directly_composited_image_size_ = size;
1104   NoteLayerPropertyChanged();
1105 }
1106 
ShouldDirectlyCompositeImage(float raster_scale) const1107 bool PictureLayerImpl::ShouldDirectlyCompositeImage(float raster_scale) const {
1108   // Even if there are minor rendering differences, we want to apply directly
1109   // compositing images in cases where doing so is going to save memory.
1110   if (raster_scale < 0.1f)
1111     return true;
1112 
1113 #if defined(OS_FUCHSIA)
1114   // Always downscale images on low-end devices to save memory. This is a
1115   // temporary fix to work around crbug.com/1161327 .
1116   // TODO(crbug.com/1161327): Implement proper solution that works on all
1117   // devices.
1118   if (base::SysInfo::IsLowEndDevice() && raster_scale > 1.0)
1119     return false;
1120 #endif  // defined(OS_FUCHSIA)
1121 
1122   // If the results of scaling the bounds by the expected raster scale
1123   // would end up with a content rect whose width/height are more than one
1124   // pixel different from the layer bounds, don't directly composite the image
1125   // to avoid incorrect rendering.
1126   gfx::SizeF layer_bounds(bounds());
1127   gfx::RectF scaled_bounds_rect(layer_bounds);
1128   scaled_bounds_rect.Scale(raster_scale);
1129 
1130   // Take the scaled bounds, get the enclosing rect then scale it back down -
1131   // this is the same set of operations that will happen when using the tiling
1132   // at that raster scale.
1133   gfx::RectF content_rect(gfx::ToEnclosingRect(scaled_bounds_rect));
1134   content_rect.Scale(1 / raster_scale);
1135 
1136   return std::abs(layer_bounds.width() - content_rect.width()) < 1.f &&
1137          std::abs(layer_bounds.height() - content_rect.height()) < 1.f;
1138 }
1139 
GetDefaultDirectlyCompositedImageRasterScale() const1140 float PictureLayerImpl::GetDefaultDirectlyCompositedImageRasterScale() const {
1141   DCHECK(directly_composited_image_size_.has_value());
1142   float x = static_cast<float>(directly_composited_image_size_->width()) /
1143             bounds().width();
1144   float y = static_cast<float>(directly_composited_image_size_->height()) /
1145             bounds().height();
1146   return GetPreferredRasterScale(gfx::Vector2dF(x, y));
1147 }
1148 
CalculateDirectlyCompositedImageRasterScale() const1149 float PictureLayerImpl::CalculateDirectlyCompositedImageRasterScale() const {
1150   float default_raster_scale = GetDefaultDirectlyCompositedImageRasterScale();
1151   bool default_raster_scale_changed =
1152       default_raster_scale != directly_composited_image_initial_raster_scale_;
1153 
1154   // If the default raster scale didn't change, we will calculate based on the
1155   // previous raster source scale. The calculation may change based on updated
1156   // ideal source scale.
1157   float adjusted_raster_scale = default_raster_scale_changed
1158                                     ? default_raster_scale
1159                                     : raster_source_scale_;
1160 
1161   // We never want a raster scale larger than the default, since that uses more
1162   // memory but can't result it better quality (upscaling will happen in the
1163   // display compositor instead).
1164   float max_scale = std::max(default_raster_scale, MinimumContentsScale());
1165   float min_scale = MinimumContentsScale();
1166 
1167   float clamped_ideal_source_scale =
1168       base::ClampToRange(ideal_source_scale_, min_scale, max_scale);
1169   while (adjusted_raster_scale < clamped_ideal_source_scale)
1170     adjusted_raster_scale *= 2.f;
1171   while (adjusted_raster_scale > 4 * clamped_ideal_source_scale)
1172     adjusted_raster_scale /= 2.f;
1173 
1174   adjusted_raster_scale =
1175       base::ClampToRange(adjusted_raster_scale, min_scale, max_scale);
1176   return adjusted_raster_scale;
1177 }
1178 
AddTiling(const gfx::AxisTransform2d & raster_transform)1179 PictureLayerTiling* PictureLayerImpl::AddTiling(
1180     const gfx::AxisTransform2d& raster_transform) {
1181   DCHECK(CanHaveTilings());
1182   DCHECK_GE(raster_transform.scale(), MinimumContentsScale());
1183   DCHECK_LE(raster_transform.scale(), MaximumContentsScale());
1184   DCHECK(raster_source_->HasRecordings());
1185   bool tiling_can_use_lcd_text =
1186       can_use_lcd_text() && raster_transform.scale() == raster_contents_scale_;
1187   return tilings_->AddTiling(raster_transform, raster_source_,
1188                              tiling_can_use_lcd_text);
1189 }
1190 
RemoveAllTilings()1191 void PictureLayerImpl::RemoveAllTilings() {
1192   tilings_->RemoveAllTilings();
1193   // If there are no tilings, then raster scales are no longer meaningful.
1194   ResetRasterScale();
1195 }
1196 
CanRecreateHighResTilingForLCDTextAndRasterTranslation(const PictureLayerTiling & high_res) const1197 bool PictureLayerImpl::CanRecreateHighResTilingForLCDTextAndRasterTranslation(
1198     const PictureLayerTiling& high_res) const {
1199   // This is for the sync tree only to avoid flickering.
1200   if (!layer_tree_impl()->IsSyncTree())
1201     return false;
1202   // We can recreate the tiling if we would invalidate all of its tiles.
1203   if (high_res.may_contain_low_resolution_tiles())
1204     return true;
1205   // Keep the non-ideal raster translation unchanged for transform animations
1206   // to avoid re-rasterization during animation.
1207   if (draw_properties().screen_space_transform_is_animating ||
1208       HasWillChangeTransformHint())
1209     return false;
1210   // Also avoid re-rasterization during pinch-zoom.
1211   if (layer_tree_impl()->PinchGestureActive())
1212     return false;
1213   // Keep the current LCD text and raster translation if there is no text.
1214   if (lcd_text_disallowed_reason_ == LCDTextDisallowedReason::kNoText)
1215     return false;
1216   return true;
1217 }
1218 
UpdateTilingsForRasterScaleAndTranslation(bool has_adjusted_raster_scale)1219 void PictureLayerImpl::UpdateTilingsForRasterScaleAndTranslation(
1220     bool has_adjusted_raster_scale) {
1221   PictureLayerTiling* high_res =
1222       tilings_->FindTilingWithScaleKey(raster_contents_scale_);
1223 
1224   gfx::Vector2dF raster_translation;
1225   bool raster_translation_aligns_pixels =
1226       CalculateRasterTranslation(raster_translation);
1227   UpdateCanUseLCDText(raster_translation_aligns_pixels);
1228   if (high_res) {
1229     bool raster_translation_is_not_ideal =
1230         high_res->raster_transform().translation() != raster_translation;
1231     bool can_use_lcd_text_changed =
1232         high_res->can_use_lcd_text() != can_use_lcd_text();
1233     bool should_recreate_high_res =
1234         (raster_translation_is_not_ideal || can_use_lcd_text_changed) &&
1235         CanRecreateHighResTilingForLCDTextAndRasterTranslation(*high_res);
1236     if (should_recreate_high_res) {
1237       tilings_->Remove(high_res);
1238       high_res = nullptr;
1239     } else if (!has_adjusted_raster_scale) {
1240       // Nothing changed, no need to update tilings.
1241       DCHECK_EQ(HIGH_RESOLUTION, high_res->resolution());
1242       SanityCheckTilingState();
1243       return;
1244     }
1245   }
1246 
1247   // Reset all resolution enums on tilings, we'll be setting new values in this
1248   // function.
1249   tilings_->MarkAllTilingsNonIdeal();
1250 
1251   if (!high_res) {
1252     // We always need a high res tiling, so create one if it doesn't exist.
1253     high_res = AddTiling(
1254         gfx::AxisTransform2d(raster_contents_scale_, raster_translation));
1255   } else if (high_res->may_contain_low_resolution_tiles()) {
1256     // If the tiling we find here was LOW_RESOLUTION previously, it may not be
1257     // fully rastered, so destroy the old tiles.
1258     high_res->Reset();
1259     // Reset the flag now that we'll make it high res, it will have fully
1260     // rastered content.
1261     high_res->reset_may_contain_low_resolution_tiles();
1262   }
1263   high_res->set_resolution(HIGH_RESOLUTION);
1264 
1265   if (layer_tree_impl()->IsPendingTree() ||
1266       (layer_tree_impl()->settings().commit_to_active_tree &&
1267        directly_composited_image_size_.has_value())) {
1268     // On the pending tree, drop any tilings that are non-ideal since we don't
1269     // need them to activate anyway.
1270 
1271     // For DirectlyCompositedImages, if we recomputed a new raster scale, we
1272     // should drop the non-ideal ones if we're committing to the active tree.
1273     // Otherwise a non-ideal scale that is _larger_ than the HIGH_RESOLUTION
1274     // tile will be used as the coverage scale, and we'll produce a slightly
1275     // different rendering. We don't drop the tilings on the active tree if
1276     // we're not committing to the active tree to prevent checkerboarding.
1277     tilings_->RemoveNonIdealTilings();
1278   }
1279 
1280   SanityCheckTilingState();
1281 }
1282 
ShouldAdjustRasterScale() const1283 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
1284   if (!raster_contents_scale_)
1285     return true;
1286 
1287   if (directly_composited_image_size_) {
1288     // If we have a directly composited image size, but previous raster scale
1289     // calculations did not set an initial raster scale, we must recalcluate.
1290     if (directly_composited_image_initial_raster_scale_ == 0)
1291       return true;
1292 
1293     float default_raster_scale = GetDefaultDirectlyCompositedImageRasterScale();
1294 
1295     // First check to see if we need to adjust based on ideal_source_scale_
1296     // changing (i.e. scale transform has been modified). These limits exist
1297     // so that we don't raster at the intrinsic image size if the layer will
1298     // be scaled down more than 4x ideal. This saves memory without sacrificing
1299     // noticeable quality. We'll also bump the scale back up in the case where
1300     // the ideal scale is increased.
1301     float max_scale = std::max(default_raster_scale, MinimumContentsScale());
1302     if (raster_source_scale_ < std::min(ideal_source_scale_, max_scale))
1303       return true;
1304     if (raster_source_scale_ > 4 * ideal_source_scale_)
1305       return true;
1306 
1307     // If the default raster scale changed, that means the bounds or image size
1308     // changed. We should recalculate in order to raster at the intrinsic image
1309     // size. Note that this is not a comparison of the used raster_source_scale_
1310     // and desired because of the adjustments in RecalculateRasterScales.
1311     bool default_raster_scale_changed =
1312         default_raster_scale != directly_composited_image_initial_raster_scale_;
1313     return default_raster_scale_changed;
1314   }
1315 
1316   if (was_screen_space_transform_animating_ !=
1317       draw_properties().screen_space_transform_is_animating) {
1318     // Skip adjusting raster scale when animations finish if we have a
1319     // will-change: transform hint to preserve maximum resolution tiles
1320     // needed.
1321     if (draw_properties().screen_space_transform_is_animating ||
1322         !HasWillChangeTransformHint())
1323       return true;
1324   }
1325 
1326   bool is_pinching = layer_tree_impl()->PinchGestureActive();
1327   if (is_pinching && raster_page_scale_) {
1328     // We change our raster scale when it is:
1329     // - Higher than ideal (need a lower-res tiling available)
1330     // - Too far from ideal (need a higher-res tiling available)
1331     float ratio = ideal_page_scale_ / raster_page_scale_;
1332     if (raster_page_scale_ > ideal_page_scale_ ||
1333         ratio > kMaxScaleRatioDuringPinch)
1334       return true;
1335   }
1336 
1337   if (!is_pinching) {
1338     // When not pinching, match the ideal page scale factor.
1339     if (raster_page_scale_ != ideal_page_scale_)
1340       return true;
1341   }
1342 
1343   // Always match the ideal device scale factor.
1344   if (raster_device_scale_ != ideal_device_scale_)
1345     return true;
1346 
1347   if (raster_contents_scale_ > MaximumContentsScale())
1348     return true;
1349   if (raster_contents_scale_ < MinimumContentsScale())
1350     return true;
1351 
1352   // Don't change the raster scale if any of the following are true:
1353   //  - We have an animating transform.
1354   //  - The raster scale is already ideal.
1355   if (draw_properties().screen_space_transform_is_animating ||
1356       raster_source_scale_ == ideal_source_scale_) {
1357     return false;
1358   }
1359 
1360   // Don't update will-change: transform layers if the raster contents scale is
1361   // bigger than the minimum scale.
1362   if (HasWillChangeTransformHint() &&
1363       raster_contents_scale_ >=
1364           MinimumRasterContentsScaleForWillChangeTransform()) {
1365     return false;
1366   }
1367 
1368   // Match the raster scale in all other cases.
1369   return true;
1370 }
1371 
AddLowResolutionTilingIfNeeded()1372 void PictureLayerImpl::AddLowResolutionTilingIfNeeded() {
1373   DCHECK(layer_tree_impl()->IsActiveTree());
1374 
1375   if (!layer_tree_impl()->create_low_res_tiling())
1376     return;
1377 
1378   // We should have a high resolution tiling at raster_contents_scale, so if the
1379   // low res one is the same then we shouldn't try to override this tiling by
1380   // marking it as a low res.
1381   if (raster_contents_scale_ == low_res_raster_contents_scale_)
1382     return;
1383 
1384   PictureLayerTiling* low_res =
1385       tilings_->FindTilingWithScaleKey(low_res_raster_contents_scale_);
1386   DCHECK(!low_res || low_res->resolution() != HIGH_RESOLUTION);
1387 
1388   // Only create new low res tilings when the transform is static.  This
1389   // prevents wastefully creating a paired low res tiling for every new high
1390   // res tiling during a pinch or a CSS animation.
1391   bool is_pinching = layer_tree_impl()->PinchGestureActive();
1392   bool is_animating = draw_properties().screen_space_transform_is_animating;
1393   if (!is_pinching && !is_animating) {
1394     if (!low_res)
1395       low_res = AddTiling(gfx::AxisTransform2d(low_res_raster_contents_scale_,
1396                                                gfx::Vector2dF()));
1397     low_res->set_resolution(LOW_RESOLUTION);
1398   }
1399 }
1400 
RecalculateRasterScales()1401 void PictureLayerImpl::RecalculateRasterScales() {
1402   if (directly_composited_image_size_) {
1403     float used_raster_scale = CalculateDirectlyCompositedImageRasterScale();
1404     if (ShouldDirectlyCompositeImage(used_raster_scale)) {
1405       directly_composited_image_initial_raster_scale_ =
1406           GetDefaultDirectlyCompositedImageRasterScale();
1407       raster_source_scale_ = used_raster_scale;
1408       raster_page_scale_ = 1.f;
1409       raster_device_scale_ = 1.f;
1410       raster_contents_scale_ = raster_source_scale_;
1411       low_res_raster_contents_scale_ = raster_contents_scale_;
1412       return;
1413     }
1414 
1415     // If we should not directly composite this image, reset values and fall
1416     // back to normal raster scale calculations below.
1417     directly_composited_image_size_ = base::nullopt;
1418     directly_composited_image_initial_raster_scale_ = 0.f;
1419   }
1420 
1421   float old_raster_contents_scale = raster_contents_scale_;
1422   float old_raster_page_scale = raster_page_scale_;
1423 
1424   // The raster scale if previous tilings should be preserved.
1425   float preserved_raster_contents_scale = old_raster_contents_scale;
1426 
1427   raster_device_scale_ = ideal_device_scale_;
1428   raster_page_scale_ = ideal_page_scale_;
1429   raster_source_scale_ = ideal_source_scale_;
1430   raster_contents_scale_ = ideal_contents_scale_;
1431 
1432   // During pinch we completely ignore the current ideal scale, and just use
1433   // a multiple of the previous scale.
1434   bool is_pinching = layer_tree_impl()->PinchGestureActive();
1435   if (is_pinching && old_raster_contents_scale) {
1436     // See ShouldAdjustRasterScale:
1437     // - When zooming out, preemptively create new tiling at lower resolution.
1438     // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1439     bool zooming_out = old_raster_page_scale > ideal_page_scale_;
1440     float desired_contents_scale = old_raster_contents_scale;
1441     if (zooming_out) {
1442       while (desired_contents_scale > ideal_contents_scale_)
1443         desired_contents_scale /= kMaxScaleRatioDuringPinch;
1444     } else {
1445       while (desired_contents_scale < ideal_contents_scale_)
1446         desired_contents_scale *= kMaxScaleRatioDuringPinch;
1447     }
1448     raster_contents_scale_ = preserved_raster_contents_scale =
1449         tilings_->GetSnappedContentsScaleKey(desired_contents_scale,
1450                                              kSnapToExistingTilingRatio);
1451     raster_page_scale_ =
1452         raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
1453   }
1454 
1455   if (draw_properties().screen_space_transform_is_animating)
1456     AdjustRasterScaleForTransformAnimation(preserved_raster_contents_scale);
1457 
1458   if (HasWillChangeTransformHint()) {
1459     raster_contents_scale_ =
1460         std::max(raster_contents_scale_,
1461                  MinimumRasterContentsScaleForWillChangeTransform());
1462   }
1463 
1464   raster_contents_scale_ =
1465       std::max(raster_contents_scale_, MinimumContentsScale());
1466   raster_contents_scale_ =
1467       std::min(raster_contents_scale_, MaximumContentsScale());
1468   DCHECK_GE(raster_contents_scale_, MinimumContentsScale());
1469   DCHECK_LE(raster_contents_scale_, MaximumContentsScale());
1470 
1471   // If this layer would create zero or one tiles at this content scale,
1472   // don't create a low res tiling.
1473   gfx::Size raster_bounds =
1474       gfx::ScaleToCeiledSize(raster_source_->GetSize(), raster_contents_scale_);
1475   gfx::Size tile_size = CalculateTileSize(raster_bounds);
1476   bool tile_covers_bounds = tile_size.width() >= raster_bounds.width() &&
1477                             tile_size.height() >= raster_bounds.height();
1478   if (tile_size.IsEmpty() || tile_covers_bounds) {
1479     low_res_raster_contents_scale_ = raster_contents_scale_;
1480     return;
1481   }
1482 
1483   float low_res_factor =
1484       layer_tree_impl()->settings().low_res_contents_scale_factor;
1485   low_res_raster_contents_scale_ =
1486       std::max(raster_contents_scale_ * low_res_factor, MinimumContentsScale());
1487   DCHECK_LE(low_res_raster_contents_scale_, raster_contents_scale_);
1488   DCHECK_GE(low_res_raster_contents_scale_, MinimumContentsScale());
1489   DCHECK_LE(low_res_raster_contents_scale_, MaximumContentsScale());
1490 }
1491 
AdjustRasterScaleForTransformAnimation(float preserved_raster_contents_scale)1492 void PictureLayerImpl::AdjustRasterScaleForTransformAnimation(
1493     float preserved_raster_contents_scale) {
1494   DCHECK(draw_properties().screen_space_transform_is_animating);
1495 
1496   CombinedAnimationScale animation_scales =
1497       layer_tree_impl()->property_trees()->GetAnimationScales(
1498           transform_tree_index(), layer_tree_impl());
1499   float maximum_scale = animation_scales.maximum_animation_scale;
1500   float starting_scale = animation_scales.starting_animation_scale;
1501   // Adjust raster scale only if the animation scale is known.
1502   if (maximum_scale == kNotScaled && starting_scale == kNotScaled) {
1503     // Use at least the native scale if the animation scale is unknown.
1504     raster_contents_scale_ = std::max(raster_contents_scale_,
1505                                       ideal_page_scale_ * ideal_device_scale_);
1506   } else {
1507     // We rasterize at the maximum scale that will occur during the animation.
1508     raster_contents_scale_ = std::max(maximum_scale, starting_scale);
1509   }
1510   DCHECK_NE(raster_contents_scale_, kNotScaled);
1511 
1512   // We will cap the adjusted scale with the viewport area, which is impossible
1513   // if the viewport is empty.
1514   gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
1515   if (viewport.IsEmpty())
1516     return;
1517 
1518   // However we want to avoid excessive memory use. Choose a scale at which this
1519   // layer's rastered content is not larger than the viewport.
1520   float max_viewport_dimension = std::max(viewport.width(), viewport.height());
1521   DCHECK(max_viewport_dimension);
1522   // Use square to compensate for viewports with different aspect ratios.
1523   float squared_viewport_area = max_viewport_dimension * max_viewport_dimension;
1524   gfx::Size bounds_at_maximum_scale =
1525       gfx::ScaleToCeiledSize(raster_source_->GetSize(), raster_contents_scale_);
1526   float maximum_area = static_cast<float>(bounds_at_maximum_scale.width()) *
1527                        bounds_at_maximum_scale.height();
1528   // Clamp the scale to make the rastered content not larger than the viewport.
1529   if (UNLIKELY(maximum_area > squared_viewport_area))
1530     raster_contents_scale_ /= std::sqrt(maximum_area / squared_viewport_area);
1531 
1532   if (HasWillChangeTransformHint()) {
1533     // If we have a will-change: transform hint, do not shrink the content
1534     // raster scale, otherwise we will end up throwing away larger tiles we
1535     // may need again.
1536     raster_contents_scale_ =
1537         std::max(preserved_raster_contents_scale, raster_contents_scale_);
1538   }
1539 }
1540 
CleanUpTilingsOnActiveLayer(const std::vector<PictureLayerTiling * > & used_tilings)1541 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1542     const std::vector<PictureLayerTiling*>& used_tilings) {
1543   DCHECK(layer_tree_impl()->IsActiveTree());
1544   if (tilings_->num_tilings() == 0)
1545     return;
1546 
1547   float min_acceptable_high_res_scale = std::min(
1548       raster_contents_scale_, ideal_contents_scale_);
1549   float max_acceptable_high_res_scale = std::max(
1550       raster_contents_scale_, ideal_contents_scale_);
1551 
1552   PictureLayerImpl* twin = GetPendingOrActiveTwinLayer();
1553   if (twin && twin->CanHaveTilings()) {
1554     min_acceptable_high_res_scale =
1555         std::min({min_acceptable_high_res_scale, twin->raster_contents_scale_,
1556                   twin->ideal_contents_scale_});
1557     max_acceptable_high_res_scale =
1558         std::max({max_acceptable_high_res_scale, twin->raster_contents_scale_,
1559                   twin->ideal_contents_scale_});
1560   }
1561 
1562   PictureLayerTilingSet* twin_set = twin ? twin->tilings_.get() : nullptr;
1563   tilings_->CleanUpTilings(min_acceptable_high_res_scale,
1564                            max_acceptable_high_res_scale, used_tilings,
1565                            twin_set);
1566   DCHECK_GT(tilings_->num_tilings(), 0u);
1567   SanityCheckTilingState();
1568 }
1569 
MinimumRasterContentsScaleForWillChangeTransform() const1570 float PictureLayerImpl::MinimumRasterContentsScaleForWillChangeTransform()
1571     const {
1572   DCHECK(HasWillChangeTransformHint());
1573   float native_scale = ideal_device_scale_ * ideal_page_scale_;
1574   // Clamp will-change: transform layers to be at least the native scale,
1575   // unless the scale is too small to avoid too many tiles using too much tile
1576   // memory.
1577   if (ideal_contents_scale_ <
1578       native_scale * kMinScaleRatioForWillChangeTransform) {
1579     // Don't let the scale too small compared to the ideal scale.
1580     return ideal_contents_scale_ * kMinScaleRatioForWillChangeTransform;
1581   }
1582   return native_scale;
1583 }
1584 
CalculateRasterTranslation(gfx::Vector2dF & raster_translation) const1585 bool PictureLayerImpl::CalculateRasterTranslation(
1586     gfx::Vector2dF& raster_translation) const {
1587   // If this setting is set, the client (e.g. the Chromium UI) is sure that it
1588   // can almost always align raster pixels to physical pixels, and doesn't care
1589   // about temporary misalignment, so don't bother raster translation.
1590   if (layer_tree_impl()->settings().layers_always_allowed_lcd_text)
1591     return true;
1592 
1593   // No need to use raster translation if there is no text.
1594   if (!raster_source_ || !raster_source_->GetDisplayItemList() ||
1595       !raster_source_->GetDisplayItemList()->has_draw_text_ops()) {
1596     return false;
1597   }
1598 
1599   const gfx::Transform& screen_transform = ScreenSpaceTransform();
1600   gfx::Transform draw_transform = DrawTransform();
1601 
1602   if (!screen_transform.IsScaleOrTranslation() ||
1603       !draw_transform.IsScaleOrTranslation()) {
1604     return false;
1605   }
1606 
1607   // It is only useful to align the content space to the target space if their
1608   // relative pixel ratio is some small rational number. Currently we only
1609   // align if the relative pixel ratio is 1:1 (i.e. the scale components of
1610   // both the screen transform and the draw transform are approximately the same
1611   // as |raster_contents_scale_|). Good match if the maximum alignment error on
1612   // a layer of size 10000px does not exceed 0.001px.
1613   static constexpr float kPixelErrorThreshold = 0.001f;
1614   static constexpr float kScaleErrorThreshold = kPixelErrorThreshold / 10000;
1615   auto is_raster_scale = [this](float scale) -> bool {
1616     return std::abs(scale - raster_contents_scale_) <= kScaleErrorThreshold;
1617   };
1618   if (!is_raster_scale(screen_transform.matrix().getFloat(0, 0)) ||
1619       !is_raster_scale(screen_transform.matrix().getFloat(1, 1)) ||
1620       !is_raster_scale(draw_transform.matrix().getFloat(0, 0)) ||
1621       !is_raster_scale(draw_transform.matrix().getFloat(1, 1))) {
1622     return false;
1623   }
1624 
1625   // Extract the fractional part of layer origin in the screen space and in the
1626   // target space.
1627   auto fraction = [](float f) -> float { return f - floorf(f); };
1628   float screen_x_fraction = fraction(screen_transform.matrix().getFloat(0, 3));
1629   float screen_y_fraction = fraction(screen_transform.matrix().getFloat(1, 3));
1630   float target_x_fraction = fraction(draw_transform.matrix().getFloat(0, 3));
1631   float target_y_fraction = fraction(draw_transform.matrix().getFloat(1, 3));
1632 
1633   // If the origin is different in the screen space and in the target space,
1634   // it means the render target is not aligned to physical pixels, and the
1635   // text content will be blurry regardless of raster translation.
1636   if (std::abs(screen_x_fraction - target_x_fraction) > kPixelErrorThreshold ||
1637       std::abs(screen_y_fraction - target_y_fraction) > kPixelErrorThreshold) {
1638     return false;
1639   }
1640 
1641   raster_translation = gfx::Vector2dF(target_x_fraction, target_y_fraction);
1642   return true;
1643 }
1644 
MinimumContentsScale() const1645 float PictureLayerImpl::MinimumContentsScale() const {
1646   // If the contents scale is less than 1 / width (also for height),
1647   // then it will end up having less than one pixel of content in that
1648   // dimension.  Bump the minimum contents scale up in this case to prevent
1649   // this from happening.
1650   int min_dimension = std::min(raster_source_->GetSize().width(),
1651                                raster_source_->GetSize().height());
1652   return min_dimension ? 1.f / min_dimension : 1.f;
1653 }
1654 
MaximumContentsScale() const1655 float PictureLayerImpl::MaximumContentsScale() const {
1656   if (bounds().IsEmpty())
1657     return 0;
1658   // When mask tiling is disabled or the mask is single textured, masks can not
1659   // have tilings that would become larger than the max_texture_size since they
1660   // use a single tile for the entire tiling. Other layers can have tilings such
1661   // that dimension * scale does not overflow.
1662   float max_dimension = static_cast<float>(
1663       is_backdrop_filter_mask_ ? layer_tree_impl()->max_texture_size()
1664                                : std::numeric_limits<int>::max());
1665   int higher_dimension = std::max(bounds().width(), bounds().height());
1666   float max_scale = max_dimension / higher_dimension;
1667 
1668   // We require that multiplying the layer size by the contents scale and
1669   // ceiling produces a value <= |max_dimension|. Because for large layer
1670   // sizes floating point ambiguity may crop up, making the result larger or
1671   // smaller than expected, we use a slightly smaller floating point value for
1672   // the scale, to help ensure that the resulting content bounds will never end
1673   // up larger than |max_dimension|.
1674   return nextafterf(max_scale, 0.f);
1675 }
1676 
ResetRasterScale()1677 void PictureLayerImpl::ResetRasterScale() {
1678   raster_page_scale_ = 0.f;
1679   raster_device_scale_ = 0.f;
1680   raster_source_scale_ = 0.f;
1681   raster_contents_scale_ = 0.f;
1682   low_res_raster_contents_scale_ = 0.f;
1683   directly_composited_image_initial_raster_scale_ = 0.f;
1684 }
1685 
CanHaveTilings() const1686 bool PictureLayerImpl::CanHaveTilings() const {
1687   if (!raster_source_)
1688     return false;
1689   if (raster_source_->IsSolidColor())
1690     return false;
1691   if (!DrawsContent())
1692     return false;
1693   if (!raster_source_->HasRecordings())
1694     return false;
1695   // If the |raster_source_| has a recording it should have non-empty bounds.
1696   DCHECK(!raster_source_->GetSize().IsEmpty());
1697   if (MaximumContentsScale() < MinimumContentsScale())
1698     return false;
1699   return true;
1700 }
1701 
SanityCheckTilingState() const1702 void PictureLayerImpl::SanityCheckTilingState() const {
1703 #if DCHECK_IS_ON()
1704   if (!CanHaveTilings()) {
1705     DCHECK_EQ(0u, tilings_->num_tilings());
1706     return;
1707   }
1708   if (tilings_->num_tilings() == 0)
1709     return;
1710 
1711   // We should only have one high res tiling.
1712   DCHECK_EQ(1, tilings_->NumHighResTilings());
1713 #endif
1714 }
1715 
MaximumTilingContentsScale() const1716 float PictureLayerImpl::MaximumTilingContentsScale() const {
1717   float max_contents_scale = tilings_->GetMaximumContentsScale();
1718   return std::max(max_contents_scale, MinimumContentsScale());
1719 }
1720 
1721 std::unique_ptr<PictureLayerTilingSet>
CreatePictureLayerTilingSet()1722 PictureLayerImpl::CreatePictureLayerTilingSet() {
1723   const LayerTreeSettings& settings = layer_tree_impl()->settings();
1724   return PictureLayerTilingSet::Create(
1725       IsActive() ? ACTIVE_TREE : PENDING_TREE, this,
1726       settings.tiling_interest_area_padding,
1727       layer_tree_impl()->use_gpu_rasterization()
1728           ? settings.gpu_rasterization_skewport_target_time_in_seconds
1729           : settings.skewport_target_time_in_seconds,
1730       settings.skewport_extrapolation_limit_in_screen_pixels,
1731       settings.max_preraster_distance_in_screen_pixels);
1732 }
1733 
UpdateIdealScales()1734 void PictureLayerImpl::UpdateIdealScales() {
1735   DCHECK(CanHaveTilings());
1736 
1737   float min_contents_scale = MinimumContentsScale();
1738   DCHECK_GT(min_contents_scale, 0.f);
1739 
1740   ideal_device_scale_ = layer_tree_impl()->device_scale_factor();
1741   ideal_page_scale_ = 1.f;
1742   ideal_contents_scale_ = GetIdealContentsScale();
1743 
1744   if (layer_tree_impl()->PageScaleTransformNode()) {
1745     DCHECK(!layer_tree_impl()->settings().is_layer_tree_for_subframe);
1746     ideal_page_scale_ = IsAffectedByPageScale()
1747                             ? layer_tree_impl()->current_page_scale_factor()
1748                             : 1.f;
1749   }
1750 
1751   // This layer may be in a layer tree embedded in a hierarchy that has its own
1752   // page scale factor. We represent that here as 'external_page_scale_factor',
1753   // a value that affects raster scale in the same way that page_scale_factor
1754   // does, but doesn't affect any geometry calculations. In a normal main frame
1755   // or OOPIF, only one of current or external page scale factor is ever used
1756   // but not both. The only exception to this is a main frame in a portal. It
1757   // may have a current_page_scale_factor (e.g. due to a viewport <meta> tag)
1758   // as well as an external_page_scale_factor coming from the page scale of its
1759   // embedder page.
1760   float external_page_scale_factor =
1761       layer_tree_impl() ? layer_tree_impl()->external_page_scale_factor() : 1.f;
1762   DCHECK(!layer_tree_impl() ||
1763          !layer_tree_impl()->settings().is_layer_tree_for_subframe ||
1764          external_page_scale_factor == 1.f ||
1765          layer_tree_impl()->current_page_scale_factor() == 1.f);
1766   ideal_page_scale_ *= external_page_scale_factor;
1767   ideal_contents_scale_ *= external_page_scale_factor;
1768 
1769   ideal_contents_scale_ = base::ClampToRange(
1770       ideal_contents_scale_, min_contents_scale, kMaxIdealContentsScale);
1771   ideal_source_scale_ =
1772       ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_;
1773 }
1774 
GetDebugBorderProperties(SkColor * color,float * width) const1775 void PictureLayerImpl::GetDebugBorderProperties(
1776     SkColor* color,
1777     float* width) const {
1778   float device_scale_factor =
1779       layer_tree_impl() ? layer_tree_impl()->device_scale_factor() : 1;
1780 
1781   if (directly_composited_image_size_) {
1782     *color = DebugColors::ImageLayerBorderColor();
1783     *width = DebugColors::ImageLayerBorderWidth(device_scale_factor);
1784   } else {
1785     *color = DebugColors::TiledContentLayerBorderColor();
1786     *width = DebugColors::TiledContentLayerBorderWidth(device_scale_factor);
1787   }
1788 }
1789 
GetAllPrioritizedTilesForTracing(std::vector<PrioritizedTile> * prioritized_tiles) const1790 void PictureLayerImpl::GetAllPrioritizedTilesForTracing(
1791     std::vector<PrioritizedTile>* prioritized_tiles) const {
1792   if (!tilings_)
1793     return;
1794   tilings_->GetAllPrioritizedTilesForTracing(prioritized_tiles);
1795 }
1796 
AsValueInto(base::trace_event::TracedValue * state) const1797 void PictureLayerImpl::AsValueInto(
1798     base::trace_event::TracedValue* state) const {
1799   LayerImpl::AsValueInto(state);
1800   state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1801   state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1802   state->BeginArray("tilings");
1803   tilings_->AsValueInto(state);
1804   state->EndArray();
1805 
1806   MathUtil::AddToTracedValue("tile_priority_rect",
1807                              viewport_rect_for_tile_priority_in_content_space_,
1808                              state);
1809   MathUtil::AddToTracedValue("visible_rect", visible_layer_rect(), state);
1810 
1811   state->SetString(
1812       "lcd_text_disallowed_reason",
1813       LCDTextDisallowedReasonToString(lcd_text_disallowed_reason_));
1814 
1815   state->BeginArray("pictures");
1816   raster_source_->AsValueInto(state);
1817   state->EndArray();
1818 
1819   state->BeginArray("invalidation");
1820   invalidation_.AsValueInto(state);
1821   state->EndArray();
1822 
1823   state->BeginArray("coverage_tiles");
1824   for (PictureLayerTilingSet::CoverageIterator iter(
1825            tilings_.get(), MaximumTilingContentsScale(),
1826            gfx::Rect(raster_source_->GetSize()), ideal_contents_scale_);
1827        iter; ++iter) {
1828     state->BeginDictionary();
1829 
1830     MathUtil::AddToTracedValue("geometry_rect", iter.geometry_rect(), state);
1831 
1832     if (*iter)
1833       viz::TracedValue::SetIDRef(*iter, state, "tile");
1834 
1835     state->EndDictionary();
1836   }
1837   state->EndArray();
1838 
1839   state->BeginDictionary("can_have_tilings_state");
1840   state->SetBoolean("can_have_tilings", CanHaveTilings());
1841   state->SetBoolean("raster_source_solid_color",
1842                     raster_source_->IsSolidColor());
1843   state->SetBoolean("draws_content", DrawsContent());
1844   state->SetBoolean("raster_source_has_recordings",
1845                     raster_source_->HasRecordings());
1846   state->SetDouble("max_contents_scale", MaximumTilingContentsScale());
1847   state->SetDouble("min_contents_scale", MinimumContentsScale());
1848   state->EndDictionary();
1849 
1850   state->BeginDictionary("raster_scales");
1851   state->SetDouble("page_scale", raster_page_scale_);
1852   state->SetDouble("device_scale", raster_device_scale_);
1853   state->SetDouble("source_scale", raster_source_scale_);
1854   state->SetDouble("contents_scale", raster_contents_scale_);
1855   state->SetDouble("low_res_contents_scale", low_res_raster_contents_scale_);
1856   state->EndDictionary();
1857 
1858   state->BeginDictionary("ideal_scales");
1859   state->SetDouble("page_scale", ideal_page_scale_);
1860   state->SetDouble("device_scale", ideal_device_scale_);
1861   state->SetDouble("source_scale", ideal_source_scale_);
1862   state->SetDouble("contents_scale", ideal_contents_scale_);
1863   state->EndDictionary();
1864 }
1865 
GPUMemoryUsageInBytes() const1866 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1867   return tilings_->GPUMemoryUsageInBytes();
1868 }
1869 
RunMicroBenchmark(MicroBenchmarkImpl * benchmark)1870 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1871   benchmark->RunOnLayer(this);
1872 }
1873 
IsOnActiveOrPendingTree() const1874 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1875   return !layer_tree_impl()->IsRecycleTree();
1876 }
1877 
HasValidTilePriorities() const1878 bool PictureLayerImpl::HasValidTilePriorities() const {
1879   return IsOnActiveOrPendingTree() &&
1880          (contributes_to_drawn_render_surface() || raster_even_if_not_drawn());
1881 }
1882 
1883 PictureLayerImpl::ImageInvalidationResult
InvalidateRegionForImages(const PaintImageIdFlatSet & images_to_invalidate)1884 PictureLayerImpl::InvalidateRegionForImages(
1885     const PaintImageIdFlatSet& images_to_invalidate) {
1886   if (!raster_source_ || !raster_source_->GetDisplayItemList() ||
1887       raster_source_->GetDisplayItemList()->discardable_image_map().empty()) {
1888     return ImageInvalidationResult::kNoImages;
1889   }
1890 
1891   InvalidationRegion image_invalidation;
1892   for (auto image_id : images_to_invalidate) {
1893     const auto& rects = raster_source_->GetDisplayItemList()
1894                             ->discardable_image_map()
1895                             .GetRectsForImage(image_id);
1896     for (const auto& r : rects.container())
1897       image_invalidation.Union(r);
1898   }
1899   Region invalidation;
1900   image_invalidation.Swap(&invalidation);
1901 
1902   if (invalidation.IsEmpty())
1903     return ImageInvalidationResult::kNoInvalidation;
1904 
1905   // Note: We can use a rect here since this is only used to track damage for a
1906   // frame and not raster invalidation.
1907   UnionUpdateRect(invalidation.bounds());
1908 
1909   invalidation_.Union(invalidation);
1910   tilings_->Invalidate(invalidation);
1911   // TODO(crbug.com/303943): SetNeedsPushProperties() would be needed here if
1912   // PictureLayerImpl didn't always push properties every activation.
1913   return ImageInvalidationResult::kInvalidated;
1914 }
1915 
SetPaintWorkletRecord(scoped_refptr<const PaintWorkletInput> input,sk_sp<PaintRecord> record)1916 void PictureLayerImpl::SetPaintWorkletRecord(
1917     scoped_refptr<const PaintWorkletInput> input,
1918     sk_sp<PaintRecord> record) {
1919   DCHECK(paint_worklet_records_.find(input) != paint_worklet_records_.end());
1920   paint_worklet_records_[input].second = std::move(record);
1921 }
1922 
RegisterAnimatedImages()1923 void PictureLayerImpl::RegisterAnimatedImages() {
1924   if (!raster_source_ || !raster_source_->GetDisplayItemList())
1925     return;
1926 
1927   auto* controller = layer_tree_impl()->image_animation_controller();
1928   const auto& metadata = raster_source_->GetDisplayItemList()
1929                              ->discardable_image_map()
1930                              .animated_images_metadata();
1931   for (const auto& data : metadata) {
1932     // Only update the metadata from updated recordings received from a commit.
1933     if (layer_tree_impl()->IsSyncTree())
1934       controller->UpdateAnimatedImage(data);
1935     controller->RegisterAnimationDriver(data.paint_image_id, this);
1936   }
1937 }
1938 
UnregisterAnimatedImages()1939 void PictureLayerImpl::UnregisterAnimatedImages() {
1940   if (!raster_source_ || !raster_source_->GetDisplayItemList())
1941     return;
1942 
1943   auto* controller = layer_tree_impl()->image_animation_controller();
1944   const auto& metadata = raster_source_->GetDisplayItemList()
1945                              ->discardable_image_map()
1946                              .animated_images_metadata();
1947   for (const auto& data : metadata)
1948     controller->UnregisterAnimationDriver(data.paint_image_id, this);
1949 }
1950 
SetPaintWorkletInputs(const std::vector<DiscardableImageMap::PaintWorkletInputWithImageId> & inputs)1951 void PictureLayerImpl::SetPaintWorkletInputs(
1952     const std::vector<DiscardableImageMap::PaintWorkletInputWithImageId>&
1953         inputs) {
1954   // PaintWorklets are not supported when committing directly to the active
1955   // tree, so in that case the |inputs| should always be empty.
1956   DCHECK(layer_tree_impl()->IsPendingTree() || inputs.empty());
1957 
1958   bool had_paint_worklets = !paint_worklet_records_.empty();
1959   PaintWorkletRecordMap new_records;
1960   for (const auto& input_with_id : inputs) {
1961     const auto& input = input_with_id.first;
1962     const auto& paint_image_id = input_with_id.second;
1963     auto it = new_records.find(input);
1964     // We should never have multiple PaintImages sharing the same paint worklet.
1965     DCHECK(it == new_records.end() || it->second.first == paint_image_id);
1966     // Attempt to re-use an existing PaintRecord if possible.
1967     new_records[input] = std::make_pair(
1968         paint_image_id, std::move(paint_worklet_records_[input].second));
1969   }
1970   paint_worklet_records_.swap(new_records);
1971 
1972   // The pending tree tracks which PictureLayerImpls have PaintWorkletInputs as
1973   // an optimization to avoid walking all picture layers.
1974   bool has_paint_worklets = !paint_worklet_records_.empty();
1975   if ((has_paint_worklets != had_paint_worklets) &&
1976       layer_tree_impl()->IsPendingTree()) {
1977     // TODO(xidachen): We don't need additional tracking on LayerTreeImpl. The
1978     // tracking in AnimatedPaintWorkletTracker should be enough.
1979     layer_tree_impl()->NotifyLayerHasPaintWorkletsChanged(this,
1980                                                           has_paint_worklets);
1981   }
1982   if (layer_tree_impl()->IsPendingTree()) {
1983     layer_tree_impl()
1984         ->paint_worklet_tracker()
1985         .UpdatePaintWorkletInputProperties(inputs, this);
1986   }
1987 }
1988 
InvalidatePaintWorklets(const PaintWorkletInput::PropertyKey & key)1989 void PictureLayerImpl::InvalidatePaintWorklets(
1990     const PaintWorkletInput::PropertyKey& key) {
1991   for (auto& entry : paint_worklet_records_) {
1992     const std::vector<PaintWorkletInput::PropertyKey>& prop_ids =
1993         entry.first->GetPropertyKeys();
1994     // If the PaintWorklet depends on the property whose value was changed by
1995     // the animation system, then invalidate its associated PaintRecord so that
1996     // we can repaint the PaintWorklet during impl side invalidation.
1997     if (base::Contains(prop_ids, key))
1998       entry.second.second = nullptr;
1999   }
2000 }
2001 
GetContentColorUsage() const2002 gfx::ContentColorUsage PictureLayerImpl::GetContentColorUsage() const {
2003   auto display_item_list = raster_source_->GetDisplayItemList();
2004   if (!display_item_list)
2005     return gfx::ContentColorUsage::kSRGB;
2006 
2007   return display_item_list->discardable_image_map().content_color_usage();
2008 }
2009 
2010 }  // namespace cc
2011