Bug 1436659 - Support pending playback rates on compositor animations; r?hiro
MozReview-Commit-ID: 54EiZkv4S7Q
--- a/gfx/layers/AnimationInfo.cpp
+++ b/gfx/layers/AnimationInfo.cpp
@@ -99,16 +99,30 @@ AnimationInfo::SetCompositorAnimations(c
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 doing an async update of its playback rate, then we
+ // want to match whatever its current time would be at *aReadyTime*.
+ if (!std::isnan(anim.previousPlaybackRate()) &&
+ anim.startTime().type() == MaybeTimeDuration::TTimeDuration &&
+ !anim.originTime().IsNull() && !anim.isNotPlaying()) {
+ TimeDuration readyTime = aReadyTime - anim.originTime();
+ anim.holdTime() = dom::Animation::CurrentTimeFromTimelineTime(
+ readyTime,
+ anim.startTime().get_TimeDuration(),
+ anim.previousPlaybackRate());
+ // Make start time null so that we know to update it below.
+ anim.startTime() = null_t();
+ }
+
// If the animation is play-pending, resolve the start time.
if (anim.startTime().type() == MaybeTimeDuration::Tnull_t &&
!anim.originTime().IsNull() &&
!anim.isNotPlaying()) {
TimeDuration readyTime = aReadyTime - anim.originTime();
anim.startTime() = dom::Animation::StartTimeFromTimelineTime(
readyTime, anim.holdTime(), anim.playbackRate());
updated = true;
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -236,16 +236,25 @@ struct Animation {
float iterationStart;
// This uses the NS_STYLE_ANIMATION_DIRECTION_* constants.
uint8_t direction;
// This uses dom::FillMode.
uint8_t fillMode;
nsCSSPropertyID property;
AnimationData data;
float playbackRate;
+ // When performing an asynchronous update to the playbackRate, |playbackRate|
+ // above is the updated playbackRate while |previousPlaybackRate| is the
+ // existing playbackRate. This is used by AnimationInfo to update the
+ // startTime based on the 'readyTime' (timestamp at the end of painting)
+ // and is not used beyond that point.
+ //
+ // It is set to numeric_limits<float>::quiet_NaN() when no asynchronous update
+ // to the playbackRate is being performed.
+ float previousPlaybackRate;
// This is used in the transformed progress calculation.
TimingFunction easingFunction;
uint8_t iterationComposite;
// True if the animation has a fixed current time (e.g. paused and
// forward-filling animations).
bool isNotPlaying;
// The base style that animations should composite with. This is only set for
// animations with a composite mode of additive or accumulate, and only for
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -566,17 +566,21 @@ AddAnimationForProperty(nsIFrame* aFrame
animation->delay() = timing.Delay();
animation->endDelay() = timing.EndDelay();
animation->duration() = computedTiming.mDuration;
animation->iterations() = computedTiming.mIterations;
animation->iterationStart() = computedTiming.mIterationStart;
animation->direction() = static_cast<uint8_t>(timing.Direction());
animation->fillMode() = static_cast<uint8_t>(computedTiming.mFill);
animation->property() = aProperty.mProperty;
- animation->playbackRate() = aAnimation->PlaybackRate();
+ animation->playbackRate() = aAnimation->CurrentOrPendingPlaybackRate();
+ animation->previousPlaybackRate() =
+ aAnimation->HasPendingPlaybackRate()
+ ? aAnimation->PlaybackRate()
+ : std::numeric_limits<float>::quiet_NaN();
animation->data() = aData;
animation->easingFunction() = ToTimingFunction(timing.TimingFunction());
animation->iterationComposite() =
static_cast<uint8_t>(aAnimation->GetEffect()->
AsKeyframeEffect()->IterationComposite());
animation->isNotPlaying() = !aAnimation->IsPlaying();
TransformReferenceBox refBox(aFrame);