mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-14 00:14:33 +00:00
6310cd82fb
Instead of always discarding the compositor animation id, and then sometimes un-discarding it (which involves a linear lookup in nsTArray), this patch now has the WebRenderLayerManager keep a set of active animation ids, and uses that to avoid discarding the same animation twice. In addition, because the display item can be destroyed at any time (e.g. in the middle of an animation), we were previously "leaking" compositor animations in that the compositor side never got notified to discard the IDs. This resulted in infinite composition loops. This patch solves this problem by having any unused WebRenderAnimationData trigger discard of the animation id during destruction. This way, even if the nsDisplayItem is deleted in the middle of the animation we have a fallback mechanism to discard the id. MozReview-Commit-ID: 8G3EYHcg9Kl --HG-- extra : rebase_source : 45e99a0d71a76a15b7fc7a0d498a6149501a722d
169 lines
3.9 KiB
C++
169 lines
3.9 KiB
C++
/* -*- 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;
|
|
}
|
|
|
|
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
|