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