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