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