summaryrefslogtreecommitdiffstats
path: root/chromium/cc/animation/keyframe_effect.h
blob: e4b002926022769f51f09ef4393775c4e678e1ad (plain)
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
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_ANIMATION_KEYFRAME_EFFECT_H_
#define CC_ANIMATION_KEYFRAME_EFFECT_H_

#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "cc/animation/animation_events.h"
#include "cc/animation/animation_export.h"
#include "cc/animation/element_animations.h"
#include "cc/paint/element_id.h"
#include "cc/trees/mutator_host_client.h"
#include "cc/trees/target_property.h"
#include "ui/gfx/geometry/box_f.h"
#include "ui/gfx/geometry/scroll_offset.h"

#include <memory>
#include <vector>

namespace cc {

class Animation;
struct PropertyAnimationState;

typedef size_t KeyframeEffectId;

// A KeyframeEffect owns a group of KeyframeModels for a single target
// (identified by an ElementId). It is responsible for managing the
// KeyframeModels' running states (starting, running, paused, etc), as well as
// ticking the KeyframeModels when it is requested to produce new outputs for a
// given time.
//
// Note that a single KeyframeEffect may not own all the KeyframeModels for a
// given target. KeyframeEffect is only a grouping mechanism for related
// KeyframeModels. The commonality between keyframe models on the same target
// is found via ElementAnimations - there is only one ElementAnimations for a
// given target.
class CC_ANIMATION_EXPORT KeyframeEffect {
 public:
  explicit KeyframeEffect(KeyframeEffectId id);
  KeyframeEffect(const KeyframeEffect&) = delete;
  virtual ~KeyframeEffect();

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

  static std::unique_ptr<KeyframeEffect> Create(KeyframeEffectId id);
  std::unique_ptr<KeyframeEffect> CreateImplInstance() const;

  // ElementAnimations object where this controller is listed.
  scoped_refptr<ElementAnimations> element_animations() const {
    return element_animations_;
  }

  bool has_bound_element_animations() const { return !!element_animations_; }

  bool has_attached_element() const { return !!element_id_; }

  ElementId element_id() const { return element_id_; }

  // Returns true if there are any KeyframeModels at all to process.
  bool has_any_keyframe_model() const { return !keyframe_models_.empty(); }

  // When a scroll animation is removed on the main thread, its compositor
  // thread counterpart continues producing scroll deltas until activation.
  // These scroll deltas need to be cleared at activation, so that the active
  // element's scroll offset matches the offset provided by the main thread
  // rather than a combination of this offset and scroll deltas produced by the
  // removed animation. This is to provide the illusion of synchronicity to JS
  // that simultaneously removes an animation and sets the scroll offset.
  bool scroll_offset_animation_was_interrupted() const {
    return scroll_offset_animation_was_interrupted_;
  }

  bool needs_push_properties() const { return needs_push_properties_; }
  void SetNeedsPushProperties();

  void BindElementAnimations(ElementAnimations* element_animations);
  void UnbindElementAnimations();

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

  virtual void Tick(base::TimeTicks monotonic_time);
  static void TickKeyframeModel(base::TimeTicks monotonic_time,
                                KeyframeModel* keyframe_model,
                                AnimationTarget* target);
  void RemoveFromTicking();
  bool is_ticking() const { return is_ticking_; }

  void UpdateState(bool start_ready_keyframe_models, AnimationEvents* events);
  void UpdateTickingState();

  void Pause(base::TimeDelta pause_offset);

  void AddKeyframeModel(std::unique_ptr<KeyframeModel> keyframe_model);
  void PauseKeyframeModel(int keyframe_model_id, double time_offset);
  void RemoveKeyframeModel(int keyframe_model_id);
  void AbortKeyframeModel(int keyframe_model_id);
  void AbortKeyframeModelsWithProperty(TargetProperty::Type target_property,
                                       bool needs_completion);

  void ActivateKeyframeEffects();

  void KeyframeModelAdded();

