Bug 1458457 - Move the logic that we use whether the previous time stamp or the last compose time stamp into SampleAnimationForEachNode. r?birtles
So that we can do an additional check depending on each animation in a subsequent
patch in this patch series.
MozReview-Commit-ID: C1ZJMdwraVk
--- a/gfx/layers/AnimationHelper.cpp
+++ b/gfx/layers/AnimationHelper.cpp
@@ -143,17 +143,18 @@ CompositorAnimationStorage::SetAnimation
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
AnimationArray* value = new AnimationArray(aValue);
mAnimations.Put(aId, value);
}
AnimationHelper::SampleResult
AnimationHelper::SampleAnimationForEachNode(
- TimeStamp aTime,
+ TimeStamp aPreviousFrameTime,
+ TimeStamp aCurrentFrameTime,
AnimationArray& aAnimations,
InfallibleTArray<AnimData>& aAnimationData,
RefPtr<RawServoAnimationValue>& aAnimationValue)
{
MOZ_ASSERT(!aAnimations.IsEmpty(), "Should be called with animations");
bool hasInEffectAnimations = false;
#ifdef DEBUG
@@ -170,23 +171,33 @@ AnimationHelper::SampleAnimationForEachN
AnimData& animData = aAnimationData[i];
MOZ_ASSERT((!animation.originTime().IsNull() &&
animation.startTime().type() ==
MaybeTimeDuration::TTimeDuration) ||
animation.isNotPlaying(),
"If we are playing, we should have an origin time and a start"
" time");
+
+ // Use a previous vsync time to make main thread animations and compositor
+ // more in sync with each other.
+ // On the initial frame we use the current frame time here so the timestamp
+ // on the second frame are the same as the initial frame, but it does not
+ // matter.
+ const TimeStamp& timeStamp = !aPreviousFrameTime.IsNull()
+ ? aPreviousFrameTime
+ : aCurrentFrameTime;
+
// If the animation is not currently playing, e.g. paused or
// finished, then use the hold time to stay at the same position.
TimeDuration elapsedDuration =
animation.isNotPlaying() ||
animation.startTime().type() != MaybeTimeDuration::TTimeDuration
? animation.holdTime()
- : (aTime - animation.originTime() -
+ : (timeStamp - animation.originTime() -
animation.startTime().get_TimeDuration())
.MultDouble(animation.playbackRate());
ComputedTiming computedTiming =
dom::AnimationEffectReadOnly::GetComputedTimingAt(
dom::Nullable<TimeDuration>(elapsedDuration), animData.mTiming,
animation.playbackRate());
@@ -566,17 +577,18 @@ AnimationHelper::GetNextCompositorAnimat
uint32_t procId = static_cast<uint32_t>(base::GetCurrentProcId());
uint64_t nextId = procId;
nextId = nextId << 32 | sNextId;
return nextId;
}
void
AnimationHelper::SampleAnimations(CompositorAnimationStorage* aStorage,
- TimeStamp aTime)
+ TimeStamp aPreviousFrameTime,
+ TimeStamp aCurrentFrameTime)
{
MOZ_ASSERT(aStorage);
// Do nothing if there are no compositor animations
if (!aStorage->AnimationsCount()) {
return;
}
@@ -589,17 +601,18 @@ AnimationHelper::SampleAnimations(Compos
}
RefPtr<RawServoAnimationValue> animationValue;
InfallibleTArray<AnimData> animationData;
AnimationHelper::SetAnimations(*animations,
animationData,
animationValue);
AnimationHelper::SampleResult sampleResult =
- AnimationHelper::SampleAnimationForEachNode(aTime,
+ AnimationHelper::SampleAnimationForEachNode(aPreviousFrameTime,
+ aCurrentFrameTime,
*animations,
animationData,
animationValue);
if (sampleResult != AnimationHelper::SampleResult::Sampled) {
continue;
}
--- a/gfx/layers/AnimationHelper.h
+++ b/gfx/layers/AnimationHelper.h
@@ -209,25 +209,29 @@ public:
None,
Skipped,
Sampled
};
/**
* Sample animations based on a given time stamp for a element(layer) with
* its animation data.
+ * Generally |aPreviousFrameTimeStamp| is used for the sampling if it's
+ * supplied to make the animation more in sync with other animations on the
+ * main-thread.
*
* 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.
*/
static SampleResult
- SampleAnimationForEachNode(TimeStamp aTime,
+ SampleAnimationForEachNode(TimeStamp aPreviousFrameTime,
+ TimeStamp aCurrentFrameTime,
AnimationArray& aAnimations,
InfallibleTArray<AnimData>& aAnimationData,
RefPtr<RawServoAnimationValue>& aAnimationValue);
/**
* Populates AnimData stuctures into |aAnimData| and |aBaseAnimationStyle|
* based on |aAnimations|.
*/
static void
@@ -246,15 +250,16 @@ public:
/**
* 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.
*/
static void
SampleAnimations(CompositorAnimationStorage* aStorage,
- TimeStamp aTime);
+ TimeStamp aPreviousFrameTime,
+ TimeStamp aCurrentFrameTime);
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_AnimationHelper_h
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -668,33 +668,35 @@ ApplyAnimatedValue(Layer* aLayer,
default:
MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
}
}
static bool
SampleAnimations(Layer* aLayer,
CompositorAnimationStorage* aStorage,
- TimeStamp aTime)
+ TimeStamp aPreviousFrameTime,
+ TimeStamp aCurrentFrameTime)
{
bool isAnimating = false;
ForEachNode<ForwardIterator>(
aLayer,
[&] (Layer* layer)
{
AnimationArray& animations = layer->GetAnimations();
if (animations.IsEmpty()) {
return;
}
isAnimating = true;
RefPtr<RawServoAnimationValue> animationValue =
layer->GetBaseAnimationStyle();
AnimationHelper::SampleResult sampleResult =
- AnimationHelper::SampleAnimationForEachNode(aTime,
+ AnimationHelper::SampleAnimationForEachNode(aPreviousFrameTime,
+ aCurrentFrameTime,
animations,
layer->GetAnimationData(),
animationValue);
switch (sampleResult) {
case AnimationHelper::SampleResult::Sampled: {
Animation& animation = animations.LastElement();
ApplyAnimatedValue(layer,
aStorage,
@@ -1254,25 +1256,21 @@ AsyncCompositionManager::TransformShadow
return false;
}
CompositorAnimationStorage* storage =
mCompositorBridge->GetAnimationStorage();
// First, compute and set the shadow transforms from OMT animations.
// NB: we must sample animations *before* sampling pan/zoom
// transforms.
- // Use a previous vsync time to make main thread animations and compositor
- // more in sync with each other.
- // On the initial frame we use aVsyncTimestamp here so the timestamp on the
- // second frame are the same as the initial frame, but it does not matter.
bool wantNextFrame =
SampleAnimations(root,
storage,
- !mPreviousFrameTimeStamp.IsNull() ?
- mPreviousFrameTimeStamp : aCurrentFrame);
+ mPreviousFrameTimeStamp,
+ aCurrentFrame);
if (!wantNextFrame) {
// Clean up the CompositorAnimationStorage because
// there are no active animations running
storage->Clear();
}
// Advance animations to the next expected vsync timestamp, if we can
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -1217,28 +1217,27 @@ WebRenderBridgeParent::AdvanceAnimations
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
Maybe<TimeStamp> testingTimeStamp = cbp->GetTestingTimeStamp();
if (testingTimeStamp) {
// If we are on testing refresh mode, use the testing time stamp. And
// also we don't update mPreviousFrameTimeStamp since unlike normal
// refresh mode, on the testing mode animations on the compositor are
// synchronously composed, so we don't need to worry about the time gap
// between the main thread and compositor thread.
- AnimationHelper::SampleAnimations(mAnimStorage, *testingTimeStamp);
+ AnimationHelper::SampleAnimations(mAnimStorage,
+ *testingTimeStamp,
+ *testingTimeStamp);
return;
}
}
TimeStamp lastComposeTime = mCompositorScheduler->GetLastComposeTime();
- // if we have already mPreviousTimeStamp, use it since on the compositor the
- // time in the previous tick is more closer to the main-thread tick time.
AnimationHelper::SampleAnimations(mAnimStorage,
- !mPreviousFrameTimeStamp.IsNull()
- ? mPreviousFrameTimeStamp
- : lastComposeTime);
+ mPreviousFrameTimeStamp,
+ lastComposeTime);
// Reset the previous time stamp if we don't already have any running
// animations to avoid using the time which is far behind for newly
// started animations.
mPreviousFrameTimeStamp =
mAnimStorage->AnimatedValueCount() ? lastComposeTime : TimeStamp();
}