Bug 1456679 - Make SampleAnimations return boolean to tell there is any animations even if the animation in delay phase. r=kats
☠☠ backed out by 52e0b45195cb ☠ ☠
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Thu, 26 Apr 2018 08:28:44 +0900
changeset 469138 351ae90cc6a0ac002a270233edcaaadafeee71bd
parent 469137 fc793911d371a449b30a81575e5e9a39c6f4f072
child 469139 c40209504a45529f23a2722a16a012424eb01ed6
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1456679
milestone61.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 1456679 - Make SampleAnimations return boolean to tell there is any animations even if the animation in delay phase. r=kats If the animation is in delay phase, we shouldn't produce any values for the animation but we have to make sure subsequent ticks happen in order to the time when the animation starts. So what we should do here is that 1) Make AnimationHelper::SampleAnimations() return boolean, return true if there is any animation. 2) Schedule the next tick if AnimationHelper::SampleAnimations return true This setup is equivalent to what we do non-WebRender. So that we don't need to set non-animated value as AnimatedValue for delay phase to make subsequent ticks happen for the delay phase animations. The non-animated value will be dropped in the next patch. MozReview-Commit-ID: IwltLGgvT7K
gfx/layers/AnimationHelper.cpp
gfx/layers/AnimationHelper.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
--- a/gfx/layers/AnimationHelper.cpp
+++ b/gfx/layers/AnimationHelper.cpp
@@ -541,35 +541,37 @@ AnimationHelper::GetNextCompositorAnimat
   ++sNextId;
 
   uint32_t procId = static_cast<uint32_t>(base::GetCurrentProcId());
   uint64_t nextId = procId;
   nextId = nextId << 32 | sNextId;
   return nextId;
 }
 
-void
+bool
 AnimationHelper::SampleAnimations(CompositorAnimationStorage* aStorage,
                                   TimeStamp aTime)
 {
   MOZ_ASSERT(aStorage);
+  bool isAnimating = false;
 
   // Do nothing if there are no compositor animations
   if (!aStorage->AnimationsCount()) {
-    return;
+    return isAnimating;
   }
 
   //Sample the animations in CompositorAnimationStorage
   for (auto iter = aStorage->ConstAnimationsTableIter();
        !iter.Done(); iter.Next()) {
     AnimationArray* animations = iter.UserData();
     if (animations->IsEmpty()) {
       continue;
     }
 
+    isAnimating = true;
     RefPtr<RawServoAnimationValue> animationValue;
     InfallibleTArray<AnimData> animationData;
     AnimationHelper::SetAnimations(*animations,
                                    animationData,
                                    animationValue);
     AnimationHelper::SampleResult sampleResult =
       AnimationHelper::SampleAnimationForEachNode(aTime,
                                                   *animations,
@@ -621,12 +623,14 @@ AnimationHelper::SampleAnimations(Compos
                                    Move(transform), Move(frameTransform),
                                    transformData);
         break;
       }
       default:
         MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
     }
   }
+
+  return isAnimating;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/AnimationHelper.h
+++ b/gfx/layers/AnimationHelper.h
@@ -243,18 +243,23 @@ public:
    * data.
    */
   static uint64_t GetNextCompositorAnimationsId();
 
   /**
    * 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.
+   *
+   * Returns true if there is any animation.
+   * Note that even if there are only in-delay phase animations (i.e. not
+   * visually effective), this function returns true to ensure we composite
+   * again on the next tick.
    */
-  static void
+  static bool
   SampleAnimations(CompositorAnimationStorage* aStorage,
                    TimeStamp aTime);
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_AnimationHelper_h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -1171,67 +1171,71 @@ WebRenderBridgeParent::RecvGetAPZTestDat
 }
 
 void
 WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   Destroy();
 }
 
-void
+bool
 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);
-      return;
+      return AnimationHelper::SampleAnimations(mAnimStorage, *testingTimeStamp);
     }
   }
 
   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,
+  const bool isAnimating =
+    AnimationHelper::SampleAnimations(mAnimStorage,
       !mPreviousFrameTimeStamp.IsNull()
       ? 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();
+
+  return isAnimating;
 }
 
-void
+bool
 WebRenderBridgeParent::SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                                         nsTArray<wr::WrTransformProperty>& aTransformArray)
 {
-  AdvanceAnimations();
+  const bool isAnimating = AdvanceAnimations();
 
   // return the animated data if has
   if (mAnimStorage->AnimatedValueCount()) {
     for(auto iter = mAnimStorage->ConstAnimatedValueTableIter();
         !iter.Done(); iter.Next()) {
       AnimatedValue * value = iter.UserData();
       if (value->mType == AnimatedValue::TRANSFORM) {
         aTransformArray.AppendElement(
           wr::ToWrTransformProperty(iter.Key(), value->mTransform.mTransformInDevSpace));
       } else if (value->mType == AnimatedValue::OPACITY) {
         aOpacityArray.AppendElement(
           wr::ToWrOpacityProperty(iter.Key(), value->mOpacity));
       }
     }
   }
+
+  return isAnimating;
 }
 
 void
 WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect)
 {
   // This function should only get called in the root WRBP
   MOZ_ASSERT(mWidget);
 
@@ -1268,18 +1272,17 @@ WebRenderBridgeParent::CompositeToTarget
     return;
   }
 
   wr::TransactionBuilder txn;
 
   nsTArray<wr::WrOpacityProperty> opacityArray;
   nsTArray<wr::WrTransformProperty> transformArray;
 
-  SampleAnimations(opacityArray, transformArray);
-  if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
+  if (SampleAnimations(opacityArray, transformArray)) {
     ScheduleGenerateFrame();
   }
   // We do this even if the arrays are empty, because it will clear out any
   // previous properties store on the WR side, which is desirable.
   txn.UpdateDynamicProperties(opacityArray, transformArray);
 
   SetAPZSampleTime();
 
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -209,18 +209,20 @@ private:
   LayersId GetLayersId() const;
   void ProcessWebRenderParentCommands(const InfallibleTArray<WebRenderParentCommand>& aCommands);
 
   void ClearResources();
   uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
   bool ShouldParentObserveEpoch();
   mozilla::ipc::IPCResult HandleShutdown();
 
-  void AdvanceAnimations();
-  void SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
+  // Returns true if there is any animation (including animations in delay
+  // phase).
+  bool AdvanceAnimations();
+  bool SampleAnimations(nsTArray<wr::WrOpacityProperty>& aOpacityArray,
                         nsTArray<wr::WrTransformProperty>& aTransformArray);
 
   CompositorBridgeParent* GetRootCompositorBridgeParent() const;
 
   // Tell APZ what the subsequent sampling's timestamp should be.
   void SetAPZSampleTime();
 
   wr::Epoch GetNextWrEpoch();