1 // Copyright 2017 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 THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
6 #define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
7 
8 #include "base/optional.h"
9 #include "third_party/blink/renderer/bindings/modules/v8/document_timeline_or_scroll_timeline.h"
10 #include "third_party/blink/renderer/core/animation/animation.h"
11 #include "third_party/blink/renderer/core/animation/animation_effect_owner.h"
12 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
13 #include "third_party/blink/renderer/core/animation/worklet_animation_base.h"
14 #include "third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h"
15 #include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h"
16 #include "third_party/blink/renderer/modules/modules_export.h"
17 #include "third_party/blink/renderer/platform/animation/compositor_animation.h"
18 #include "third_party/blink/renderer/platform/animation/compositor_animation_client.h"
19 #include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.h"
20 #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h"
21 
22 namespace blink {
23 
24 class AnimationEffectOrAnimationEffectSequence;
25 class ScriptValue;
26 class SerializedScriptValue;
27 
28 // The main-thread controller for a single AnimationWorklet animator instance.
29 //
30 // WorkletAnimation instances exist in the document execution context (i.e. in
31 // the main javascript thread), and are a type of animation that delegates
32 // actual playback to an 'animator instance'. The animator instance runs in a
33 // separate worklet execution context (which can either also be on the main
34 // thread or may be in a separate worklet thread).
35 //
36 // All methods in this class should be called in the document execution context.
37 //
38 // Spec: https://wicg.github.io/animation-worklet/#worklet-animation-desc
39 class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
40                                         public CompositorAnimationClient,
41                                         public CompositorAnimationDelegate,
42                                         public AnimationEffectOwner {
43   DEFINE_WRAPPERTYPEINFO();
44   USING_GARBAGE_COLLECTED_MIXIN(WorkletAnimation);
45   USING_PRE_FINALIZER(WorkletAnimation, Dispose);
46 
47  public:
48   static WorkletAnimation* Create(
49       ScriptState*,
50       String animator_name,
51       const AnimationEffectOrAnimationEffectSequence&,
52       ExceptionState&);
53   static WorkletAnimation* Create(
54       ScriptState*,
55       String animator_name,
56       const AnimationEffectOrAnimationEffectSequence&,
57       DocumentTimelineOrScrollTimeline,
58       ExceptionState&);
59   static WorkletAnimation* Create(
60       ScriptState*,
61       String animator_name,
62       const AnimationEffectOrAnimationEffectSequence&,
63       DocumentTimelineOrScrollTimeline,
64       const ScriptValue& options,
65       ExceptionState&);
66 
67   WorkletAnimation(WorkletAnimationId id,
68                    const String& animator_name,
69                    Document&,
70                    const HeapVector<Member<KeyframeEffect>>&,
71                    AnimationTimeline*,
72                    scoped_refptr<SerializedScriptValue> options);
73   ~WorkletAnimation() override = default;
74 
animatorName()75   String animatorName() { return animator_name_; }
effect()76   AnimationEffect* effect() { return GetEffect(); }
timeline()77   AnimationTimeline* timeline() { return timeline_; }
78   String playState();
79   base::Optional<double> currentTime();
80   base::Optional<double> startTime();
81   // TODO(crbug.com/1060971): Remove |is_null| version.
82   double currentTime(bool& is_null);  // DEPRECATED
83   double startTime(bool& is_null);    // DEPRECATED
84 
85   double playbackRate(ScriptState* script_state) const;
86   void setPlaybackRate(ScriptState* script_state, double playback_rate);
87   void play(ExceptionState& exception_state);
88   void pause(ExceptionState& exception_state);
89   void cancel();
90 
91   // AnimationEffectOwner implementation:
SequenceNumber()92   unsigned SequenceNumber() const override { return sequence_number_; }
93   bool Playing() const override;
94   // Always allow dispatching events for worklet animations. This is only ever
95   // relevant to CSS animations which means it does not have any material effect
96   // on worklet animations either way.
IsEventDispatchAllowed()97   bool IsEventDispatchAllowed() const override { return true; }
98   // Effect suppression is used by devtool's animation inspection machinery
99   // which is not currently supported by worklet animations.
EffectSuppressed()100   bool EffectSuppressed() const override { return false; }
101   // Worklet animations are not currently replaceable.
102   // TODO(crbug.com/833846): Make replaceable once a proper subclass of
103   // Animation.
ReplaceStateRemoved()104   bool ReplaceStateRemoved() const override { return false; }
105 
106   void EffectInvalidated() override;
107   void UpdateIfNecessary() override;
108 
GetAnimation()109   Animation* GetAnimation() override { return nullptr; }
110 
111   // WorkletAnimationBase implementation.
112   void Update(TimingUpdateReason) override;
113   void UpdateCompositingState() override;
114   void InvalidateCompositingState() override;
115 
116   // CompositorAnimationClient implementation.
GetCompositorAnimation()117   CompositorAnimation* GetCompositorAnimation() const override {
118     return compositor_animation_.get();
119   }
120 
121   // CompositorAnimationDelegate implementation.
NotifyAnimationStarted(double monotonic_time,int group)122   void NotifyAnimationStarted(double monotonic_time, int group) override {}
NotifyAnimationFinished(double monotonic_time,int group)123   void NotifyAnimationFinished(double monotonic_time, int group) override {}
NotifyAnimationAborted(double monotonic_time,int group)124   void NotifyAnimationAborted(double monotonic_time, int group) override {}
125   void NotifyLocalTimeUpdated(
126       base::Optional<base::TimeDelta> local_time) override;
127 
GetDocument()128   Document* GetDocument() const override { return document_.Get(); }
GetTimeline()129   AnimationTimeline* GetTimeline() const override { return timeline_; }
Name()130   const String& Name() { return animator_name_; }
131 
132   KeyframeEffect* GetEffect() const override;
GetWorkletAnimationId()133   const WorkletAnimationId& GetWorkletAnimationId() const override {
134     return id_;
135   }
136   bool IsActiveAnimation() const override;
137 
138   void UpdateInputState(AnimationWorkletDispatcherInput* input_state) override;
139   void SetOutputState(
140       const AnimationWorkletOutput::AnimationState& state) override;
141 
SetRunningOnMainThreadForTesting(bool running_on_main_thread)142   void SetRunningOnMainThreadForTesting(bool running_on_main_thread) {
143     running_on_main_thread_ = running_on_main_thread;
144   }
145 
146   void Trace(Visitor*) override;
147   void Dispose();
148 
149  private:
150   void DestroyCompositorAnimation();
151   bool IsTimelineActive() const;
152   base::Optional<base::TimeDelta> CurrentTime();
153   base::Optional<base::TimeDelta> CurrentTimeInternal() const;
154   void UpdateCurrentTimeIfNeeded();
155   bool IsCurrentTimeInitialized() const;
156   base::Optional<base::TimeDelta> InitialCurrentTime() const;
157 
158   bool CanStartOnCompositor();
159   // Attempts to start the animation on the compositor side, returning true if
160   // it succeeds or false otherwise. If false is returned and the animation
161   // cannot be started on main.
162   bool StartOnCompositor();
163   void StartOnMain();
164   bool CheckCanStart(String* failure_message);
165 
166   // Sets the current time for the animation.
167   //
168   // Note that the current time of the animation is a computed value that
169   // depends on either the start time (for playing animations) or the hold time
170   // (for pending, paused, or idle animations). So this procedure updates either
171   // the start time or the hold time so that the computed current time is
172   // matched.
173   //
174   // Generally, when an animation play state transitions, we expect to see the
175   // current time is set. Here are some interesting examples of this:
176   //  - when transitioning to play, the current time is either set to
177   //  zero (first time) or the last current time (when resuming from pause).
178   //  - when transitioning to idle or cancel, the current time is set to
179   //  "null".
180   //  - when transitioning to pause, the current time is set to the last
181   //  current time for holding.
182   void SetCurrentTime(base::Optional<base::TimeDelta> current_time);
183 
184   // Adjusts start_time_ according to playback rate change to preserve current
185   // time and avoid the animation output from jumping.
186   void SetPlaybackRateInternal(double);
187 
188   // Updates a running animation on the compositor side. Returns false if the
189   // update is terminated. e.g. the animated target is gone.
190   bool UpdateOnCompositor();
191 
CloneOptions()192   std::unique_ptr<cc::AnimationOptions> CloneOptions() const {
193     return options_ ? options_->Clone() : nullptr;
194   }
195 
CloneEffectTimings()196   std::unique_ptr<cc::AnimationEffectTimings> CloneEffectTimings() const {
197     return effect_timings_ ? effect_timings_->Clone() : nullptr;
198   }
199 
PlayState()200   Animation::AnimationPlayState PlayState() const { return play_state_; }
SetPlayState(const Animation::AnimationPlayState & state)201   void SetPlayState(const Animation::AnimationPlayState& state) {
202     play_state_ = state;
203   }
204 
205   unsigned sequence_number_;
206 
207   WorkletAnimationId id_;
208 
209   const String animator_name_;
210   Animation::AnimationPlayState play_state_;
211   Animation::AnimationPlayState last_play_state_;
212   // Controls speed of the animation.
213   // https://drafts.csswg.org/web-animations-2/#animation-effect-playback-rate
214   double playback_rate_;
215   base::Optional<base::TimeDelta> start_time_;
216   Vector<base::Optional<base::TimeDelta>> local_times_;
217   // Hold time is used when animation is paused.
218   // TODO(majidvp): Replace base::TimeDelta usage with AnimationTimeDelta.
219   base::Optional<base::TimeDelta> hold_time_;
220   // Keeps last set or calculated current time. It's used as a hold time when
221   // the timeline is inactive.
222   base::Optional<base::TimeDelta> last_current_time_;
223   // Indicates if the timeline was active when the current time was calculated
224   // last time.
225   bool was_timeline_active_;
226   // We use this to skip updating if current time has not changed since last
227   // update.
228   base::Optional<base::TimeDelta> last_input_update_current_time_;
229 
230   Member<Document> document_;
231 
232   HeapVector<Member<KeyframeEffect>> effects_;
233   Member<AnimationTimeline> timeline_;
234   std::unique_ptr<WorkletAnimationOptions> options_;
235   std::unique_ptr<WorkletAnimationEffectTimings> effect_timings_;
236 
237   std::unique_ptr<CompositorAnimation> compositor_animation_;
238   bool running_on_main_thread_;
239   bool has_started_;
240   // Tracks whether any KeyframeEffect associated with this WorkletAnimation has
241   // been invalidated and needs to be restarted. Used to avoid unnecessarily
242   // restarting the effect on the compositor. When true, a call to
243   // |UpdateOnCompositor| will update the effect on the compositor.
244   bool effect_needs_restart_;
245 
246   FRIEND_TEST_ALL_PREFIXES(WorkletAnimationTest, PausePlay);
247 };
248 
249 }  // namespace blink
250 
251 #endif
252