1 // Copyright 2011 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/trees/layer_tree_impl.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <iterator>
12 #include <limits>
13 #include <set>
14
15 #include "base/containers/adapters.h"
16 #include "base/debug/crash_logging.h"
17 #include "base/debug/dump_without_crashing.h"
18 #include "base/json/json_writer.h"
19 #include "base/metrics/histogram_macros.h"
20 #include "base/numerics/ranges.h"
21 #include "base/stl_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/timer/elapsed_timer.h"
24 #include "base/trace_event/trace_event.h"
25 #include "base/trace_event/traced_value.h"
26 #include "cc/base/devtools_instrumentation.h"
27 #include "cc/base/histograms.h"
28 #include "cc/base/math_util.h"
29 #include "cc/base/synced_property.h"
30 #include "cc/input/page_scale_animation.h"
31 #include "cc/input/scrollbar_animation_controller.h"
32 #include "cc/layers/effect_tree_layer_list_iterator.h"
33 #include "cc/layers/heads_up_display_layer_impl.h"
34 #include "cc/layers/layer.h"
35 #include "cc/layers/render_surface_impl.h"
36 #include "cc/layers/scrollbar_layer_impl_base.h"
37 #include "cc/resources/ui_resource_request.h"
38 #include "cc/trees/clip_node.h"
39 #include "cc/trees/draw_property_utils.h"
40 #include "cc/trees/effect_node.h"
41 #include "cc/trees/layer_tree_frame_sink.h"
42 #include "cc/trees/layer_tree_host_impl.h"
43 #include "cc/trees/mutator_host.h"
44 #include "cc/trees/occlusion_tracker.h"
45 #include "cc/trees/property_tree.h"
46 #include "cc/trees/scroll_node.h"
47 #include "cc/trees/transform_node.h"
48 #include "components/viz/common/traced_value.h"
49 #include "ui/gfx/geometry/box_f.h"
50 #include "ui/gfx/geometry/point_conversions.h"
51 #include "ui/gfx/geometry/rect_conversions.h"
52 #include "ui/gfx/geometry/size_conversions.h"
53 #include "ui/gfx/geometry/vector2d_conversions.h"
54
55 namespace cc {
56 namespace {
57 // Small helper class that saves the current viewport location as the user sees
58 // it and resets to the same location.
59 class ViewportAnchor {
60 public:
ViewportAnchor(ScrollNode * inner_scroll,ScrollNode * outer_scroll,LayerTreeImpl * tree_impl)61 ViewportAnchor(ScrollNode* inner_scroll,
62 ScrollNode* outer_scroll,
63 LayerTreeImpl* tree_impl)
64 : inner_(inner_scroll), outer_(outer_scroll), tree_impl_(tree_impl) {
65 viewport_in_content_coordinates_ =
66 scroll_tree().current_scroll_offset(inner_->element_id);
67
68 if (outer_) {
69 viewport_in_content_coordinates_ +=
70 scroll_tree().current_scroll_offset(outer_->element_id);
71 }
72 }
73
ResetViewportToAnchoredPosition()74 void ResetViewportToAnchoredPosition() {
75 DCHECK(outer_);
76
77 scroll_tree().ClampScrollToMaxScrollOffset(*inner_, tree_impl_);
78 scroll_tree().ClampScrollToMaxScrollOffset(*outer_, tree_impl_);
79
80 gfx::ScrollOffset viewport_location =
81 scroll_tree().current_scroll_offset(inner_->element_id) +
82 scroll_tree().current_scroll_offset(outer_->element_id);
83
84 gfx::Vector2dF delta =
85 viewport_in_content_coordinates_.DeltaFrom(viewport_location);
86
87 delta = scroll_tree().ScrollBy(*inner_, delta, tree_impl_);
88 scroll_tree().ScrollBy(*outer_, delta, tree_impl_);
89 }
90
91 private:
scroll_tree()92 ScrollTree& scroll_tree() {
93 return tree_impl_->property_trees()->scroll_tree;
94 }
95
96 ScrollNode* inner_;
97 ScrollNode* outer_;
98 LayerTreeImpl* tree_impl_;
99 gfx::ScrollOffset viewport_in_content_coordinates_;
100 };
101
GetVisibleSelectionEndPoints(const gfx::RectF & rect,const gfx::PointF & top,const gfx::PointF & bottom)102 std::pair<gfx::PointF, gfx::PointF> GetVisibleSelectionEndPoints(
103 const gfx::RectF& rect,
104 const gfx::PointF& top,
105 const gfx::PointF& bottom) {
106 gfx::PointF start(base::ClampToRange(top.x(), rect.x(), rect.right()),
107 base::ClampToRange(top.y(), rect.y(), rect.bottom()));
108 gfx::PointF end =
109 start + gfx::Vector2dF(bottom.x() - top.x(), bottom.y() - top.y());
110 return {start, end};
111 }
112
113 } // namespace
114
AdvanceTo(LifecycleState next_state)115 void LayerTreeLifecycle::AdvanceTo(LifecycleState next_state) {
116 switch (next_state) {
117 case (kNotSyncing):
118 DCHECK_EQ(state_, kLastSyncState);
119 break;
120 case (kBeginningSync):
121 case (kSyncedPropertyTrees):
122 case (kSyncedLayerProperties):
123 // Only allow tree synchronization states to be transitioned in order.
124 DCHECK_EQ(state_ + 1, next_state);
125 break;
126 }
127 state_ = next_state;
128 }
129
LayerTreeImpl(LayerTreeHostImpl * host_impl,scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,scoped_refptr<SyncedBrowserControls> top_controls_shown_ratio,scoped_refptr<SyncedBrowserControls> bottom_controls_shown_ratio,scoped_refptr<SyncedElasticOverscroll> elastic_overscroll)130 LayerTreeImpl::LayerTreeImpl(
131 LayerTreeHostImpl* host_impl,
132 scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
133 scoped_refptr<SyncedBrowserControls> top_controls_shown_ratio,
134 scoped_refptr<SyncedBrowserControls> bottom_controls_shown_ratio,
135 scoped_refptr<SyncedElasticOverscroll> elastic_overscroll)
136 : host_impl_(host_impl),
137 source_frame_number_(-1),
138 is_first_frame_after_commit_tracker_(-1),
139 hud_layer_(nullptr),
140 background_color_(0),
141 last_scrolled_scroll_node_index_(ScrollTree::kInvalidNodeId),
142 page_scale_factor_(page_scale_factor),
143 min_page_scale_factor_(0),
144 max_page_scale_factor_(0),
145 external_page_scale_factor_(1.f),
146 device_scale_factor_(1.f),
147 painted_device_scale_factor_(1.f),
148 elastic_overscroll_(elastic_overscroll),
149 needs_update_draw_properties_(true),
150 scrollbar_geometries_need_update_(false),
151 needs_full_tree_sync_(true),
152 needs_surface_ranges_sync_(false),
153 next_activation_forces_redraw_(false),
154 has_ever_been_drawn_(false),
155 handle_visibility_changed_(false),
156 have_scroll_event_handlers_(false),
157 event_listener_properties_(),
158 top_controls_shown_ratio_(std::move(top_controls_shown_ratio)),
159 bottom_controls_shown_ratio_(std::move(bottom_controls_shown_ratio)) {
160 property_trees()->is_main_thread = false;
161 }
162
~LayerTreeImpl()163 LayerTreeImpl::~LayerTreeImpl() {
164 // Need to explicitly clear the tree prior to destroying this so that
165 // the LayerTreeImpl pointer is still valid in the LayerImpl dtor.
166 DCHECK(LayerListIsEmpty());
167 }
168
Shutdown()169 void LayerTreeImpl::Shutdown() {
170 DetachLayers();
171 BreakSwapPromises(IsActiveTree() ? SwapPromise::SWAP_FAILS
172 : SwapPromise::ACTIVATION_FAILS);
173 DCHECK(LayerListIsEmpty());
174 }
175
ReleaseResources()176 void LayerTreeImpl::ReleaseResources() {
177 for (auto* layer : *this)
178 layer->ReleaseResources();
179 }
180
OnPurgeMemory()181 void LayerTreeImpl::OnPurgeMemory() {
182 for (auto* layer : *this)
183 layer->OnPurgeMemory();
184 }
185
ReleaseTileResources()186 void LayerTreeImpl::ReleaseTileResources() {
187 for (auto* layer : *this)
188 layer->ReleaseTileResources();
189 }
190
RecreateTileResources()191 void LayerTreeImpl::RecreateTileResources() {
192 for (auto* layer : *this)
193 layer->RecreateTileResources();
194 }
195
DidUpdateScrollOffset(ElementId id)196 void LayerTreeImpl::DidUpdateScrollOffset(ElementId id) {
197 // Scrollbar positions depend on the current scroll offset.
198 SetScrollbarGeometriesNeedUpdate();
199
200 DCHECK(lifecycle().AllowsPropertyTreeAccess());
201 ScrollTree& scroll_tree = property_trees()->scroll_tree;
202 const auto* scroll_node = scroll_tree.FindNodeFromElementId(id);
203
204 if (!scroll_node) {
205 // A scroll node should always exist on the active tree but may not exist
206 // if we're updating the other trees from the active tree. This can occur
207 // when the pending tree represents a different page, for example.
208 DCHECK(!IsActiveTree());
209 return;
210 }
211
212 DCHECK(scroll_node->transform_id != TransformTree::kInvalidNodeId);
213 TransformTree& transform_tree = property_trees()->transform_tree;
214 auto* transform_node = transform_tree.Node(scroll_node->transform_id);
215 if (transform_node->scroll_offset != scroll_tree.current_scroll_offset(id)) {
216 transform_node->scroll_offset = scroll_tree.current_scroll_offset(id);
217 transform_node->needs_local_transform_update = true;
218 transform_tree.set_needs_update(true);
219 }
220 transform_node->transform_changed = true;
221 property_trees()->changed = true;
222 set_needs_update_draw_properties();
223
224 if (IsActiveTree()) {
225 // Ensure the other trees are kept in sync.
226 if (host_impl_->pending_tree())
227 host_impl_->pending_tree()->DidUpdateScrollOffset(id);
228 if (host_impl_->recycle_tree())
229 host_impl_->recycle_tree()->DidUpdateScrollOffset(id);
230 }
231 }
232
UpdateScrollbarGeometries()233 void LayerTreeImpl::UpdateScrollbarGeometries() {
234 if (!IsActiveTree())
235 return;
236
237 DCHECK(lifecycle().AllowsPropertyTreeAccess());
238
239 // Layer properties such as bounds should be up-to-date.
240 DCHECK(lifecycle().AllowsLayerPropertyAccess());
241
242 if (!scrollbar_geometries_need_update_)
243 return;
244
245 for (auto& pair : element_id_to_scrollbar_layer_ids_) {
246 ElementId scrolling_element_id = pair.first;
247
248 auto& scroll_tree = property_trees()->scroll_tree;
249 auto* scroll_node = scroll_tree.FindNodeFromElementId(scrolling_element_id);
250 if (!scroll_node)
251 continue;
252 gfx::ScrollOffset current_offset =
253 scroll_tree.current_scroll_offset(scrolling_element_id);
254 gfx::SizeF scrolling_size(scroll_node->bounds);
255 gfx::Size bounds_size(scroll_tree.container_bounds(scroll_node->id));
256
257 bool is_viewport_scrollbar = scroll_node == InnerViewportScrollNode() ||
258 scroll_node == OuterViewportScrollNode();
259 if (is_viewport_scrollbar) {
260 gfx::SizeF viewport_bounds(bounds_size);
261 if (scroll_node == InnerViewportScrollNode()) {
262 DCHECK_EQ(scroll_node, InnerViewportScrollNode());
263 auto* outer_scroll_node = OuterViewportScrollNode();
264 DCHECK(outer_scroll_node);
265
266 // Add offset and bounds contribution of outer viewport.
267 current_offset +=
268 scroll_tree.current_scroll_offset(outer_scroll_node->element_id);
269 gfx::SizeF outer_viewport_bounds(
270 scroll_tree.container_bounds(outer_scroll_node->id));
271 viewport_bounds.SetToMin(outer_viewport_bounds);
272 // The scrolling size is only determined by the outer viewport.
273 scrolling_size = gfx::SizeF(outer_scroll_node->bounds);
274 } else {
275 DCHECK_EQ(scroll_node, OuterViewportScrollNode());
276 auto* inner_scroll_node = InnerViewportScrollNode();
277 DCHECK(inner_scroll_node);
278 // Add offset and bounds contribution of inner viewport.
279 current_offset +=
280 scroll_tree.current_scroll_offset(inner_scroll_node->element_id);
281 gfx::SizeF inner_viewport_bounds(
282 scroll_tree.container_bounds(inner_scroll_node->id));
283 viewport_bounds.SetToMin(inner_viewport_bounds);
284 }
285 viewport_bounds.Scale(1 / current_page_scale_factor());
286 bounds_size = ToCeiledSize(viewport_bounds);
287 }
288
289 for (auto* scrollbar : ScrollbarsFor(scrolling_element_id)) {
290 if (scrollbar->orientation() == HORIZONTAL) {
291 scrollbar->SetCurrentPos(current_offset.x());
292 scrollbar->SetClipLayerLength(bounds_size.width());
293 scrollbar->SetScrollLayerLength(scrolling_size.width());
294 } else {
295 scrollbar->SetCurrentPos(current_offset.y());
296 scrollbar->SetClipLayerLength(bounds_size.height());
297 scrollbar->SetScrollLayerLength(scrolling_size.height());
298 }
299 if (is_viewport_scrollbar) {
300 scrollbar->SetVerticalAdjust(
301 property_trees_.inner_viewport_container_bounds_delta().y());
302 }
303 }
304 }
305
306 scrollbar_geometries_need_update_ = false;
307 }
308
RootRenderSurface() const309 const RenderSurfaceImpl* LayerTreeImpl::RootRenderSurface() const {
310 return property_trees_.effect_tree.GetRenderSurface(
311 EffectTree::kContentsRootNodeId);
312 }
313
LayerListIsEmpty() const314 bool LayerTreeImpl::LayerListIsEmpty() const {
315 return layer_list_.empty();
316 }
317
SetRootLayerForTesting(std::unique_ptr<LayerImpl> layer)318 void LayerTreeImpl::SetRootLayerForTesting(std::unique_ptr<LayerImpl> layer) {
319 DetachLayers();
320 if (layer)
321 AddLayer(std::move(layer));
322 host_impl_->OnCanDrawStateChangedForTree();
323 }
324
OnCanDrawStateChangedForTree()325 void LayerTreeImpl::OnCanDrawStateChangedForTree() {
326 host_impl_->OnCanDrawStateChangedForTree();
327 }
328
InvalidateRegionForImages(const PaintImageIdFlatSet & images_to_invalidate)329 void LayerTreeImpl::InvalidateRegionForImages(
330 const PaintImageIdFlatSet& images_to_invalidate) {
331 TRACE_EVENT_BEGIN1("cc", "LayerTreeImpl::InvalidateRegionForImages",
332 "total_layer_count", picture_layers_.size());
333 DCHECK(IsSyncTree());
334
335 size_t no_images_count = 0;
336 size_t no_invalidation_count = 0;
337 size_t invalidated_count = 0;
338 if (!images_to_invalidate.empty()) {
339 // TODO(khushalsagar): It might be better to keep track of layers with
340 // images and only iterate through those here.
341 for (auto* picture_layer : picture_layers_) {
342 auto result =
343 picture_layer->InvalidateRegionForImages(images_to_invalidate);
344 switch (result) {
345 case PictureLayerImpl::ImageInvalidationResult::kNoImages:
346 ++no_images_count;
347 break;
348 case PictureLayerImpl::ImageInvalidationResult::kNoInvalidation:
349 ++no_invalidation_count;
350 break;
351 case PictureLayerImpl::ImageInvalidationResult::kInvalidated:
352 ++invalidated_count;
353 break;
354 }
355 }
356 }
357 TRACE_EVENT_END1(
358 "cc", "LayerTreeImpl::InvalidateRegionForImages", "counts",
359 base::StringPrintf("no_images[%zu] no_invalidaton[%zu] invalidated[%zu]",
360 no_images_count, no_invalidation_count,
361 invalidated_count));
362 }
363
UpdateViewportContainerSizes()364 void LayerTreeImpl::UpdateViewportContainerSizes() {
365 if (!InnerViewportScrollNode())
366 return;
367
368 DCHECK(OuterViewportScrollNode());
369 ViewportAnchor anchor(InnerViewportScrollNode(), OuterViewportScrollNode(),
370 this);
371
372 float top_controls_shown_ratio =
373 top_controls_shown_ratio_->Current(IsActiveTree());
374 float bottom_controls_shown_ratio =
375 bottom_controls_shown_ratio_->Current(IsActiveTree());
376 float top_controls_layout_height = browser_controls_shrink_blink_size()
377 ? top_controls_height()
378 : top_controls_min_height();
379 float top_content_offset =
380 top_controls_height() > 0
381 ? top_controls_height() * top_controls_shown_ratio
382 : 0.f;
383 float delta_from_top_controls =
384 top_controls_layout_height - top_content_offset;
385 float bottom_controls_layout_height = browser_controls_shrink_blink_size()
386 ? bottom_controls_height()
387 : bottom_controls_min_height();
388 float bottom_content_offset =
389 bottom_controls_height() > 0
390 ? bottom_controls_height() * bottom_controls_shown_ratio
391 : 0.f;
392 delta_from_top_controls +=
393 bottom_controls_layout_height - bottom_content_offset;
394
395 // Adjust the viewport layers by shrinking/expanding the container to account
396 // for changes in the size (e.g. browser controls) since the last resize from
397 // Blink.
398 auto* property_trees = this->property_trees();
399 gfx::Vector2dF bounds_delta(0.f, delta_from_top_controls);
400 if (property_trees->inner_viewport_container_bounds_delta() == bounds_delta)
401 return;
402
403 property_trees->SetInnerViewportContainerBoundsDelta(bounds_delta);
404
405 // Adjust the outer viewport container as well, since adjusting only the
406 // inner may cause its bounds to exceed those of the outer, causing scroll
407 // clamping.
408 gfx::Vector2dF scaled_bounds_delta =
409 gfx::ScaleVector2d(bounds_delta, 1.f / min_page_scale_factor());
410
411 property_trees->SetOuterViewportContainerBoundsDelta(scaled_bounds_delta);
412 // outer_viewport_container_bounds_delta and
413 // inner_viewport_scroll_bounds_delta are the same thing.
414 DCHECK_EQ(scaled_bounds_delta,
415 property_trees->inner_viewport_scroll_bounds_delta());
416
417 if (auto* outer_clip_node = OuterViewportClipNode()) {
418 float adjusted_container_height =
419 OuterViewportScrollNode()->container_bounds.height() +
420 scaled_bounds_delta.y();
421 outer_clip_node->clip.set_height(adjusted_container_height);
422 }
423
424 anchor.ResetViewportToAnchoredPosition();
425
426 property_trees->clip_tree.set_needs_update(true);
427 property_trees->full_tree_damaged = true;
428 set_needs_update_draw_properties();
429
430 // Viewport scrollbar positions are determined using the viewport bounds
431 // delta.
432 SetScrollbarGeometriesNeedUpdate();
433 set_needs_update_draw_properties();
434 }
435
IsRootLayer(const LayerImpl * layer) const436 bool LayerTreeImpl::IsRootLayer(const LayerImpl* layer) const {
437 return !layer_list_.empty() && layer_list_[0].get() == layer;
438 }
439
TotalScrollOffset() const440 gfx::ScrollOffset LayerTreeImpl::TotalScrollOffset() const {
441 gfx::ScrollOffset offset;
442 const auto& scroll_tree = property_trees()->scroll_tree;
443
444 if (auto* inner_scroll = InnerViewportScrollNode()) {
445 offset += scroll_tree.current_scroll_offset(inner_scroll->element_id);
446 DCHECK(OuterViewportScrollNode());
447 offset += scroll_tree.current_scroll_offset(
448 OuterViewportScrollNode()->element_id);
449 }
450
451 return offset;
452 }
453
TotalMaxScrollOffset() const454 gfx::ScrollOffset LayerTreeImpl::TotalMaxScrollOffset() const {
455 gfx::ScrollOffset offset;
456 const auto& scroll_tree = property_trees()->scroll_tree;
457
458 if (viewport_property_ids_.inner_scroll != ScrollTree::kInvalidNodeId)
459 offset += scroll_tree.MaxScrollOffset(viewport_property_ids_.inner_scroll);
460
461 if (viewport_property_ids_.outer_scroll != ScrollTree::kInvalidNodeId)
462 offset += scroll_tree.MaxScrollOffset(viewport_property_ids_.outer_scroll);
463
464 return offset;
465 }
466
DetachLayers()467 OwnedLayerImplList LayerTreeImpl::DetachLayers() {
468 render_surface_list_.clear();
469 set_needs_update_draw_properties();
470 return std::move(layer_list_);
471 }
472
DetachLayersKeepingRootLayerForTesting()473 OwnedLayerImplList LayerTreeImpl::DetachLayersKeepingRootLayerForTesting() {
474 auto layers = DetachLayers();
475 SetRootLayerForTesting(std::move(layers[0]));
476 return layers;
477 }
478
SetPropertyTrees(PropertyTrees * property_trees)479 void LayerTreeImpl::SetPropertyTrees(PropertyTrees* property_trees) {
480 std::vector<std::unique_ptr<RenderSurfaceImpl>> old_render_surfaces;
481 property_trees_.effect_tree.TakeRenderSurfaces(&old_render_surfaces);
482 property_trees_ = *property_trees;
483 bool render_surfaces_changed =
484 property_trees_.effect_tree.CreateOrReuseRenderSurfaces(
485 &old_render_surfaces, this);
486 if (render_surfaces_changed)
487 set_needs_update_draw_properties();
488 property_trees->effect_tree.PushCopyRequestsTo(&property_trees_.effect_tree);
489 property_trees_.is_main_thread = false;
490 property_trees_.is_active = IsActiveTree();
491 // The value of some effect node properties (like is_drawn) depends on
492 // whether we are on the active tree or not. So, we need to update the
493 // effect tree.
494 if (IsActiveTree())
495 property_trees_.effect_tree.set_needs_update(true);
496 }
497
PushPropertyTreesTo(LayerTreeImpl * target_tree)498 void LayerTreeImpl::PushPropertyTreesTo(LayerTreeImpl* target_tree) {
499 TRACE_EVENT0("cc", "LayerTreeImpl::PushPropertyTreesTo");
500 // Property trees may store damage status. We preserve the active tree
501 // damage status by pushing the damage status from active tree property
502 // trees to pending tree property trees or by moving it onto the layers.
503 if (target_tree->property_trees()->changed) {
504 if (property_trees()->sequence_number ==
505 target_tree->property_trees()->sequence_number)
506 target_tree->property_trees()->PushChangeTrackingTo(property_trees());
507 else
508 target_tree->MoveChangeTrackingToLayers();
509 }
510
511 // To maintain the current scrolling node we need to use element ids which
512 // are stable across the property tree update in SetPropertyTrees.
513 ElementId scrolling_element_id;
514 if (ScrollNode* scrolling_node = target_tree->CurrentlyScrollingNode())
515 scrolling_element_id = scrolling_node->element_id;
516
517 target_tree->SetPropertyTrees(&property_trees_);
518
519 const ScrollNode* scrolling_node = nullptr;
520 if (scrolling_element_id) {
521 auto& scroll_tree = target_tree->property_trees()->scroll_tree;
522 scrolling_node = scroll_tree.FindNodeFromElementId(scrolling_element_id);
523 }
524 target_tree->SetCurrentlyScrollingNode(scrolling_node);
525
526 std::vector<EventMetrics> events_metrics;
527 events_metrics.swap(events_metrics_from_main_thread_);
528 target_tree->AppendEventsMetricsFromMainThread(std::move(events_metrics));
529 }
530
PushSurfaceRangesTo(LayerTreeImpl * target_tree)531 void LayerTreeImpl::PushSurfaceRangesTo(LayerTreeImpl* target_tree) {
532 if (needs_surface_ranges_sync()) {
533 target_tree->ClearSurfaceRanges();
534 target_tree->SetSurfaceRanges(SurfaceRanges());
535 // Reset for next update
536 set_needs_surface_ranges_sync(false);
537 }
538 }
539
PushPropertiesTo(LayerTreeImpl * target_tree)540 void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
541 TRACE_EVENT0("cc", "LayerTreeImpl::PushPropertiesTo");
542 // The request queue should have been processed and does not require a push.
543 DCHECK_EQ(ui_resource_request_queue_.size(), 0u);
544
545 PushSurfaceRangesTo(target_tree);
546 target_tree->property_trees()->scroll_tree.PushScrollUpdatesFromPendingTree(
547 &property_trees_, target_tree);
548
549 if (next_activation_forces_redraw_) {
550 target_tree->ForceRedrawNextActivation();
551 next_activation_forces_redraw_ = false;
552 }
553
554 target_tree->PassSwapPromises(std::move(swap_promise_list_));
555 swap_promise_list_.clear();
556
557 // The page scale factor update can affect scrolling which requires that
558 // these ids are set, so this must be before PushPageScaleFactorAndLimits.
559 // Setting browser controls below also needs viewport scroll properties.
560 target_tree->SetViewportPropertyIds(viewport_property_ids_);
561
562 // Active tree already shares the page_scale_factor object with pending
563 // tree so only the limits need to be provided.
564 target_tree->PushPageScaleFactorAndLimits(nullptr, min_page_scale_factor(),
565 max_page_scale_factor());
566 target_tree->SetExternalPageScaleFactor(external_page_scale_factor_);
567
568 target_tree->SetBrowserControlsParams(browser_controls_params_);
569 target_tree->PushBrowserControls(nullptr, nullptr);
570
571 target_tree->set_overscroll_behavior(overscroll_behavior_);
572
573 target_tree->SetRasterColorSpace(raster_color_space_);
574 target_tree->elastic_overscroll()->PushPendingToActive();
575
576 target_tree->set_painted_device_scale_factor(painted_device_scale_factor());
577 target_tree->SetDeviceScaleFactor(device_scale_factor());
578 target_tree->SetDeviceViewportRect(device_viewport_rect_);
579
580 if (TakeNewLocalSurfaceIdRequest())
581 target_tree->RequestNewLocalSurfaceId();
582 target_tree->SetLocalSurfaceIdAllocationFromParent(
583 local_surface_id_allocation_from_parent());
584
585 target_tree->pending_page_scale_animation_ =
586 std::move(pending_page_scale_animation_);
587
588 if (TakeForceSendMetadataRequest())
589 target_tree->RequestForceSendMetadata();
590
591 target_tree->RegisterSelection(selection_);
592
593 // This should match the property synchronization in
594 // LayerTreeHost::finishCommitOnImplThread().
595 target_tree->set_source_frame_number(source_frame_number());
596 target_tree->set_background_color(background_color());
597 target_tree->set_have_scroll_event_handlers(have_scroll_event_handlers());
598 target_tree->set_event_listener_properties(
599 EventListenerClass::kTouchStartOrMove,
600 event_listener_properties(EventListenerClass::kTouchStartOrMove));
601 target_tree->set_event_listener_properties(
602 EventListenerClass::kMouseWheel,
603 event_listener_properties(EventListenerClass::kMouseWheel));
604 target_tree->set_event_listener_properties(
605 EventListenerClass::kTouchEndOrCancel,
606 event_listener_properties(EventListenerClass::kTouchEndOrCancel));
607
608 if (hud_layer())
609 target_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(
610 target_tree->LayerById(hud_layer()->id())));
611 else
612 target_tree->set_hud_layer(nullptr);
613
614 target_tree->has_ever_been_drawn_ = false;
615
616 // Note: this needs to happen after SetPropertyTrees.
617 target_tree->HandleTickmarksVisibilityChange();
618 target_tree->HandleScrollbarShowRequestsFromMain();
619 target_tree->AddPresentationCallbacks(std::move(presentation_callbacks_));
620 presentation_callbacks_.clear();
621 }
622
HandleTickmarksVisibilityChange()623 void LayerTreeImpl::HandleTickmarksVisibilityChange() {
624 if (!host_impl_->OuterViewportScrollNode())
625 return;
626
627 ScrollbarAnimationController* controller =
628 host_impl_->ScrollbarAnimationControllerForElementId(
629 host_impl_->OuterViewportScrollNode()->element_id);
630
631 if (!controller)
632 return;
633
634 for (ScrollbarLayerImplBase* scrollbar : controller->Scrollbars()) {
635 if (scrollbar->orientation() != VERTICAL)
636 continue;
637
638 // Android Overlay Scrollbar don't have FindInPage Tickmarks.
639 if (scrollbar->GetScrollbarAnimator() != LayerTreeSettings::AURA_OVERLAY)
640 DCHECK(!scrollbar->HasFindInPageTickmarks());
641
642 controller->UpdateTickmarksVisibility(scrollbar->HasFindInPageTickmarks());
643 }
644 }
645
HandleScrollbarShowRequestsFromMain()646 void LayerTreeImpl::HandleScrollbarShowRequestsFromMain() {
647 for (auto* layer : *this) {
648 if (!layer->needs_show_scrollbars())
649 continue;
650 ScrollbarAnimationController* controller =
651 host_impl_->ScrollbarAnimationControllerForElementId(
652 layer->element_id());
653 if (controller) {
654 controller->DidRequestShowFromMainThread();
655 layer->set_needs_show_scrollbars(false);
656 }
657 }
658 }
659
MoveChangeTrackingToLayers()660 void LayerTreeImpl::MoveChangeTrackingToLayers() {
661 // We need to update the change tracking on property trees before we move it
662 // onto the layers.
663 property_trees_.UpdateChangeTracking();
664 for (auto* layer : *this) {
665 if (layer->LayerPropertyChangedFromPropertyTrees())
666 layer->NoteLayerPropertyChangedFromPropertyTrees();
667 }
668 EffectTree& effect_tree = property_trees_.effect_tree;
669 for (int id = EffectTree::kContentsRootNodeId;
670 id < static_cast<int>(effect_tree.size()); ++id) {
671 RenderSurfaceImpl* render_surface = effect_tree.GetRenderSurface(id);
672 if (render_surface && render_surface->AncestorPropertyChanged())
673 render_surface->NoteAncestorPropertyChanged();
674 }
675 }
676
ForceRecalculateRasterScales()677 void LayerTreeImpl::ForceRecalculateRasterScales() {
678 for (auto* layer : picture_layers_)
679 layer->ResetRasterScale();
680 }
681
IsElementInPropertyTree(ElementId element_id) const682 bool LayerTreeImpl::IsElementInPropertyTree(ElementId element_id) const {
683 return property_trees()->HasElement(element_id);
684 }
685
GetElementTypeForAnimation() const686 ElementListType LayerTreeImpl::GetElementTypeForAnimation() const {
687 return IsActiveTree() ? ElementListType::ACTIVE : ElementListType::PENDING;
688 }
689
AddToElementLayerList(ElementId element_id,LayerImpl * layer)690 void LayerTreeImpl::AddToElementLayerList(ElementId element_id,
691 LayerImpl* layer) {
692 if (!element_id)
693 return;
694
695 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("layer-element"),
696 "LayerTreeImpl::AddToElementLayerList", "element",
697 element_id.ToString());
698
699 if (!settings().use_layer_lists) {
700 host_impl_->mutator_host()->RegisterElementId(element_id,
701 GetElementTypeForAnimation());
702 }
703 }
704
RemoveFromElementLayerList(ElementId element_id)705 void LayerTreeImpl::RemoveFromElementLayerList(ElementId element_id) {
706 if (!element_id)
707 return;
708
709 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("layer-element"),
710 "LayerTreeImpl::RemoveFromElementLayerList", "element",
711 element_id.ToString());
712
713 if (!settings().use_layer_lists) {
714 host_impl_->mutator_host()->UnregisterElementId(
715 element_id, GetElementTypeForAnimation());
716 }
717 }
718
SetTransformMutated(ElementId element_id,const gfx::Transform & transform)719 void LayerTreeImpl::SetTransformMutated(ElementId element_id,
720 const gfx::Transform& transform) {
721 DCHECK_EQ(1u, property_trees()->element_id_to_transform_node_index.count(
722 element_id));
723 if (IsSyncTree() || IsRecycleTree())
724 element_id_to_transform_animations_[element_id] = transform;
725 if (property_trees()->transform_tree.OnTransformAnimated(element_id,
726 transform))
727 set_needs_update_draw_properties();
728 }
729
SetOpacityMutated(ElementId element_id,float opacity)730 void LayerTreeImpl::SetOpacityMutated(ElementId element_id, float opacity) {
731 DCHECK_EQ(
732 1u, property_trees()->element_id_to_effect_node_index.count(element_id));
733 if (IsSyncTree() || IsRecycleTree())
734 element_id_to_opacity_animations_[element_id] = opacity;
735 if (property_trees()->effect_tree.OnOpacityAnimated(element_id, opacity))
736 set_needs_update_draw_properties();
737 }
738
SetFilterMutated(ElementId element_id,const FilterOperations & filters)739 void LayerTreeImpl::SetFilterMutated(ElementId element_id,
740 const FilterOperations& filters) {
741 DCHECK_EQ(
742 1u, property_trees()->element_id_to_effect_node_index.count(element_id));
743 if (IsSyncTree() || IsRecycleTree())
744 element_id_to_filter_animations_[element_id] = filters;
745 if (property_trees()->effect_tree.OnFilterAnimated(element_id, filters))
746 set_needs_update_draw_properties();
747 }
748
SetBackdropFilterMutated(ElementId element_id,const FilterOperations & backdrop_filters)749 void LayerTreeImpl::SetBackdropFilterMutated(
750 ElementId element_id,
751 const FilterOperations& backdrop_filters) {
752 DCHECK_EQ(
753 1u, property_trees()->element_id_to_effect_node_index.count(element_id));
754 if (IsSyncTree() || IsRecycleTree())
755 element_id_to_backdrop_filter_animations_[element_id] = backdrop_filters;
756 if (property_trees()->effect_tree.OnBackdropFilterAnimated(element_id,
757 backdrop_filters))
758 set_needs_update_draw_properties();
759 }
760
AddPresentationCallbacks(std::vector<LayerTreeHost::PresentationTimeCallback> callbacks)761 void LayerTreeImpl::AddPresentationCallbacks(
762 std::vector<LayerTreeHost::PresentationTimeCallback> callbacks) {
763 std::copy(std::make_move_iterator(callbacks.begin()),
764 std::make_move_iterator(callbacks.end()),
765 std::back_inserter(presentation_callbacks_));
766 }
767
768 std::vector<LayerTreeHost::PresentationTimeCallback>
TakePresentationCallbacks()769 LayerTreeImpl::TakePresentationCallbacks() {
770 std::vector<LayerTreeHost::PresentationTimeCallback> callbacks;
771 callbacks.swap(presentation_callbacks_);
772 return callbacks;
773 }
774
InnerViewportScrollLayerForTesting() const775 LayerImpl* LayerTreeImpl::InnerViewportScrollLayerForTesting() const {
776 if (auto* scroll_node = InnerViewportScrollNode())
777 return LayerByElementId(scroll_node->element_id);
778 return nullptr;
779 }
780
OuterViewportScrollLayerForTesting() const781 LayerImpl* LayerTreeImpl::OuterViewportScrollLayerForTesting() const {
782 if (auto* scroll_node = OuterViewportScrollNode())
783 return LayerByElementId(scroll_node->element_id);
784 return nullptr;
785 }
786
CurrentlyScrollingNode()787 ScrollNode* LayerTreeImpl::CurrentlyScrollingNode() {
788 DCHECK(IsActiveTree());
789 return property_trees_.scroll_tree.CurrentlyScrollingNode();
790 }
791
CurrentlyScrollingNode() const792 const ScrollNode* LayerTreeImpl::CurrentlyScrollingNode() const {
793 return property_trees_.scroll_tree.CurrentlyScrollingNode();
794 }
795
LastScrolledScrollNodeIndex() const796 int LayerTreeImpl::LastScrolledScrollNodeIndex() const {
797 return last_scrolled_scroll_node_index_;
798 }
799
SetCurrentlyScrollingNode(const ScrollNode * node)800 void LayerTreeImpl::SetCurrentlyScrollingNode(const ScrollNode* node) {
801 if (node)
802 last_scrolled_scroll_node_index_ = node->id;
803
804 ScrollTree& scroll_tree = property_trees()->scroll_tree;
805 ScrollNode* old_node = scroll_tree.CurrentlyScrollingNode();
806
807 ElementId old_element_id = old_node ? old_node->element_id : ElementId();
808 ElementId new_element_id = node ? node->element_id : ElementId();
809 if (old_element_id == new_element_id)
810 return;
811
812 scroll_tree.set_currently_scrolling_node(node ? node->id
813 : ScrollTree::kInvalidNodeId);
814 }
815
ClearCurrentlyScrollingNode()816 void LayerTreeImpl::ClearCurrentlyScrollingNode() {
817 SetCurrentlyScrollingNode(nullptr);
818 }
819
ClampPageScaleFactorToLimits(float page_scale_factor) const820 float LayerTreeImpl::ClampPageScaleFactorToLimits(
821 float page_scale_factor) const {
822 if (min_page_scale_factor_ && page_scale_factor < min_page_scale_factor_)
823 page_scale_factor = min_page_scale_factor_;
824 else if (max_page_scale_factor_ && page_scale_factor > max_page_scale_factor_)
825 page_scale_factor = max_page_scale_factor_;
826 return page_scale_factor;
827 }
828
UpdatePropertyTreeAnimationFromMainThread()829 void LayerTreeImpl::UpdatePropertyTreeAnimationFromMainThread() {
830 // TODO(enne): This should get replaced by pulling out animations into their
831 // own trees. Then animations would have their own ways of synchronizing
832 // across commits. This occurs to push updates from animations that have
833 // ticked since begin frame to a newly-committed property tree.
834 if (layer_list_.empty())
835 return;
836
837 // Note we lazily delete element ids from the |element_id_to_xxx|
838 // maps below if we find they have no node present in their
839 // respective tree. This can be the case if the layer associated
840 // with that element id has been removed.
841
842 // This code is assumed to only run on the sync tree; the node updates are
843 // then synced when the tree is activated. See http://crbug.com/916512
844 DCHECK(IsSyncTree());
845
846 auto element_id_to_opacity = element_id_to_opacity_animations_.begin();
847 while (element_id_to_opacity != element_id_to_opacity_animations_.end()) {
848 const ElementId id = element_id_to_opacity->first;
849 EffectNode* node = property_trees_.effect_tree.FindNodeFromElementId(id);
850 if (!node || !node->is_currently_animating_opacity ||
851 node->opacity == element_id_to_opacity->second) {
852 element_id_to_opacity_animations_.erase(element_id_to_opacity++);
853 continue;
854 }
855 node->opacity = element_id_to_opacity->second;
856 property_trees_.effect_tree.set_needs_update(true);
857 ++element_id_to_opacity;
858 }
859
860 auto element_id_to_filter = element_id_to_filter_animations_.begin();
861 while (element_id_to_filter != element_id_to_filter_animations_.end()) {
862 const ElementId id = element_id_to_filter->first;
863 EffectNode* node = property_trees_.effect_tree.FindNodeFromElementId(id);
864 if (!node || !node->is_currently_animating_filter ||
865 node->filters == element_id_to_filter->second) {
866 element_id_to_filter_animations_.erase(element_id_to_filter++);
867 continue;
868 }
869 node->filters = element_id_to_filter->second;
870 property_trees_.effect_tree.set_needs_update(true);
871 ++element_id_to_filter;
872 }
873
874 auto element_id_to_backdrop_filter =
875 element_id_to_backdrop_filter_animations_.begin();
876 while (element_id_to_backdrop_filter !=
877 element_id_to_backdrop_filter_animations_.end()) {
878 const ElementId id = element_id_to_backdrop_filter->first;
879 EffectNode* node = property_trees_.effect_tree.FindNodeFromElementId(id);
880 if (!node || !node->is_currently_animating_backdrop_filter ||
881 node->backdrop_filters == element_id_to_backdrop_filter->second) {
882 element_id_to_backdrop_filter_animations_.erase(
883 element_id_to_backdrop_filter++);
884 continue;
885 }
886 node->backdrop_filters = element_id_to_backdrop_filter->second;
887 property_trees_.effect_tree.set_needs_update(true);
888 ++element_id_to_backdrop_filter;
889 }
890
891 auto element_id_to_transform = element_id_to_transform_animations_.begin();
892 while (element_id_to_transform != element_id_to_transform_animations_.end()) {
893 const ElementId id = element_id_to_transform->first;
894 TransformNode* node =
895 property_trees_.transform_tree.FindNodeFromElementId(id);
896 if (!node || !node->is_currently_animating ||
897 node->local == element_id_to_transform->second) {
898 element_id_to_transform_animations_.erase(element_id_to_transform++);
899 continue;
900 }
901 node->local = element_id_to_transform->second;
902 node->needs_local_transform_update = true;
903 property_trees_.transform_tree.set_needs_update(true);
904 ++element_id_to_transform;
905 }
906
907 for (auto transform_it : property_trees()->element_id_to_transform_node_index)
908 UpdateTransformAnimation(transform_it.first, transform_it.second);
909 }
910
UpdateTransformAnimation(ElementId element_id,int transform_node_index)911 void LayerTreeImpl::UpdateTransformAnimation(ElementId element_id,
912 int transform_node_index) {
913 // This includes all animations, even those that are finished but
914 // haven't yet been deleted.
915 if (mutator_host()->HasAnyAnimationTargetingProperty(
916 element_id, TargetProperty::TRANSFORM)) {
917 TransformTree& transform_tree = property_trees()->transform_tree;
918 if (TransformNode* node = transform_tree.Node(transform_node_index)) {
919 ElementListType list_type = GetElementTypeForAnimation();
920 bool has_potential_animation =
921 mutator_host()->HasPotentiallyRunningTransformAnimation(element_id,
922 list_type);
923 if (node->has_potential_animation != has_potential_animation) {
924 node->has_potential_animation = has_potential_animation;
925 mutator_host()->GetAnimationScales(element_id, list_type,
926 &node->maximum_animation_scale,
927 &node->starting_animation_scale);
928 transform_tree.set_needs_update(true);
929 set_needs_update_draw_properties();
930 }
931 }
932 }
933 }
934
UpdatePageScaleNode()935 void LayerTreeImpl::UpdatePageScaleNode() {
936 if (!PageScaleTransformNode()) {
937 DCHECK(layer_list_.empty() || current_page_scale_factor() == 1);
938 return;
939 }
940 draw_property_utils::UpdatePageScaleFactor(
941 property_trees(), PageScaleTransformNode(), current_page_scale_factor());
942 }
943
SetPageScaleOnActiveTree(float active_page_scale)944 void LayerTreeImpl::SetPageScaleOnActiveTree(float active_page_scale) {
945 DCHECK(IsActiveTree());
946 DCHECK(lifecycle().AllowsPropertyTreeAccess());
947 float clamped_page_scale = ClampPageScaleFactorToLimits(active_page_scale);
948 // Temporary crash logging for https://crbug.com/845097.
949 static bool has_dumped_without_crashing = false;
950 if (host_impl_->settings().is_layer_tree_for_subframe &&
951 clamped_page_scale != 1.f && !has_dumped_without_crashing) {
952 has_dumped_without_crashing = true;
953 static auto* psf_oopif_error = base::debug::AllocateCrashKeyString(
954 "psf_oopif_error", base::debug::CrashKeySize::Size32);
955 base::debug::SetCrashKeyString(
956 psf_oopif_error, base::StringPrintf("%f", clamped_page_scale));
957 base::debug::DumpWithoutCrashing();
958 }
959 if (page_scale_factor()->SetCurrent(clamped_page_scale)) {
960 DidUpdatePageScale();
961 UpdatePageScaleNode();
962 }
963 }
964
PushPageScaleFromMainThread(float page_scale_factor,float min_page_scale_factor,float max_page_scale_factor)965 void LayerTreeImpl::PushPageScaleFromMainThread(float page_scale_factor,
966 float min_page_scale_factor,
967 float max_page_scale_factor) {
968 PushPageScaleFactorAndLimits(&page_scale_factor, min_page_scale_factor,
969 max_page_scale_factor);
970 }
971
PushPageScaleFactorAndLimits(const float * page_scale_factor,float min_page_scale_factor,float max_page_scale_factor)972 void LayerTreeImpl::PushPageScaleFactorAndLimits(const float* page_scale_factor,
973 float min_page_scale_factor,
974 float max_page_scale_factor) {
975 DCHECK(page_scale_factor || IsActiveTree());
976 bool changed_page_scale = false;
977
978 changed_page_scale |=
979 SetPageScaleFactorLimits(min_page_scale_factor, max_page_scale_factor);
980
981 if (page_scale_factor) {
982 DCHECK(!IsActiveTree() || !host_impl_->pending_tree());
983 changed_page_scale |=
984 page_scale_factor_->PushMainToPending(*page_scale_factor);
985 }
986
987 if (IsActiveTree()) {
988 changed_page_scale |= page_scale_factor_->PushPendingToActive();
989 }
990
991 if (changed_page_scale)
992 DidUpdatePageScale();
993
994 DCHECK(lifecycle().AllowsPropertyTreeAccess());
995 if (page_scale_factor)
996 UpdatePageScaleNode();
997 }
998
SetBrowserControlsParams(const BrowserControlsParams & params)999 void LayerTreeImpl::SetBrowserControlsParams(
1000 const BrowserControlsParams& params) {
1001 if (browser_controls_params_ == params)
1002 return;
1003
1004 browser_controls_params_ = params;
1005 UpdateViewportContainerSizes();
1006
1007 if (IsActiveTree()) {
1008 host_impl_->browser_controls_manager()->OnBrowserControlsParamsChanged(
1009 params.animate_browser_controls_height_changes);
1010 }
1011 }
1012
set_overscroll_behavior(const OverscrollBehavior & behavior)1013 void LayerTreeImpl::set_overscroll_behavior(
1014 const OverscrollBehavior& behavior) {
1015 overscroll_behavior_ = behavior;
1016 }
1017
ClampTopControlsShownRatio()1018 bool LayerTreeImpl::ClampTopControlsShownRatio() {
1019 float ratio = top_controls_shown_ratio_->Current(true);
1020 auto range = std::make_pair(0.f, 1.f);
1021 if (IsActiveTree()) {
1022 // BCOM might need to set ratios outside the [0, 1] range (e.g. animation
1023 // running). So, use the values it provides instead of clamping to [0, 1].
1024 range =
1025 host_impl_->browser_controls_manager()->TopControlsShownRatioRange();
1026 }
1027 return top_controls_shown_ratio_->SetCurrent(
1028 base::ClampToRange(ratio, range.first, range.second));
1029 }
1030
ClampBottomControlsShownRatio()1031 bool LayerTreeImpl::ClampBottomControlsShownRatio() {
1032 float ratio = bottom_controls_shown_ratio_->Current(true);
1033 auto range = std::make_pair(0.f, 1.f);
1034 if (IsActiveTree()) {
1035 // BCOM might need to set ratios outside the [0, 1] range (e.g. animation
1036 // running). So, use the values it provides instead of clamping to [0, 1].
1037 range =
1038 host_impl_->browser_controls_manager()->BottomControlsShownRatioRange();
1039 }
1040 return bottom_controls_shown_ratio_->SetCurrent(
1041 base::ClampToRange(ratio, range.first, range.second));
1042 }
1043
SetCurrentBrowserControlsShownRatio(float top_ratio,float bottom_ratio)1044 bool LayerTreeImpl::SetCurrentBrowserControlsShownRatio(float top_ratio,
1045 float bottom_ratio) {
1046 TRACE_EVENT2("cc", "LayerTreeImpl::SetCurrentBrowserControlsShownRatio",
1047 "top_ratio", top_ratio, "bottom_ratio", bottom_ratio);
1048 bool changed = top_controls_shown_ratio_->SetCurrent(top_ratio);
1049 changed |= ClampTopControlsShownRatio();
1050 changed |= bottom_controls_shown_ratio_->SetCurrent(bottom_ratio);
1051 changed |= ClampBottomControlsShownRatio();
1052 return changed;
1053 }
1054
PushBrowserControlsFromMainThread(float top_controls_shown_ratio,float bottom_controls_shown_ratio)1055 void LayerTreeImpl::PushBrowserControlsFromMainThread(
1056 float top_controls_shown_ratio,
1057 float bottom_controls_shown_ratio) {
1058 PushBrowserControls(&top_controls_shown_ratio, &bottom_controls_shown_ratio);
1059 }
1060
PushBrowserControls(const float * top_controls_shown_ratio,const float * bottom_controls_shown_ratio)1061 void LayerTreeImpl::PushBrowserControls(
1062 const float* top_controls_shown_ratio,
1063 const float* bottom_controls_shown_ratio) {
1064 DCHECK(top_controls_shown_ratio || bottom_controls_shown_ratio ||
1065 IsActiveTree());
1066 DCHECK(!top_controls_shown_ratio || bottom_controls_shown_ratio);
1067 DCHECK(top_controls_shown_ratio || IsActiveTree());
1068
1069 if (top_controls_shown_ratio) {
1070 DCHECK(!IsActiveTree() || !host_impl_->pending_tree());
1071 bool changed_pending =
1072 top_controls_shown_ratio_->PushMainToPending(*top_controls_shown_ratio);
1073 changed_pending |= bottom_controls_shown_ratio_->PushMainToPending(
1074 *bottom_controls_shown_ratio);
1075 if (!IsActiveTree() && changed_pending)
1076 UpdateViewportContainerSizes();
1077 }
1078 if (IsActiveTree()) {
1079 bool changed_active = top_controls_shown_ratio_->PushPendingToActive();
1080 changed_active |= ClampTopControlsShownRatio();
1081 changed_active |= bottom_controls_shown_ratio_->PushPendingToActive();
1082 changed_active |= ClampBottomControlsShownRatio();
1083 if (changed_active)
1084 host_impl_->DidChangeBrowserControlsPosition();
1085 }
1086 }
1087
SetPageScaleFactorLimits(float min_page_scale_factor,float max_page_scale_factor)1088 bool LayerTreeImpl::SetPageScaleFactorLimits(float min_page_scale_factor,
1089 float max_page_scale_factor) {
1090 if (min_page_scale_factor == min_page_scale_factor_ &&
1091 max_page_scale_factor == max_page_scale_factor_)
1092 return false;
1093
1094 min_page_scale_factor_ = min_page_scale_factor;
1095 max_page_scale_factor_ = max_page_scale_factor;
1096
1097 return true;
1098 }
1099
DidUpdatePageScale()1100 void LayerTreeImpl::DidUpdatePageScale() {
1101 if (IsActiveTree())
1102 page_scale_factor()->SetCurrent(
1103 ClampPageScaleFactorToLimits(current_page_scale_factor()));
1104
1105 set_needs_update_draw_properties();
1106
1107 // Viewport scrollbar sizes depend on the page scale factor.
1108 SetScrollbarGeometriesNeedUpdate();
1109
1110 if (IsActiveTree()) {
1111 if (settings().scrollbar_flash_after_any_scroll_update) {
1112 host_impl_->FlashAllScrollbars(true);
1113 return;
1114 }
1115 if (auto* scroll_node = host_impl_->OuterViewportScrollNode()) {
1116 if (ScrollbarAnimationController* controller =
1117 host_impl_->ScrollbarAnimationControllerForElementId(
1118 scroll_node->element_id))
1119 controller->DidScrollUpdate();
1120 }
1121 }
1122 }
1123
SetDeviceScaleFactor(float device_scale_factor)1124 void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) {
1125 if (device_scale_factor == device_scale_factor_)
1126 return;
1127 device_scale_factor_ = device_scale_factor;
1128
1129 set_needs_update_draw_properties();
1130 if (IsActiveTree())
1131 host_impl_->SetViewportDamage(GetDeviceViewport());
1132 host_impl_->SetNeedUpdateGpuRasterizationStatus();
1133 }
1134
SetLocalSurfaceIdAllocationFromParent(const viz::LocalSurfaceIdAllocation & local_surface_id_allocation_from_parent)1135 void LayerTreeImpl::SetLocalSurfaceIdAllocationFromParent(
1136 const viz::LocalSurfaceIdAllocation&
1137 local_surface_id_allocation_from_parent) {
1138 local_surface_id_allocation_from_parent_ =
1139 local_surface_id_allocation_from_parent;
1140 }
1141
RequestNewLocalSurfaceId()1142 void LayerTreeImpl::RequestNewLocalSurfaceId() {
1143 new_local_surface_id_request_ = true;
1144 }
1145
TakeNewLocalSurfaceIdRequest()1146 bool LayerTreeImpl::TakeNewLocalSurfaceIdRequest() {
1147 bool new_local_surface_id_request = new_local_surface_id_request_;
1148 new_local_surface_id_request_ = false;
1149 return new_local_surface_id_request;
1150 }
1151
SetDeviceViewportRect(const gfx::Rect & device_viewport_rect)1152 void LayerTreeImpl::SetDeviceViewportRect(
1153 const gfx::Rect& device_viewport_rect) {
1154 if (device_viewport_rect == device_viewport_rect_)
1155 return;
1156 device_viewport_rect_ = device_viewport_rect;
1157
1158 set_needs_update_draw_properties();
1159 if (!IsActiveTree())
1160 return;
1161
1162 UpdateViewportContainerSizes();
1163 host_impl_->OnCanDrawStateChangedForTree();
1164 host_impl_->SetViewportDamage(GetDeviceViewport());
1165 }
1166
GetDeviceViewport() const1167 gfx::Rect LayerTreeImpl::GetDeviceViewport() const {
1168 // TODO(fsamuel): We should plumb |external_viewport| similar to the
1169 // way we plumb |device_viewport_rect_|.
1170 const gfx::Rect& external_viewport = host_impl_->external_viewport();
1171 if (external_viewport.IsEmpty())
1172 return device_viewport_rect_;
1173 return external_viewport;
1174 }
1175
SetRasterColorSpace(const gfx::ColorSpace & raster_color_space)1176 void LayerTreeImpl::SetRasterColorSpace(
1177 const gfx::ColorSpace& raster_color_space) {
1178 if (raster_color_space == raster_color_space_)
1179 return;
1180 raster_color_space_ = raster_color_space;
1181 }
1182
SetExternalPageScaleFactor(float external_page_scale_factor)1183 void LayerTreeImpl::SetExternalPageScaleFactor(
1184 float external_page_scale_factor) {
1185 if (external_page_scale_factor_ == external_page_scale_factor)
1186 return;
1187
1188 external_page_scale_factor_ = external_page_scale_factor;
1189 DidUpdatePageScale();
1190 }
1191
page_scale_factor()1192 SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() {
1193 return page_scale_factor_.get();
1194 }
1195
page_scale_factor() const1196 const SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() const {
1197 return page_scale_factor_.get();
1198 }
1199
ScrollableViewportSize() const1200 gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const {
1201 auto* inner_node = InnerViewportScrollNode();
1202 if (!inner_node)
1203 return gfx::SizeF();
1204
1205 return gfx::ScaleSize(gfx::SizeF(inner_node->container_bounds),
1206 1.0f / page_scale_factor_for_scroll());
1207 }
1208
RootScrollLayerDeviceViewportBounds() const1209 gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const {
1210 const ScrollNode* root_scroll_node = OuterViewportScrollNode();
1211 if (!root_scroll_node) {
1212 DCHECK(!InnerViewportScrollNode());
1213 return gfx::Rect();
1214 }
1215 return MathUtil::MapEnclosingClippedRect(
1216 property_trees()->transform_tree.ToScreen(root_scroll_node->transform_id),
1217 gfx::Rect(root_scroll_node->bounds));
1218 }
1219
ApplySentScrollAndScaleDeltasFromAbortedCommit()1220 void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() {
1221 DCHECK(IsActiveTree());
1222
1223 page_scale_factor()->AbortCommit();
1224 top_controls_shown_ratio()->AbortCommit();
1225 elastic_overscroll()->AbortCommit();
1226
1227 if (layer_list_.empty())
1228 return;
1229
1230 property_trees()->scroll_tree.ApplySentScrollDeltasFromAbortedCommit();
1231 }
1232
SetViewportPropertyIds(const ViewportPropertyIds & ids)1233 void LayerTreeImpl::SetViewportPropertyIds(const ViewportPropertyIds& ids) {
1234 viewport_property_ids_ = ids;
1235 // Outer viewport properties exist only if inner viewport property exists.
1236 DCHECK(ids.inner_scroll != ScrollTree::kInvalidNodeId ||
1237 (ids.outer_scroll == ScrollTree::kInvalidNodeId &&
1238 ids.outer_clip == ClipTree::kInvalidNodeId));
1239
1240 if (auto* inner_scroll = InnerViewportScrollNode()) {
1241 if (auto* inner_scroll_layer = LayerByElementId(inner_scroll->element_id))
1242 inner_scroll_layer->set_is_inner_viewport_scroll_layer();
1243 }
1244 }
1245
OverscrollElasticityTransformNode() const1246 const TransformNode* LayerTreeImpl::OverscrollElasticityTransformNode() const {
1247 return property_trees()->transform_tree.Node(
1248 viewport_property_ids_.overscroll_elasticity_transform);
1249 }
1250
PageScaleTransformNode() const1251 const TransformNode* LayerTreeImpl::PageScaleTransformNode() const {
1252 return property_trees()->transform_tree.Node(
1253 viewport_property_ids_.page_scale_transform);
1254 }
1255
InnerViewportScrollNode() const1256 const ScrollNode* LayerTreeImpl::InnerViewportScrollNode() const {
1257 return property_trees()->scroll_tree.Node(
1258 viewport_property_ids_.inner_scroll);
1259 }
1260
OuterViewportClipNode() const1261 const ClipNode* LayerTreeImpl::OuterViewportClipNode() const {
1262 return property_trees()->clip_tree.Node(viewport_property_ids_.outer_clip);
1263 }
1264
OuterViewportScrollNode() const1265 const ScrollNode* LayerTreeImpl::OuterViewportScrollNode() const {
1266 return property_trees()->scroll_tree.Node(
1267 viewport_property_ids_.outer_scroll);
1268 }
1269
1270 // For unit tests, we use the layer's id as its element id.
SetElementIdsForTesting()1271 void LayerTreeImpl::SetElementIdsForTesting() {
1272 for (auto* layer : *this) {
1273 if (!layer->element_id())
1274 layer->SetElementId(LayerIdToElementIdForTesting(layer->id()));
1275 }
1276 }
1277
UpdateDrawProperties(bool update_image_animation_controller,LayerImplList * output_update_layer_list_for_testing)1278 bool LayerTreeImpl::UpdateDrawProperties(
1279 bool update_image_animation_controller,
1280 LayerImplList* output_update_layer_list_for_testing) {
1281 if (!needs_update_draw_properties_)
1282 return true;
1283
1284 TRACE_EVENT0("cc,benchmark", "LayerTreeImpl::UpdateDrawProperties");
1285
1286 // Ensure the scrollbar geometries are up-to-date for hit testing and quads
1287 // generation. This may cause damage on the scrollbar layers which is why
1288 // it occurs before we reset |needs_update_draw_properties_|.
1289 UpdateScrollbarGeometries();
1290
1291 // Calling UpdateDrawProperties must clear this flag, so there can be no
1292 // early outs before this.
1293 needs_update_draw_properties_ = false;
1294
1295 // For max_texture_size. When a new output surface is received the needs
1296 // update draw properties flag is set again.
1297 if (!host_impl_->layer_tree_frame_sink())
1298 return false;
1299
1300 // Clear this after the renderer early out, as it should still be
1301 // possible to hit test even without a renderer.
1302 render_surface_list_.clear();
1303
1304 if (layer_list_.empty())
1305 return false;
1306
1307 {
1308 base::ElapsedTimer timer;
1309 TRACE_EVENT2("cc,benchmark",
1310 "LayerTreeImpl::UpdateDrawProperties::CalculateDrawProperties",
1311 "IsActive", IsActiveTree(), "SourceFrameNumber",
1312 source_frame_number_);
1313 // We verify visible rect calculations whenever we verify clip tree
1314 // calculations except when this function is explicitly passed a flag asking
1315 // us to skip it.
1316 draw_property_utils::CalculateDrawProperties(
1317 this, &render_surface_list_, output_update_layer_list_for_testing);
1318
1319 if (const char* client_name = GetClientNameForMetrics()) {
1320 UMA_HISTOGRAM_COUNTS_1M(
1321 base::StringPrintf(
1322 "Compositing.%s.LayerTreeImpl.CalculateDrawPropertiesUs",
1323 client_name),
1324 timer.Elapsed().InMicroseconds());
1325 UMA_HISTOGRAM_COUNTS_100(
1326 base::StringPrintf("Compositing.%s.NumRenderSurfaces", client_name),
1327 base::saturated_cast<int>(render_surface_list_.size()));
1328 }
1329 }
1330
1331 if (settings().enable_occlusion) {
1332 TRACE_EVENT2("cc,benchmark",
1333 "LayerTreeImpl::UpdateDrawProperties::Occlusion", "IsActive",
1334 IsActiveTree(), "SourceFrameNumber", source_frame_number_);
1335 OcclusionTracker occlusion_tracker(RootRenderSurface()->content_rect());
1336 occlusion_tracker.set_minimum_tracking_size(
1337 settings().minimum_occlusion_tracking_size);
1338
1339 for (EffectTreeLayerListIterator it(this);
1340 it.state() != EffectTreeLayerListIterator::State::END; ++it) {
1341 occlusion_tracker.EnterLayer(it);
1342
1343 if (it.state() == EffectTreeLayerListIterator::State::LAYER) {
1344 LayerImpl* layer = it.current_layer();
1345 layer->draw_properties().occlusion_in_content_space =
1346 occlusion_tracker.GetCurrentOcclusionForLayer(
1347 layer->DrawTransform());
1348 }
1349
1350 if (it.state() ==
1351 EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) {
1352 const RenderSurfaceImpl* occlusion_surface =
1353 occlusion_tracker.OcclusionSurfaceForContributingSurface();
1354 gfx::Transform draw_transform;
1355 RenderSurfaceImpl* render_surface = it.current_render_surface();
1356 if (occlusion_surface) {
1357 // We are calculating transform between two render surfaces. So, we
1358 // need to apply the surface contents scale at target and remove the
1359 // surface contents scale at source.
1360 property_trees()->GetToTarget(render_surface->TransformTreeIndex(),
1361 occlusion_surface->EffectTreeIndex(),
1362 &draw_transform);
1363 const EffectNode* effect_node = property_trees()->effect_tree.Node(
1364 render_surface->EffectTreeIndex());
1365 draw_property_utils::ConcatInverseSurfaceContentsScale(
1366 effect_node, &draw_transform);
1367 }
1368
1369 Occlusion occlusion =
1370 occlusion_tracker.GetCurrentOcclusionForContributingSurface(
1371 draw_transform);
1372 render_surface->set_occlusion_in_content_space(occlusion);
1373 }
1374
1375 occlusion_tracker.LeaveLayer(it);
1376 }
1377
1378 unoccluded_screen_space_region_ =
1379 occlusion_tracker.ComputeVisibleRegionInScreen(this);
1380 } else {
1381 // No occlusion, entire root content rect is unoccluded.
1382 unoccluded_screen_space_region_ =
1383 Region(RootRenderSurface()->content_rect());
1384 }
1385
1386 // Resourceless draw do not need tiles and should not affect existing tile
1387 // priorities.
1388 if (!is_in_resourceless_software_draw_mode()) {
1389 TRACE_EVENT_BEGIN2(
1390 "cc,benchmark", "LayerTreeImpl::UpdateDrawProperties::UpdateTiles",
1391 "IsActive", IsActiveTree(), "SourceFrameNumber", source_frame_number_);
1392 size_t layers_updated_count = 0;
1393 bool tile_priorities_updated = false;
1394 for (PictureLayerImpl* layer : picture_layers_) {
1395 if (!layer->HasValidTilePriorities())
1396 continue;
1397 ++layers_updated_count;
1398 tile_priorities_updated |= layer->UpdateTiles();
1399 }
1400
1401 if (tile_priorities_updated)
1402 DidModifyTilePriorities();
1403
1404 TRACE_EVENT_END1("cc,benchmark",
1405 "LayerTreeImpl::UpdateDrawProperties::UpdateTiles",
1406 "layers_updated_count", layers_updated_count);
1407 }
1408
1409 if (update_image_animation_controller && image_animation_controller()) {
1410 image_animation_controller()->UpdateStateFromDrivers();
1411 }
1412
1413 DCHECK(!needs_update_draw_properties_)
1414 << "CalcDrawProperties should not set_needs_update_draw_properties()";
1415 return true;
1416 }
1417
UpdateCanUseLCDText()1418 void LayerTreeImpl::UpdateCanUseLCDText() {
1419 // If this is not the sync tree, then it is not safe to update lcd text
1420 // as it causes invalidations and the tiles may be in use.
1421 DCHECK(IsSyncTree());
1422 bool tile_priorities_updated = false;
1423 for (auto* layer : picture_layers_)
1424 tile_priorities_updated |= layer->UpdateCanUseLCDTextAfterCommit();
1425 if (tile_priorities_updated)
1426 DidModifyTilePriorities();
1427 }
1428
GetRenderSurfaceList() const1429 const RenderSurfaceList& LayerTreeImpl::GetRenderSurfaceList() const {
1430 // If this assert triggers, then the list is dirty.
1431 DCHECK(!needs_update_draw_properties_);
1432 return render_surface_list_;
1433 }
1434
UnoccludedScreenSpaceRegion() const1435 const Region& LayerTreeImpl::UnoccludedScreenSpaceRegion() const {
1436 // If this assert triggers, then the render_surface_list_ is dirty, so the
1437 // unoccluded_screen_space_region_ is not valid anymore.
1438 DCHECK(!needs_update_draw_properties_);
1439 return unoccluded_screen_space_region_;
1440 }
1441
ScrollableSize() const1442 gfx::SizeF LayerTreeImpl::ScrollableSize() const {
1443 auto* scroll_node = OuterViewportScrollNode();
1444 if (!scroll_node) {
1445 DCHECK(!InnerViewportScrollNode());
1446 return gfx::SizeF();
1447 }
1448 const auto& scroll_tree = property_trees()->scroll_tree;
1449 auto size = scroll_tree.scroll_bounds(scroll_node->id);
1450 size.SetToMax(gfx::SizeF(scroll_tree.container_bounds(scroll_node->id)));
1451 return size;
1452 }
1453
LayerById(int id) const1454 LayerImpl* LayerTreeImpl::LayerById(int id) const {
1455 auto iter = layer_id_map_.find(id);
1456 return iter != layer_id_map_.end() ? iter->second : nullptr;
1457 }
1458
1459 // TODO(masonfreed): If this shows up on profiles, this could use
1460 // a layer_element_map_ approach similar to LayerById().
LayerByElementId(ElementId element_id) const1461 LayerImpl* LayerTreeImpl::LayerByElementId(ElementId element_id) const {
1462 auto it =
1463 std::find_if(rbegin(), rend(), [&element_id](LayerImpl* layer_impl) {
1464 return layer_impl->element_id() == element_id;
1465 });
1466 if (it == rend())
1467 return nullptr;
1468 return *it;
1469 }
1470
SetSurfaceRanges(const base::flat_set<viz::SurfaceRange> surface_ranges)1471 void LayerTreeImpl::SetSurfaceRanges(
1472 const base::flat_set<viz::SurfaceRange> surface_ranges) {
1473 DCHECK(surface_layer_ranges_.empty());
1474 surface_layer_ranges_ = std::move(surface_ranges);
1475 needs_surface_ranges_sync_ = true;
1476 }
1477
SurfaceRanges() const1478 const base::flat_set<viz::SurfaceRange>& LayerTreeImpl::SurfaceRanges() const {
1479 return surface_layer_ranges_;
1480 }
1481
ClearSurfaceRanges()1482 void LayerTreeImpl::ClearSurfaceRanges() {
1483 surface_layer_ranges_.clear();
1484 needs_surface_ranges_sync_ = true;
1485 }
1486
AddLayerShouldPushProperties(LayerImpl * layer)1487 void LayerTreeImpl::AddLayerShouldPushProperties(LayerImpl* layer) {
1488 DCHECK(!IsActiveTree()) << "The active tree does not push layer properties";
1489 // TODO(crbug.com/303943): PictureLayerImpls always push properties so should
1490 // not go into this set or we'd push them twice.
1491 DCHECK(!base::Contains(picture_layers_, layer));
1492 layers_that_should_push_properties_.insert(layer);
1493 }
1494
ClearLayersThatShouldPushProperties()1495 void LayerTreeImpl::ClearLayersThatShouldPushProperties() {
1496 layers_that_should_push_properties_.clear();
1497 }
1498
RegisterLayer(LayerImpl * layer)1499 void LayerTreeImpl::RegisterLayer(LayerImpl* layer) {
1500 DCHECK(!LayerById(layer->id()));
1501 layer_id_map_[layer->id()] = layer;
1502 }
1503
UnregisterLayer(LayerImpl * layer)1504 void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) {
1505 DCHECK(LayerById(layer->id()));
1506 layers_that_should_push_properties_.erase(layer);
1507 layer_id_map_.erase(layer->id());
1508 }
1509
AddLayer(std::unique_ptr<LayerImpl> layer)1510 void LayerTreeImpl::AddLayer(std::unique_ptr<LayerImpl> layer) {
1511 DCHECK(layer);
1512 DCHECK(!base::Contains(layer_list_, layer));
1513 layer_list_.push_back(std::move(layer));
1514 set_needs_update_draw_properties();
1515 }
1516
NumLayers()1517 size_t LayerTreeImpl::NumLayers() {
1518 return layer_id_map_.size();
1519 }
1520
DidBecomeActive()1521 void LayerTreeImpl::DidBecomeActive() {
1522 if (next_activation_forces_redraw_) {
1523 host_impl_->SetViewportDamage(GetDeviceViewport());
1524 next_activation_forces_redraw_ = false;
1525 }
1526
1527 // Always reset this flag on activation, as we would only have activated
1528 // if we were in a good state.
1529 host_impl_->ResetRequiresHighResToDraw();
1530
1531 for (auto* layer : *this)
1532 layer->DidBecomeActive();
1533
1534 for (const auto& swap_promise : swap_promise_list_)
1535 swap_promise->DidActivate();
1536 devtools_instrumentation::DidActivateLayerTree(host_impl_->id(),
1537 source_frame_number_);
1538 }
1539
RequiresHighResToDraw() const1540 bool LayerTreeImpl::RequiresHighResToDraw() const {
1541 return host_impl_->RequiresHighResToDraw();
1542 }
1543
task_runner_provider() const1544 TaskRunnerProvider* LayerTreeImpl::task_runner_provider() const {
1545 return host_impl_->task_runner_provider();
1546 }
1547
layer_tree_frame_sink()1548 LayerTreeFrameSink* LayerTreeImpl::layer_tree_frame_sink() {
1549 return host_impl_->layer_tree_frame_sink();
1550 }
1551
max_texture_size() const1552 int LayerTreeImpl::max_texture_size() const {
1553 return host_impl_->max_texture_size();
1554 }
1555
settings() const1556 const LayerTreeSettings& LayerTreeImpl::settings() const {
1557 return host_impl_->settings();
1558 }
1559
debug_state() const1560 const LayerTreeDebugState& LayerTreeImpl::debug_state() const {
1561 return host_impl_->debug_state();
1562 }
1563
context_provider() const1564 viz::ContextProvider* LayerTreeImpl::context_provider() const {
1565 return host_impl_->layer_tree_frame_sink()->context_provider();
1566 }
1567
resource_provider() const1568 viz::ClientResourceProvider* LayerTreeImpl::resource_provider() const {
1569 return host_impl_->resource_provider();
1570 }
1571
tile_manager() const1572 TileManager* LayerTreeImpl::tile_manager() const {
1573 return host_impl_->tile_manager();
1574 }
1575
image_decode_cache() const1576 ImageDecodeCache* LayerTreeImpl::image_decode_cache() const {
1577 return host_impl_->image_decode_cache();
1578 }
1579
image_animation_controller() const1580 ImageAnimationController* LayerTreeImpl::image_animation_controller() const {
1581 return host_impl_->image_animation_controller();
1582 }
1583
frame_rate_counter() const1584 FrameRateCounter* LayerTreeImpl::frame_rate_counter() const {
1585 return host_impl_->fps_counter();
1586 }
1587
memory_history() const1588 MemoryHistory* LayerTreeImpl::memory_history() const {
1589 return host_impl_->memory_history();
1590 }
1591
debug_rect_history() const1592 DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
1593 return host_impl_->debug_rect_history();
1594 }
1595
IsActiveTree() const1596 bool LayerTreeImpl::IsActiveTree() const {
1597 return host_impl_->active_tree() == this;
1598 }
1599
IsPendingTree() const1600 bool LayerTreeImpl::IsPendingTree() const {
1601 return host_impl_->pending_tree() == this;
1602 }
1603
IsRecycleTree() const1604 bool LayerTreeImpl::IsRecycleTree() const {
1605 return host_impl_->recycle_tree() == this;
1606 }
1607
IsSyncTree() const1608 bool LayerTreeImpl::IsSyncTree() const {
1609 return host_impl_->sync_tree() == this;
1610 }
1611
FindActiveTreeLayerById(int id)1612 LayerImpl* LayerTreeImpl::FindActiveTreeLayerById(int id) {
1613 LayerTreeImpl* tree = host_impl_->active_tree();
1614 if (!tree)
1615 return nullptr;
1616 return tree->LayerById(id);
1617 }
1618
FindPendingTreeLayerById(int id)1619 LayerImpl* LayerTreeImpl::FindPendingTreeLayerById(int id) {
1620 LayerTreeImpl* tree = host_impl_->pending_tree();
1621 if (!tree)
1622 return nullptr;
1623 return tree->LayerById(id);
1624 }
1625
PinchGestureActive() const1626 bool LayerTreeImpl::PinchGestureActive() const {
1627 return host_impl_->pinch_gesture_active();
1628 }
1629
CurrentBeginFrameArgs() const1630 viz::BeginFrameArgs LayerTreeImpl::CurrentBeginFrameArgs() const {
1631 return host_impl_->CurrentBeginFrameArgs();
1632 }
1633
CurrentBeginFrameInterval() const1634 base::TimeDelta LayerTreeImpl::CurrentBeginFrameInterval() const {
1635 return host_impl_->CurrentBeginFrameInterval();
1636 }
1637
ViewportRectForTilePriority() const1638 const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const {
1639 const gfx::Rect& viewport_rect_for_tile_priority =
1640 host_impl_->viewport_rect_for_tile_priority();
1641 return viewport_rect_for_tile_priority.IsEmpty()
1642 ? GetDeviceViewport()
1643 : viewport_rect_for_tile_priority;
1644 }
1645
1646 std::unique_ptr<ScrollbarAnimationController>
CreateScrollbarAnimationController(ElementId scroll_element_id,float initial_opacity)1647 LayerTreeImpl::CreateScrollbarAnimationController(ElementId scroll_element_id,
1648 float initial_opacity) {
1649 DCHECK(!settings().scrollbar_fade_delay.is_zero());
1650 DCHECK(!settings().scrollbar_fade_duration.is_zero());
1651 base::TimeDelta fade_delay = settings().scrollbar_fade_delay;
1652 base::TimeDelta fade_duration = settings().scrollbar_fade_duration;
1653 switch (settings().scrollbar_animator) {
1654 case LayerTreeSettings::ANDROID_OVERLAY: {
1655 return ScrollbarAnimationController::
1656 CreateScrollbarAnimationControllerAndroid(
1657 scroll_element_id, host_impl_, fade_delay, fade_duration,
1658 initial_opacity);
1659 }
1660 case LayerTreeSettings::AURA_OVERLAY: {
1661 base::TimeDelta thinning_duration =
1662 settings().scrollbar_thinning_duration;
1663 return ScrollbarAnimationController::
1664 CreateScrollbarAnimationControllerAuraOverlay(
1665 scroll_element_id, host_impl_, fade_delay, fade_duration,
1666 thinning_duration, initial_opacity);
1667 }
1668 case LayerTreeSettings::NO_ANIMATOR:
1669 NOTREACHED();
1670 break;
1671 }
1672 return nullptr;
1673 }
1674
DidAnimateScrollOffset()1675 void LayerTreeImpl::DidAnimateScrollOffset() {
1676 host_impl_->DidAnimateScrollOffset();
1677 }
1678
use_gpu_rasterization() const1679 bool LayerTreeImpl::use_gpu_rasterization() const {
1680 return host_impl_->use_gpu_rasterization();
1681 }
1682
GetGpuRasterizationStatus() const1683 GpuRasterizationStatus LayerTreeImpl::GetGpuRasterizationStatus() const {
1684 return host_impl_->gpu_rasterization_status();
1685 }
1686
create_low_res_tiling() const1687 bool LayerTreeImpl::create_low_res_tiling() const {
1688 return host_impl_->create_low_res_tiling();
1689 }
1690
SetNeedsRedraw()1691 void LayerTreeImpl::SetNeedsRedraw() {
1692 host_impl_->SetNeedsRedraw();
1693 }
1694
GetAllPrioritizedTilesForTracing(std::vector<PrioritizedTile> * prioritized_tiles) const1695 void LayerTreeImpl::GetAllPrioritizedTilesForTracing(
1696 std::vector<PrioritizedTile>* prioritized_tiles) const {
1697 for (auto* layer : base::Reversed(*this)) {
1698 if (!layer->contributes_to_drawn_render_surface())
1699 continue;
1700 layer->GetAllPrioritizedTilesForTracing(prioritized_tiles);
1701 }
1702 }
1703
AsValueInto(base::trace_event::TracedValue * state) const1704 void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const {
1705 viz::TracedValue::MakeDictIntoImplicitSnapshot(state, "cc::LayerTreeImpl",
1706 this);
1707 state->SetInteger("source_frame_number", source_frame_number_);
1708
1709 state->BeginArray("render_surface_layer_list");
1710 for (auto* layer : base::Reversed(*this)) {
1711 if (layer->contributes_to_drawn_render_surface())
1712 continue;
1713 viz::TracedValue::AppendIDRef(layer, state);
1714 }
1715 state->EndArray();
1716
1717 state->BeginArray("swap_promise_trace_ids");
1718 for (const auto& swap_promise : swap_promise_list_)
1719 state->AppendDouble(swap_promise->TraceId());
1720 state->EndArray();
1721
1722 state->BeginArray("pinned_swap_promise_trace_ids");
1723 for (const auto& swap_promise : pinned_swap_promise_list_)
1724 state->AppendDouble(swap_promise->TraceId());
1725 state->EndArray();
1726
1727 state->BeginArray("layers");
1728 for (auto* layer : *this) {
1729 state->BeginDictionary();
1730 layer->AsValueInto(state);
1731 state->EndDictionary();
1732 }
1733 state->EndArray();
1734 }
1735
QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise)1736 void LayerTreeImpl::QueueSwapPromise(
1737 std::unique_ptr<SwapPromise> swap_promise) {
1738 DCHECK(swap_promise);
1739 swap_promise_list_.push_back(std::move(swap_promise));
1740 }
1741
QueuePinnedSwapPromise(std::unique_ptr<SwapPromise> swap_promise)1742 void LayerTreeImpl::QueuePinnedSwapPromise(
1743 std::unique_ptr<SwapPromise> swap_promise) {
1744 DCHECK(IsActiveTree());
1745 DCHECK(swap_promise);
1746 pinned_swap_promise_list_.push_back(std::move(swap_promise));
1747 }
1748
PassSwapPromises(std::vector<std::unique_ptr<SwapPromise>> new_swap_promises)1749 void LayerTreeImpl::PassSwapPromises(
1750 std::vector<std::unique_ptr<SwapPromise>> new_swap_promises) {
1751 for (auto& swap_promise : swap_promise_list_) {
1752 if (swap_promise->DidNotSwap(SwapPromise::SWAP_FAILS) ==
1753 SwapPromise::DidNotSwapAction::KEEP_ACTIVE) {
1754 // |swap_promise| must remain active, so place it in |new_swap_promises|
1755 // in order to keep it alive and active.
1756 new_swap_promises.push_back(std::move(swap_promise));
1757 }
1758 }
1759 swap_promise_list_.clear();
1760 swap_promise_list_.swap(new_swap_promises);
1761 }
1762
AppendSwapPromises(std::vector<std::unique_ptr<SwapPromise>> new_swap_promises)1763 void LayerTreeImpl::AppendSwapPromises(
1764 std::vector<std::unique_ptr<SwapPromise>> new_swap_promises) {
1765 std::move(new_swap_promises.begin(), new_swap_promises.end(),
1766 std::back_inserter(swap_promise_list_));
1767 new_swap_promises.clear();
1768 }
1769
FinishSwapPromises(viz::CompositorFrameMetadata * metadata)1770 void LayerTreeImpl::FinishSwapPromises(viz::CompositorFrameMetadata* metadata) {
1771 for (const auto& swap_promise : swap_promise_list_)
1772 swap_promise->WillSwap(metadata);
1773 for (const auto& swap_promise : pinned_swap_promise_list_)
1774 swap_promise->WillSwap(metadata);
1775 }
1776
ClearSwapPromises()1777 void LayerTreeImpl::ClearSwapPromises() {
1778 for (const auto& swap_promise : swap_promise_list_)
1779 swap_promise->DidSwap();
1780 swap_promise_list_.clear();
1781 for (const auto& swap_promise : pinned_swap_promise_list_)
1782 swap_promise->DidSwap();
1783 pinned_swap_promise_list_.clear();
1784 }
1785
BreakSwapPromises(SwapPromise::DidNotSwapReason reason)1786 void LayerTreeImpl::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
1787 {
1788 std::vector<std::unique_ptr<SwapPromise>> persistent_swap_promises;
1789 for (auto& swap_promise : swap_promise_list_) {
1790 if (swap_promise->DidNotSwap(reason) ==
1791 SwapPromise::DidNotSwapAction::KEEP_ACTIVE) {
1792 persistent_swap_promises.push_back(std::move(swap_promise));
1793 }
1794 }
1795 // |persistent_swap_promises| must remain active even when swap fails.
1796 swap_promise_list_ = std::move(persistent_swap_promises);
1797 }
1798
1799 {
1800 std::vector<std::unique_ptr<SwapPromise>> persistent_swap_promises;
1801 for (auto& swap_promise : pinned_swap_promise_list_) {
1802 if (swap_promise->DidNotSwap(reason) ==
1803 SwapPromise::DidNotSwapAction::KEEP_ACTIVE) {
1804 persistent_swap_promises.push_back(std::move(swap_promise));
1805 }
1806 }
1807
1808 // |persistent_swap_promises| must remain active even when swap fails.
1809 pinned_swap_promise_list_ = std::move(persistent_swap_promises);
1810 }
1811 }
1812
DidModifyTilePriorities()1813 void LayerTreeImpl::DidModifyTilePriorities() {
1814 host_impl_->DidModifyTilePriorities();
1815 }
1816
set_ui_resource_request_queue(UIResourceRequestQueue queue)1817 void LayerTreeImpl::set_ui_resource_request_queue(
1818 UIResourceRequestQueue queue) {
1819 ui_resource_request_queue_ = std::move(queue);
1820 }
1821
ResourceIdForUIResource(UIResourceId uid) const1822 viz::ResourceId LayerTreeImpl::ResourceIdForUIResource(UIResourceId uid) const {
1823 return host_impl_->ResourceIdForUIResource(uid);
1824 }
1825
IsUIResourceOpaque(UIResourceId uid) const1826 bool LayerTreeImpl::IsUIResourceOpaque(UIResourceId uid) const {
1827 return host_impl_->IsUIResourceOpaque(uid);
1828 }
1829
ProcessUIResourceRequestQueue()1830 void LayerTreeImpl::ProcessUIResourceRequestQueue() {
1831 TRACE_EVENT1("cc", "ProcessUIResourceRequestQueue", "queue_size",
1832 ui_resource_request_queue_.size());
1833 for (const auto& req : ui_resource_request_queue_) {
1834 switch (req.GetType()) {
1835 case UIResourceRequest::UI_RESOURCE_CREATE:
1836 host_impl_->CreateUIResource(req.GetId(), req.GetBitmap());
1837 break;
1838 case UIResourceRequest::UI_RESOURCE_DELETE:
1839 host_impl_->DeleteUIResource(req.GetId());
1840 break;
1841 case UIResourceRequest::UI_RESOURCE_INVALID_REQUEST:
1842 NOTREACHED();
1843 break;
1844 }
1845 }
1846 ui_resource_request_queue_.clear();
1847
1848 // If all UI resource evictions were not recreated by processing this queue,
1849 // then another commit is required.
1850 if (host_impl_->EvictedUIResourcesExist())
1851 host_impl_->SetNeedsCommit();
1852 }
1853
RegisterPictureLayerImpl(PictureLayerImpl * layer)1854 void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) {
1855 DCHECK(!base::Contains(picture_layers_, layer));
1856 picture_layers_.push_back(layer);
1857 }
1858
UnregisterPictureLayerImpl(PictureLayerImpl * layer)1859 void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) {
1860 auto it = std::find(picture_layers_.begin(), picture_layers_.end(), layer);
1861 DCHECK(it != picture_layers_.end());
1862 picture_layers_.erase(it);
1863
1864 // Make sure that |picture_layers_with_paint_worklets_| doesn't get left with
1865 // dead layers. They should already have been removed (via calling
1866 // NotifyLayerHasPaintWorkletsChanged) before the layer was unregistered.
1867 DCHECK(!picture_layers_with_paint_worklets_.contains(layer));
1868 }
1869
NotifyLayerHasPaintWorkletsChanged(PictureLayerImpl * layer,bool has_worklets)1870 void LayerTreeImpl::NotifyLayerHasPaintWorkletsChanged(PictureLayerImpl* layer,
1871 bool has_worklets) {
1872 if (has_worklets) {
1873 auto insert_pair = picture_layers_with_paint_worklets_.insert(layer);
1874 DCHECK(insert_pair.second);
1875 } else {
1876 auto it = picture_layers_with_paint_worklets_.find(layer);
1877 DCHECK(it != picture_layers_with_paint_worklets_.end());
1878 picture_layers_with_paint_worklets_.erase(it);
1879 }
1880 }
1881
RegisterScrollbar(ScrollbarLayerImplBase * scrollbar_layer)1882 void LayerTreeImpl::RegisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer) {
1883 ElementId scroll_element_id = scrollbar_layer->scroll_element_id();
1884 if (!scroll_element_id)
1885 return;
1886
1887 auto* scrollbar_ids = &element_id_to_scrollbar_layer_ids_[scroll_element_id];
1888 int* scrollbar_layer_id = scrollbar_layer->orientation() == HORIZONTAL
1889 ? &scrollbar_ids->horizontal
1890 : &scrollbar_ids->vertical;
1891
1892 // We used to DCHECK this was not the case but this can occur on Android: as
1893 // the visual viewport supplies scrollbars for the outer viewport, if the
1894 // outer viewport is changed, we race between updating the visual viewport
1895 // scrollbars and registering new scrollbars on the old outer viewport. It'd
1896 // be nice if we could fix this to be cleaner but its harmless to just
1897 // unregister here.
1898 if (*scrollbar_layer_id != Layer::INVALID_ID) {
1899 UnregisterScrollbar(scrollbar_layer);
1900
1901 // The scrollbar_ids could have been erased above so get it again.
1902 scrollbar_ids = &element_id_to_scrollbar_layer_ids_[scroll_element_id];
1903 scrollbar_layer_id = scrollbar_layer->orientation() == HORIZONTAL
1904 ? &scrollbar_ids->horizontal
1905 : &scrollbar_ids->vertical;
1906 }
1907
1908 *scrollbar_layer_id = scrollbar_layer->id();
1909
1910 if (IsActiveTree() && scrollbar_layer->is_overlay_scrollbar() &&
1911 scrollbar_layer->GetScrollbarAnimator() !=
1912 LayerTreeSettings::NO_ANIMATOR) {
1913 host_impl_->RegisterScrollbarAnimationController(
1914 scroll_element_id, scrollbar_layer->Opacity());
1915 }
1916
1917 // The new scrollbar's geometries need to be initialized.
1918 SetScrollbarGeometriesNeedUpdate();
1919 }
1920
UnregisterScrollbar(ScrollbarLayerImplBase * scrollbar_layer)1921 void LayerTreeImpl::UnregisterScrollbar(
1922 ScrollbarLayerImplBase* scrollbar_layer) {
1923 ElementId scroll_element_id = scrollbar_layer->scroll_element_id();
1924 if (!scroll_element_id)
1925 return;
1926
1927 auto& scrollbar_ids = element_id_to_scrollbar_layer_ids_[scroll_element_id];
1928 if (scrollbar_layer->orientation() == HORIZONTAL)
1929 scrollbar_ids.horizontal = Layer::INVALID_ID;
1930 else
1931 scrollbar_ids.vertical = Layer::INVALID_ID;
1932
1933 if (scrollbar_ids.horizontal == Layer::INVALID_ID &&
1934 scrollbar_ids.vertical == Layer::INVALID_ID) {
1935 element_id_to_scrollbar_layer_ids_.erase(scroll_element_id);
1936 if (IsActiveTree()) {
1937 host_impl_->DidUnregisterScrollbarLayer(scroll_element_id);
1938 }
1939 }
1940 }
1941
ScrollbarsFor(ElementId scroll_element_id) const1942 ScrollbarSet LayerTreeImpl::ScrollbarsFor(ElementId scroll_element_id) const {
1943 ScrollbarSet scrollbars;
1944 auto it = element_id_to_scrollbar_layer_ids_.find(scroll_element_id);
1945 if (it != element_id_to_scrollbar_layer_ids_.end()) {
1946 const ScrollbarLayerIds& layer_ids = it->second;
1947 if (layer_ids.horizontal != Layer::INVALID_ID)
1948 scrollbars.insert(LayerById(layer_ids.horizontal)->ToScrollbarLayer());
1949 if (layer_ids.vertical != Layer::INVALID_ID)
1950 scrollbars.insert(LayerById(layer_ids.vertical)->ToScrollbarLayer());
1951 }
1952 return scrollbars;
1953 }
1954
PointHitsRect(const gfx::PointF & screen_space_point,const gfx::Transform & local_space_to_screen_space_transform,const gfx::Rect & local_space_rect,float * distance_to_camera)1955 static bool PointHitsRect(
1956 const gfx::PointF& screen_space_point,
1957 const gfx::Transform& local_space_to_screen_space_transform,
1958 const gfx::Rect& local_space_rect,
1959 float* distance_to_camera) {
1960 // If the transform is not invertible, then assume that this point doesn't hit
1961 // this rect.
1962 gfx::Transform inverse_local_space_to_screen_space(
1963 gfx::Transform::kSkipInitialization);
1964 if (!local_space_to_screen_space_transform.GetInverse(
1965 &inverse_local_space_to_screen_space))
1966 return false;
1967
1968 // Transform the hit test point from screen space to the local space of the
1969 // given rect.
1970 bool clipped = false;
1971 gfx::Point3F planar_point = MathUtil::ProjectPoint3D(
1972 inverse_local_space_to_screen_space, screen_space_point, &clipped);
1973 gfx::PointF hit_test_point_in_local_space =
1974 gfx::PointF(planar_point.x(), planar_point.y());
1975
1976 // If ProjectPoint could not project to a valid value, then we assume that
1977 // this point doesn't hit this rect.
1978 if (clipped)
1979 return false;
1980
1981 if (!gfx::RectF(local_space_rect).Contains(hit_test_point_in_local_space))
1982 return false;
1983
1984 if (distance_to_camera) {
1985 // To compute the distance to the camera, we have to take the planar point
1986 // and pull it back to world space and compute the displacement along the
1987 // z-axis.
1988 gfx::Point3F planar_point_in_screen_space(planar_point);
1989 local_space_to_screen_space_transform.TransformPoint(
1990 &planar_point_in_screen_space);
1991 *distance_to_camera = planar_point_in_screen_space.z();
1992 }
1993
1994 return true;
1995 }
1996
PointIsClippedByAncestorClipNode(const gfx::PointF & screen_space_point,const LayerImpl * layer)1997 static bool PointIsClippedByAncestorClipNode(
1998 const gfx::PointF& screen_space_point,
1999 const LayerImpl* layer) {
2000 // We need to visit all ancestor clip nodes to check this. Checking with just
2001 // the combined clip stored at a clip node is not enough because parent
2002 // combined clip can sometimes be smaller than current combined clip. This can
2003 // happen when we have transforms like rotation that inflate the combined
2004 // clip's bounds. Also, the point can be clipped by the content rect of an
2005 // ancestor render surface.
2006
2007 // We first check if the point is clipped by viewport.
2008 const PropertyTrees* property_trees =
2009 layer->layer_tree_impl()->property_trees();
2010 const ClipTree& clip_tree = property_trees->clip_tree;
2011 const TransformTree& transform_tree = property_trees->transform_tree;
2012 gfx::Rect clip = gfx::ToEnclosingRect(clip_tree.Node(1)->clip);
2013 if (!PointHitsRect(screen_space_point, gfx::Transform(), clip, nullptr))
2014 return true;
2015
2016 for (const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
2017 clip_node->id > ClipTree::kViewportNodeId;
2018 clip_node = clip_tree.parent(clip_node)) {
2019 if (clip_node->clip_type == ClipNode::ClipType::APPLIES_LOCAL_CLIP) {
2020 clip = gfx::ToEnclosingRect(clip_node->clip);
2021
2022 gfx::Transform screen_space_transform =
2023 transform_tree.ToScreen(clip_node->transform_id);
2024 if (!PointHitsRect(screen_space_point, screen_space_transform, clip,
2025 nullptr)) {
2026 return true;
2027 }
2028 }
2029 }
2030 return false;
2031 }
2032
PointIsClippedBySurfaceOrClipRect(const gfx::PointF & screen_space_point,const LayerImpl * layer)2033 static bool PointIsClippedBySurfaceOrClipRect(
2034 const gfx::PointF& screen_space_point,
2035 const LayerImpl* layer) {
2036 // Walk up the layer tree and hit-test any render_surfaces and any layer
2037 // clip rects that are active.
2038 return PointIsClippedByAncestorClipNode(screen_space_point, layer);
2039 }
2040
PointHitsRegion(const gfx::PointF & screen_space_point,const gfx::Transform & screen_space_transform,const Region & layer_space_region,const LayerImpl * layer_impl)2041 static bool PointHitsRegion(const gfx::PointF& screen_space_point,
2042 const gfx::Transform& screen_space_transform,
2043 const Region& layer_space_region,
2044 const LayerImpl* layer_impl) {
2045 if (layer_space_region.IsEmpty())
2046 return false;
2047
2048 // If the transform is not invertible, then assume that this point doesn't hit
2049 // this region.
2050 gfx::Transform inverse_screen_space_transform(
2051 gfx::Transform::kSkipInitialization);
2052 if (!screen_space_transform.GetInverse(&inverse_screen_space_transform))
2053 return false;
2054
2055 // Transform the hit test point from screen space to the local space of the
2056 // given region.
2057 bool clipped = false;
2058 gfx::PointF hit_test_point_in_layer_space = MathUtil::ProjectPoint(
2059 inverse_screen_space_transform, screen_space_point, &clipped);
2060
2061 // If ProjectPoint could not project to a valid value, then we assume that
2062 // this point doesn't hit this region.
2063 if (clipped)
2064 return false;
2065
2066 // We need to walk up the parents to ensure that the layer is not clipped in
2067 // such a way that it is impossible for the point to hit the layer.
2068 if (layer_impl &&
2069 PointIsClippedBySurfaceOrClipRect(screen_space_point, layer_impl))
2070 return false;
2071
2072 return layer_space_region.Contains(
2073 gfx::ToRoundedPoint(hit_test_point_in_layer_space));
2074 }
2075
PointHitsLayer(const LayerImpl * layer,const gfx::PointF & screen_space_point,float * distance_to_intersection)2076 static bool PointHitsLayer(const LayerImpl* layer,
2077 const gfx::PointF& screen_space_point,
2078 float* distance_to_intersection) {
2079 gfx::Rect content_rect(layer->bounds());
2080 if (!PointHitsRect(screen_space_point, layer->ScreenSpaceTransform(),
2081 content_rect, distance_to_intersection)) {
2082 return false;
2083 }
2084
2085 // At this point, we think the point does hit the layer, but we need to walk
2086 // up the parents to ensure that the layer was not clipped in such a way
2087 // that the hit point actually should not hit the layer.
2088 if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer))
2089 return false;
2090
2091 // Skip the HUD layer.
2092 if (layer == layer->layer_tree_impl()->hud_layer())
2093 return false;
2094
2095 return true;
2096 }
2097
2098 struct FindClosestMatchingLayerState {
FindClosestMatchingLayerStatecc::FindClosestMatchingLayerState2099 FindClosestMatchingLayerState()
2100 : closest_match(nullptr),
2101 closest_distance(-std::numeric_limits<float>::infinity()) {}
2102 LayerImpl* closest_match;
2103 // Note that the positive z-axis points towards the camera, so bigger means
2104 // closer in this case, counterintuitively.
2105 float closest_distance;
2106 };
2107
2108 template <typename Functor>
FindClosestMatchingLayer(const gfx::PointF & screen_space_point,LayerImpl * root_layer,const Functor & func,FindClosestMatchingLayerState * state)2109 static void FindClosestMatchingLayer(const gfx::PointF& screen_space_point,
2110 LayerImpl* root_layer,
2111 const Functor& func,
2112 FindClosestMatchingLayerState* state) {
2113 base::ElapsedTimer timer;
2114 // We want to iterate from front to back when hit testing.
2115 for (auto* layer : base::Reversed(*root_layer->layer_tree_impl())) {
2116 if (!func(layer))
2117 continue;
2118
2119 float distance_to_intersection = 0.f;
2120 bool hit = false;
2121 if (layer->Is3dSorted()) {
2122 hit =
2123 PointHitsLayer(layer, screen_space_point, &distance_to_intersection);
2124 } else {
2125 hit = PointHitsLayer(layer, screen_space_point, nullptr);
2126 }
2127
2128 if (!hit)
2129 continue;
2130
2131 bool in_front_of_previous_candidate =
2132 state->closest_match &&
2133 layer->GetSortingContextId() ==
2134 state->closest_match->GetSortingContextId() &&
2135 distance_to_intersection >
2136 state->closest_distance + std::numeric_limits<float>::epsilon();
2137
2138 if (!state->closest_match || in_front_of_previous_candidate) {
2139 state->closest_distance = distance_to_intersection;
2140 state->closest_match = layer;
2141 }
2142 }
2143 if (const char* client_name = GetClientNameForMetrics()) {
2144 UMA_HISTOGRAM_COUNTS_1M(
2145 base::StringPrintf("Compositing.%s.HitTestTimeToFindClosestLayer",
2146 client_name),
2147 timer.Elapsed().InMicroseconds());
2148 }
2149 }
2150
FindFirstScrollingLayerOrScrollbarThatIsHitByPoint(const gfx::PointF & screen_space_point)2151 LayerImpl* LayerTreeImpl::FindFirstScrollingLayerOrScrollbarThatIsHitByPoint(
2152 const gfx::PointF& screen_space_point) {
2153 if (layer_list_.empty())
2154 return nullptr;
2155
2156 FindClosestMatchingLayerState state;
2157 LayerImpl* root_layer = layer_list_[0].get();
2158 auto HitTestScrollingLayerOrScrollbarFunctor =
2159 [this](const LayerImpl* layer) {
2160 return layer->HitTestable() &&
2161 (layer->is_scrollbar() ||
2162 (property_trees()->scroll_tree.FindNodeFromElementId(
2163 layer->element_id())));
2164 };
2165 FindClosestMatchingLayer(screen_space_point, root_layer,
2166 HitTestScrollingLayerOrScrollbarFunctor, &state);
2167 return state.closest_match;
2168 }
2169
2170 struct HitTestVisibleScrollableOrTouchableFunctor {
operator ()cc::HitTestVisibleScrollableOrTouchableFunctor2171 bool operator()(LayerImpl* layer) const { return layer->HitTestable(); }
2172 };
2173
FindLayerThatIsHitByPoint(const gfx::PointF & screen_space_point)2174 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint(
2175 const gfx::PointF& screen_space_point) {
2176 if (layer_list_.empty())
2177 return nullptr;
2178 if (!UpdateDrawProperties())
2179 return nullptr;
2180 FindClosestMatchingLayerState state;
2181 FindClosestMatchingLayer(screen_space_point, layer_list_[0].get(),
2182 HitTestVisibleScrollableOrTouchableFunctor(),
2183 &state);
2184 return state.closest_match;
2185 }
2186
2187 struct FindTouchEventLayerFunctor {
operator ()cc::FindTouchEventLayerFunctor2188 bool operator()(LayerImpl* layer) const {
2189 if (!layer->has_touch_action_regions())
2190 return false;
2191 return PointHitsRegion(screen_space_point, layer->ScreenSpaceTransform(),
2192 layer->GetAllTouchActionRegions(), layer);
2193 }
2194 const gfx::PointF screen_space_point;
2195 };
2196
2197 struct FindWheelEventHandlerLayerFunctor {
operator ()cc::FindWheelEventHandlerLayerFunctor2198 bool operator()(LayerImpl* layer) const {
2199 return PointHitsRegion(screen_space_point, layer->ScreenSpaceTransform(),
2200 layer->wheel_event_handler_region(), layer);
2201 }
2202 const gfx::PointF screen_space_point;
2203 };
2204
2205 template <typename Functor>
FindLayerThatIsHitByPointInEventHandlerRegion(const gfx::PointF & screen_space_point,const Functor & func)2206 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInEventHandlerRegion(
2207 const gfx::PointF& screen_space_point,
2208 const Functor& func) {
2209 if (layer_list_.empty())
2210 return nullptr;
2211 if (!UpdateDrawProperties())
2212 return nullptr;
2213 FindClosestMatchingLayerState state;
2214 FindClosestMatchingLayer(screen_space_point, layer_list_[0].get(), func,
2215 &state);
2216 return state.closest_match;
2217 }
2218
FindLayerThatIsHitByPointInTouchHandlerRegion(const gfx::PointF & screen_space_point)2219 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInTouchHandlerRegion(
2220 const gfx::PointF& screen_space_point) {
2221 FindTouchEventLayerFunctor func = {screen_space_point};
2222 return FindLayerThatIsHitByPointInEventHandlerRegion(screen_space_point,
2223 func);
2224 }
2225
FindLayerThatIsHitByPointInWheelEventHandlerRegion(const gfx::PointF & screen_space_point)2226 LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInWheelEventHandlerRegion(
2227 const gfx::PointF& screen_space_point) {
2228 FindWheelEventHandlerLayerFunctor func = {screen_space_point};
2229 return FindLayerThatIsHitByPointInEventHandlerRegion(screen_space_point,
2230 func);
2231 }
2232
2233 std::vector<const LayerImpl*>
FindLayersHitByPointInNonFastScrollableRegion(const gfx::PointF & screen_space_point)2234 LayerTreeImpl::FindLayersHitByPointInNonFastScrollableRegion(
2235 const gfx::PointF& screen_space_point) {
2236 std::vector<const LayerImpl*> layers;
2237 if (layer_list_.empty())
2238 return layers;
2239 if (!UpdateDrawProperties())
2240 return layers;
2241 for (const auto* layer : *this) {
2242 if (layer->non_fast_scrollable_region().IsEmpty())
2243 continue;
2244 if (!PointHitsLayer(layer, screen_space_point, nullptr))
2245 continue;
2246 if (PointHitsRegion(screen_space_point, layer->ScreenSpaceTransform(),
2247 layer->non_fast_scrollable_region(), layer)) {
2248 layers.push_back(layer);
2249 }
2250 }
2251
2252 return layers;
2253 }
2254
2255 struct HitTestFramedVisibleScrollableOrTouchableFunctor {
operator ()cc::HitTestFramedVisibleScrollableOrTouchableFunctor2256 bool operator()(LayerImpl* layer) const {
2257 return layer->HitTestable() && layer->frame_element_id();
2258 }
2259 };
2260
FindFrameElementIdAtPoint(const gfx::PointF & screen_space_point)2261 ElementId LayerTreeImpl::FindFrameElementIdAtPoint(
2262 const gfx::PointF& screen_space_point) {
2263 if (layer_list_.empty())
2264 return {};
2265 if (!UpdateDrawProperties())
2266 return {};
2267 FindClosestMatchingLayerState state;
2268 FindClosestMatchingLayer(screen_space_point, layer_list_[0].get(),
2269 HitTestFramedVisibleScrollableOrTouchableFunctor(),
2270 &state);
2271
2272 if (auto* layer = state.closest_match) {
2273 // TODO(https://crbug.com/1058870): Permit hit testing only if the framed
2274 // element hit has a simple mask/clip. We don't have enough information
2275 // about complex masks/clips on the impl-side to do accurate hit testing.
2276 bool layer_hit_test_region_is_masked =
2277 property_trees()->effect_tree.HitTestMayBeAffectedByMask(
2278 layer->effect_tree_index());
2279
2280 if (!layer_hit_test_region_is_masked)
2281 return layer->frame_element_id();
2282 }
2283 return {};
2284 }
2285
RegisterSelection(const LayerSelection & selection)2286 void LayerTreeImpl::RegisterSelection(const LayerSelection& selection) {
2287 if (selection_ == selection)
2288 return;
2289
2290 handle_visibility_changed_ = true;
2291 selection_ = selection;
2292 }
2293
ResetHandleVisibilityChanged()2294 void LayerTreeImpl::ResetHandleVisibilityChanged() {
2295 handle_visibility_changed_ = false;
2296 }
2297
ComputeViewportSelectionBound(const LayerSelectionBound & layer_bound,LayerImpl * layer,float device_scale_factor)2298 static gfx::SelectionBound ComputeViewportSelectionBound(
2299 const LayerSelectionBound& layer_bound,
2300 LayerImpl* layer,
2301 float device_scale_factor) {
2302 gfx::SelectionBound viewport_bound;
2303 viewport_bound.set_type(layer_bound.type);
2304
2305 if (!layer || layer_bound.type == gfx::SelectionBound::EMPTY)
2306 return viewport_bound;
2307
2308 auto layer_start = gfx::PointF(layer_bound.edge_start);
2309 auto layer_end = gfx::PointF(layer_bound.edge_end);
2310 gfx::Transform screen_space_transform = layer->ScreenSpaceTransform();
2311
2312 bool clipped = false;
2313 gfx::PointF screen_start =
2314 MathUtil::MapPoint(screen_space_transform, layer_start, &clipped);
2315 gfx::PointF screen_end =
2316 MathUtil::MapPoint(screen_space_transform, layer_end, &clipped);
2317
2318 // MapPoint can produce points with NaN components (even when no inputs are
2319 // NaN). Since consumers of gfx::SelectionBounds may round |edge_start| or
2320 // |edge_end| (and since rounding will crash on NaN), we return an empty
2321 // bound instead.
2322 if (std::isnan(screen_start.x()) || std::isnan(screen_start.y()) ||
2323 std::isnan(screen_end.x()) || std::isnan(screen_end.y()))
2324 return gfx::SelectionBound();
2325
2326 const float inv_scale = 1.f / device_scale_factor;
2327 viewport_bound.SetEdgeStart(gfx::ScalePoint(screen_start, inv_scale));
2328 viewport_bound.SetEdgeEnd(gfx::ScalePoint(screen_end, inv_scale));
2329
2330 // If |layer_bound| is already hidden due to being occluded by painted content
2331 // within the layer, it must remain hidden. Otherwise, check whether its
2332 // position is outside the bounds of the layer.
2333 if (layer_bound.hidden) {
2334 viewport_bound.set_visible(false);
2335 } else {
2336 // The bottom edge point is used for visibility testing as it is the logical
2337 // focal point for bound selection handles (this may change in the future).
2338 // Shifting the visibility point fractionally inward ensures that
2339 // neighboring or logically coincident layers aligned to integral DPI
2340 // coordinates will not spuriously occlude the bound.
2341 gfx::Vector2dF visibility_offset = layer_start - layer_end;
2342 visibility_offset.Scale(device_scale_factor / visibility_offset.Length());
2343 gfx::PointF visibility_point = layer_end + visibility_offset;
2344 if (visibility_point.x() <= 0)
2345 visibility_point.set_x(visibility_point.x() + device_scale_factor);
2346 visibility_point =
2347 MathUtil::MapPoint(screen_space_transform, visibility_point, &clipped);
2348
2349 float intersect_distance = 0.f;
2350 viewport_bound.set_visible(
2351 PointHitsLayer(layer, visibility_point, &intersect_distance));
2352 }
2353
2354 if (viewport_bound.visible()) {
2355 viewport_bound.SetVisibleEdge(viewport_bound.edge_start(),
2356 viewport_bound.edge_end());
2357 } else {
2358 // The |layer_start| and |layer_end| might be clipped.
2359 gfx::RectF visible_layer_rect(layer->visible_layer_rect());
2360 auto visible_layer_start = layer_start;
2361 auto visible_layer_end = layer_end;
2362 if (!visible_layer_rect.Contains(visible_layer_start) &&
2363 !visible_layer_rect.Contains(visible_layer_end))
2364 std::tie(visible_layer_start, visible_layer_end) =
2365 GetVisibleSelectionEndPoints(visible_layer_rect, layer_start,
2366 layer_end);
2367
2368 gfx::PointF visible_screen_start = MathUtil::MapPoint(
2369 screen_space_transform, visible_layer_start, &clipped);
2370 gfx::PointF visible_screen_end =
2371 MathUtil::MapPoint(screen_space_transform, visible_layer_end, &clipped);
2372
2373 viewport_bound.SetVisibleEdgeStart(
2374 gfx::ScalePoint(visible_screen_start, inv_scale));
2375 viewport_bound.SetVisibleEdgeEnd(
2376 gfx::ScalePoint(visible_screen_end, inv_scale));
2377 }
2378
2379 return viewport_bound;
2380 }
2381
GetViewportSelection(viz::Selection<gfx::SelectionBound> * selection)2382 void LayerTreeImpl::GetViewportSelection(
2383 viz::Selection<gfx::SelectionBound>* selection) {
2384 DCHECK(selection);
2385
2386 selection->start = ComputeViewportSelectionBound(
2387 selection_.start,
2388 selection_.start.layer_id ? LayerById(selection_.start.layer_id)
2389 : nullptr,
2390 device_scale_factor() * painted_device_scale_factor());
2391 if (selection->start.type() == gfx::SelectionBound::CENTER ||
2392 selection->start.type() == gfx::SelectionBound::EMPTY) {
2393 selection->end = selection->start;
2394 } else {
2395 selection->end = ComputeViewportSelectionBound(
2396 selection_.end,
2397 selection_.end.layer_id ? LayerById(selection_.end.layer_id) : nullptr,
2398 device_scale_factor() * painted_device_scale_factor());
2399 }
2400 }
2401
SmoothnessTakesPriority() const2402 bool LayerTreeImpl::SmoothnessTakesPriority() const {
2403 return host_impl_->GetTreePriority() == SMOOTHNESS_TAKES_PRIORITY;
2404 }
2405
GetVideoFrameControllerClient() const2406 VideoFrameControllerClient* LayerTreeImpl::GetVideoFrameControllerClient()
2407 const {
2408 return host_impl_;
2409 }
2410
UpdateImageDecodingHints(base::flat_map<PaintImage::Id,PaintImage::DecodingMode> decoding_mode_map)2411 void LayerTreeImpl::UpdateImageDecodingHints(
2412 base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
2413 decoding_mode_map) {
2414 host_impl_->UpdateImageDecodingHints(std::move(decoding_mode_map));
2415 }
2416
GetMSAASampleCountForRaster(const scoped_refptr<DisplayItemList> & display_list)2417 int LayerTreeImpl::GetMSAASampleCountForRaster(
2418 const scoped_refptr<DisplayItemList>& display_list) {
2419 return host_impl_->GetMSAASampleCountForRaster(display_list);
2420 }
2421
SetPendingPageScaleAnimation(std::unique_ptr<PendingPageScaleAnimation> pending_animation)2422 void LayerTreeImpl::SetPendingPageScaleAnimation(
2423 std::unique_ptr<PendingPageScaleAnimation> pending_animation) {
2424 pending_page_scale_animation_ = std::move(pending_animation);
2425 }
2426
2427 std::unique_ptr<PendingPageScaleAnimation>
TakePendingPageScaleAnimation()2428 LayerTreeImpl::TakePendingPageScaleAnimation() {
2429 return std::move(pending_page_scale_animation_);
2430 }
2431
AppendEventsMetricsFromMainThread(std::vector<EventMetrics> events_metrics)2432 void LayerTreeImpl::AppendEventsMetricsFromMainThread(
2433 std::vector<EventMetrics> events_metrics) {
2434 events_metrics_from_main_thread_.reserve(
2435 events_metrics_from_main_thread_.size() + events_metrics.size());
2436 events_metrics_from_main_thread_.insert(
2437 events_metrics_from_main_thread_.end(), events_metrics.begin(),
2438 events_metrics.end());
2439 }
2440
TakeEventsMetrics()2441 std::vector<EventMetrics> LayerTreeImpl::TakeEventsMetrics() {
2442 std::vector<EventMetrics> main_event_metrics_result;
2443 main_event_metrics_result.swap(events_metrics_from_main_thread_);
2444 return main_event_metrics_result;
2445 }
2446
TakeForceSendMetadataRequest()2447 bool LayerTreeImpl::TakeForceSendMetadataRequest() {
2448 bool force_send_metadata_request = force_send_metadata_request_;
2449 force_send_metadata_request_ = false;
2450 return force_send_metadata_request;
2451 }
2452
ResetAllChangeTracking()2453 void LayerTreeImpl::ResetAllChangeTracking() {
2454 layers_that_should_push_properties_.clear();
2455 // Iterate over all layers, including masks.
2456 for (auto* layer : *this)
2457 layer->ResetChangeTracking();
2458 property_trees_.ResetAllChangeTracking();
2459 }
2460
LayerListAsJson() const2461 std::string LayerTreeImpl::LayerListAsJson() const {
2462 base::trace_event::TracedValueJSON value;
2463 value.BeginArray("LayerTreeImpl");
2464 for (auto* layer : *this) {
2465 value.BeginDictionary();
2466 layer->AsValueInto(&value);
2467 value.EndDictionary();
2468 }
2469 value.EndArray();
2470 return value.ToFormattedJSON();
2471 }
2472
2473 } // namespace cc
2474