#ifndef CC_TREES_PROPERTY_TREE_H_
#define CC_TREES_PROPERTY_TREE_H_
#include <stddef.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "cc/base/synced_property.h"
#include "cc/cc_export.h"
#include "cc/input/scroll_snap_data.h"
#include "cc/paint/element_id.h"
#include "cc/paint/filter_operations.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/sticky_position_constraint.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/view_transition_element_resource_id.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace base {
namespace trace_event {
class TracedValue;
}
}
namespace viz {
class CopyOutputRequest;
}
namespace cc {
class LayerTreeImpl;
class RenderSurfaceImpl;
struct RenderSurfacePropertyChangedFlags;
struct CompositorCommitData;
struct ViewportPropertyIds;
using SyncedScrollOffset =
SyncedProperty<AdditionGroup<gfx::PointF, gfx::Vector2dF>>;
class PropertyTrees;
enum {
kInvalidPropertyNodeId = -1,
kRootPropertyNodeId = 0,
kSecondaryRootPropertyNodeId = 1,
kContentsRootPropertyNodeId = kSecondaryRootPropertyNodeId,
kViewportPropertyNodeId = kSecondaryRootPropertyNodeId
};
template <typename T>
class CC_EXPORT PropertyTree {
friend class PropertyTrees;
public:
PropertyTree(const PropertyTree& other) = delete;
~PropertyTree();
PropertyTree<T>& operator=(const PropertyTree<T>&);
#if DCHECK_IS_ON()
bool operator==(const PropertyTree<T>& other) const;
#endif
int Insert(const T& tree_node, int parent_id);
T* Node(int i) {
CHECK_LT(i, static_cast<int>(nodes_.size()));
return i > kInvalidPropertyNodeId ? &nodes_[i] : nullptr;
}
const T* Node(int i) const {
CHECK_LT(i, static_cast<int>(nodes_.size()));
return i > kInvalidPropertyNodeId ? &nodes_[i] : nullptr;
}
T* parent(const T* t) { return Node(t->parent_id); }
const T* parent(const T* t) const { return Node(t->parent_id); }
T* back() { return size() ? &nodes_.back() : nullptr; }
const T* back() const { return size() ? &nodes_.back() : nullptr; }
void SetElementIdForNodeId(int node_id, ElementId element_id) {
element_id_to_node_index_[element_id] = node_id;
}
T* FindNodeFromElementId(ElementId id) {
auto iterator = element_id_to_node_index_.find(id);
if (iterator == element_id_to_node_index_.end())
return nullptr;
return Node(iterator->second);
}
const T* FindNodeFromElementId(ElementId id) const {
auto iterator = element_id_to_node_index_.find(id);
if (iterator == element_id_to_node_index_.end())
return nullptr;
return Node(iterator->second);
}
void clear();
size_t size() const { return nodes_.size(); }
void set_needs_update(bool needs_update) {
needs_update_ = needs_update;
}
bool needs_update() const { return needs_update_; }
std::vector<T>& nodes() { return nodes_; }
const std::vector<T>& nodes() const { return nodes_; }
int next_available_id() const { return static_cast<int>(size()); }
PropertyTrees* property_trees() const { return property_trees_; }
void AsValueInto(base::trace_event::TracedValue* value) const;
const base::flat_map<ElementId, int>& element_id_to_node_index() const {
return element_id_to_node_index_;
}
protected:
explicit PropertyTree(PropertyTrees* property_trees);
std::vector<T> nodes_;
private:
void SetPropertyTrees(PropertyTrees* property_trees) {
property_trees_ = property_trees;
}
bool needs_update_;
raw_ptr<PropertyTrees> property_trees_;
base::flat_map<ElementId, int> element_id_to_node_index_;
};
struct AnchorScrollContainersData;
struct StickyPositionNodeData;
class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
public:
explicit TransformTree(PropertyTrees* property_trees = nullptr);
TransformTree(const TransformTree&) = delete;
~TransformTree();
TransformTree& operator=(const TransformTree&);
#if DCHECK_IS_ON()
bool operator==(const TransformTree& other) const;
#endif
int Insert(const TransformNode& tree_node, int parent_id);
void clear();
bool OnTransformAnimated(ElementId element_id,
const gfx::Transform& transform);
void ResetChangeTracking();
void UpdateTransforms(
int id,
const ViewportPropertyIds* viewport_property_ids = nullptr);
void UpdateTransformChanged(TransformNode* node, TransformNode* parent_node);
void UpdateNodeAndAncestorsAreAnimatedOrInvertible(
TransformNode* node,
TransformNode* parent_node);
void UpdateNodeOrAncestorsWillChangeTransform(TransformNode* node,
TransformNode* parent_node);
void set_needs_update(bool needs_update);
void set_page_scale_factor(float page_scale_factor) {
page_scale_factor_ = page_scale_factor;
}
float page_scale_factor() const { return page_scale_factor_; }
void set_device_scale_factor(float device_scale_factor) {
device_scale_factor_ = device_scale_factor;
}
float device_scale_factor() const { return device_scale_factor_; }
void SetRootScaleAndTransform(float device_scale_factor,
const gfx::Transform& device_transform);
float device_transform_scale_factor() const {
return device_transform_scale_factor_;
}
void UpdateOuterViewportContainerBoundsDelta();
void AddNodeAffectedByOuterViewportBoundsDelta(int node_id);
bool HasNodesAffectedByOuterViewportBoundsDelta() const;
const std::vector<int>& nodes_affected_by_outer_viewport_bounds_delta()
const {
return nodes_affected_by_outer_viewport_bounds_delta_;
}
const gfx::Transform& FromScreen(int node_id) const;
void SetFromScreen(int node_id, const gfx::Transform& transform);
const gfx::Transform& ToScreen(int node_id) const;
void SetToScreen(int node_id, const gfx::Transform& transform);
int TargetId(int node_id) const;
void SetTargetId(int node_id, int target_id);
int ContentTargetId(int node_id) const;
void SetContentTargetId(int node_id, int content_target_id);
const std::vector<TransformCachedNodeData>& cached_data() const {
return cached_data_;
}
void UndoOverscroll(const TransformNode* node,
gfx::Vector2dF& position_adjustment,
const ViewportPropertyIds* viewport_property_ids);
const StickyPositionNodeData* GetStickyPositionData(int node_id) const {
return const_cast<TransformTree*>(this)->MutableStickyPositionData(node_id);
}
StickyPositionNodeData& EnsureStickyPositionData(int node_id);
const AnchorScrollContainersData* GetAnchorScrollContainersData(
int node_id) const;
AnchorScrollContainersData& EnsureAnchorScrollContainersData(int node_id);
void CombineTransformsBetween(int source_id,
int dest_id,
gfx::Transform* transform) const;
bool CombineInversesBetween(int source_id,
int dest_id,
gfx::Transform* transform) const;
private:
bool IsDescendant(int desc_id, int anc_id) const;
StickyPositionNodeData* MutableStickyPositionData(int node_id);
gfx::Vector2dF StickyPositionOffset(TransformNode* node);
gfx::Vector2dF AnchorScrollOffset(TransformNode* node);
void UpdateLocalTransform(TransformNode* node,
const ViewportPropertyIds* viewport_property_ids);
void UpdateScreenSpaceTransform(TransformNode* node,
TransformNode* parent_node);
void UpdateAnimationProperties(TransformNode* node,
TransformNode* parent_node);
void UndoSnapping(TransformNode* node);
void UpdateSnapping(TransformNode* node);
void UpdateNodeAndAncestorsHaveIntegerTranslations(
TransformNode* node,
TransformNode* parent_node);
float page_scale_factor_;
float device_scale_factor_;
float device_transform_scale_factor_;
std::vector<int> nodes_affected_by_outer_viewport_bounds_delta_;
std::vector<TransformCachedNodeData> cached_data_;
std::vector<StickyPositionNodeData> sticky_position_data_;
std::vector<AnchorScrollContainersData> anchor_scroll_containers_data_;
};
struct CC_EXPORT AnchorScrollContainersData {
AnchorScrollContainersData();
~AnchorScrollContainersData();
AnchorScrollContainersData(const AnchorScrollContainersData&);
bool operator==(const AnchorScrollContainersData&) const;
bool operator!=(const AnchorScrollContainersData&) const;
std::vector<ElementId> scroll_container_ids;
gfx::Vector2d accumulated_scroll_origin;
};
struct StickyPositionNodeData {
int scroll_ancestor;
StickyPositionConstraint constraints;
int nearest_node_shifting_sticky_box;
int nearest_node_shifting_containing_block;
gfx::Vector2dF total_sticky_box_sticky_offset;
gfx::Vector2dF total_containing_block_sticky_offset;
StickyPositionNodeData()
: scroll_ancestor(kInvalidPropertyNodeId),
nearest_node_shifting_sticky_box(kInvalidPropertyNodeId),
nearest_node_shifting_containing_block(kInvalidPropertyNodeId) {}
};
class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {
public:
explicit ClipTree(PropertyTrees* property_trees = nullptr);
#if DCHECK_IS_ON()
bool operator==(const ClipTree& other) const;
#endif
void SetViewportClip(gfx::RectF viewport_rect);
gfx::RectF ViewportClip() const;
};
class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
public:
explicit EffectTree(PropertyTrees* property_trees = nullptr);
~EffectTree();
EffectTree& operator=(const EffectTree& from);
#if DCHECK_IS_ON()
bool operator==(const EffectTree& other) const;
#endif
int Insert(const EffectNode& tree_node, int parent_id);
void clear();
float EffectiveOpacity(const EffectNode* node) const;
void UpdateSurfaceContentsScale(EffectNode* node);
bool OnOpacityAnimated(ElementId id, float opacity);
bool OnFilterAnimated(ElementId id, const FilterOperations& filters);
bool OnBackdropFilterAnimated(ElementId id,
const FilterOperations& backdrop_filters);
void UpdateEffects(int id);
void UpdateEffectChanged(EffectNode* node, EffectNode* parent_node);
void UpdateHasFilters(EffectNode* node, EffectNode* parent_node);
typedef std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>>
CopyRequestMap;
void AddCopyRequest(int node_id,
std::unique_ptr<viz::CopyOutputRequest> request);
void PullCopyRequestsFrom(CopyRequestMap& new_copy_requests);
void PushCopyRequestsTo(EffectTree* other_tree);
void TakeCopyRequestsAndTransformToSurface(
int node_id,
std::vector<std::unique_ptr<viz::CopyOutputRequest>>* requests);
bool HasCopyRequests() const;
void ClearCopyRequests();
void GetRenderSurfaceChangedFlags(
std::vector<RenderSurfacePropertyChangedFlags>& flags) const;
void ApplyRenderSurfaceChangedFlags(
const std::vector<RenderSurfacePropertyChangedFlags>& flags);
int LowestCommonAncestorWithRenderSurface(int id_1, int id_2) const;
RenderSurfaceImpl* GetRenderSurface(int id) {
return render_surfaces_[static_cast<size_t>(id)].get();
}
const RenderSurfaceImpl* GetRenderSurface(int id) const {
return render_surfaces_[static_cast<size_t>(id)].get();
}
void ClearTransitionPseudoElementEffectNodes();
void AddTransitionPseudoElementEffectId(int id);
std::vector<RenderSurfaceImpl*> GetTransitionPseudoElementRenderSurfaces();
bool ContributesToDrawnSurface(int id) const;
void ResetChangeTracking();
void TakeRenderSurfaces(
std::vector<std::unique_ptr<RenderSurfaceImpl>>* render_surfaces);
bool CreateOrReuseRenderSurfaces(
std::vector<std::unique_ptr<RenderSurfaceImpl>>* old_render_surfaces,
LayerTreeImpl* layer_tree_impl);
bool ClippedHitTestRegionIsRectangle(int effect_node_id) const;
bool HitTestMayBeAffectedByMask(int effect_node_id) const;
CopyRequestMap TakeCopyRequests();
private:
void UpdateOpacities(EffectNode* node, EffectNode* parent_node);
void UpdateSubtreeHidden(EffectNode* node, EffectNode* parent_node);
void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node);
void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node);
void UpdateHasMaskingChild(EffectNode* node, EffectNode* parent_node);
void UpdateOnlyDrawsVisibleContent(EffectNode* node, EffectNode* parent_node);
void UpdateClosestAncestorSharedElement(EffectNode* node,
EffectNode* parent_node);
std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>>
copy_requests_;
std::vector<std::unique_ptr<RenderSurfaceImpl>> render_surfaces_;
std::unordered_set<int> transition_pseudo_element_effect_nodes_;
};
class ScrollCallbacks {
public:
virtual void DidCompositorScroll(
ElementId scroll_element_id,
const gfx::PointF&,
const absl::optional<TargetSnapAreaElementIds>&) = 0;
virtual void DidChangeScrollbarsHidden(ElementId scroll_element_id,
bool hidden) = 0;
protected:
virtual ~ScrollCallbacks() {}
};
class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
public:
explicit ScrollTree(PropertyTrees* property_trees = nullptr);
~ScrollTree();
ScrollTree& operator=(const ScrollTree& from);
#if DCHECK_IS_ON()
bool operator==(const ScrollTree& other) const;
#endif
void clear();
gfx::PointF MaxScrollOffset(int scroll_node_id) const;
void OnScrollOffsetAnimated(ElementId id,
int scroll_tree_index,
const gfx::PointF& scroll_offset,
LayerTreeImpl* layer_tree_impl);
gfx::Size container_bounds(int scroll_node_id) const;
gfx::SizeF scroll_bounds(int scroll_node_id) const;
ScrollNode* CurrentlyScrollingNode();
const ScrollNode* CurrentlyScrollingNode() const;
#if DCHECK_IS_ON()
int CurrentlyScrollingNodeId() const;
#endif
void set_currently_scrolling_node(int scroll_node_id);
int currently_scrolling_node() const { return currently_scrolling_node_id_; }
gfx::Transform ScreenSpaceTransform(int scroll_node_id) const;
gfx::Vector2dF ClampScrollToMaxScrollOffset(const ScrollNode& node,
LayerTreeImpl*);
const gfx::PointF current_scroll_offset(ElementId id) const;
const gfx::PointF GetPixelSnappedScrollOffset(int scroll_node_id) const;
void CollectScrollDeltas(
CompositorCommitData* commit_data,
ElementId inner_viewport_scroll_element_id,
bool use_fractional_deltas,
const base::flat_map<ElementId, TargetSnapAreaElementIds>&
snapped_elements,
const MutatorHost* main_thread_mutator_host);
void ApplySentScrollDeltasFromAbortedCommit(bool next_bmf,
bool main_frame_applied_deltas);
void PushScrollUpdatesFromMainThread(const PropertyTrees& main_property_trees,
LayerTreeImpl* sync_tree,
bool use_fractional_deltas);
void PushScrollUpdatesFromPendingTree(PropertyTrees* pending_property_trees,
LayerTreeImpl* active_tree);
void SetBaseScrollOffset(ElementId id, const gfx::PointF& scroll_offset);
bool SetScrollOffset(ElementId id, const gfx::PointF& scroll_offset);
void SetScrollOffsetClobberActiveValue(ElementId id) {
if (auto* synced_offset = GetSyncedScrollOffset(id))
synced_offset->set_clobber_active_value();
}
SyncedScrollOffset* GetOrCreateSyncedScrollOffsetForTesting(ElementId id);
bool UpdateScrollOffsetBaseForTesting(ElementId id,
const gfx::PointF& offset);
bool SetScrollOffsetDeltaForTesting(ElementId id,
const gfx::Vector2dF& delta);
const gfx::PointF GetScrollOffsetBaseForTesting(ElementId id) const;
const gfx::Vector2dF GetScrollOffsetDeltaForTesting(ElementId id) const;
void CollectScrollDeltasForTesting(bool use_fractional_deltas = false);
gfx::Vector2dF ScrollBy(const ScrollNode& scroll_node,
const gfx::Vector2dF& scroll,
LayerTreeImpl* layer_tree_impl);
gfx::PointF ClampScrollOffsetToLimits(gfx::PointF offset,
const ScrollNode& scroll_node) const;
SyncedScrollOffset* GetSyncedScrollOffset(ElementId id);
const SyncedScrollOffset* GetSyncedScrollOffset(ElementId id) const;
#if DCHECK_IS_ON()
void CopyCompleteTreeState(const ScrollTree& other);
#endif
void SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks);
void NotifyDidCompositorScroll(
ElementId scroll_element_id,
const gfx::PointF& scroll_offset,
const absl::optional<TargetSnapAreaElementIds>& snap_target_ids);
void NotifyDidChangeScrollbarsHidden(ElementId scroll_element_id,
bool hidden) const;
bool IsComposited(const ScrollNode& node) const;
bool CanRealizeScrollsOnCompositor(const ScrollNode& node) const;
uint32_t GetMainThreadRepaintReasons(const ScrollNode& node) const;
private:
using PropertyTree::needs_update;
using PropertyTree::set_needs_update;
using ScrollOffsetMap = base::flat_map<ElementId, gfx::PointF>;
using SyncedScrollOffsetMap =
base::flat_map<ElementId, scoped_refptr<SyncedScrollOffset>>;
int currently_scrolling_node_id_ = kInvalidPropertyNodeId;
ScrollOffsetMap scroll_offset_map_;
SyncedScrollOffsetMap synced_scroll_offset_map_;
base::WeakPtr<ScrollCallbacks> callbacks_;
gfx::Vector2dF PullDeltaForMainThread(SyncedScrollOffset* scroll_offset,
bool use_fractional_deltas,
bool next_bmf);
};
constexpr int kInvalidUpdateNumber = -1;
struct AnimationScaleData {
int update_number = kInvalidUpdateNumber;
float maximum_to_screen_scale = kInvalidScale;
bool affected_by_animation_scale = false;
bool affected_by_invalid_scale = false;
};
struct DrawTransforms {
bool might_be_invertible;
bool from_valid;
bool to_valid;
gfx::Transform from_target;
gfx::Transform to_target;
DrawTransforms(gfx::Transform from, gfx::Transform to)
: might_be_invertible(true),
from_valid(false),
to_valid(false),
from_target(from),
to_target(to) {}
bool operator==(const DrawTransforms& other) const {
return from_valid == other.from_valid && to_valid == other.to_valid &&
from_target == other.from_target && to_target == other.to_target;
}
};
struct DrawTransformData {
int update_number = kInvalidUpdateNumber;
int target_id = kInvalidPropertyNodeId;
DrawTransforms transforms{gfx::Transform(), gfx::Transform()};
};
struct PropertyTreesCachedData {
int transform_tree_update_number;
std::vector<AnimationScaleData> animation_scales;
mutable std::vector<std::vector<DrawTransformData>> draw_transforms;
PropertyTreesCachedData();
~PropertyTreesCachedData();
};
struct PropertyTreesChangeState {
PropertyTreesChangeState();
~PropertyTreesChangeState();
bool changed = false;
bool needs_rebuild = false;
bool full_tree_damaged = false;
EffectTree::CopyRequestMap effect_tree_copy_requests;
std::vector<int> changed_effect_nodes;
std::vector<int> changed_transform_nodes;
std::vector<RenderSurfacePropertyChangedFlags> surface_property_changed_flags;
};
class CC_EXPORT PropertyTrees final {
public:
explicit PropertyTrees(const ProtectedSequenceSynchronizer& synchronizer);
PropertyTrees(const PropertyTrees& other) = delete;
void* operator new(size_t) = delete;
void* operator new(size_t, void*) = delete;
void* operator new[](size_t) = delete;
void* operator new[](size_t, void*) = delete;
~PropertyTrees();
PropertyTrees& operator=(const PropertyTrees& from);
#if DCHECK_IS_ON()
bool operator==(const PropertyTrees& other) const;
#endif
const ProtectedSequenceSynchronizer& synchronizer() const {
return *synchronizer_;
}
const ClipTree& clip_tree() const { return clip_tree_; }
ClipTree& clip_tree_mutable() { return clip_tree_; }
const EffectTree& effect_tree() const { return effect_tree_; }
EffectTree& effect_tree_mutable() { return effect_tree_; }
const ScrollTree& scroll_tree() const { return scroll_tree_; }
ScrollTree& scroll_tree_mutable() { return scroll_tree_; }
const TransformTree& transform_tree() const { return transform_tree_; }
TransformTree& transform_tree_mutable() { return transform_tree_; }
void set_needs_rebuild(bool value) {
needs_rebuild_.Write(synchronizer()) = value;
}
bool needs_rebuild() const { return needs_rebuild_.Read(synchronizer()); }
void set_changed(bool value) { changed_.Write(synchronizer()) = value; }
bool changed() const { return changed_.Read(synchronizer()); }
void set_full_tree_damaged(bool value) {
full_tree_damaged_.Write(synchronizer()) = value;
}
bool full_tree_damaged() const {
return full_tree_damaged_.Read(synchronizer());
}
void set_is_main_thread(bool value) {
is_main_thread_.Write(synchronizer()) = value;
}
bool is_main_thread() const { return is_main_thread_.Read(synchronizer()); }
void set_is_active(bool value) { is_active_.Write(synchronizer()) = value; }
bool is_active() const { return is_active_.Read(synchronizer()); }
void set_sequence_number(int n) {
sequence_number_.Write(synchronizer()) = n;
}
void increment_sequence_number() { sequence_number_.Write(synchronizer())++; }
int sequence_number() const { return sequence_number_.Read(synchronizer()); }
void clear();
bool ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map,
const PropertyAnimationState& mask,
const PropertyAnimationState& state,
bool check_node_existence);
void MaximumAnimationScaleChanged(ElementId element_id, float maximum_scale);
void SetInnerViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta);
void SetOuterViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta);
void UpdateChangeTracking();
void GetChangedNodes(std::vector<int>& effect_nodes,
std::vector<int>& transform_nodes) const;
void ApplyChangedNodes(const std::vector<int>& effect_nodes,
const std::vector<int>& transform_nodes);
void GetChangeState(PropertyTreesChangeState& change_state);
void ResetAllChangeTracking();
gfx::Vector2dF inner_viewport_container_bounds_delta() const {
return inner_viewport_container_bounds_delta_.Read(synchronizer());
}
gfx::Vector2dF inner_viewport_scroll_bounds_delta() const {
return outer_viewport_container_bounds_delta();
}
gfx::Vector2dF outer_viewport_container_bounds_delta() const {
return outer_viewport_container_bounds_delta_.Read(synchronizer());
}
std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
void AsValueInto(base::trace_event::TracedValue* value) const;
std::string ToString() const;
bool AnimationScaleCacheIsInvalid(int transform_id) const;
float MaximumAnimationToScreenScale(int transform_id);
bool AnimationAffectedByInvalidScale(int transform_id);
void SetMaximumAnimationToScreenScaleForTesting(
int transform_id,
float maximum_scale,
bool affected_by_invalid_scale);
bool GetToTarget(int transform_id,
int effect_id,
gfx::Transform* to_target) const;
bool GetFromTarget(int transform_id,
int effect_id,
gfx::Transform* from_target) const;
void ResetCachedData();
void UpdateTransformTreeUpdateNumber();
gfx::Transform ToScreenSpaceTransformWithoutSurfaceContentsScale(
int transform_id,
int effect_id) const;
ClipRectData* FetchClipRectFromCache(int clip_id, int target_id);
bool HasElement(ElementId element_id) const;
private:
const raw_ref<const ProtectedSequenceSynchronizer> synchronizer_;
TransformTree transform_tree_;
EffectTree effect_tree_;
ClipTree clip_tree_;
ScrollTree scroll_tree_;
ProtectedSequenceReadable<bool> needs_rebuild_;
ProtectedSequenceReadable<bool> changed_;
ProtectedSequenceReadable<bool> full_tree_damaged_;
ProtectedSequenceReadable<bool> is_main_thread_;
ProtectedSequenceReadable<bool> is_active_;
ProtectedSequenceReadable<int> sequence_number_;
ProtectedSequenceReadable<gfx::Vector2dF>
inner_viewport_container_bounds_delta_;
ProtectedSequenceReadable<gfx::Vector2dF>
outer_viewport_container_bounds_delta_;
const AnimationScaleData& GetAnimationScaleData(int transform_id);
DrawTransforms& GetDrawTransforms(int transform_id, int effect_id) const;
DrawTransformData& FetchDrawTransformsDataFromCache(int transform_id,
int effect_id) const;
mutable PropertyTreesCachedData cached_data_;
};
}
#endif