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
cc / animation / worklet_animation.h [blame]
// Copyright 2017 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_WORKLET_ANIMATION_H_
#define CC_ANIMATION_WORKLET_ANIMATION_H_
#include <memory>
#include <optional>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_export.h"
#include "cc/animation/animation_host.h"
#include "cc/trees/property_tree.h"
namespace cc {
class AnimationOptions;
class AnimationEffectTimings;
// A WorkletAnimation is an animation that allows its animation
// timing to be controlled by an animator instance that is running in a
// AnimationWorkletGlobalScope.
// Two instances of this class are created for Blink WorkletAnimation:
// 1. UI thread instance that keeps all the meta data.
// 2. Impl thread instance that ticks the animations on the Impl thread.
// When Blink WorkletAnimation is updated, it calls the UI thread instance to
// modify its properties. The updated properties are pushed by the UI thread
// instance to the Impl thread instance during commit.
class CC_ANIMATION_EXPORT WorkletAnimation final : public Animation {
public:
enum class State { kPending, kRunning, kRemoved };
WorkletAnimation(int cc_animation_id,
WorkletAnimationId worklet_animation_id,
const std::string& name,
double playback_rate_value,
std::unique_ptr<AnimationOptions> options,
std::unique_ptr<AnimationEffectTimings> effect_timings,
bool is_controlling_instance);
static scoped_refptr<WorkletAnimation> Create(
WorkletAnimationId worklet_animation_id,
const std::string& name,
double playback_rate_value,
std::unique_ptr<AnimationOptions> options,
std::unique_ptr<AnimationEffectTimings> effect_timings);
scoped_refptr<Animation> CreateImplInstance() const override;
WorkletAnimationId worklet_animation_id() { return worklet_animation_id_; }
const std::string& name() const { return name_; }
bool IsWorkletAnimation() const override;
bool Tick(base::TimeTicks monotonic_time) override;
void UpdateState(bool start_ready_animations,
AnimationEvents* events) override;
void TakeTimeUpdatedEvent(AnimationEvents* events) override;
void UpdateInputState(MutatorInputState* input_state,
base::TimeTicks monotonic_time,
const ScrollTree& scroll_tree,
bool is_active_tree);
void SetOutputState(const MutatorOutputState::AnimationState& state);
void PushPropertiesTo(Animation* animation_impl) override;
// Called by Blink WorkletAnimation when its playback rate is updated.
void UpdatePlaybackRate(double rate);
void SetPlaybackRateForTesting(double playback_rate) {
SetPlaybackRate(playback_rate);
}
void RemoveKeyframeModel(int keyframe_model_id) override;
void ReleasePendingTreeLock();
private:
~WorkletAnimation() override;
double playback_rate() const { return playback_rate_.Read(*this); }
// Returns the current time to be passed into the underlying AnimationWorklet.
// The current time is based on the timeline associated with the animation and
// in case of scroll timeline it may be nullopt when the associated scrolling
// node is not available in the particular ScrollTree.
std::optional<base::TimeDelta> CurrentTime(base::TimeTicks monotonic_time,
const ScrollTree& scroll_tree,
bool is_active_tree);
// Returns true if the worklet animation needs to be updated which happens iff
// its current time is going to be different from last time given these input.
bool NeedsUpdate(base::TimeTicks monotonic_time,
const ScrollTree& scroll_tree,
bool is_active_tree);
std::unique_ptr<AnimationOptions> CloneOptions() const {
return options_ ? options_->Clone() : nullptr;
}
std::unique_ptr<AnimationEffectTimings> CloneEffectTimings() const {
return effect_timings_ ? effect_timings_->Clone() : nullptr;
}
// Updates the playback rate of the Impl thread instance.
// Called by the UI thread WorkletAnimation instance during commit.
void SetPlaybackRate(double rate);
bool IsTimelineActive(const ScrollTree& scroll_tree,
bool is_active_tree) const;
const WorkletAnimationId worklet_animation_id_;
const std::string name_;
// Controls speed of the animation.
// https://drafts.csswg.org/web-animations-2/#animation-effect-playback-rate
// For UI thread instance contains the meta value to be pushed to the Impl
// thread instance.
// For the Impl thread instance contains the actual playback rate of the
// animation.
ProtectedSequenceReadable<double> playback_rate_;
// These are set once, and never change.
std::unique_ptr<AnimationOptions> options_;
std::unique_ptr<AnimationEffectTimings> effect_timings_;
// Local time is used as an input to the keyframe effect of this animation.
// The value comes from the user script that runs inside the animation worklet
// global scope.
ProtectedSequenceReadable<std::optional<base::TimeDelta>> local_time_;
// Local time passed to the main thread worklet animation to update its
// keyframe effect. We only set the most recent local time, meaning that if
// there are multiple compositor frames without a single main frame only
// the local time associated with the latest frame is sent to the main thread.
ProtectedSequenceReadable<std::optional<base::TimeDelta>>
last_synced_local_time_;
ProtectedSequenceReadable<std::optional<base::TimeTicks>> start_time_;
// Last current time used for updating. We use this to skip updating if
// current time has not changed since last update.
ProtectedSequenceReadable<std::optional<base::TimeDelta>> last_current_time_;
// To ensure that 'time' progresses forward for scroll animations, we guard
// against allowing active tree mutations while the pending tree has a
// lock in the worklet. The lock is established when updating the input state
// for the pending tree and release on pending tree activation.
ProtectedSequenceReadable<bool> has_pending_tree_lock_{false};
ProtectedSequenceReadable<State> state_{State::kPending};
const bool is_impl_instance_;
};
inline WorkletAnimation* ToWorkletAnimation(Animation* animation) {
DCHECK(animation->IsWorkletAnimation());
return static_cast<WorkletAnimation*>(animation);
}
} // namespace cc
#endif // CC_ANIMATION_WORKLET_ANIMATION_H_