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

cc / animation / keyframe_model.h [blame]

// Copyright 2012 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_KEYFRAME_MODEL_H_
#define CC_ANIMATION_KEYFRAME_MODEL_H_

#include <memory>
#include <string>

#include "base/check.h"
#include "base/time/time.h"
#include "cc/animation/animation_export.h"
#include "cc/paint/element_id.h"
#include "cc/paint/paint_worklet_input.h"
#include "ui/gfx/animation/keyframe/keyframe_model.h"

namespace cc {

// A KeyframeModel contains all the state required to play an AnimationCurve.
// Specifically, the affected property, the run state (paused, finished, etc.),
// loop count, last pause time, and the total time spent paused.
// It represents a model of the keyframes (internally represented as a curve).
class CC_ANIMATION_EXPORT KeyframeModel : public gfx::KeyframeModel {
 public:
  static const KeyframeModel* ToCcKeyframeModel(
      const gfx::KeyframeModel* keyframe_model);

  static KeyframeModel* ToCcKeyframeModel(gfx::KeyframeModel* keyframe_model);

  static const int kInvalidGroup = -1;

  // Bundles a property id with its name and native type.
  class CC_ANIMATION_EXPORT TargetPropertyId {
   public:
    // For a property that is neither TargetProperty::CSS_CUSTOM_PROPERTY nor
    // TargetProperty::NATIVE_PROPERTY.
    explicit TargetPropertyId(int target_property_type);
    // For TargetProperty::CSS_CUSTOM_PROPERTY, the string is the custom
    // property name.
    TargetPropertyId(int target_property_type,
                     const std::string& custom_property_name);
    // For TargetProperty::NATIVE_PROPERTY.
    TargetPropertyId(
        int target_property_type,
        PaintWorkletInput::NativePropertyType native_property_type);
    TargetPropertyId(const TargetPropertyId&);
    TargetPropertyId(TargetPropertyId&&);
    ~TargetPropertyId();

    TargetPropertyId& operator=(TargetPropertyId&& other);

    int target_property_type() const { return target_property_type_; }
    const std::string& custom_property_name() const {
      return custom_property_name_;
    }
    PaintWorkletInput::NativePropertyType native_property_type() const {
      return native_property_type_;
    }

   private:
    int target_property_type_;
    // Name of the animated custom property. Empty if it is an animated native
    // property.
    std::string custom_property_name_;
    // Type of the animated native property.
    PaintWorkletInput::NativePropertyType native_property_type_;
  };

  static std::unique_ptr<KeyframeModel> Create(
      std::unique_ptr<gfx::AnimationCurve> curve,
      int keyframe_model_id,
      int group_id,
      TargetPropertyId target_property_id);

  std::unique_ptr<KeyframeModel> CreateImplInstance(
      RunState initial_run_state) const;

  KeyframeModel(const KeyframeModel&) = delete;
  ~KeyframeModel() override;

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

  int group() const { return group_; }
  void ungroup() { group_ = kInvalidGroup; }

  int TargetProperty() const override;

  void SetRunState(RunState run_state, base::TimeTicks monotonic_time) override;

  ElementId element_id() const { return element_id_; }
  void set_element_id(ElementId element_id) { element_id_ = element_id; }

  bool InEffect(base::TimeTicks monotonic_time) const;

  // If this is true, even if the keyframe model is running, it will not be
  // tickable until it is given a start time. This is true for KeyframeModels
  // running on the main thread.
  bool needs_synchronized_start_time() const {
    return needs_synchronized_start_time_;
  }
  void set_needs_synchronized_start_time(bool needs_synchronized_start_time) {
    needs_synchronized_start_time_ = needs_synchronized_start_time;
  }

  // This is true for KeyframeModels running on the main thread when the
  // FINISHED event sent by the corresponding impl keyframe model has been
  // received.
  bool received_finished_event() const { return received_finished_event_; }
  void set_received_finished_event(bool received_finished_event) {
    received_finished_event_ = received_finished_event;
  }

  void set_is_controlling_instance_for_test(bool is_controlling_instance) {
    is_controlling_instance_ = is_controlling_instance;
  }
  bool is_controlling_instance() const { return is_controlling_instance_; }

  void PushPropertiesTo(KeyframeModel* other) const;

  std::string ToString() const;

  void SetIsImplOnly();
  bool is_impl_only() const { return is_impl_only_; }

  void set_affects_active_elements(bool affects_active_elements) {
    affects_active_elements_ = affects_active_elements;
  }
  bool affects_active_elements() const { return affects_active_elements_; }

  void set_affects_pending_elements(bool affects_pending_elements) {
    affects_pending_elements_ = affects_pending_elements;
  }
  bool affects_pending_elements() const { return affects_pending_elements_; }

  const std::string& custom_property_name() const {
    return target_property_id_.custom_property_name();
  }

  PaintWorkletInput::NativePropertyType native_property_type() const {
    return target_property_id_.native_property_type();
  }

  bool StartShouldBeDeferred() const override;

 private:
  KeyframeModel(std::unique_ptr<gfx::AnimationCurve> curve,
                int keyframe_model_id,
                int group_id,
                TargetPropertyId target_property_id);
  // KeyframeModels that must be run together are called 'grouped' and have the
  // same group id. Grouped KeyframeModels are guaranteed to start at the same
  // time and no other KeyframeModels may animate any of the group's target
  // properties until all KeyframeModels in the group have finished animating.
  int group_;

  TargetPropertyId target_property_id_;

  // If specified, overrides the ElementId to apply this KeyframeModel's effect
  // value on.
  ElementId element_id_;

#if DCHECK_IS_ON()
  // This id is unique, modulo overflow. Permits quick instance equality checks.
  int debug_id_ = 0;
#endif

  bool needs_synchronized_start_time_;
  bool received_finished_event_;

  // KeyframeModels lead dual lives. An active keyframe model will be
  // conceptually owned by two controllers, one on the impl thread and one on
  // the main. In reality, there will be two separate KeyframeModel instances
  // for the same keyframe model. They will have the same group id and the same
  // target property (these two values uniquely identify a keyframe model). The
  // instance on the impl thread is the instance that ultimately controls the
  // values of the animating layer and so we will refer to it as the
  // 'controlling instance'.
  // Impl only keyframe models are the exception to this rule. They have only a
  // single instance. We consider this instance as the 'controlling instance'.
  bool is_controlling_instance_;

  bool is_impl_only_;

  // When pushed from a main-thread controller to a compositor-thread
  // controller, a keyframe model will initially only affect pending elements
  // (corresponding to layers in the pending tree). KeyframeModels that only
  // affect pending elements are able to reach the STARTING state and tick
  // pending elements, but cannot proceed any further and do not tick active
  // elements. After activation, such KeyframeModels affect both kinds of
  // elements and are able to proceed past the STARTING state. When the removal
  // of a keyframe model is pushed from a main-thread controller to a
  // compositor-thread controller, this initially only makes the keyframe model
  // stop affecting pending elements. After activation, such KeyframeModels no
  // longer affect any elements, and are deleted.
  bool affects_active_elements_;
  bool affects_pending_elements_;
};

}  // namespace cc

#endif  // CC_ANIMATION_KEYFRAME_MODEL_H_