File: worklet_animation.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (255 lines) | stat: -rw-r--r-- 11,049 bytes parent folder | download | duplicates (6)
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_