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 214 215 216 217 218 219 220 221 222 223 224 225 226
|
/* -*- 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;
using AnimationArray = nsTArray<layers::Animation>;
using SampledAnimationArray = AutoTArray<RefPtr<StyleAnimationValue>, 1>;
struct AnimationTransform {
/*
* This transform is calculated from frame used for WebRender and used by
* getOMTAStyle() for OMTA testing.
*/
gfx::Matrix4x4 mFrameTransform;
TransformData mData;
/*
* Store the previous sampled transform-like animation values.
* It's unfortunate we have to keep the previous sampled animation value for
* replacing the running transition, because we can not re-create the
* AnimationValues from the matrix.
* Note: We expect the length is one in most cases.
*/
SampledAnimationArray mAnimationValues;
};
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& aFrameTransform,
const TransformData& aData, SampledAnimationArray&& aValue)
: mValue(AsVariant(
AnimationTransform{aFrameTransform, aData, std::move(aValue)})) {}
explicit AnimatedValue(const float& aValue) : mValue(AsVariant(aValue)) {}
explicit AnimatedValue(nscolor aValue) : mValue(AsVariant(aValue)) {}
// Note: Only transforms need to store the sampled AnimationValue because it's
// impossible to re-create the AnimationValue from the matrix.
void SetTransform(const gfx::Matrix4x4& aFrameTransform,
const TransformData& aData,
SampledAnimationArray&& aValue) {
MOZ_ASSERT(mValue.is<AnimationTransform>());
AnimationTransform& previous = mValue.as<AnimationTransform>();
previous.mFrameTransform = aFrameTransform;
if (previous.mData != aData) {
previous.mData = aData;
}
previous.mAnimationValues = std::move(aValue);
}
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;
}
already_AddRefed<StyleAnimationValue> AsAnimationValue(
NonCustomCSSPropertyId) const;
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,
const TimeStamp& aPreviousSampleTime);
/**
* 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);
/**
* Return the animated value if a given id can map to its animated value
*/
AnimatedValue* GetAnimatedValue(const uint64_t& aId) const;
private:
~CompositorAnimationStorage() = default;
/**
* 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,
SampledAnimationArray&& aValue);
/**
* 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(
NonCustomCSSPropertyId aProperty, uint64_t aId,
const std::unique_ptr<AnimationStorageData>& aAnimationStorageData,
SampledAnimationArray&& 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
|