  // The following methods should be called to notify the KeyframeEffect that
  // an animation event has been received for the same target (ElementId) as
  // this keyframe_effect. If the event matches a KeyframeModel owned by this
  // KeyframeEffect the call will return true, else it will return false.
  bool NotifyKeyframeModelStarted(const AnimationEvent& event);
  bool NotifyKeyframeModelFinished(const AnimationEvent& event);
  void NotifyKeyframeModelTakeover(const AnimationEvent& event);
  bool NotifyKeyframeModelAborted(const AnimationEvent& event);

  // Returns true if there are any KeyframeModels that have neither finished
  // nor aborted.
  bool HasTickingKeyframeModel() const;
  size_t TickingKeyframeModelsCount() const;

  bool HasNonDeletedKeyframeModel() const;

  bool AnimationsPreserveAxisAlignment() const;

  // Gets scales transform animations. On return, |maximum_scale| is the maximum
  // scale along any dimension at any destination in active scale animations,
  // and |starting_scale| is the maximum of starting animation scale along any
  // dimension at any destination in active scale animations. They are set to
  // kNotScaled if there is no active scale animation or the scales cannot be
  // computed. Returns false if the scales cannot be computed.
  bool GetAnimationScales(ElementListType,
                          float* maximum_scale,
                          float* starting_scale) const;

  // Returns true if there is a keyframe_model that is either currently
  // animating the given property or scheduled to animate this property in the
  // future, and that affects the given tree type.
  bool IsPotentiallyAnimatingProperty(TargetProperty::Type target_property,
                                      ElementListType list_type) const;

  // Returns true if there is a keyframe_model that is currently animating the
  // given property and that affects the given tree type.
  bool IsCurrentlyAnimatingProperty(TargetProperty::Type target_property,
                                    ElementListType list_type) const;

  KeyframeModel* GetKeyframeModel(TargetProperty::Type target_property) const;
  KeyframeModel* GetKeyframeModelById(int keyframe_model_id) const;

  void GetPropertyAnimationState(PropertyAnimationState* pending_state,
                                 PropertyAnimationState* active_state) const;

  void MarkAbortedKeyframeModelsForDeletion(
      KeyframeEffect* element_keyframe_effect_impl);
  void PurgeKeyframeModelsMarkedForDeletion(bool impl_only);
  void PushNewKeyframeModelsToImplThread(
      KeyframeEffect* element_keyframe_effect_impl) const;
  void RemoveKeyframeModelsCompletedOnMainThread(
      KeyframeEffect* element_keyframe_effect_impl) const;
  void PushPropertiesTo(KeyframeEffect* keyframe_effect_impl);

  void SetAnimation(Animation* animation);

  std::string KeyframeModelsToString() const;
  KeyframeEffectId id() const { return id_; }

 private:
  void StartKeyframeModels(base::TimeTicks monotonic_time);
  void PromoteStartedKeyframeModels(AnimationEvents* events);
  void PurgeDeletedKeyframeModels();

  void MarkKeyframeModelsForDeletion(base::TimeTicks, AnimationEvents* events);
  void MarkFinishedKeyframeModels(base::TimeTicks monotonic_time);

  bool HasElementInActiveList() const;
  gfx::ScrollOffset ScrollOffsetForAnimation() const;
  void GenerateEvent(AnimationEvents* events,
                     const KeyframeModel& keyframe_model,
                     AnimationEvent::Type type,
                     base::TimeTicks monotonic_time);
  void GenerateTakeoverEventForScrollAnimation(
      AnimationEvents* events,
      const KeyframeModel& keyframe_model,
      base::TimeTicks monotonic_time);

  std::vector<std::unique_ptr<KeyframeModel>> keyframe_models_;
  Animation* animation_;

  KeyframeEffectId id_;
  ElementId element_id_;

  // element_animations_ is non-null if controller is attached to an element.
  scoped_refptr<ElementAnimations> element_animations_;

  // Only try to start KeyframeModels when new keyframe models are added or
  // when the previous attempt at starting KeyframeModels failed to start all
  // KeyframeModels.
  bool needs_to_start_keyframe_models_;

  bool scroll_offset_animation_was_interrupted_;

  bool is_ticking_;
  base::TimeTicks last_tick_time_;

  bool needs_push_properties_;
};

}  // namespace cc

#endif  // CC_ANIMATION_KEYFRAME_EFFECT_H_