2017-01-25 05:51:30 +03:00
|
|
|
/* -*- 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_AnimationHelper_h
|
|
|
|
#define mozilla_layers_AnimationHelper_h
|
|
|
|
|
2018-04-24 03:27:54 +03:00
|
|
|
#include "mozilla/dom/Nullable.h"
|
2017-01-25 05:51:30 +03:00
|
|
|
#include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction
|
2017-02-10 01:30:11 +03:00
|
|
|
#include "mozilla/layers/LayersMessages.h" // for TransformData, etc
|
2017-01-25 05:51:30 +03:00
|
|
|
#include "mozilla/TimeStamp.h" // for TimeStamp
|
2018-04-24 03:27:53 +03:00
|
|
|
#include "mozilla/TimingParams.h"
|
2018-04-24 03:27:54 +03:00
|
|
|
#include "X11UndefineNone.h"
|
2017-01-25 05:51:30 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
2017-09-21 12:01:48 +03:00
|
|
|
struct AnimationValue;
|
2017-01-25 05:51:30 +03:00
|
|
|
namespace layers {
|
|
|
|
class Animation;
|
|
|
|
|
|
|
|
typedef InfallibleTArray<layers::Animation> AnimationArray;
|
|
|
|
|
|
|
|
struct AnimData {
|
2018-04-19 07:50:14 +03:00
|
|
|
InfallibleTArray<RefPtr<RawServoAnimationValue>> mStartValues;
|
|
|
|
InfallibleTArray<RefPtr<RawServoAnimationValue>> mEndValues;
|
2017-01-25 05:51:30 +03:00
|
|
|
InfallibleTArray<Maybe<mozilla::ComputedTimingFunction>> mFunctions;
|
2018-04-24 03:27:53 +03:00
|
|
|
TimingParams mTiming;
|
2018-04-24 03:27:54 +03:00
|
|
|
// These two variables correspond to the variables of the same name in
|
|
|
|
// KeyframeEffectReadOnly and are used for the same purpose: to skip composing
|
|
|
|
// animations whose progress has not changed.
|
|
|
|
dom::Nullable<double> mProgressOnLastCompose;
|
|
|
|
uint64_t mCurrentIterationOnLastCompose = 0;
|
|
|
|
// These two variables are used for a similar optimization above but are
|
|
|
|
// applied to the timing function in each keyframe.
|
|
|
|
uint32_t mSegmentIndexOnLastCompose = 0;
|
|
|
|
dom::Nullable<double> mPortionInSegmentOnLastCompose;
|
2017-01-25 05:51:30 +03:00
|
|
|
};
|
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
struct AnimationTransform {
|
|
|
|
/*
|
|
|
|
* This transform is calculated from sampleanimation in device pixel
|
|
|
|
* and used by compositor.
|
|
|
|
*/
|
|
|
|
gfx::Matrix4x4 mTransformInDevSpace;
|
|
|
|
/*
|
|
|
|
* This transform is calculated from frame and used by getOMTAStyle()
|
|
|
|
* for OMTA testing.
|
|
|
|
*/
|
|
|
|
gfx::Matrix4x4 mFrameTransform;
|
|
|
|
TransformData mData;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AnimatedValue {
|
|
|
|
enum {
|
|
|
|
TRANSFORM,
|
|
|
|
OPACITY,
|
|
|
|
NONE
|
|
|
|
} mType {NONE};
|
|
|
|
|
|
|
|
union {
|
|
|
|
AnimationTransform mTransform;
|
|
|
|
float mOpacity;
|
|
|
|
};
|
|
|
|
|
|
|
|
AnimatedValue(gfx::Matrix4x4&& aTransformInDevSpace,
|
|
|
|
gfx::Matrix4x4&& aFrameTransform,
|
|
|
|
const TransformData& aData)
|
|
|
|
: mType(AnimatedValue::TRANSFORM)
|
|
|
|
{
|
2018-05-30 22:15:35 +03:00
|
|
|
mTransform.mTransformInDevSpace = std::move(aTransformInDevSpace);
|
|
|
|
mTransform.mFrameTransform = std::move(aFrameTransform);
|
2017-02-10 01:30:11 +03:00
|
|
|
mTransform.mData = aData;
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit AnimatedValue(const float& aValue)
|
|
|
|
: mType(AnimatedValue::OPACITY)
|
|
|
|
, mOpacity(aValue)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~AnimatedValue() {}
|
|
|
|
|
|
|
|
private:
|
|
|
|
AnimatedValue() = delete;
|
|
|
|
};
|
|
|
|
|
2017-09-22 23:39:53 +03:00
|
|
|
// 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).
|
2017-02-10 01:30:11 +03:00
|
|
|
class CompositorAnimationStorage final
|
2017-01-25 05:51:30 +03:00
|
|
|
{
|
2017-02-10 01:30:11 +03:00
|
|
|
typedef nsClassHashtable<nsUint64HashKey, AnimatedValue> AnimatedValueTable;
|
|
|
|
typedef nsClassHashtable<nsUint64HashKey, AnimationArray> AnimationsTable;
|
|
|
|
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorAnimationStorage)
|
2017-01-25 05:51:30 +03:00
|
|
|
public:
|
2017-01-26 10:04:16 +03:00
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
/**
|
2017-04-25 06:52:44 +03:00
|
|
|
* Set the animation transform based on the unique id and also
|
|
|
|
* set up |aFrameTransform| and |aData| for OMTA testing
|
2017-02-10 01:30:11 +03:00
|
|
|
*/
|
|
|
|
void SetAnimatedValue(uint64_t aId,
|
|
|
|
gfx::Matrix4x4&& aTransformInDevSpace,
|
|
|
|
gfx::Matrix4x4&& aFrameTransform,
|
|
|
|
const TransformData& aData);
|
|
|
|
|
2017-04-25 06:52:44 +03:00
|
|
|
/**
|
|
|
|
* Set the animation transform in device pixel based on the unique id
|
|
|
|
*/
|
|
|
|
void SetAnimatedValue(uint64_t aId,
|
|
|
|
gfx::Matrix4x4&& aTransformInDevSpace);
|
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
/**
|
|
|
|
* Set the animation opacity based on the unique id
|
|
|
|
*/
|
|
|
|
void SetAnimatedValue(uint64_t aId, const float& aOpacity);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the animated value if a given id can map to its animated value
|
|
|
|
*/
|
|
|
|
AnimatedValue* GetAnimatedValue(const uint64_t& aId) const;
|
|
|
|
|
2018-07-31 00:13:15 +03:00
|
|
|
OMTAValue GetOMTAValue(const uint64_t& aId) const;
|
|
|
|
|
2017-04-12 11:40:48 +03:00
|
|
|
/**
|
|
|
|
* Return the iterator of animated value table
|
|
|
|
*/
|
|
|
|
AnimatedValueTable::Iterator ConstAnimatedValueTableIter() const
|
|
|
|
{
|
|
|
|
return mAnimatedValues.ConstIter();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t AnimatedValueCount() const
|
|
|
|
{
|
|
|
|
return mAnimatedValues.Count();
|
|
|
|
}
|
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
/**
|
|
|
|
* Set the animations based on the unique id
|
|
|
|
*/
|
|
|
|
void SetAnimations(uint64_t aId, const AnimationArray& aAnimations);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the animations if a given id can map to its animations
|
|
|
|
*/
|
|
|
|
AnimationArray* GetAnimations(const uint64_t& aId) const;
|
|
|
|
|
2017-04-12 11:40:48 +03:00
|
|
|
/**
|
|
|
|
* Return the iterator of animations table
|
|
|
|
*/
|
|
|
|
AnimationsTable::Iterator ConstAnimationsTableIter() const
|
|
|
|
{
|
|
|
|
return mAnimations.ConstIter();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t AnimationsCount() const
|
|
|
|
{
|
|
|
|
return mAnimations.Count();
|
|
|
|
}
|
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
/**
|
|
|
|
* Clear AnimatedValues and Animations data
|
|
|
|
*/
|
|
|
|
void Clear();
|
2017-04-12 11:40:48 +03:00
|
|
|
void ClearById(const uint64_t& aId);
|
2017-09-22 23:39:53 +03:00
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
private:
|
2017-07-06 06:06:41 +03:00
|
|
|
~CompositorAnimationStorage() { };
|
2017-02-10 01:30:11 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
AnimatedValueTable mAnimatedValues;
|
|
|
|
AnimationsTable mAnimations;
|
|
|
|
};
|
|
|
|
|
2017-09-22 23:39:53 +03:00
|
|
|
/**
|
|
|
|
* This utility class allows reusing code between the webrender and
|
|
|
|
* non-webrender compositor-side implementations. It provides
|
|
|
|
* utility functions for sampling animations at particular timestamps.
|
|
|
|
*/
|
2017-02-10 01:30:11 +03:00
|
|
|
class AnimationHelper
|
|
|
|
{
|
|
|
|
public:
|
2017-04-12 11:40:48 +03:00
|
|
|
|
2018-04-24 03:27:54 +03:00
|
|
|
enum class SampleResult {
|
|
|
|
None,
|
|
|
|
Skipped,
|
|
|
|
Sampled
|
|
|
|
};
|
|
|
|
|
2017-09-22 23:39:53 +03:00
|
|
|
/**
|
2017-04-12 11:40:48 +03:00
|
|
|
* Sample animations based on a given time stamp for a element(layer) with
|
|
|
|
* its animation data.
|
2018-05-08 06:58:42 +03:00
|
|
|
* Generally |aPreviousFrameTimeStamp| is used for the sampling if it's
|
|
|
|
* supplied to make the animation more in sync with other animations on the
|
2018-05-08 10:58:06 +03:00
|
|
|
* main-thread. But in the case where the animation just started at the time
|
|
|
|
* when the animation was sent to the compositor, |aCurrentTime| is used for
|
|
|
|
* the sampling instead to avoid flickering the animation.
|
2018-04-24 03:27:54 +03:00
|
|
|
*
|
|
|
|
* Returns SampleResult::None if none of the animations are producing a result
|
|
|
|
* (e.g. they are in the delay phase with no backwards fill),
|
|
|
|
* SampleResult::Skipped if the animation output did not change since the last
|
|
|
|
* call of this function,
|
|
|
|
* SampleResult::Sampled if the animation output was updated.
|
2017-04-12 11:40:48 +03:00
|
|
|
*/
|
2018-04-24 03:27:54 +03:00
|
|
|
static SampleResult
|
2018-05-08 06:58:42 +03:00
|
|
|
SampleAnimationForEachNode(TimeStamp aPreviousFrameTime,
|
|
|
|
TimeStamp aCurrentFrameTime,
|
2017-01-26 10:04:16 +03:00
|
|
|
AnimationArray& aAnimations,
|
|
|
|
InfallibleTArray<AnimData>& aAnimationData,
|
2018-05-08 10:58:06 +03:00
|
|
|
RefPtr<RawServoAnimationValue>& aAnimationValue,
|
|
|
|
const AnimatedValue* aPreviousValue);
|
2017-09-22 23:39:53 +03:00
|
|
|
/**
|
|
|
|
* Populates AnimData stuctures into |aAnimData| and |aBaseAnimationStyle|
|
|
|
|
* based on |aAnimations|.
|
2017-04-12 11:40:48 +03:00
|
|
|
*/
|
2017-01-25 05:51:30 +03:00
|
|
|
static void
|
|
|
|
SetAnimations(AnimationArray& aAnimations,
|
|
|
|
InfallibleTArray<AnimData>& aAnimData,
|
2018-04-19 07:50:14 +03:00
|
|
|
RefPtr<RawServoAnimationValue>& aBaseAnimationStyle);
|
2017-04-12 11:40:48 +03:00
|
|
|
|
2017-09-22 23:39:53 +03:00
|
|
|
/**
|
2017-04-12 11:40:48 +03:00
|
|
|
* Get a unique id to represent the compositor animation between child
|
|
|
|
* and parent side. This id will be used as a key to store animation
|
|
|
|
* data in the CompositorAnimationStorage per compositor.
|
|
|
|
* Each layer on the content side calls this when it gets new animation
|
|
|
|
* data.
|
|
|
|
*/
|
2017-02-08 22:31:45 +03:00
|
|
|
static uint64_t GetNextCompositorAnimationsId();
|
2017-04-12 11:40:48 +03:00
|
|
|
|
2017-09-22 23:39:53 +03:00
|
|
|
/**
|
2017-04-12 11:40:48 +03:00
|
|
|
* Sample animation based a given time stamp |aTime| and the animation
|
|
|
|
* data inside CompositorAnimationStorage |aStorage|. The animated values
|
|
|
|
* after sampling will be stored in CompositorAnimationStorage as well.
|
2018-05-08 09:48:27 +03:00
|
|
|
*
|
|
|
|
* 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.
|
2017-04-12 11:40:48 +03:00
|
|
|
*/
|
2018-05-08 09:48:27 +03:00
|
|
|
static bool
|
2017-04-12 11:40:48 +03:00
|
|
|
SampleAnimations(CompositorAnimationStorage* aStorage,
|
2018-05-08 06:58:42 +03:00
|
|
|
TimeStamp aPreviousFrameTime,
|
|
|
|
TimeStamp aCurrentFrameTime);
|
2017-01-25 05:51:30 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_layers_AnimationHelper_h
|