Bug 1436659 - Support pending playback rates on compositor animations; r=hiro
authorBrian Birtles <birtles@gmail.com>
Tue, 13 Feb 2018 15:04:18 +0900
changeset 456278 0b4efe60e6ec6bdc23d44f86f65a4bd0ace7d9e8
parent 456277 3fc608432c52da556e179d5a36ce15f1a8a031a7
child 456279 1082bb7dbc526b11b32794bbc5d0f0501dcf3477
push id8799
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 16:46:23 +0000
treeherdermozilla-beta@15334014dc67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1436659
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1436659 - Support pending playback rates on compositor animations; r=hiro MozReview-Commit-ID: 54EiZkv4S7Q
gfx/layers/AnimationInfo.cpp
gfx/layers/ipc/LayersMessages.ipdlh
layout/painting/nsDisplayList.cpp
--- 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);