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

cc / animation / animation.h [blame]

// Copyright 2015 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_ANIMATION_H_
#define CC_ANIMATION_ANIMATION_H_

#include <memory>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "cc/animation/animation_export.h"
#include "cc/animation/element_animations.h"
#include "cc/animation/keyframe_model.h"
#include "cc/base/protected_sequence_synchronizer.h"
#include "cc/paint/element_id.h"
#include "ui/gfx/animation/keyframe/animation_curve.h"

namespace cc {

class AnimationDelegate;
class AnimationEvents;
class AnimationHost;
class AnimationTimeline;
class KeyframeEffect;
struct AnimationEvent;

// An Animation is responsible for managing animating properties for a set of
// targets. Each target is represented by a KeyframeEffect and can be animating
// multiple properties on that target; see the KeyframeEffect class.
//
// A particular Animation may not own all the KeyframeEffects for a given
// target. Animation is only a grouping mechanism for related effects, and the
// grouping relationship is defined by the client. It is also the client's
// responsibility to deal with any conflicts that arise from animating the same
// property of the same target across multiple Animations.
//
// Each Animation has a copy on the impl thread, and will take care of
// synchronizing to/from the impl thread when requested.
//
// There is a 1:1 relationship between Animation and KeyframeEffect.
class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation>,
                                      public ProtectedSequenceSynchronizer {
 public:
  static scoped_refptr<Animation> Create(int id);
  virtual scoped_refptr<Animation> CreateImplInstance() const;

  Animation(const Animation&) = delete;
  Animation& operator=(const Animation&) = delete;

  int id() const { return id_; }
  ElementId element_id() const;

  KeyframeEffect* keyframe_effect() {
    return keyframe_effect_.Write(*this).get();
  }

  const KeyframeEffect* keyframe_effect() const {
    return keyframe_effect_.Read(*this);
  }

  // Parent AnimationHost. Animation can be detached from AnimationTimeline.
  AnimationHost* animation_host() {
    DCHECK(IsOwnerThread() || InProtectedSequence());
    return animation_host_;
  }
  const AnimationHost* animation_host() const {
    DCHECK(IsOwnerThread() || InProtectedSequence());
    return animation_host_;
  }
  void SetAnimationHost(AnimationHost* animation_host);
  bool has_animation_host() const { return !!animation_host(); }

  // Parent AnimationTimeline.
  AnimationTimeline* animation_timeline() {
    return animation_timeline_.Read(*this);
  }
  const AnimationTimeline* animation_timeline() const {
    return animation_timeline_.Read(*this);
  }
  void SetAnimationTimeline(AnimationTimeline* timeline);

  scoped_refptr<const ElementAnimations> element_animations() const;

  void set_animation_delegate(AnimationDelegate* delegate) {
    animation_delegate_ = delegate;
  }

  void AttachElement(ElementId element_id);
  void AttachPaintWorkletElement();
  void DetachElement();

  void AddKeyframeModel(std::unique_ptr<KeyframeModel> keyframe_model);
  void PauseKeyframeModel(int keyframe_model_id, base::TimeDelta time_offset);
  virtual void RemoveKeyframeModel(int keyframe_model_id);
  void AbortKeyframeModel(int keyframe_model_id);

  void NotifyKeyframeModelFinishedForTesting(
      int timeline_id,
      int keyframe_model_id,
      TargetProperty::Type target_property,
      int group_id);

  void AbortKeyframeModelsWithProperty(TargetProperty::Type target_property,
                                       bool needs_completion);

  virtual void PushPropertiesTo(Animation* animation_impl);

  virtual void UpdateState(bool start_ready_keyframe_models,
                           AnimationEvents* events);
  // Adds TIME_UPDATED event generated in the current frame to the given
  // animation events.
  virtual void TakeTimeUpdatedEvent(AnimationEvents* events) {}
  virtual bool Tick(base::TimeTicks tick_time);
  bool IsScrollLinkedAnimation() const;

  void AddToTicking();
  void RemoveFromTicking();

  // Dispatches animation event to the animation keyframe effect and model when
  // appropriate, based on the event characteristics.
  // Delegates animation event that was successfully dispatched or doesn't need
  // to be dispatched.
  void DispatchAndDelegateAnimationEvent(const AnimationEvent& event);

  // Returns true if this animation effects pending tree, such as a custom
  // property animation with paint worklet.
  bool RequiresInvalidation() const;
  // Returns true if this animation effects active tree, such as a transform
  // animation.
  bool AffectsNativeProperty() const;

  void SetNeedsPushProperties();

  // Make KeyframeModels affect active elements if and only if they affect
  // pending elements. Any KeyframeModels that no longer affect any elements
  // are deleted.
  void ActivateKeyframeModels();

  // Returns the keyframe model animating the given property that is either
  // running, or is next to run, if such a keyframe model exists.
  KeyframeModel* GetKeyframeModel(TargetProperty::Type target_property) const;

  std::string ToString() const;

  void SetNeedsCommit();

  void set_is_replacement() { is_replacement_ = true; }

  std::optional<base::TimeTicks> GetStartTime() const;

  virtual bool IsWorkletAnimation() const;

  void SetKeyframeEffectForTesting(std::unique_ptr<KeyframeEffect>);

  // ProtectedSequenceSynchronizer implementation
  bool IsOwnerThread() const override;
  bool InProtectedSequence() const override;
  void WaitForProtectedSequenceCompletion() const override;

 private:
  friend class base::RefCounted<Animation>;

  void RegisterAnimation();
  void UnregisterAnimation();

  // Delegates animation event
  void DelegateAnimationEvent(const AnimationEvent& event);

  // Common code between AttachElement and AttachNoElement.
  void AttachElementInternal(ElementId element_id);

 protected:
  explicit Animation(int id);
  ~Animation() override;

  raw_ptr<AnimationDelegate> animation_delegate_ = nullptr;

  const int id_;

 private:
  // If this Animation was created to replace an existing one of the same id,
  // it should take the start time from the impl instance before replacing it,
  // since the start time may not yet have been committed back to the client at
  // the time the animation was restarted. The client sets this bit to true
  // when such an animation is created so that the first commit pulls the start
  // time into this Animation before pushing it.
  //
  // When this animation is pushed to the impl thread, it will update the
  // existing Animation and KeyframeEffect rather than creating new ones. It
  // will silently replace the effect's keyframe models with the new ones
  // specified in this animation.
  //
  // Used only from the main thread and isn't synced to the compositor thread.
  bool is_replacement_ = false;

  // Animation's ProtectedSequenceSynchronizer implementation is implemented
  // using this member. As such the various helpers can not be used to protect
  // access (otherwise we would get infinite recursion).
  raw_ptr<AnimationHost> animation_host_ = nullptr;
  ProtectedSequenceReadable<raw_ptr<AnimationTimeline>> animation_timeline_{
      nullptr};
  ProtectedSequenceWritable<std::unique_ptr<KeyframeEffect>> keyframe_effect_;
};

}  // namespace cc

#endif  // CC_ANIMATION_ANIMATION_H_