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
|
// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
#include <optional>
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_effect_owner.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/worklet_animation_base.h"
#include "third_party/blink/renderer/modules/animationworklet/worklet_animation_effect_timings.h"
#include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_client.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.h"
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutators_state.h"
#include "third_party/blink/renderer/platform/heap/prefinalizer.h"
namespace blink {
class ScriptValue;
class SerializedScriptValue;
class V8AnimationPlayState;
class V8UnionAnimationEffectOrAnimationEffectSequence;
class V8UnionDocumentTimelineOrScrollTimeline;
// The main-thread controller for a single AnimationWorklet animator instance.
//
// WorkletAnimation instances exist in the document execution context (i.e. in
// the main javascript thread), and are a type of animation that delegates
// actual playback to an 'animator instance'. The animator instance runs in a
// separate worklet execution context (which can either also be on the main
// thread or may be in a separate worklet thread).
//
// All methods in this class should be called in the document execution context.
//
// Spec: https://wicg.github.io/animation-worklet/#worklet-animation-desc
class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
public CompositorAnimationClient,
public CompositorAnimationDelegate,
public AnimationEffectOwner {
DEFINE_WRAPPERTYPEINFO();
USING_PRE_FINALIZER(WorkletAnimation, Dispose);
public:
static WorkletAnimation* Create(
ScriptState* script_state,
const String& animator_name,
const V8UnionAnimationEffectOrAnimationEffectSequence* effects,
ExceptionState& exception_state);
static WorkletAnimation* Create(
ScriptState* script_state,
const String& animator_name,
const V8UnionAnimationEffectOrAnimationEffectSequence* effects,
const V8UnionDocumentTimelineOrScrollTimeline* timeline,
ExceptionState& exception_state);
static WorkletAnimation* Create(
ScriptState* script_state,
const String& animator_name,
const V8UnionAnimationEffectOrAnimationEffectSequence* effects,
const V8UnionDocumentTimelineOrScrollTimeline* timeline,
const ScriptValue& options,
ExceptionState& exception_state);
WorkletAnimation(WorkletAnimationId id,
const String& animator_name,
Document&,
const HeapVector<Member<KeyframeEffect>>&,
AnimationTimeline*,
scoped_refptr<SerializedScriptValue> options);
~WorkletAnimation() override = default;
String animatorName() { return animator_name_; }
AnimationEffect* effect() { return GetEffect(); }
AnimationTimeline* timeline() { return timeline_.Get(); }
V8AnimationPlayState playState();
std::optional<double> currentTime();
std::optional<double> startTime();
double playbackRate(ScriptState* script_state) const;
void setPlaybackRate(ScriptState* script_state, double playback_rate);
void play(ExceptionState& exception_state);
void pause(ExceptionState& exception_state);
void cancel();
// AnimationEffectOwner implementation:
unsigned SequenceNumber() const override { return sequence_number_; }
bool Playing() const override;
// Always allow dispatching events for worklet animations. This is only ever
// relevant to CSS animations which means it does not have any material effect
// on worklet animations either way.
bool IsEventDispatchAllowed() const override { return true; }
// Effect suppression is used by devtool's animation inspection machinery
// which is not currently supported by worklet animations.
bool EffectSuppressed() const override { return false; }
// Worklet animations are not currently replaceable.
// TODO(crbug.com/833846): Make replaceable once a proper subclass of
// Animation.
bool ReplaceStateRemoved() const override { return false; }
void EffectInvalidated() override;
void UpdateIfNecessary() override;
Animation* GetAnimation() override { return nullptr; }
// WorkletAnimationBase implementation.
void Update(TimingUpdateReason) override;
void UpdateCompositingState() override;
void InvalidateCompositingState() override;
// CompositorAnimationClient implementation.
CompositorAnimation* GetCompositorAnimation() const override {
return compositor_animation_.get();
}
// CompositorAnimationDelegate implementation.
void NotifyAnimationStarted(base::TimeDelta monotonic_time,
int group) override {}
void NotifyAnimationFinished(base::TimeDelta monotonic_time,
int group) override {}
void NotifyAnimationAborted(base::TimeDelta monotonic_time,
int group) override {}
void NotifyLocalTimeUpdated(
std::optional<base::TimeDelta> local_time) override;
Document* GetDocument() const override { return document_.Get(); }
AnimationTimeline* GetTimeline() const override { return timeline_.Get(); }
const String& Name() { return animator_name_; }
KeyframeEffect* GetEffect() const override;
const WorkletAnimationId& GetWorkletAnimationId() const override {
return id_;
}
bool IsActiveAnimation() const override;
void UpdateInputState(AnimationWorkletDispatcherInput* input_state) override;
void SetOutputState(
const AnimationWorkletOutput::AnimationState& state) override;
void SetRunningOnMainThreadForTesting(bool running_on_main_thread) {
running_on_main_thread_ = running_on_main_thread;
}
void Trace(Visitor*) const override;
void Dispose();
private:
void DestroyCompositorAnimation();
bool IsTimelineActive() const;
std::optional<base::TimeDelta> CurrentTime();
std::optional<base::TimeDelta> CurrentTimeInternal() const;
void UpdateCurrentTimeIfNeeded();
bool IsCurrentTimeInitialized() const;
std::optional<base::TimeDelta> InitialCurrentTime() const;
bool CanStartOnCompositor();
// Attempts to start the animation on the compositor side, returning true if
// it succeeds or false otherwise. If false is returned and the animation
// cannot be started on main.
bool StartOnCompositor();
void StartOnMain();
bool CheckCanStart(String* failure_message);
// Sets the current time for the animation.
//
// Note that the current time of the animation is a computed value that
// depends on either the start time (for playing animations) or the hold time
// (for pending, paused, or idle animations). So this procedure updates either
// the start time or the hold time so that the computed current time is
// matched.
//
// Generally, when an animation play state transitions, we expect to see the
// current time is set. Here are some interesting examples of this:
// - when transitioning to play, the current time is either set to
// zero (first time) or the last current time (when resuming from pause).
// - when transitioning to idle or cancel, the current time is set to
// "null".
// - when transitioning to pause, the current time is set to the last
// current time for holding.
void SetCurrentTime(std::optional<base::TimeDelta> current_time);
// Adjusts start_time_ according to playback rate change to preserve current
// time and avoid the animation output from jumping.
void SetPlaybackRateInternal(double);
// Updates a running animation on the compositor side. Returns false if the
// update is terminated. e.g. the animated target is gone.
bool UpdateOnCompositor();
std::unique_ptr<cc::AnimationOptions> CloneOptions() const {
return options_ ? options_->Clone() : nullptr;
}
std::unique_ptr<cc::AnimationEffectTimings> CloneEffectTimings() const {
return effect_timings_ ? effect_timings_->Clone() : nullptr;
}
V8AnimationPlayState::Enum PlayState() const { return play_state_; }
void SetPlayState(V8AnimationPlayState::Enum state) { play_state_ = state; }
unsigned sequence_number_;
WorkletAnimationId id_;
const String animator_name_;
V8AnimationPlayState::Enum play_state_ = V8AnimationPlayState::Enum::kIdle;
V8AnimationPlayState::Enum last_play_state_ =
V8AnimationPlayState::Enum::kIdle;
// Controls speed of the animation.
// https://drafts.csswg.org/web-animations-2/#animation-effect-playback-rate
double playback_rate_;
std::optional<base::TimeDelta> start_time_;
Vector<std::optional<base::TimeDelta>> local_times_;
// Hold time is used when animation is paused.
// TODO(majidvp): Replace base::TimeDelta usage with AnimationTimeDelta.
std::optional<base::TimeDelta> hold_time_;
// Keeps last set or calculated current time. It's used as a hold time when
// the timeline is inactive.
std::optional<base::TimeDelta> last_current_time_;
// Indicates if the timeline was active when the current time was calculated
// last time.
bool was_timeline_active_;
// We use this to skip updating if current time has not changed since last
// update.
std::optional<base::TimeDelta> last_input_update_current_time_;
Member<Document> document_;
HeapVector<Member<KeyframeEffect>> effects_;
Member<AnimationTimeline> timeline_;
std::unique_ptr<WorkletAnimationOptions> options_;
std::unique_ptr<WorkletAnimationEffectTimings> effect_timings_;
std::unique_ptr<CompositorAnimation> compositor_animation_;
bool running_on_main_thread_;
bool has_started_;
// Tracks whether any KeyframeEffect associated with this WorkletAnimation has
// been invalidated and needs to be restarted. Used to avoid unnecessarily
// restarting the effect on the compositor. When true, a call to
// |UpdateOnCompositor| will update the effect on the compositor.
bool effect_needs_restart_;
FRIEND_TEST_ALL_PREFIXES(WorkletAnimationTest, PausePlay);
FRIEND_TEST_ALL_PREFIXES(WorkletAnimationTest, SetCurrentTimeInfNotCrash);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
|