1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
cc / animation / animation_host.h [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_ANIMATION_ANIMATION_HOST_H_
#define CC_ANIMATION_ANIMATION_HOST_H_
#include <memory>
#include <unordered_map>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "cc/animation/animation_export.h"
#include "cc/animation/keyframe_model.h"
#include "cc/base/protected_sequence_synchronizer.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/mutator_host_client.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace cc {
class Animation;
class AnimationTimeline;
class ElementAnimations;
class LayerTreeHost;
class ScrollOffsetAnimations;
class ScrollOffsetAnimationsImpl;
class WorkletAnimation;
enum class ThreadInstance { kMain, kImpl };
// An AnimationHost contains all the state required to play animations.
// Specifically, it owns all the AnimationTimelines objects.
// There is just one AnimationHost for LayerTreeHost on main renderer thread
// and just one AnimationHost for LayerTreeHostImpl on impl thread.
// We synchronize them during the commit process in a one-way data flow process
// (PushPropertiesTo).
// An AnimationHost talks to its correspondent LayerTreeHost via
// MutatorHostClient interface.
class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost,
public LayerTreeMutatorClient,
public ProtectedSequenceSynchronizer {
public:
using ElementToAnimationsMap =
std::unordered_map<ElementId,
scoped_refptr<ElementAnimations>,
ElementIdHash>;
using AnimationsList = std::vector<scoped_refptr<Animation>>;
static std::unique_ptr<AnimationHost> CreateMainInstance();
static std::unique_ptr<AnimationHost> CreateForTesting(
ThreadInstance thread_instance);
AnimationHost(const AnimationHost&) = delete;
~AnimationHost() override;
AnimationHost& operator=(const AnimationHost&) = delete;
using IdToTimelineMap =
std::unordered_map<int, scoped_refptr<AnimationTimeline>>;
const IdToTimelineMap& timelines() const {
return id_to_timeline_map_.Read(*this);
}
void AddAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
void RemoveAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
// Lazy removal of an unused timeline.
void DetachAnimationTimeline(scoped_refptr<AnimationTimeline> timeline);
const AnimationTimeline* GetTimelineById(int timeline_id) const;
AnimationTimeline* GetTimelineById(int timeline_id);
void RegisterAnimationForElement(ElementId element_id, Animation* animation);
void UnregisterAnimationForElement(ElementId element_id,
Animation* animation);
void UpdateClientAnimationStateForElementAnimations(ElementId element_id);
gfx::PointF GetScrollOffsetForAnimation(ElementId element_id) const;
scoped_refptr<const ElementAnimations>
GetElementAnimationsForElementIdForTesting(ElementId element_id) const;
// Parent LayerTreeHost or LayerTreeHostImpl.
MutatorHostClient* mutator_host_client() {
DCHECK(IsOwnerThread() || InProtectedSequence());
return mutator_host_client_;
}
const MutatorHostClient* mutator_host_client() const {
DCHECK(IsOwnerThread() || InProtectedSequence());
return mutator_host_client_;
}
// ProtectedSequenceSynchronizer implementation
bool IsOwnerThread() const override;
bool InProtectedSequence() const override;
void WaitForProtectedSequenceCompletion() const override;
void SetNeedsCommit();
void SetNeedsPushProperties();
void ResetNeedsPushProperties();
bool needs_push_properties() const {
return needs_push_properties_.Read(*this);
}
// MutatorHost implementation.
std::unique_ptr<MutatorHost> CreateImplInstance() const override;
void ClearMutators() override;
base::TimeDelta MinimumTickInterval() const override;
void InitClientAnimationState() override;
void RemoveElementId(ElementId element_id) override;
void SetMutatorHostClient(MutatorHostClient* client) override;
void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator) override;
void PushPropertiesTo(MutatorHost* host_impl,
const PropertyTrees& property_trees) override;
void RemoveStaleTimelines() override;
void SetScrollAnimationDurationForTesting(base::TimeDelta duration) override;
bool NeedsTickAnimations() const override;
bool ActivateAnimations(MutatorEvents* events) override;
bool TickAnimations(base::TimeTicks monotonic_time,
const ScrollTree& scroll_tree,
bool is_active_tree) override;
void TickScrollAnimations(base::TimeTicks monotonic_time,
const ScrollTree& scroll_tree) override;
void TickWorkletAnimations() override;
bool UpdateAnimationState(bool start_ready_animations,
MutatorEvents* events) override;
void TakeTimeUpdatedEvents(MutatorEvents* events) override;
// Should be called when the pending tree is promoted to active, as this may
// require updating the ElementId for the ScrollTimeline scroll source.
void PromoteScrollTimelinesPendingToActive() override;
std::unique_ptr<MutatorEvents> CreateEvents() override;
void SetAnimationEvents(std::unique_ptr<MutatorEvents> events) override;
bool ScrollOffsetAnimationWasInterrupted(ElementId element_id) const override;
bool IsAnimatingProperty(ElementId element_id,
ElementListType list_type,
TargetProperty::Type property) const override;
bool HasPotentiallyRunningAnimationForProperty(
ElementId element_id,
ElementListType list_type,
TargetProperty::Type property) const override;
bool HasAnyAnimationTargetingProperty(
ElementId element_id,
TargetProperty::Type property) const override;
bool AnimationsPreserveAxisAlignment(ElementId element_id) const override;
float MaximumScale(ElementId element_id,
ElementListType list_type) const override;
bool IsElementAnimating(ElementId element_id) const override;
bool HasTickingKeyframeModelForTesting(ElementId element_id) const override;
void ImplOnlyAutoScrollAnimationCreate(
ElementId element_id,
const gfx::PointF& target_offset,
const gfx::PointF& current_offset,
float autoscroll_velocity,
base::TimeDelta animation_start_offset) override;
void ImplOnlyScrollAnimationCreate(
ElementId element_id,
const gfx::PointF& target_offset,
const gfx::PointF& current_offset,
base::TimeDelta delayed_by,
base::TimeDelta animation_start_offset) override;
std::optional<gfx::PointF> ImplOnlyScrollAnimationUpdateTarget(
const gfx::Vector2dF& scroll_delta,
const gfx::PointF& max_scroll_offset,
base::TimeTicks frame_monotonic_time,
base::TimeDelta delayed_by,
ElementId element_id) override;
void ScrollAnimationAbort(ElementId element_id) override;
bool HasImplOnlyScrollAnimatingElement() const override;
bool HasImplOnlyAutoScrollAnimatingElement() const override;
bool ElementHasImplOnlyScrollAnimation(ElementId) const override;
bool IsElementInPropertyTrees(ElementId element_id,
bool commits_to_active) const;
void HandleRemovedScrollAnimatingElements(bool commits_to_active) override;
// This should only be called from the main thread.
ScrollOffsetAnimations& scroll_offset_animations();
// Registers the given animation as ticking. A ticking animation is one that
// has a running keyframe model.
void AddToTicking(scoped_refptr<Animation> animation);
// Unregisters the given animation. When this happens, the animation will no
// longer be ticked.
void RemoveFromTicking(scoped_refptr<Animation> animation);
const AnimationsList& ticking_animations_for_testing() const;
const ElementToAnimationsMap& element_animations_for_testing() const;
// LayerTreeMutatorClient.
void SetMutationUpdate(
std::unique_ptr<MutatorOutputState> output_state) override;
size_t MainThreadAnimationsCount() const override;
// Returns true if there is any animation that affects pending tree, such as
// custom property animations via paint worklet.
bool HasInvalidationAnimation() const override;
// Returns true if there is any animation that affects active tree, such as
// transform animation.
bool HasNativePropertyAnimation() const override;
bool CurrentFrameHadRAF() const override;
bool NextFrameHasPendingRAF() const override;
PendingCompositorMetricsTrackerInfos
TakePendingCompositorMetricsTrackerInfos() override;
bool HasCanvasInvalidation() const override;
bool HasJSAnimation() const override;
bool HasSmilAnimation() const override;
bool HasViewTransition() const override;
bool HasScrollLinkedAnimation(ElementId for_scroller) const override;
// Starts/stops metrics tracking represented by `sequence_id`.
void StartCompositorMetricsTracking(TrackedAnimationSequenceId sequence_id);
void StopCompositorMetricsTracking(TrackedAnimationSequenceId sequence_id);
void SetAnimationCounts(size_t total_animations_count);
void SetHasCanvasInvalidation(bool has_canvas_invalidation);
void SetHasInlineStyleMutation(bool has_inline_style_mutation);
void SetHasSmilAnimation(bool has_svg_smil_animation);
void SetHasViewTransition(bool has_view_transition);
void SetCurrentFrameHadRaf(bool current_frame_had_raf);
void SetNextFrameHasPendingRaf(bool next_frame_has_pending_raf);
private:
explicit AnimationHost(ThreadInstance thread_instance);
const ElementAnimations* GetElementAnimationsForElementId(
ElementId element_id) const;
scoped_refptr<ElementAnimations> GetElementAnimationsForElementId(
ElementId element_id);
void PushTimelinesToImplThread(AnimationHost* host_impl) const;
void RemoveTimelinesFromImplThread(AnimationHost* host_impl) const;
void PushPropertiesToImplThread(AnimationHost* host_impl);
void EraseTimeline(scoped_refptr<AnimationTimeline> timeline);
// Return true if there are any animations that get mutated.
void TickMutator(base::TimeTicks monotonic_time,
const ScrollTree& scroll_tree,
bool is_active_tree);
// Return the state representing all ticking worklet animations.
std::unique_ptr<MutatorInputState> CollectWorkletAnimationsState(
base::TimeTicks timeline_time,
const ScrollTree& scroll_tree,
bool is_active_tree);
// Returns a pointer to a worklet animation by worklet animation id or null
// if there is no match.
WorkletAnimation* FindWorkletAnimation(WorkletAnimationId id);
ProtectedSequenceReadable<ElementToAnimationsMap> element_to_animations_map_;
ProtectedSequenceReadable<AnimationsList> ticking_animations_;
// A list of all timelines which this host owns.
ProtectedSequenceReadable<IdToTimelineMap> id_to_timeline_map_;
// A list of IDs for detached timelines. A timeline may be detached on the
// owner thread even during a protected sequence. These timelines are no
// longer used and should be cleaned up at the next opportune moment.
ProtectedSequenceForbidden<IdToTimelineMap> detached_timeline_map_;
// AnimationHosts's ProtectedSequenceSynchronizer implementation is
// implemented using this member. As such the various helpers can not be used
// to protect access (otherwise we would get infinite recursion).
raw_ptr<MutatorHostClient> mutator_host_client_ = nullptr;
// This is only non-null within the call scope of PushPropertiesTo().
raw_ptr<const PropertyTrees> property_trees_ = nullptr;
// Exactly one of scroll_offset_animations_ and scroll_offset_animations_impl_
// will be non-null for a given AnimationHost instance (the former if
// thread_instance_ == ThreadInstance::MAIN, the latter if thread_instance_ ==
// ThreadInstance::IMPL).
ProtectedSequenceWritable<std::unique_ptr<ScrollOffsetAnimations>>
scroll_offset_animations_;
ProtectedSequenceReadable<std::unique_ptr<ScrollOffsetAnimationsImpl>>
scroll_offset_animations_impl_;
const ThreadInstance thread_instance_;
ProtectedSequenceWritable<bool> needs_push_properties_{false};
ProtectedSequenceReadable<std::unique_ptr<LayerTreeMutator>> mutator_;
ProtectedSequenceReadable<size_t> main_thread_animations_count_{0};
ProtectedSequenceReadable<bool> current_frame_had_raf_{false};
ProtectedSequenceReadable<bool> next_frame_has_pending_raf_{false};
ProtectedSequenceReadable<bool> has_canvas_invalidation_{false};
ProtectedSequenceReadable<bool> has_inline_style_mutation_{false};
ProtectedSequenceReadable<bool> has_smil_animation_{false};
ProtectedSequenceReadable<bool> has_view_transition_{false};
ProtectedSequenceWritable<PendingCompositorMetricsTrackerInfos>
pending_compositor_metrics_tracker_infos_;
base::WeakPtrFactory<AnimationHost> weak_factory_{this};
};
} // namespace cc
#endif // CC_ANIMATION_ANIMATION_HOST_H_