1 // Copyright 2014 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 #ifndef CC_TREES_PROPERTY_TREE_H_ 6 #define CC_TREES_PROPERTY_TREE_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <string> 12 #include <unordered_map> 13 #include <vector> 14 15 #include "base/callback.h" 16 #include "base/containers/flat_map.h" 17 #include "base/containers/flat_set.h" 18 #include "base/memory/weak_ptr.h" 19 #include "cc/base/synced_property.h" 20 #include "cc/cc_export.h" 21 #include "cc/input/scroll_snap_data.h" 22 #include "cc/paint/element_id.h" 23 #include "cc/paint/filter_operations.h" 24 #include "cc/trees/mutator_host_client.h" 25 #include "cc/trees/sticky_position_constraint.h" 26 #include "ui/gfx/geometry/rect_f.h" 27 #include "ui/gfx/geometry/scroll_offset.h" 28 #include "ui/gfx/transform.h" 29 30 namespace base { 31 namespace trace_event { 32 class TracedValue; 33 } 34 } // namespace base 35 36 namespace viz { 37 class CopyOutputRequest; 38 } 39 40 namespace cc { 41 42 class LayerTreeImpl; 43 class RenderSurfaceImpl; 44 struct ClipNode; 45 struct EffectNode; 46 struct CompositorCommitData; 47 struct ScrollNode; 48 struct TransformNode; 49 struct TransformCachedNodeData; 50 51 typedef SyncedProperty<AdditionGroup<gfx::ScrollOffset>> SyncedScrollOffset; 52 53 class PropertyTrees; 54 55 template <typename T> 56 class CC_EXPORT PropertyTree { 57 public: 58 PropertyTree(); 59 PropertyTree(const PropertyTree& other) = delete; 60 61 // These C++ special member functions cannot be implicit inline because 62 // they are exported by CC_EXPORT. They will be instantiated in every 63 // compilation units that included this header, and compilation can fail 64 // because T may be incomplete. 65 virtual ~PropertyTree(); 66 PropertyTree<T>& operator=(const PropertyTree<T>&); 67 68 // Property tree node starts from index 0. See equivalent constants in 69 // property_tree_manager.cc for comments. 70 static const int kInvalidNodeId = -1; 71 static const int kRootNodeId = 0; 72 static const int kSecondaryRootNodeId = 1; 73 74 #if DCHECK_IS_ON() 75 bool operator==(const PropertyTree<T>& other) const; 76 #endif 77 78 int Insert(const T& tree_node, int parent_id); 79 Node(int i)80 T* Node(int i) { 81 DCHECK(i < static_cast<int>(nodes_.size())); 82 return i > kInvalidNodeId ? &nodes_[i] : nullptr; 83 } Node(int i)84 const T* Node(int i) const { 85 DCHECK(i < static_cast<int>(nodes_.size())); 86 return i > kInvalidNodeId ? &nodes_[i] : nullptr; 87 } 88 parent(const T * t)89 T* parent(const T* t) { return Node(t->parent_id); } parent(const T * t)90 const T* parent(const T* t) const { return Node(t->parent_id); } 91 back()92 T* back() { return size() ? &nodes_.back() : nullptr; } back()93 const T* back() const { return size() ? &nodes_.back() : nullptr; } 94 95 void clear(); size()96 size_t size() const { return nodes_.size(); } 97 set_needs_update(bool needs_update)98 virtual void set_needs_update(bool needs_update) { 99 needs_update_ = needs_update; 100 } needs_update()101 bool needs_update() const { return needs_update_; } 102 nodes()103 std::vector<T>& nodes() { return nodes_; } nodes()104 const std::vector<T>& nodes() const { return nodes_; } 105 next_available_id()106 int next_available_id() const { return static_cast<int>(size()); } 107 SetPropertyTrees(PropertyTrees * property_trees)108 void SetPropertyTrees(PropertyTrees* property_trees) { 109 property_trees_ = property_trees; 110 } property_trees()111 PropertyTrees* property_trees() const { return property_trees_; } 112 113 void AsValueInto(base::trace_event::TracedValue* value) const; 114 115 protected: 116 std::vector<T> nodes_; 117 bool needs_update_; 118 PropertyTrees* property_trees_; 119 }; 120 121 struct StickyPositionNodeData; 122 123 class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { 124 public: 125 TransformTree(); 126 127 // These C++ special member functions cannot be implicit inline because 128 // they are exported by CC_EXPORT. They will be instantiated in every 129 // compilation units that included this header, and compilation can fail 130 // because TransformCachedNodeData may be incomplete. 131 TransformTree(const TransformTree&) = delete; 132 ~TransformTree() final; 133 TransformTree& operator=(const TransformTree&); 134 135 #if DCHECK_IS_ON() 136 bool operator==(const TransformTree& other) const; 137 #endif 138 139 static const int kContentsRootNodeId = 1; 140 141 int Insert(const TransformNode& tree_node, int parent_id); 142 143 void clear(); 144 145 TransformNode* FindNodeFromElementId(ElementId id); 146 bool OnTransformAnimated(ElementId element_id, 147 const gfx::Transform& transform); 148 void ResetChangeTracking(); 149 // Updates the parent, target, and screen space transforms and snapping. 150 void UpdateTransforms(int id); 151 void UpdateTransformChanged(TransformNode* node, TransformNode* parent_node); 152 void UpdateNodeAndAncestorsAreAnimatedOrInvertible( 153 TransformNode* node, 154 TransformNode* parent_node); 155 void UpdateNodeOrAncestorsWillChangeTransform(TransformNode* node, 156 TransformNode* parent_node); 157 158 void set_needs_update(bool needs_update) final; 159 160 // We store the page scale factor on the transform tree so that it can be 161 // easily be retrieved and updated in UpdatePageScale. set_page_scale_factor(float page_scale_factor)162 void set_page_scale_factor(float page_scale_factor) { 163 page_scale_factor_ = page_scale_factor; 164 } page_scale_factor()165 float page_scale_factor() const { return page_scale_factor_; } 166 set_device_scale_factor(float device_scale_factor)167 void set_device_scale_factor(float device_scale_factor) { 168 device_scale_factor_ = device_scale_factor; 169 } device_scale_factor()170 float device_scale_factor() const { return device_scale_factor_; } 171 172 void SetRootScaleAndTransform(float device_scale_factor, 173 const gfx::Transform& device_transform); device_transform_scale_factor()174 float device_transform_scale_factor() const { 175 return device_transform_scale_factor_; 176 } 177 178 void UpdateOuterViewportContainerBoundsDelta(); 179 180 void AddNodeAffectedByOuterViewportBoundsDelta(int node_id); 181 182 bool HasNodesAffectedByOuterViewportBoundsDelta() const; 183 nodes_affected_by_outer_viewport_bounds_delta()184 const std::vector<int>& nodes_affected_by_outer_viewport_bounds_delta() 185 const { 186 return nodes_affected_by_outer_viewport_bounds_delta_; 187 } 188 189 const gfx::Transform& FromScreen(int node_id) const; 190 void SetFromScreen(int node_id, const gfx::Transform& transform); 191 192 const gfx::Transform& ToScreen(int node_id) const; 193 void SetToScreen(int node_id, const gfx::Transform& transform); 194 195 int TargetId(int node_id) const; 196 void SetTargetId(int node_id, int target_id); 197 198 int ContentTargetId(int node_id) const; 199 void SetContentTargetId(int node_id, int content_target_id); 200 cached_data()201 const std::vector<TransformCachedNodeData>& cached_data() const { 202 return cached_data_; 203 } 204 GetStickyPositionData(int node_id)205 const StickyPositionNodeData* GetStickyPositionData(int node_id) const { 206 return const_cast<TransformTree*>(this)->MutableStickyPositionData(node_id); 207 } 208 StickyPositionNodeData& EnsureStickyPositionData(int node_id); 209 210 // Computes the combined transform between |source_id| and |dest_id|. These 211 // two nodes must be on the same ancestor chain. 212 void CombineTransformsBetween(int source_id, 213 int dest_id, 214 gfx::Transform* transform) const; 215 216 // Computes the combined inverse transform between |source_id| and |dest_id| 217 // and returns false if the inverse of a singular transform was used. These 218 // two nodes must be on the same ancestor chain. 219 bool CombineInversesBetween(int source_id, 220 int dest_id, 221 gfx::Transform* transform) const; 222 223 private: 224 // Returns true iff the node at |desc_id| is a descendant of the node at 225 // |anc_id|. 226 bool IsDescendant(int desc_id, int anc_id) const; 227 228 StickyPositionNodeData* MutableStickyPositionData(int node_id); 229 gfx::Vector2dF StickyPositionOffset(TransformNode* node); 230 void UpdateLocalTransform(TransformNode* node); 231 void UpdateScreenSpaceTransform(TransformNode* node, 232 TransformNode* parent_node); 233 void UpdateAnimationProperties(TransformNode* node, 234 TransformNode* parent_node); 235 void UndoSnapping(TransformNode* node); 236 void UpdateSnapping(TransformNode* node); 237 void UpdateNodeAndAncestorsHaveIntegerTranslations( 238 TransformNode* node, 239 TransformNode* parent_node); 240 241 // When to_screen transform has perspective, the transform node's sublayer 242 // scale is calculated using page scale factor, device scale factor and the 243 // scale factor of device transform. So we need to store them explicitly. 244 float page_scale_factor_; 245 float device_scale_factor_; 246 float device_transform_scale_factor_; 247 std::vector<int> nodes_affected_by_outer_viewport_bounds_delta_; 248 std::vector<TransformCachedNodeData> cached_data_; 249 std::vector<StickyPositionNodeData> sticky_position_data_; 250 }; 251 252 struct StickyPositionNodeData { 253 int scroll_ancestor; 254 StickyPositionConstraint constraints; 255 256 // In order to properly compute the sticky offset, we need to know if we have 257 // any sticky ancestors both between ourselves and our containing block and 258 // between our containing block and the viewport. These ancestors are then 259 // used to correct the constraining rect locations. 260 int nearest_node_shifting_sticky_box; 261 int nearest_node_shifting_containing_block; 262 263 // For performance we cache our accumulated sticky offset to allow descendant 264 // sticky elements to offset their constraint rects. Because we can either 265 // affect the sticky box constraint rect or the containing block constraint 266 // rect, we need to accumulate both. 267 gfx::Vector2dF total_sticky_box_sticky_offset; 268 gfx::Vector2dF total_containing_block_sticky_offset; 269 StickyPositionNodeDataStickyPositionNodeData270 StickyPositionNodeData() 271 : scroll_ancestor(TransformTree::kInvalidNodeId), 272 nearest_node_shifting_sticky_box(TransformTree::kInvalidNodeId), 273 nearest_node_shifting_containing_block(TransformTree::kInvalidNodeId) {} 274 }; 275 276 class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> { 277 public: 278 #if DCHECK_IS_ON() 279 bool operator==(const ClipTree& other) const; 280 #endif 281 282 static const int kViewportNodeId = 1; 283 284 void SetViewportClip(gfx::RectF viewport_rect); 285 gfx::RectF ViewportClip() const; 286 }; 287 288 class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { 289 public: 290 EffectTree(); 291 ~EffectTree() final; 292 293 EffectTree& operator=(const EffectTree& from); 294 295 #if DCHECK_IS_ON() 296 bool operator==(const EffectTree& other) const; 297 #endif 298 299 static const int kContentsRootNodeId = 1; 300 301 int Insert(const EffectNode& tree_node, int parent_id); 302 303 void clear(); 304 305 float EffectiveOpacity(const EffectNode* node) const; 306 307 void UpdateSurfaceContentsScale(EffectNode* node); 308 309 EffectNode* FindNodeFromElementId(ElementId id); 310 bool OnOpacityAnimated(ElementId id, float opacity); 311 bool OnFilterAnimated(ElementId id, const FilterOperations& filters); 312 bool OnBackdropFilterAnimated(ElementId id, 313 const FilterOperations& backdrop_filters); 314 315 void UpdateEffects(int id); 316 317 void UpdateEffectChanged(EffectNode* node, EffectNode* parent_node); 318 319 void UpdateHasFilters(EffectNode* node, EffectNode* parent_node); 320 321 void AddCopyRequest(int node_id, 322 std::unique_ptr<viz::CopyOutputRequest> request); 323 void PushCopyRequestsTo(EffectTree* other_tree); 324 void TakeCopyRequestsAndTransformToSurface( 325 int node_id, 326 std::vector<std::unique_ptr<viz::CopyOutputRequest>>* requests); 327 bool HasCopyRequests() const; 328 void ClearCopyRequests(); 329 330 // Given the ids of two effect nodes that have render surfaces, returns the 331 // id of the lowest common ancestor effect node that also has a render 332 // surface. 333 int LowestCommonAncestorWithRenderSurface(int id_1, int id_2) const; 334 GetRenderSurface(int id)335 RenderSurfaceImpl* GetRenderSurface(int id) { 336 return render_surfaces_[id].get(); 337 } 338 GetRenderSurface(int id)339 const RenderSurfaceImpl* GetRenderSurface(int id) const { 340 return render_surfaces_[id].get(); 341 } 342 343 bool ContributesToDrawnSurface(int id); 344 345 void ResetChangeTracking(); 346 347 void TakeRenderSurfaces( 348 std::vector<std::unique_ptr<RenderSurfaceImpl>>* render_surfaces); 349 350 // Returns true if render surfaces changed (that is, if any render surfaces 351 // were created or destroyed). 352 bool CreateOrReuseRenderSurfaces( 353 std::vector<std::unique_ptr<RenderSurfaceImpl>>* old_render_surfaces, 354 LayerTreeImpl* layer_tree_impl); 355 356 // This function checks if the layer's hit test region is a rectangle so that 357 // we may be able to use |visible_layer_rect| for viz hit test. It returns 358 // true when the following three conditions are met: 359 // 1) All clips preserve 2d axis. 360 // 2) There are no mask layers. 361 bool ClippedHitTestRegionIsRectangle(int effect_node_id) const; 362 363 // This function checks if the associated layer can use its layer bounds to 364 // correctly hit test. It returns true if the layer bounds cannot be trusted. 365 bool HitTestMayBeAffectedByMask(int effect_node_id) const; 366 367 private: 368 void UpdateOpacities(EffectNode* node, EffectNode* parent_node); 369 void UpdateSubtreeHidden(EffectNode* node, EffectNode* parent_node); 370 void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node); 371 void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node); 372 void UpdateHasMaskingChild(EffectNode* node, EffectNode* parent_node); 373 void UpdateOnlyDrawsVisibleContent(EffectNode* node, EffectNode* parent_node); 374 375 // Stores copy requests, keyed by node id. 376 std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>> 377 copy_requests_; 378 379 // Indexed by node id. 380 std::vector<std::unique_ptr<RenderSurfaceImpl>> render_surfaces_; 381 }; 382 383 // These callbacks are called in the main thread to notify changes of scroll 384 // information in the compositor thread during commit. 385 class ScrollCallbacks { 386 public: 387 // Called after the composited scroll offset changed. 388 virtual void DidScroll(ElementId scroll_element_id, 389 const gfx::ScrollOffset&, 390 const base::Optional<TargetSnapAreaElementIds>&) = 0; 391 // Called after the hidden status of composited scrollbars changed. Note that 392 // |scroll_element_id| is the element id of the scroll not of the scrollbars. 393 virtual void DidChangeScrollbarsHidden(ElementId scroll_element_id, 394 bool hidden) = 0; 395 396 protected: ~ScrollCallbacks()397 virtual ~ScrollCallbacks() {} 398 }; 399 400 class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { 401 public: 402 ScrollTree(); 403 ~ScrollTree() final; 404 405 ScrollTree& operator=(const ScrollTree& from); 406 407 #if DCHECK_IS_ON() 408 bool operator==(const ScrollTree& other) const; 409 #endif 410 411 void clear(); 412 413 gfx::ScrollOffset MaxScrollOffset(int scroll_node_id) const; 414 void OnScrollOffsetAnimated(ElementId id, 415 int scroll_tree_index, 416 const gfx::ScrollOffset& scroll_offset, 417 LayerTreeImpl* layer_tree_impl); 418 gfx::Size container_bounds(int scroll_node_id) const; 419 gfx::SizeF scroll_bounds(int scroll_node_id) const; 420 ScrollNode* CurrentlyScrollingNode(); 421 const ScrollNode* CurrentlyScrollingNode() const; 422 #if DCHECK_IS_ON() 423 int CurrentlyScrollingNodeId() const; 424 #endif 425 void set_currently_scrolling_node(int scroll_node_id); currently_scrolling_node()426 int currently_scrolling_node() const { return currently_scrolling_node_id_; } 427 gfx::Transform ScreenSpaceTransform(int scroll_node_id) const; 428 429 gfx::Vector2dF ClampScrollToMaxScrollOffset(const ScrollNode& node, 430 LayerTreeImpl*); 431 432 // Returns the current scroll offset. On the main thread this would return the 433 // value for the LayerTree while on the impl thread this is the current value 434 // on the active tree. 435 const gfx::ScrollOffset current_scroll_offset(ElementId id) const; 436 437 // Returns the scroll offset taking into account any adjustments that may be 438 // included due to pixel snapping. 439 // 440 // Note: Using this method may causes the associated transform node for this 441 // scroll node to update its transforms. 442 // 443 // TODO(crbug.com/585458): Updating single transform node only works for 444 // simple cases but we really should update the whole transform tree otherwise 445 // we are ignoring any parent transform node that needs updating and thus our 446 // snap amount can be incorrect. 447 const gfx::ScrollOffset GetPixelSnappedScrollOffset(int scroll_node_id) const; 448 449 // Collects deltas for scroll changes on the impl thread that need to be 450 // reported to the main thread during the main frame. As such, should only be 451 // called on the impl thread side PropertyTrees. 452 void CollectScrollDeltas(CompositorCommitData* commit_data, 453 ElementId inner_viewport_scroll_element_id, 454 bool use_fractional_deltas, 455 const base::flat_set<ElementId>& snapped_elements); 456 457 // Applies deltas sent in the previous main frame onto the impl thread state. 458 // Should only be called on the impl thread side PropertyTrees. 459 void ApplySentScrollDeltasFromAbortedCommit(); 460 461 // Pushes scroll updates from the ScrollTree on the main thread onto the 462 // impl thread associated state. 463 void PushScrollUpdatesFromMainThread(PropertyTrees* main_property_trees, 464 LayerTreeImpl* sync_tree); 465 466 // Pushes scroll updates from the ScrollTree on the pending tree onto the 467 // active tree associated state. 468 void PushScrollUpdatesFromPendingTree(PropertyTrees* pending_property_trees, 469 LayerTreeImpl* active_tree); 470 471 void SetBaseScrollOffset(ElementId id, 472 const gfx::ScrollOffset& scroll_offset); 473 // Returns true if the scroll offset is changed. 474 bool SetScrollOffset(ElementId id, const gfx::ScrollOffset& scroll_offset); SetScrollOffsetClobberActiveValue(ElementId id)475 void SetScrollOffsetClobberActiveValue(ElementId id) { 476 GetOrCreateSyncedScrollOffset(id)->set_clobber_active_value(); 477 } 478 bool UpdateScrollOffsetBaseForTesting(ElementId id, 479 const gfx::ScrollOffset& offset); 480 bool SetScrollOffsetDeltaForTesting(ElementId id, 481 const gfx::Vector2dF& delta); 482 const gfx::ScrollOffset GetScrollOffsetBaseForTesting(ElementId id) const; 483 const gfx::ScrollOffset GetScrollOffsetDeltaForTesting(ElementId id) const; 484 void CollectScrollDeltasForTesting(); 485 486 gfx::Vector2dF ScrollBy(const ScrollNode& scroll_node, 487 const gfx::Vector2dF& scroll, 488 LayerTreeImpl* layer_tree_impl); 489 gfx::ScrollOffset ClampScrollOffsetToLimits( 490 gfx::ScrollOffset offset, 491 const ScrollNode& scroll_node) const; 492 493 const SyncedScrollOffset* GetSyncedScrollOffset(ElementId id) const; 494 495 #if DCHECK_IS_ON() 496 void CopyCompleteTreeState(const ScrollTree& other); 497 #endif 498 499 ScrollNode* FindNodeFromElementId(ElementId id); 500 const ScrollNode* FindNodeFromElementId(ElementId id) const; 501 502 void SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks); 503 504 void NotifyDidScroll( 505 ElementId scroll_element_id, 506 const gfx::ScrollOffset& scroll_offset, 507 const base::Optional<TargetSnapAreaElementIds>& snap_target_ids); 508 void NotifyDidChangeScrollbarsHidden(ElementId scroll_element_id, 509 bool hidden); 510 511 // A composited scroll node is a scroll node that has an associated composited 512 // layer, otherwise the scroll node corresponds to a scroller that requires 513 // repainting. 514 bool IsComposited(const ScrollNode& node) const; 515 516 private: 517 // ScrollTree doesn't use the needs_update flag. 518 using PropertyTree::needs_update; 519 using PropertyTree::set_needs_update; 520 521 using ScrollOffsetMap = base::flat_map<ElementId, gfx::ScrollOffset>; 522 using SyncedScrollOffsetMap = 523 base::flat_map<ElementId, scoped_refptr<SyncedScrollOffset>>; 524 525 int currently_scrolling_node_id_; 526 527 // On the main thread we store the scroll offsets directly since the main 528 // thread only needs to keep track of the current main thread state. The impl 529 // thread stores a map of SyncedProperty instances in order to track 530 // additional state necessary to synchronize scroll changes between the main 531 // and impl threads. 532 ScrollOffsetMap scroll_offset_map_; 533 SyncedScrollOffsetMap synced_scroll_offset_map_; 534 535 base::WeakPtr<ScrollCallbacks> callbacks_; 536 537 SyncedScrollOffset* GetOrCreateSyncedScrollOffset(ElementId id); 538 gfx::ScrollOffset PullDeltaForMainThread(SyncedScrollOffset* scroll_offset, 539 bool use_fractional_deltas); 540 }; 541 542 struct AnimationScaleData { 543 // Variable used to invalidate cached animation scale data when transform tree 544 // updates. 545 int update_number; 546 547 // The maximum scale that this node's |to_target| transform will have during 548 // current animations, considering only scales at keyframes not incuding the 549 // starting keyframe of each animation. 550 float combined_maximum_animation_target_scale; 551 552 // The maximum scale that this node's |to_target| transform will have during 553 // current animations, considering only the starting scale of each animation. 554 float combined_starting_animation_scale; 555 556 bool to_screen_has_scale_animation; 557 AnimationScaleDataAnimationScaleData558 AnimationScaleData() { 559 update_number = -1; 560 combined_maximum_animation_target_scale = 0.f; 561 combined_starting_animation_scale = 0.f; 562 to_screen_has_scale_animation = false; 563 } 564 }; 565 566 struct CombinedAnimationScale { 567 float maximum_animation_scale; 568 float starting_animation_scale; 569 CombinedAnimationScaleCombinedAnimationScale570 CombinedAnimationScale(float maximum, float starting) 571 : maximum_animation_scale(maximum), starting_animation_scale(starting) {} 572 bool operator==(const CombinedAnimationScale& other) const { 573 return maximum_animation_scale == other.maximum_animation_scale && 574 starting_animation_scale == other.starting_animation_scale; 575 } 576 }; 577 578 struct DrawTransforms { 579 // We compute invertibility of a draw transforms lazily. 580 // Might_be_invertible is true if we have not computed the inverse of either 581 // to_target or from_target, or to_target / from_target is invertible. 582 bool might_be_invertible; 583 // From_valid is true if the from_target is already computed directly or 584 // computed by inverting an invertible to_target. 585 bool from_valid; 586 // To_valid is true if to_target stores a valid result, similar to from_valid. 587 bool to_valid; 588 gfx::Transform from_target; 589 gfx::Transform to_target; 590 DrawTransformsDrawTransforms591 DrawTransforms(gfx::Transform from, gfx::Transform to) 592 : might_be_invertible(true), 593 from_valid(false), 594 to_valid(false), 595 from_target(from), 596 to_target(to) {} 597 bool operator==(const DrawTransforms& other) const { 598 return from_valid == other.from_valid && to_valid == other.to_valid && 599 from_target == other.from_target && to_target == other.to_target; 600 } 601 }; 602 603 struct DrawTransformData { 604 int update_number; 605 int target_id; 606 607 DrawTransforms transforms; 608 609 // TODO(sunxd): Move screen space transforms here if it can improve 610 // performance. DrawTransformDataDrawTransformData611 DrawTransformData() 612 : update_number(-1), 613 target_id(EffectTree::kInvalidNodeId), 614 transforms(gfx::Transform(), gfx::Transform()) {} 615 }; 616 617 struct ConditionalClip { 618 bool is_clipped; 619 gfx::RectF clip_rect; 620 }; 621 622 struct ClipRectData { 623 int target_id; 624 ConditionalClip clip; 625 ClipRectDataClipRectData626 ClipRectData() : target_id(-1) {} 627 }; 628 629 struct PropertyTreesCachedData { 630 int transform_tree_update_number; 631 std::vector<AnimationScaleData> animation_scales; 632 mutable std::vector<std::vector<DrawTransformData>> draw_transforms; 633 634 PropertyTreesCachedData(); 635 ~PropertyTreesCachedData(); 636 }; 637 638 class CC_EXPORT PropertyTrees final { 639 public: 640 PropertyTrees(); 641 PropertyTrees(const PropertyTrees& other) = delete; 642 ~PropertyTrees(); 643 644 PropertyTrees& operator=(const PropertyTrees& from); 645 646 #if DCHECK_IS_ON() 647 bool operator==(const PropertyTrees& other) const; 648 #endif 649 650 // These maps allow mapping directly from a compositor element id to the 651 // respective property node. This will eventually allow simplifying logic in 652 // various places that today has to map from element id to layer id, and then 653 // from layer id to the respective property node. Completing that work is 654 // pending the launch of BlinkGenPropertyTrees and reworking UI compositor 655 // logic to produce cc property trees and these maps. 656 base::flat_map<ElementId, int> element_id_to_effect_node_index; 657 base::flat_map<ElementId, int> element_id_to_scroll_node_index; 658 base::flat_map<ElementId, int> element_id_to_transform_node_index; 659 660 TransformTree transform_tree; 661 EffectTree effect_tree; 662 ClipTree clip_tree; 663 ScrollTree scroll_tree; 664 bool needs_rebuild; 665 // Change tracking done on property trees needs to be preserved across commits 666 // (when they are not rebuild). We cache a global bool which stores whether 667 // we did any change tracking so that we can skip copying the change status 668 // between property trees when this bool is false. 669 bool changed; 670 // We cache a global bool for full tree damages to avoid walking the entire 671 // tree. 672 // TODO(jaydasika): Changes to transform and effects that damage the entire 673 // tree should be tracked by this bool. Currently, they are tracked by the 674 // individual nodes. 675 bool full_tree_damaged; 676 int sequence_number; 677 bool is_main_thread; 678 bool is_active; 679 680 void clear(); 681 682 // Applies an animation state change for a particular element in 683 // this property tree. Returns whether a draw property update is 684 // needed. 685 bool ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map, 686 const PropertyAnimationState& mask, 687 const PropertyAnimationState& state, 688 bool check_node_existence); 689 void AnimationScalesChanged(ElementId element_id, 690 float maximum_scale, 691 float starting_scale); 692 void SetInnerViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); 693 void SetOuterViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); 694 void UpdateChangeTracking(); 695 void PushChangeTrackingTo(PropertyTrees* tree); 696 void ResetAllChangeTracking(); 697 inner_viewport_container_bounds_delta()698 gfx::Vector2dF inner_viewport_container_bounds_delta() const { 699 return inner_viewport_container_bounds_delta_; 700 } inner_viewport_scroll_bounds_delta()701 gfx::Vector2dF inner_viewport_scroll_bounds_delta() const { 702 // Inner viewport scroll bounds are always the same as outer viewport 703 // container bounds. 704 return outer_viewport_container_bounds_delta_; 705 } outer_viewport_container_bounds_delta()706 gfx::Vector2dF outer_viewport_container_bounds_delta() const { 707 return outer_viewport_container_bounds_delta_; 708 } 709 710 std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const; 711 void AsValueInto(base::trace_event::TracedValue* value) const; 712 std::string ToString() const; 713 714 CombinedAnimationScale GetAnimationScales(int transform_node_id, 715 LayerTreeImpl* layer_tree_impl); 716 void SetAnimationScalesForTesting(int transform_id, 717 float maximum_animation_scale, 718 float starting_animation_scale); 719 720 bool GetToTarget(int transform_id, 721 int effect_id, 722 gfx::Transform* to_target) const; 723 bool GetFromTarget(int transform_id, 724 int effect_id, 725 gfx::Transform* from_target) const; 726 727 void ResetCachedData(); 728 void UpdateTransformTreeUpdateNumber(); 729 gfx::Transform ToScreenSpaceTransformWithoutSurfaceContentsScale( 730 int transform_id, 731 int effect_id) const; 732 733 ClipRectData* FetchClipRectFromCache(int clip_id, int target_id); 734 735 bool HasElement(ElementId element_id) const; 736 737 private: 738 gfx::Vector2dF inner_viewport_container_bounds_delta_; 739 gfx::Vector2dF outer_viewport_container_bounds_delta_; 740 741 // GetDrawTransforms may change the value of cached_data_. 742 DrawTransforms& GetDrawTransforms(int transform_id, int effect_id) const; 743 DrawTransformData& FetchDrawTransformsDataFromCache(int transform_id, 744 int effect_id) const; 745 746 PropertyTreesCachedData cached_data_; 747 }; 748 749 } // namespace cc 750 751 #endif // CC_TREES_PROPERTY_TREE_H_ 752