summaryrefslogtreecommitdiffstats
path: root/gfx/layers/CompositorAnimationStorage.h
blob: 7d6b7dc3a7a7150d72e7fc3bb9678a0edf21bb02 (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
211
212
213
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_layers_CompositorAnimationStorage_h
#define mozilla_layers_CompositorAnimationStorage_h

#include "mozilla/layers/AnimationStorageData.h"
#include "mozilla/layers/LayersMessages.h"  // for TransformData, etc
#include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/Variant.h"
#include "nsClassHashtable.h"
#include "X11UndefineNone.h"
#include <memory>
#include <unordered_map>
#include <unordered_set>

namespace mozilla {
namespace layers {
class APZSampler;
class Animation;
class CompositorBridgeParent;
class OMTAController;

typedef nsTArray<layers::Animation> AnimationArray;

struct AnimationTransform {
  /*
   * This transform is calculated from sampleanimation in device pixel
   * and used for layers (i.e. non WebRender)
   */
  gfx::Matrix4x4 mTransformInDevSpace;
  /*
   * This transform is calculated from frame used for WebRender and used by
   * getOMTAStyle() for OMTA testing.
   */
  gfx::Matrix4x4 mFrameTransform;
  TransformData mData;
};

struct AnimatedValue final {
  typedef Variant<AnimationTransform, float, nscolor> AnimatedValueType;

  const AnimatedValueType& Value() const { return mValue; }
  const AnimationTransform& Transform() const {
    return mValue.as<AnimationTransform>();
  }
  const float& Opacity() const { return mValue.as<float>(); }
  const nscolor& Color() const { return mValue.as<nscolor>(); }
  template <typename T>
  bool Is() const {
    return mValue.is<T>();
  }

  AnimatedValue(const gfx::Matrix4x4& aTransformInDevSpace,
                const gfx::Matrix4x4& aFrameTransform,
                const TransformData& aData)
      : mValue(AsVariant(AnimationTransform{aTransformInDevSpace,
                                            aFrameTransform, aData})) {}

  explicit AnimatedValue(const float& aValue) : mValue(AsVariant(aValue)) {}

  explicit AnimatedValue(nscolor aValue) : mValue(AsVariant(aValue)) {}

  void SetTransform(const gfx::Matrix4x4& aFrameTransform,
                    const TransformData& aData) {
    MOZ_ASSERT(mValue.is<AnimationTransform>());
    AnimationTransform& previous = mValue.as<AnimationTransform>();
    previous.mFrameTransform = aFrameTransform;
    if (previous.mData != aData) {
      previous.mData = aData;
    }
  }
  void SetOpacity(float aOpacity) {
    MOZ_ASSERT(mValue.is<float>());
    mValue.as<float>() = aOpacity;
  }
  void SetColor(nscolor aColor) {
    MOZ_ASSERT(mValue.is<nscolor>());
    mValue.as<nscolor>() = aColor;
  }

 private:
  AnimatedValueType mValue;
};

struct WrAnimations {
  nsTArray<wr::WrOpacityProperty> mOpacityArrays;
  nsTArray<wr::WrTransformProperty> mTransformArrays;
  nsTArray<wr::WrColorProperty> mColorArrays;
};

// CompositorAnimationStorage stores the animations and animated values
// keyed by a CompositorAnimationsId. The "animations" are a representation of
// an entire animation over time, while the "animated values" are values sampled
// from the animations at a particular point in time.
//
// There is one CompositorAnimationStorage per CompositorBridgeParent (i.e.
// one per browser window), and the CompositorAnimationsId key is unique within
// a particular CompositorAnimationStorage instance.
//
// Each layer which has animations gets a CompositorAnimationsId key, and reuses
// that key during its lifetime. Likewise, in layers-free webrender, a display
// item that is animated (e.g. nsDisplayTransform) gets a CompositorAnimationsId
// key and reuses that key (it persists the key via the frame user-data
// mechanism).
class CompositorAnimationStorage final {
  typedef nsClassHashtable<nsUint64HashKey, AnimatedValue> AnimatedValueTable;
  typedef std::unordered_map<uint64_t, std::unique_ptr<AnimationStorageData>>
      AnimationsTable;

  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorAnimationStorage)
 public:
  explicit CompositorAnimationStorage(CompositorBridgeParent* aCompositorBridge)
      : mLock("CompositorAnimationStorage::mLock"),
        mCompositorBridge(aCompositorBridge) {}

  OMTAValue GetOMTAValue(const uint64_t& aId) const;

  /**
   * Collect all animations in this class as WebRender type properties.
   */
  WrAnimations CollectWebRenderAnimations() const;

  /**
   * Set the animations based on the unique id
   */
  void SetAnimations(uint64_t aId, const LayersId& aLayersId,
                     const AnimationArray& aAnimations);

  /**
   * Sample animation based the given timestamps and store them in this
   * CompositorAnimationStorage. The animated values after sampling will be
   * stored in CompositorAnimationStorage as well.
   *
   * Returns true if there is any animation.
   * Note that even if there are only in-delay phase animations (i.e. not
   * visually effective), this function returns true to ensure we composite
   * again on the next tick.
   *
   * Note: This is called only by WebRender.
   */
  bool SampleAnimations(const OMTAController* aOMTAController,
                        TimeStamp aPreviousFrameTime,
                        TimeStamp aCurrentFrameTime);

  bool HasAnimations() const;

  /**
   * Clear AnimatedValues and Animations data
   */
  void ClearById(const uint64_t& aId);

 private:
  ~CompositorAnimationStorage() = default;

  /**
   * Return the animated value if a given id can map to its animated value
   */
  AnimatedValue* GetAnimatedValue(const uint64_t& aId) const;

  /**
   * Set the animation transform based on the unique id and also
   * set up |aFrameTransform| and |aData| for OMTA testing.
   * If |aPreviousValue| is not null, the animation transform replaces the value
   * in the |aPreviousValue|.
   * NOTE: |aPreviousValue| should be the value for the |aId|.
   */
  void SetAnimatedValue(uint64_t aId, AnimatedValue* aPreviousValue,
                        const gfx::Matrix4x4& aFrameTransform,
                        const TransformData& aData);

  /**
   * Similar to above but for opacity.
   */
  void SetAnimatedValue(uint64_t aId, AnimatedValue* aPreviousValue,
                        float aOpacity);

  /**
   * Similar to above but for color.
   */
  void SetAnimatedValue(uint64_t aId, AnimatedValue* aPreviousValue,
                        nscolor aColor);

  using JankedAnimationMap =
      std::unordered_map<LayersId, nsTArray<uint64_t>, LayersId::HashFn>;

  /*
   * Store the animated values from |aAnimationValues|.
   */
  void StoreAnimatedValue(
      nsCSSPropertyID aProperty, uint64_t aId,
      const std::unique_ptr<AnimationStorageData>& aAnimationStorageData,
      const AutoTArray<RefPtr<StyleAnimationValue>, 1>& aAnimationValues,
      const MutexAutoLock& aProofOfMapLock,
      const RefPtr<APZSampler>& aApzSampler, AnimatedValue* aAnimatedValueEntry,
      JankedAnimationMap& aJankedAnimationMap);

 private:
  AnimatedValueTable mAnimatedValues;
  AnimationsTable mAnimations;
  std::unordered_set<uint64_t> mNewAnimations;
  mutable Mutex mLock MOZ_UNANNOTATED;
  // CompositorBridgeParent owns this CompositorAnimationStorage instance.
  CompositorBridgeParent* MOZ_NON_OWNING_REF mCompositorBridge;
};

}  // namespace layers
}  // namespace mozilla

#endif  // mozilla_layers_CompositorAnimationStorage_h