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
|
// 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_
|