Bug 1458457 - Move the logic that we use whether the previous time stamp or the last compose time stamp into SampleAnimationForEachNode. r?birtles draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Thu, 03 May 2018 15:59:09 +0900
changeset 790934 4e57d321978bf805a9573111f886af0e87c4293f
parent 790933 21c08809a891a46ee82517ebea5995fd98c97466
child 790935 814ec4967b0e1f6fab91ab366f076882ea502d95
push id108653
push userhikezoe@mozilla.com
push dateThu, 03 May 2018 07:00:31 +0000
reviewersbirtles
bugs1458457
milestone61.0a1
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
gfx/layers/AnimationHelper.cpp
gfx/layers/AnimationHelper.h
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
--- 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
@@ -217,17 +217,18 @@ public:
    *
    * 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 +247,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();
 }