new file mode 100644
--- /dev/null
+++ b/gfx/layers/AnimationInfo.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
+
+#include "AnimationInfo.h"
+#include "mozilla/layers/WebRenderLayerManager.h"
+#include "mozilla/layers/AnimationHelper.h"
+
+namespace mozilla {
+namespace layers {
+
+AnimationInfo::AnimationInfo(LayerManager* aManager) :
+ mManager(aManager),
+ mCompositorAnimationsId(0),
+ mAnimationGeneration(0),
+ mMutated(false)
+{
+}
+
+AnimationInfo::~AnimationInfo()
+{
+}
+
+void
+AnimationInfo::EnsureAnimationsId()
+{
+ if (!mCompositorAnimationsId) {
+ mCompositorAnimationsId = AnimationHelper::GetNextCompositorAnimationsId();
+ }
+}
+
+Animation*
+AnimationInfo::AddAnimation()
+{
+ // Here generates a new id when the first animation is added and
+ // this id is used to represent the animations in this layer.
+ EnsureAnimationsId();
+
+ MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first");
+
+ Animation* anim = mAnimations.AppendElement();
+
+ mMutated = true;
+
+ return anim;
+}
+
+Animation*
+AnimationInfo::AddAnimationForNextTransaction()
+{
+ MOZ_ASSERT(mPendingAnimations,
+ "should have called ClearAnimationsForNextTransaction first");
+
+ Animation* anim = mPendingAnimations->AppendElement();
+
+ return anim;
+}
+
+void
+AnimationInfo::ClearAnimations()
+{
+ mPendingAnimations = nullptr;
+
+ if (mAnimations.IsEmpty() && mAnimationData.IsEmpty()) {
+ return;
+ }
+
+ if (mManager->AsWebRenderLayerManager()) {
+ mManager->AsWebRenderLayerManager()->
+ AddCompositorAnimationsIdForDiscard(mCompositorAnimationsId);
+ }
+
+ mAnimations.Clear();
+ mAnimationData.Clear();
+
+ mMutated = true;
+}
+
+void
+AnimationInfo::ClearAnimationsForNextTransaction()
+{
+ // Ensure we have a non-null mPendingAnimations to mark a future clear.
+ if (!mPendingAnimations) {
+ mPendingAnimations = new AnimationArray;
+ }
+
+ mPendingAnimations->Clear();
+}
+
+void
+AnimationInfo::SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations)
+{
+ mAnimations = aCompositorAnimations.animations();
+ mCompositorAnimationsId = aCompositorAnimations.id();
+ mAnimationData.Clear();
+ AnimationHelper::SetAnimations(mAnimations,
+ mAnimationData,
+ mBaseAnimationStyle);
+}
+
+bool
+AnimationInfo::StartPendingAnimations(const TimeStamp& aReadyTime)
+{
+ bool updated = false;
+ for (size_t animIdx = 0, animEnd = mAnimations.Length();
+ animIdx < animEnd; animIdx++) {
+ Animation& anim = mAnimations[animIdx];
+
+ // If the animation is play-pending, resolve the start time.
+ // This mirrors the calculation in Animation::StartTimeFromReadyTime.
+ if (anim.startTime().type() == MaybeTimeDuration::Tnull_t &&
+ !anim.originTime().IsNull() &&
+ !anim.isNotPlaying()) {
+ TimeDuration readyTime = aReadyTime - anim.originTime();
+ anim.startTime() =
+ anim.playbackRate() == 0
+ ? readyTime
+ : readyTime - anim.holdTime().MultDouble(1.0 /
+ anim.playbackRate());
+ updated = true;
+ }
+ }
+ return updated;
+}
+
+void
+AnimationInfo::TransferMutatedFlagToLayer(Layer* aLayer)
+{
+ if (mMutated) {
+ aLayer->Mutated();
+ mMutated = false;
+ }
+}
+
+bool
+AnimationInfo::ApplyPendingUpdatesForThisTransaction()
+{
+ if (mPendingAnimations) {
+ mPendingAnimations->SwapElements(mAnimations);
+ mPendingAnimations = nullptr;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+AnimationInfo::HasOpacityAnimation() const
+{
+ for (uint32_t i = 0; i < mAnimations.Length(); i++) {
+ if (mAnimations[i].property() == eCSSProperty_opacity) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+AnimationInfo::HasTransformAnimation() const
+{
+ for (uint32_t i = 0; i < mAnimations.Length(); i++) {
+ if (mAnimations[i].property() == eCSSProperty_transform) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/AnimationInfo.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 GFX_ANIMATIONINFO_H
+#define GFX_ANIMATIONINFO_H
+
+#include "mozilla/StyleAnimationValue.h"
+
+namespace mozilla {
+namespace layers {
+
+class Animation;
+class CompositorAnimations;
+class Layer;
+class LayerManager;
+struct AnimData;
+
+class AnimationInfo
+{
+ typedef InfallibleTArray<Animation> AnimationArray;
+public:
+ explicit AnimationInfo(LayerManager* aManager);
+ virtual ~AnimationInfo();
+
+ // Ensure that this AnimationInfo has a valid (non-zero) animations id. This value is
+ // unique across layers.
+ void EnsureAnimationsId();
+
+ // Call AddAnimation to add a new animation to this layer from layout code.
+ // Caller must fill in all the properties of the returned animation.
+ // A later animation overrides an earlier one.
+ Animation* AddAnimation();
+
+ // These are a parallel to AddAnimation and clearAnimations, except
+ // they add pending animations that apply only when the next
+ // transaction is begun. (See also
+ // SetBaseTransformForNextTransaction.)
+ Animation* AddAnimationForNextTransaction();
+
+ void SetAnimationGeneration(uint64_t aCount) { mAnimationGeneration = aCount; }
+ uint64_t GetAnimationGeneration() { return mAnimationGeneration; }
+
+ // ClearAnimations clears animations on this layer.
+ void ClearAnimations();
+ void ClearAnimationsForNextTransaction();
+ void SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations);
+ bool StartPendingAnimations(const TimeStamp& aReadyTime);
+ void TransferMutatedFlagToLayer(Layer* aLayer);
+
+ uint64_t GetCompositorAnimationsId() { return mCompositorAnimationsId; }
+ StyleAnimationValue GetBaseAnimationStyle() const { return mBaseAnimationStyle; }
+ InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
+ AnimationArray& GetAnimations() { return mAnimations; }
+ bool ApplyPendingUpdatesForThisTransaction();
+ bool HasOpacityAnimation() const;
+ bool HasTransformAnimation() const;
+
+protected:
+ LayerManager* mManager;
+ AnimationArray mAnimations;
+ uint64_t mCompositorAnimationsId;
+ nsAutoPtr<AnimationArray> mPendingAnimations;
+ InfallibleTArray<AnimData> mAnimationData;
+ // If this layer is used for OMTA, then this counter is used to ensure we
+ // stay in sync with the animation manager
+ uint64_t mAnimationGeneration;
+ StyleAnimationValue mBaseAnimationStyle;
+ bool mMutated;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // GFX_ANIMATIONINFO_H
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -28,17 +28,17 @@ void ImageLayer::SetContainer(ImageConta
void ImageLayer::ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
{
gfx::Matrix4x4 local = GetLocalTransform();
// Snap image edges to pixel boundaries
gfxRect sourceRect(0, 0, 0, 0);
if (mContainer) {
- sourceRect.SizeTo(SizeDouble(mContainer->GetCurrentSize()));
+ sourceRect.SizeTo(gfx::SizeDouble(mContainer->GetCurrentSize()));
}
// Snap our local transform first, and snap the inherited transform as well.
// This makes our snapping equivalent to what would happen if our content
// was drawn into a PaintedLayer (gfxContext would snap using the local
// transform, then we'd snap again when compositing the PaintedLayer).
mEffectiveTransform =
SnapTransform(local, sourceRect, nullptr) *
SnapTransformTranslation(aTransformToSurface, nullptr);
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -24,17 +24,16 @@
#include "mozilla/DebugOnly.h" // for DebugOnly
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Telemetry.h" // for Accumulate
#include "mozilla/ToString.h"
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
#include "mozilla/gfx/Polygon.h" // for Polygon
-#include "mozilla/layers/AnimationHelper.h"
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/BSPTree.h" // for BSPTree
#include "mozilla/layers/CompositableClient.h" // for CompositableClient
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
#include "mozilla/layers/LayersMessages.h" // for TransformFunction, etc
@@ -181,141 +180,53 @@ LayerManager::RemoveUserData(void* aKey)
{
UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
return d;
}
//--------------------------------------------------
// Layer
-Layer::Layer(LayerManager* aManager, void* aImplData) :
- mManager(aManager),
- mParent(nullptr),
- mNextSibling(nullptr),
- mPrevSibling(nullptr),
- mImplData(aImplData),
- mCompositorAnimationsId(0),
- mUseTileSourceRect(false),
+Layer::Layer(LayerManager* aManager, void* aImplData)
+ : mManager(aManager)
+ , mParent(nullptr)
+ , mNextSibling(nullptr)
+ , mPrevSibling(nullptr)
+ , mImplData(aImplData)
+ , mAnimationInfo(aManager)
+ , mUseTileSourceRect(false)
#ifdef DEBUG
- mDebugColorIndex(0),
+ , mDebugColorIndex(0)
#endif
- mAnimationGeneration(0)
{
}
Layer::~Layer()
{
}
void
-Layer::EnsureAnimationsId()
-{
- if (!mCompositorAnimationsId) {
- mCompositorAnimationsId = AnimationHelper::GetNextCompositorAnimationsId();
- }
-}
-
-Animation*
-Layer::AddAnimation()
-{
- // Here generates a new id when the first animation is added and
- // this id is used to represent the animations in this layer.
- EnsureAnimationsId();
-
- MOZ_LAYERS_LOG_IF_SHADOWABLE(
- this, ("Layer::Mutated(%p) AddAnimation with id=%" PRIu64, this, mCompositorAnimationsId));
-
- MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first");
-
- Animation* anim = mAnimations.AppendElement();
-
- Mutated();
- return anim;
-}
-
-void
-Layer::ClearAnimations()
-{
- mPendingAnimations = nullptr;
-
- if (mAnimations.IsEmpty() && mAnimationData.IsEmpty()) {
- return;
- }
-
- MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClearAnimations", this));
- mAnimations.Clear();
- mAnimationData.Clear();
- Mutated();
-}
-
-Animation*
-Layer::AddAnimationForNextTransaction()
-{
- MOZ_ASSERT(mPendingAnimations,
- "should have called ClearAnimationsForNextTransaction first");
-
- Animation* anim = mPendingAnimations->AppendElement();
-
- return anim;
-}
-
-void
-Layer::ClearAnimationsForNextTransaction()
-{
- // Ensure we have a non-null mPendingAnimations to mark a future clear.
- if (!mPendingAnimations) {
- mPendingAnimations = new AnimationArray;
- }
-
- mPendingAnimations->Clear();
-}
-
-void
Layer::SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations)
{
MOZ_LAYERS_LOG_IF_SHADOWABLE(
- this, ("Layer::Mutated(%p) SetCompositorAnimations with id=%" PRIu64, this, mCompositorAnimationsId));
+ this, ("Layer::Mutated(%p) SetCompositorAnimations with id=%" PRIu64, this, mAnimationInfo.GetCompositorAnimationsId()));
- mAnimations = aCompositorAnimations.animations();
- mCompositorAnimationsId = aCompositorAnimations.id();
- mAnimationData.Clear();
- AnimationHelper::SetAnimations(mAnimations,
- mAnimationData,
- mBaseAnimationStyle);
+ mAnimationInfo.SetCompositorAnimations(aCompositorAnimations);
Mutated();
}
void
Layer::StartPendingAnimations(const TimeStamp& aReadyTime)
{
ForEachNode<ForwardIterator>(
this,
[&aReadyTime](Layer *layer)
{
- bool updated = false;
- for (size_t animIdx = 0, animEnd = layer->mAnimations.Length();
- animIdx < animEnd; animIdx++) {
- Animation& anim = layer->mAnimations[animIdx];
-
- // If the animation is play-pending, resolve the start time.
- // This mirrors the calculation in Animation::StartTimeFromReadyTime.
- if (anim.startTime().type() == MaybeTimeDuration::Tnull_t &&
- !anim.originTime().IsNull() &&
- !anim.isNotPlaying()) {
- TimeDuration readyTime = aReadyTime - anim.originTime();
- anim.startTime() =
- anim.playbackRate() == 0
- ? readyTime
- : readyTime - anim.holdTime().MultDouble(1.0 /
- anim.playbackRate());
- updated = true;
- }
- }
- if (updated) {
+ if (layer->mAnimationInfo.StartPendingAnimations(aReadyTime)) {
layer->Mutated();
}
});
}
void
Layer::SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller)
{
@@ -705,49 +616,37 @@ const LayerToParentLayerMatrix4x4
Layer::GetLocalTransformTyped()
{
return ViewAs<LayerToParentLayerMatrix4x4>(GetLocalTransform());
}
bool
Layer::HasOpacityAnimation() const
{
- for (uint32_t i = 0; i < mAnimations.Length(); i++) {
- if (mAnimations[i].property() == eCSSProperty_opacity) {
- return true;
- }
- }
- return false;
+ return mAnimationInfo.HasOpacityAnimation();
}
bool
Layer::HasTransformAnimation() const
{
- for (uint32_t i = 0; i < mAnimations.Length(); i++) {
- if (mAnimations[i].property() == eCSSProperty_transform) {
- return true;
- }
- }
- return false;
+ return mAnimationInfo.HasTransformAnimation();
}
void
Layer::ApplyPendingUpdatesForThisTransaction()
{
if (mPendingTransform && *mPendingTransform != mSimpleAttrs.Transform()) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
mSimpleAttrs.SetTransform(*mPendingTransform);
MutatedSimple();
}
mPendingTransform = nullptr;
- if (mPendingAnimations) {
+ if (mAnimationInfo.ApplyPendingUpdatesForThisTransaction()) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PendingUpdatesForThisTransaction", this));
- mPendingAnimations->SwapElements(mAnimations);
- mPendingAnimations = nullptr;
Mutated();
}
for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
FrameMetrics& fm = mScrollMetadata[i].GetMetrics();
Maybe<ScrollUpdateInfo> update = Manager()->GetPendingScrollInfoUpdate(fm.GetScrollId());
if (update) {
fm.UpdatePendingScrollInfo(update.value());
@@ -892,16 +791,22 @@ Layer::GetVisibleRegionRelativeToRootLay
// positioning code.
offset += currentLayerOffset;
}
*aLayerOffset = IntPoint(offset.x, offset.y);
return true;
}
+InfallibleTArray<AnimData>&
+Layer::GetAnimationData()
+{
+ return mAnimationInfo.GetAnimationData();
+}
+
Maybe<ParentLayerIntRect>
Layer::GetCombinedClipRect() const
{
Maybe<ParentLayerIntRect> clip = GetClipRect();
clip = IntersectMaybeRects(clip, GetScrolledClipRect());
for (size_t i = 0; i < mScrollMetadata.Length(); i++) {
@@ -1933,20 +1838,20 @@ Layer::PrintInfo(std::stringstream& aStr
aStream << nsPrintfCString(" [mMaskLayer=%p]", mMaskLayer.get()).get();
}
for (uint32_t i = 0; i < mScrollMetadata.Length(); i++) {
if (!mScrollMetadata[i].IsDefault()) {
aStream << nsPrintfCString(" [metrics%d=", i).get();
AppendToString(aStream, mScrollMetadata[i], "", "]");
}
}
- if (!mAnimations.IsEmpty()) {
+ if (!mAnimationInfo.GetAnimations().IsEmpty()) {
aStream << nsPrintfCString(" [%d animations with id=%" PRIu64 " ]",
- (int) mAnimations.Length(),
- mCompositorAnimationsId).get();
+ (int) mAnimationInfo.GetAnimations().Length(),
+ mAnimationInfo.GetCompositorAnimationsId()).get();
}
}
// The static helper function sets the transform matrix into the packet
static void
DumpTransform(layerscope::LayersPacket::Layer::Matrix* aLayerMatrix, const Matrix4x4& aMatrix)
{
aLayerMatrix->set_is2d(aMatrix.Is2D());
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -28,16 +28,17 @@
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "mozilla/gfx/BaseMargin.h" // for BaseMargin
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/TiledRegion.h" // for TiledIntRegion
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/gfx/UserData.h" // for UserData, etc
+#include "mozilla/layers/AnimationInfo.h" // for AnimationInfo
#include "mozilla/layers/BSPTree.h" // for LayerPolygon
#include "mozilla/layers/LayerAttributes.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsAutoPtr.h" // for nsAutoPtr, nsRefPtr, etc
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsCSSPropertyID.h" // for nsCSSPropertyID
#include "nsDebug.h" // for NS_ASSERTION
@@ -70,17 +71,16 @@ class GLContext;
namespace gfx {
class DrawTarget;
} // namespace gfx
namespace layers {
class Animation;
-class AnimationData;
class AsyncCanvasRenderer;
class AsyncPanZoomController;
class BasicLayerManager;
class ClientLayerManager;
class HostLayerManager;
class Layer;
class LayerMetricsWrapper;
class PaintedLayer;
@@ -1240,42 +1240,25 @@ public:
*/
void SetTransformIsPerspective(bool aTransformIsPerspective)
{
if (mSimpleAttrs.SetTransformIsPerspective(aTransformIsPerspective)) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) TransformIsPerspective", this));
MutatedSimple();
}
}
-
- // Ensure that this layer has a valid (non-zero) animations id. This value is
- // unique across layers.
- void EnsureAnimationsId();
- // Call AddAnimation to add a new animation to this layer from layout code.
- // Caller must fill in all the properties of the returned animation.
- // A later animation overrides an earlier one.
- Animation* AddAnimation();
- // ClearAnimations clears animations on this layer.
- virtual void ClearAnimations();
// This is only called when the layer tree is updated. Do not call this from
// layout code. To add an animation to this layer, use AddAnimation.
void SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations);
// Go through all animations in this layer and its children and, for
// any animations with a null start time, update their start time such
// that at |aReadyTime| the animation's current time corresponds to its
// 'initial current time' value.
void StartPendingAnimations(const TimeStamp& aReadyTime);
- // These are a parallel to AddAnimation and clearAnimations, except
- // they add pending animations that apply only when the next
- // transaction is begun. (See also
- // SetBaseTransformForNextTransaction.)
- Animation* AddAnimationForNextTransaction();
- void ClearAnimationsForNextTransaction();
-
/**
* CONSTRUCTION PHASE ONLY
* If a layer represents a fixed position element, this data is stored on the
* layer for use by the compositor.
*
* - |aScrollId| identifies the scroll frame that this element is fixed
* with respect to.
*
@@ -1442,29 +1425,28 @@ public:
* in this case, results will not be valid. Returns true on successful
* traversal.
*/
bool GetVisibleRegionRelativeToRootLayer(nsIntRegion& aResult,
nsIntPoint* aLayerOffset);
// Note that all lengths in animation data are either in CSS pixels or app
// units and must be converted to device pixels by the compositor.
- AnimationArray& GetAnimations() { return mAnimations; }
- uint64_t GetCompositorAnimationsId() { return mCompositorAnimationsId; }
- InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
-
- uint64_t GetAnimationGeneration() { return mAnimationGeneration; }
- void SetAnimationGeneration(uint64_t aCount) { mAnimationGeneration = aCount; }
+ AnimationArray& GetAnimations() { return mAnimationInfo.GetAnimations(); }
+ uint64_t GetCompositorAnimationsId() { return mAnimationInfo.GetCompositorAnimationsId(); }
+ InfallibleTArray<AnimData>& GetAnimationData();
+
+ uint64_t GetAnimationGeneration() { return mAnimationInfo.GetAnimationGeneration(); }
bool HasTransformAnimation() const;
bool HasOpacityAnimation() const;
StyleAnimationValue GetBaseAnimationStyle() const
{
- return mBaseAnimationStyle;
+ return mAnimationInfo.GetBaseAnimationStyle();
}
/**
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowBaseTransform(), in either case with the
* pre- and post-scales applied.
*/
gfx::Matrix4x4 GetLocalTransform();
@@ -1883,16 +1865,18 @@ public:
*/
void ClearExtraDumpInfo()
{
#ifdef MOZ_DUMP_PAINTING
mExtraDumpInfo.Clear();
#endif
}
+ AnimationInfo& GetAnimationInfo() { return mAnimationInfo; }
+
protected:
Layer(LayerManager* aManager, void* aImplData);
// Protected destructor, to discourage deletion outside of Release():
virtual ~Layer();
/**
* We can snap layer transforms for two reasons:
@@ -1952,39 +1936,30 @@ protected:
LayerIntRegion mVisibleRegion;
nsTArray<ScrollMetadata> mScrollMetadata;
EventRegions mEventRegions;
// A mutation of |mTransform| that we've queued to be applied at the
// end of the next transaction (if nothing else overrides it in the
// meantime).
nsAutoPtr<gfx::Matrix4x4> mPendingTransform;
gfx::Matrix4x4 mEffectiveTransform;
- AnimationArray mAnimations;
- uint64_t mCompositorAnimationsId;
- // See mPendingTransform above.
- nsAutoPtr<AnimationArray> mPendingAnimations;
- InfallibleTArray<AnimData> mAnimationData;
+ AnimationInfo mAnimationInfo;
Maybe<ParentLayerIntRect> mClipRect;
gfx::IntRect mTileSourceRect;
gfx::TiledIntRegion mInvalidRegion;
nsTArray<RefPtr<AsyncPanZoomController> > mApzcs;
bool mUseTileSourceRect;
#ifdef DEBUG
uint32_t mDebugColorIndex;
#endif
- // If this layer is used for OMTA, then this counter is used to ensure we
- // stay in sync with the animation manager
- uint64_t mAnimationGeneration;
#ifdef MOZ_DUMP_PAINTING
nsTArray<nsCString> mExtraDumpInfo;
#endif
// Store display list log.
nsCString mDisplayListLog;
-
- StyleAnimationValue mBaseAnimationStyle;
};
/**
* A Layer which we can paint into. It is a conceptually
* infinite surface, but each PaintedLayer has an associated "valid region"
* of contents that it is currently storing, which is finite. PaintedLayer
* implementations can store content between paints.
*
--- a/gfx/layers/apz/src/AndroidDynamicToolbarAnimator.cpp
+++ b/gfx/layers/apz/src/AndroidDynamicToolbarAnimator.cpp
@@ -8,17 +8,19 @@
#include <cmath>
#include "FrameMetrics.h"
#include "gfxPrefs.h"
#include "mozilla/EventForwards.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Types.h"
+#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZThreadUtils.h"
+#include "mozilla/layers/AsyncCompositionManager.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorOGL.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/UiCompositorControllerMessageTypes.h"
#include "mozilla/layers/UiCompositorControllerParent.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Move.h"
#include "mozilla/Unused.h"
@@ -504,20 +506,20 @@ AndroidDynamicToolbarAnimator::UpdateToo
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
// if the compositor has shutdown, do not create any new rendering objects.
if (mCompositorShutdown) {
return;
}
if (mCompositorToolbarPixels) {
- RefPtr<DataSourceSurface> surface = Factory::CreateWrappingDataSourceSurface(
+ RefPtr<gfx::DataSourceSurface> surface = gfx::Factory::CreateWrappingDataSourceSurface(
mCompositorToolbarPixels.ref().get<uint8_t>(),
mCompositorToolbarPixelsSize.width * 4,
- IntSize(mCompositorToolbarPixelsSize.width, mCompositorToolbarPixelsSize.height),
+ gfx::IntSize(mCompositorToolbarPixelsSize.width, mCompositorToolbarPixelsSize.height),
gfx::SurfaceFormat::B8G8R8A8);
if (!mCompositorToolbarTexture) {
mCompositorToolbarTexture = gl->CreateDataTextureSource();
mCompositorToolbarEffect = nullptr;
}
if (!mCompositorToolbarTexture->Update(surface)) {
@@ -543,17 +545,17 @@ AndroidDynamicToolbarAnimator::GetToolba
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
// if the compositor has shutdown, do not create any new rendering objects.
if (mCompositorShutdown) {
return nullptr;
}
if (mCompositorToolbarTexture) {
if (!mCompositorToolbarEffect) {
- mCompositorToolbarEffect = new EffectRGB(mCompositorToolbarTexture, true, SamplingFilter::LINEAR);
+ mCompositorToolbarEffect = new EffectRGB(mCompositorToolbarTexture, true, gfx::SamplingFilter::LINEAR);
}
float ratioVisible = (float)mCompositorToolbarHeight / (float)mCompositorMaxToolbarHeight;
mCompositorToolbarEffect->mTextureCoords.y = 1.0f - ratioVisible;
mCompositorToolbarEffect->mTextureCoords.height = ratioVisible;
}
return mCompositorToolbarEffect.get();
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -93,17 +93,17 @@ public:
wr::MaybeExternalImageId mExternalImageId;
};
static bool
WrapWithWebRenderTextureHost(ISurfaceAllocator* aDeallocator,
LayersBackend aBackend,
TextureFlags aFlags)
{
- if (!gfxVars::UseWebRender() ||
+ if (!gfx::gfxVars::UseWebRender() ||
(aFlags & TextureFlags::SNAPSHOT) ||
(aBackend != LayersBackend::LAYERS_WR) ||
(!aDeallocator->UsesImageBridge() && !aDeallocator->AsCompositorBridgeParentBase())) {
return false;
}
return true;
}
--- a/gfx/layers/mlgpu/FrameBuilder.cpp
+++ b/gfx/layers/mlgpu/FrameBuilder.cpp
@@ -4,16 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FrameBuilder.h"
#include "ContainerLayerMLGPU.h"
#include "GeckoProfiler.h" // for profiler_*
#include "LayerMLGPU.h"
#include "LayerManagerMLGPU.h"
#include "MaskOperation.h"
+#include "MLGDevice.h" // for MLGSwapChain
#include "RenderPassMLGPU.h"
#include "RenderViewMLGPU.h"
#include "mozilla/gfx/Polygon.h"
#include "mozilla/layers/BSPTree.h"
#include "mozilla/layers/LayersHelpers.h"
namespace mozilla {
namespace layers {
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -87,16 +87,17 @@ EXPORTS.gfxipc += [
]
EXPORTS.mozilla.dom += [
'apz/util/CheckerboardReportService.h',
]
EXPORTS.mozilla.layers += [
'AnimationHelper.h',
+ 'AnimationInfo.h',
'apz/public/CompositorController.h',
'apz/public/GeckoContentController.h',
'apz/public/IAPZCTreeManager.h',
'apz/public/MetricsSharingController.h',
# exporting things from apz/src is temporary until we extract a
# proper interface for the code there
'apz/src/APZCTreeManager.h',
'apz/src/APZUtils.h',
@@ -281,16 +282,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'andr
'apz/src/AndroidDynamicToolbarAnimator.cpp',
]
EXPORTS.mozilla.layers += [
'apz/src/AndroidDynamicToolbarAnimator.h',
]
UNIFIED_SOURCES += [
'AnimationHelper.cpp',
+ 'AnimationInfo.cpp',
'apz/public/IAPZCTreeManager.cpp',
'apz/src/APZCTreeManager.cpp',
'apz/src/AsyncPanZoomController.cpp',
'apz/src/Axis.cpp',
'apz/src/CheckerboardEvent.cpp',
'apz/src/DragTracker.cpp',
'apz/src/FocusState.cpp',
'apz/src/FocusTarget.cpp',
--- a/gfx/layers/wr/WebRenderContainerLayer.cpp
+++ b/gfx/layers/wr/WebRenderContainerLayer.cpp
@@ -13,31 +13,19 @@
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "UnitTransforms.h"
namespace mozilla {
namespace layers {
void
-WebRenderContainerLayer::ClearAnimations()
-{
-
- if (!GetAnimations().IsEmpty()) {
- mManager->AsWebRenderLayerManager()->
- AddCompositorAnimationsIdForDiscard(GetCompositorAnimationsId());
- }
-
- Layer::ClearAnimations();
-}
-
-void
WebRenderContainerLayer::UpdateTransformDataForAnimation()
{
- for (Animation& animation : mAnimations) {
+ for (Animation& animation : mAnimationInfo.GetAnimations()) {
if (animation.property() == eCSSProperty_transform) {
TransformData& transformData = animation.data().get_TransformData();
transformData.inheritedXScale() = GetInheritedXScale();
transformData.inheritedYScale() = GetInheritedYScale();
transformData.hasPerspectiveParent() =
GetParent() && GetParent()->GetTransformIsPerspective();
}
}
@@ -95,17 +83,17 @@ WebRenderContainerLayer::RenderLayer(wr:
// ensure that there is an animations id set on it, we will use this to give
// WebRender updated transforms for composition.
if (WrManager()->AsyncPanZoomEnabled() &&
GetScrollThumbData().mDirection != ScrollDirection::NONE) {
// A scroll thumb better not have a transform animation already or we're
// going to end up clobbering it with APZ animating it too.
MOZ_ASSERT(transformForSC);
- EnsureAnimationsId();
+ mAnimationInfo.EnsureAnimationsId();
animationsId = GetCompositorAnimationsId();
// We need to set the transform in the stacking context to null for it to
// pick up and install the animation id.
transformForSC = nullptr;
}
if (transformForSC && transform.IsIdentity()) {
// If the transform is an identity transform, strip it out so that WR
--- a/gfx/layers/wr/WebRenderContainerLayer.h
+++ b/gfx/layers/wr/WebRenderContainerLayer.h
@@ -40,17 +40,16 @@ protected:
void UpdateTransformDataForAnimation();
public:
Layer* GetLayer() override { return this; }
void RenderLayer(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc) override;
- void ClearAnimations() override;
virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
{
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
};
class WebRenderRefLayer : public WebRenderLayer,
public RefLayer {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -480,35 +480,34 @@ SetAnimatable(nsCSSPropertyID aProperty,
}
default:
MOZ_ASSERT_UNREACHABLE("Unsupported property");
}
}
static void
AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty,
- dom::Animation* aAnimation, Layer* aLayer,
+ dom::Animation* aAnimation, AnimationInfo& aAnimationInfo,
AnimationData& aData, bool aPending)
{
- MOZ_ASSERT(aLayer->AsContainerLayer(), "Should only animate ContainerLayer");
MOZ_ASSERT(aAnimation->GetEffect(),
"Should not be adding an animation without an effect");
MOZ_ASSERT(!aAnimation->GetCurrentOrPendingStartTime().IsNull() ||
!aAnimation->IsPlaying() ||
(aAnimation->GetTimeline() &&
aAnimation->GetTimeline()->TracksWallclockTime()),
"If the animation has an unresolved start time it should either"
" be static (so we don't need a start time) or else have a"
" timeline capable of converting TimeStamps (so we can calculate"
" one later");
layers::Animation* animation =
aPending ?
- aLayer->AddAnimationForNextTransaction() :
- aLayer->AddAnimation();
+ aAnimationInfo.AddAnimationForNextTransaction() :
+ aAnimationInfo.AddAnimation();
const TimingParams& timing = aAnimation->GetEffect()->SpecifiedTiming();
// If we are starting a new transition that replaces an existing transition
// running on the compositor, it is possible that the animation on the
// compositor will have advanced ahead of the main thread. If we use as
// the starting point of the new transition, the current value of the
// replaced transition as calculated on the main thread using the refresh
@@ -596,32 +595,108 @@ AddAnimationForProperty(nsIFrame* aFrame
static_cast<uint8_t>(segment.mFromComposite);
animSegment->endComposite() =
static_cast<uint8_t>(segment.mToComposite);
animSegment->sampleFn() = ToTimingFunction(segment.mTimingFunction);
}
}
static void
-AddAnimationsForProperty(nsIFrame* aFrame, nsCSSPropertyID aProperty,
- nsTArray<RefPtr<dom::Animation>>& aAnimations,
- Layer* aLayer, AnimationData& aData,
- bool aPending)
-{
+AddAnimationsForProperty(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
+ nsDisplayItem* aItem, nsCSSPropertyID aProperty,
+ AnimationInfo& aAnimationInfo, bool aPending)
+{
+ if (aPending) {
+ aAnimationInfo.ClearAnimationsForNextTransaction();
+ } else {
+ aAnimationInfo.ClearAnimations();
+ }
+
+ // Update the animation generation on the layer. We need to do this before
+ // any early returns since even if we don't add any animations to the
+ // layer, we still need to mark it as up-to-date with regards to animations.
+ // Otherwise, in RestyleManager we'll notice the discrepancy between the
+ // animation generation numbers and update the layer indefinitely.
+ uint64_t animationGeneration =
+ RestyleManager::GetAnimationGenerationForFrame(aFrame);
+ aAnimationInfo.SetAnimationGeneration(animationGeneration);
+
+ EffectCompositor::ClearIsRunningOnCompositor(aFrame, aProperty);
+ nsTArray<RefPtr<dom::Animation>> compositorAnimations =
+ EffectCompositor::GetAnimationsForCompositor(aFrame, aProperty);
+ if (compositorAnimations.IsEmpty()) {
+ return;
+ }
+
+ // If the frame is not prerendered, bail out.
+ // Do this check only during layer construction; during updating the
+ // caller is required to check it appropriately.
+ if (aItem && !aItem->CanUseAsyncAnimations(aBuilder)) {
+ // EffectCompositor needs to know that we refused to run this animation
+ // asynchronously so that it will not throttle the main thread
+ // animation.
+ aFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), true);
+
+ // We need to schedule another refresh driver run so that EffectCompositor
+ // gets a chance to unthrottle the animation.
+ aFrame->SchedulePaint();
+ return;
+ }
+
+ AnimationData data;
+ if (aProperty == eCSSProperty_transform) {
+ // XXX Performance here isn't ideal for SVG. We'd prefer to avoid resolving
+ // the dimensions of refBox. That said, we only get here if there are CSS
+ // animations or transitions on this element, and that is likely to be a
+ // lot rarer than transforms on SVG (the frequency of which drives the need
+ // for TransformReferenceBox).
+ TransformReferenceBox refBox(aFrame);
+ nsRect bounds(0, 0, refBox.Width(), refBox.Height());
+ // all data passed directly to the compositor should be in dev pixels
+ int32_t devPixelsToAppUnits = aFrame->PresContext()->AppUnitsPerDevPixel();
+ float scale = devPixelsToAppUnits;
+ Point3D offsetToTransformOrigin =
+ nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds);
+ nsPoint origin;
+ float scaleX = 1.0f;
+ float scaleY = 1.0f;
+ bool hasPerspectiveParent = false;
+ if (aItem) {
+ // This branch is for display items to leverage the cache of
+ // nsDisplayListBuilder.
+ origin = aItem->ToReferenceFrame();
+ } else {
+ // This branch is running for restyling.
+ // Animations are animated at the coordination of the reference
+ // frame outside, not the given frame itself. The given frame
+ // is also reference frame too, so the parent's reference frame
+ // are used.
+ nsIFrame* referenceFrame =
+ nsLayoutUtils::GetReferenceFrame(nsLayoutUtils::GetCrossDocParentFrame(aFrame));
+ origin = aFrame->GetOffsetToCrossDoc(referenceFrame);
+ }
+
+ data = TransformData(origin, offsetToTransformOrigin,
+ bounds, devPixelsToAppUnits,
+ scaleX, scaleY, hasPerspectiveParent);
+ } else if (aProperty == eCSSProperty_opacity) {
+ data = null_t();
+ }
+
MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty,
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR),
"inconsistent property flags");
EffectSet* effects = EffectSet::GetEffectSet(aFrame);
MOZ_ASSERT(effects);
bool sentAnimations = false;
// Add from first to last (since last overrides)
- for (size_t animIdx = 0; animIdx < aAnimations.Length(); animIdx++) {
- dom::Animation* anim = aAnimations[animIdx];
+ for (size_t animIdx = 0; animIdx < compositorAnimations.Length(); animIdx++) {
+ dom::Animation* anim = compositorAnimations[animIdx];
if (!anim->IsRelevant()) {
continue;
}
dom::KeyframeEffectReadOnly* keyframeEffect =
anim->GetEffect() ? anim->GetEffect()->AsKeyframeEffect() : nullptr;
MOZ_ASSERT(keyframeEffect,
"A playing animation should have a keyframe effect");
@@ -653,17 +728,17 @@ AddAnimationsForProperty(nsIFrame* aFram
// driver under test control. In this case, the next time the refresh
// driver is advanced it will trigger any pending animations.
if (anim->PlayState() == AnimationPlayState::Pending &&
(anim->GetTimeline() &&
!anim->GetTimeline()->TracksWallclockTime())) {
continue;
}
- AddAnimationForProperty(aFrame, *property, anim, aLayer, aData, aPending);
+ AddAnimationForProperty(aFrame, *property, anim, aAnimationInfo, data, aPending);
keyframeEffect->SetIsRunningOnCompositor(aProperty, true);
sentAnimations = true;
}
if (sentAnimations && aProperty == eCSSProperty_transform) {
TimeStamp now = aFrame->PresContext()->RefreshDriver()->MostRecentRefresh();
effects->UpdateLastTransformSyncTime(now);
}
@@ -772,96 +847,20 @@ nsDisplayListBuilder::AddAnimationsAndTr
// off-main-thread compositing.
LayersBackend backend = aLayer->Manager()->GetBackendType();
if (!(backend == layers::LayersBackend::LAYERS_CLIENT ||
backend == layers::LayersBackend::LAYERS_WR)) {
return;
}
bool pending = !aBuilder;
-
- if (pending) {
- aLayer->ClearAnimationsForNextTransaction();
- } else {
- aLayer->ClearAnimations();
- }
-
- // Update the animation generation on the layer. We need to do this before
- // any early returns since even if we don't add any animations to the
- // layer, we still need to mark it as up-to-date with regards to animations.
- // Otherwise, in RestyleManager we'll notice the discrepancy between the
- // animation generation numbers and update the layer indefinitely.
- uint64_t animationGeneration =
- RestyleManager::GetAnimationGenerationForFrame(aFrame);
- aLayer->SetAnimationGeneration(animationGeneration);
-
- EffectCompositor::ClearIsRunningOnCompositor(aFrame, aProperty);
- nsTArray<RefPtr<dom::Animation>> compositorAnimations =
- EffectCompositor::GetAnimationsForCompositor(aFrame, aProperty);
- if (compositorAnimations.IsEmpty()) {
- return;
- }
-
- // If the frame is not prerendered, bail out.
- // Do this check only during layer construction; during updating the
- // caller is required to check it appropriately.
- if (aItem && !aItem->CanUseAsyncAnimations(aBuilder)) {
- // EffectCompositor needs to know that we refused to run this animation
- // asynchronously so that it will not throttle the main thread
- // animation.
- aFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), true);
-
- // We need to schedule another refresh driver run so that EffectCompositor
- // gets a chance to unthrottle the animation.
- aFrame->SchedulePaint();
- return;
- }
-
- AnimationData data;
- if (aProperty == eCSSProperty_transform) {
- // XXX Performance here isn't ideal for SVG. We'd prefer to avoid resolving
- // the dimensions of refBox. That said, we only get here if there are CSS
- // animations or transitions on this element, and that is likely to be a
- // lot rarer than transforms on SVG (the frequency of which drives the need
- // for TransformReferenceBox).
- TransformReferenceBox refBox(aFrame);
- nsRect bounds(0, 0, refBox.Width(), refBox.Height());
- // all data passed directly to the compositor should be in dev pixels
- int32_t devPixelsToAppUnits = aFrame->PresContext()->AppUnitsPerDevPixel();
- float scale = devPixelsToAppUnits;
- Point3D offsetToTransformOrigin =
- nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds);
- nsPoint origin;
- float scaleX = 1.0f;
- float scaleY = 1.0f;
- bool hasPerspectiveParent = false;
- if (aItem) {
- // This branch is for display items to leverage the cache of
- // nsDisplayListBuilder.
- origin = aItem->ToReferenceFrame();
- } else {
- // This branch is running for restyling.
- // Animations are animated at the coordination of the reference
- // frame outside, not the given frame itself. The given frame
- // is also reference frame too, so the parent's reference frame
- // are used.
- nsIFrame* referenceFrame =
- nsLayoutUtils::GetReferenceFrame(nsLayoutUtils::GetCrossDocParentFrame(aFrame));
- origin = aFrame->GetOffsetToCrossDoc(referenceFrame);
- }
-
- data = TransformData(origin, offsetToTransformOrigin,
- bounds, devPixelsToAppUnits,
- scaleX, scaleY, hasPerspectiveParent);
- } else if (aProperty == eCSSProperty_opacity) {
- data = null_t();
- }
-
- AddAnimationsForProperty(aFrame, aProperty, compositorAnimations,
- aLayer, data, pending);
+ AnimationInfo& animationInfo = aLayer->GetAnimationInfo();
+ AddAnimationsForProperty(aFrame, aBuilder, aItem, aProperty,
+ animationInfo, pending);
+ animationInfo.TransferMutatedFlagToLayer(aLayer);
}
void
nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter::InsertScrollFrame(nsIScrollableFrame* aScrollableFrame)
{
MOZ_ASSERT(!mUsed);
size_t descendantsEndIndex = mBuilder->mActiveScrolledRoots.Length();
const ActiveScrolledRoot* parentASR = mBuilder->mCurrentActiveScrolledRoot;