Bug 927349 part 13 - Update start times on animations in layers when the animation ready time is resolved; r=nical
authorBrian Birtles <birtles@gmail.com>
Mon, 22 Dec 2014 09:35:41 +0900
changeset 220797 0743f344f853387ab01b574f43192e9bceed580e
parent 220796 f40d9ed7a3df0b7a2ca4a2d67fed371be9daff8a
child 220798 9ff976d369ff942753e52e63a200f404276be184
push id53192
push userbbirtles@mozilla.com
push dateMon, 22 Dec 2014 00:36:19 +0000
treeherdermozilla-inbound@c7aaf7025e59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs927349
milestone37.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 927349 part 13 - Update start times on animations in layers when the animation ready time is resolved; r=nical
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
layout/base/nsDisplayList.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -467,16 +467,38 @@ Layer::SetAnimations(const AnimationArra
       }
     }
   }
 
   Mutated();
 }
 
 void
+Layer::StartPendingAnimations(const TimeStamp& aReadyTime)
+{
+  bool updated = false;
+  for (size_t animIdx = 0, animEnd = mAnimations.Length();
+       animIdx < animEnd; animIdx++) {
+    Animation& anim = mAnimations[animIdx];
+    if (anim.startTime().IsNull()) {
+      anim.startTime() = aReadyTime - anim.initialCurrentTime();
+      updated = true;
+    }
+  }
+
+  if (updated) {
+    Mutated();
+  }
+
+  for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
+    child->StartPendingAnimations(aReadyTime);
+  }
+}
+
+void
 Layer::SetAsyncPanZoomController(uint32_t aIndex, AsyncPanZoomController *controller)
 {
   MOZ_ASSERT(aIndex < GetFrameMetricsCount());
   mApzcs[aIndex] = controller;
 }
 
 AsyncPanZoomController*
 Layer::GetAsyncPanZoomController(uint32_t aIndex) const
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1102,16 +1102,21 @@ public:
   // Call AddAnimation to add a new animation to this layer from layout code.
   // Caller must fill in all the properties of the returned animation.
   Animation* AddAnimation();
   // ClearAnimations clears animations on this layer.
   void ClearAnimations();
   // This is only called when the layer tree is updated. Do not call this from
   // layout code.  To add an animation to this layer, use AddAnimation.
   void SetAnimations(const AnimationArray& aAnimations);
+  // Go through all animations in this layer and its children and, for
+  // any animations with a null start time, update their start time such
+  // that at |aReadyTime| the animation's current time corresponds to its
+  // 'initial current time' value.
+  void StartPendingAnimations(const TimeStamp& aReadyTime);
 
   // These are a parallel to AddAnimation and clearAnimations, except
   // they add pending animations that apply only when the next
   // transaction is begun.  (See also
   // SetBaseTransformForNextTransaction.)
   Animation* AddAnimationForNextTransaction();
   void ClearAnimationsForNextTransaction();
 
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -542,16 +542,17 @@ BasicLayerManager::EndTransactionInterna
     if (!mTransactionIncomplete) {
       // Clear out target if we have a complete transaction.
       mTarget = nullptr;
     }
   }
 
   if (mRoot) {
     mAnimationReadyTime = TimeStamp::Now();
+    mRoot->StartPendingAnimations(mAnimationReadyTime);
   }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   Log();
   MOZ_LAYERS_LOG(("]----- EndTransaction"));
 #endif
 
   // Go back to the construction phase if the transaction isn't complete.
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -267,16 +267,17 @@ ClientLayerManager::EndTransactionIntern
 
   root->RenderLayer();
   if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) {
     GetRoot()->Mutated();
   }
 
   if (!mIsRepeatTransaction) {
     mAnimationReadyTime = TimeStamp::Now();
+    GetRoot()->StartPendingAnimations(mAnimationReadyTime);
   }
 
   mPaintedLayerCallback = nullptr;
   mPaintedLayerCallbackData = nullptr;
 
   // Go back to the construction phase if the transaction isn't complete.
   // Layout will update the layer tree and call EndTransaction().
   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -442,16 +442,18 @@ SampleAnimations(Layer* aLayer, TimeStam
   bool activeAnimations = false;
 
   for (uint32_t i = animations.Length(); i-- !=0; ) {
     Animation& animation = animations[i];
     AnimData& animData = animationData[i];
 
     activeAnimations = true;
 
+    MOZ_ASSERT(!animation.startTime().IsNull(),
+               "Failed to resolve start time of pending animations");
     TimeDuration elapsedDuration = aPoint - animation.startTime();
     // Skip animations that are yet to start.
     //
     // Currently, this should only happen when the refresh driver is under test
     // control and is made to produce a time in the past or is restored from
     // test control causing it to jump backwards in time.
     //
     // Since activeAnimations is true, this could mean we keep compositing
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -357,17 +357,19 @@ AddAnimationForProperty(nsIFrame* aFrame
   nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
 
   layers::Animation* animation =
     aPending ?
     aLayer->AddAnimationForNextTransaction() :
     aLayer->AddAnimation();
 
   const AnimationTiming& timing = aPlayer->GetSource()->Timing();
-  animation->startTime() = aPlayer->Timeline()->ToTimeStamp(
+  animation->startTime() = aPlayer->GetStartTime().IsNull()
+                         ? TimeStamp()
+                         : aPlayer->Timeline()->ToTimeStamp(
                              aPlayer->GetStartTime().Value() + timing.mDelay);
   animation->initialCurrentTime() = aPlayer->GetCurrentTime().Value()
                                     - timing.mDelay;
   animation->duration() = timing.mIterationDuration;
   animation->iterationCount() = timing.mIterationCount;
   animation->direction() = timing.mDirection;
   animation->property() = aProperty;
   animation->data() = aData;