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