Bug 1033114 Part 3: Make mStartTime a nullable TimeDuration r=birtles
authorDavid Zbarsky <dzbarsky@gmail.com>
Sat, 30 Aug 2014 02:11:57 -0400
changeset 225478 f9448cb58a5a6bc0ff6ee336ff3daaa96ab72501
parent 225477 4e2595393b7cd6df9fedc794eb9bfa73c04da216
child 225479 9db3e43c19c1177fd9b07bac0f3326e18589cddd
push id583
push userbhearsum@mozilla.com
push dateMon, 24 Nov 2014 19:04:58 +0000
treeherdermozilla-release@c107e74250f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1033114
milestone34.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 1033114 Part 3: Make mStartTime a nullable TimeDuration r=birtles
dom/animation/AnimationPlayer.cpp
dom/animation/AnimationPlayer.h
dom/animation/AnimationTimeline.cpp
dom/animation/AnimationTimeline.h
dom/animation/AnimationUtils.h
layout/base/nsDisplayList.cpp
layout/style/nsAnimationManager.cpp
layout/style/nsTransitionManager.cpp
--- a/dom/animation/AnimationPlayer.cpp
+++ b/dom/animation/AnimationPlayer.cpp
@@ -1,14 +1,15 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AnimationPlayer.h"
+#include "AnimationUtils.h"
 #include "mozilla/dom/AnimationPlayerBinding.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationPlayer, mTimeline, mSource)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationPlayer, AddRef)
@@ -18,17 +19,17 @@ JSObject*
 AnimationPlayer::WrapObject(JSContext* aCx)
 {
   return dom::AnimationPlayerBinding::Wrap(aCx, this);
 }
 
 Nullable<double>
 AnimationPlayer::GetStartTime() const
 {
-  return mTimeline->ToTimelineTime(mStartTime);
+  return AnimationUtils::TimeDurationToDouble(mStartTime);
 }
 
 Nullable<double>
 AnimationPlayer::GetCurrentTime() const
 {
   Nullable<double> result;
   Nullable<TimeDuration> currentTime = GetCurrentTimeDuration();
 
--- a/dom/animation/AnimationPlayer.h
+++ b/dom/animation/AnimationPlayer.h
@@ -67,33 +67,27 @@ public:
   bool IsCurrent() const;
 
   // Return the duration since the start time of the player, taking into
   // account the pause state.  May be negative.
   // Returns a null value if the timeline associated with this object has a
   // current timestamp that is null or if the start time of this object is
   // null.
   Nullable<TimeDuration> GetCurrentTimeDuration() const {
-    const TimeStamp& timelineTime = mTimeline->GetCurrentTimeStamp();
-    // FIXME: In order to support arbitrary timelines we will need to fix
-    // the pause logic to handle the timeline time going backwards.
-    MOZ_ASSERT(timelineTime.IsNull() || !IsPaused() ||
-               timelineTime >= mHoldTime,
-               "if paused, any non-null value of aTime must be at least"
-               " mHoldTime");
-
+    Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTimeDuration();
+    Nullable<TimeDuration> holdDuration = mTimeline->ToTimelineTime(mHoldTime);
     Nullable<TimeDuration> result; // Initializes to null
     if (!timelineTime.IsNull() && !mStartTime.IsNull()) {
-      result.SetValue((IsPaused() ? mHoldTime : timelineTime) - mStartTime);
+      result.SetValue((IsPaused() ? holdDuration.Value() : timelineTime.Value()) - mStartTime.Value());
     }
     return result;
   }
 
   // The beginning of the delay period.
-  TimeStamp mStartTime;
+  Nullable<TimeDuration> mStartTime;
   TimeStamp mHoldTime;
   uint8_t mPlayState;
   bool mIsRunningOnCompositor;
 
   nsRefPtr<AnimationTimeline> mTimeline;
   nsRefPtr<Animation> mSource;
 };
 
--- a/dom/animation/AnimationTimeline.cpp
+++ b/dom/animation/AnimationTimeline.cpp
@@ -1,15 +1,16 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AnimationTimeline.h"
 #include "mozilla/dom/AnimationTimelineBinding.h"
+#include "AnimationUtils.h"
 #include "nsContentUtils.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRefreshDriver.h"
 #include "nsDOMNavigationTiming.h"
 
 namespace mozilla {
 namespace dom {
@@ -23,17 +24,17 @@ JSObject*
 AnimationTimeline::WrapObject(JSContext* aCx)
 {
   return AnimationTimelineBinding::Wrap(aCx, this);
 }
 
 Nullable<double>
 AnimationTimeline::GetCurrentTime() const
 {
-  return ToTimelineTime(GetCurrentTimeStamp());
+  return AnimationUtils::TimeDurationToDouble(GetCurrentTimeDuration());
 }
 
 TimeStamp
 AnimationTimeline::GetCurrentTimeStamp() const
 {
   // Always return the same object to benefit from return-value optimization.
   TimeStamp result = mLastCurrentTime;
 
@@ -62,27 +63,46 @@ AnimationTimeline::GetCurrentTimeStamp()
   // FIXME: We would like to assert that:
   //   mLastCurrentTime.IsNull() || result >= mLastCurrentTime
   // but due to bug 1043078 this will not be the case when the refresh driver
   // is restored from test control.
   mLastCurrentTime = result;
   return result;
 }
 
-Nullable<double>
-AnimationTimeline::ToTimelineTime(const mozilla::TimeStamp& aTimeStamp) const
+Nullable<TimeDuration>
+AnimationTimeline::GetCurrentTimeDuration() const
 {
-  Nullable<double> result; // Initializes to null
+  return ToTimelineTime(GetCurrentTimeStamp());
+}
+
+Nullable<TimeDuration>
+AnimationTimeline::ToTimelineTime(const TimeStamp& aTimeStamp) const
+{
+  Nullable<TimeDuration> result; // Initializes to null
   if (aTimeStamp.IsNull()) {
     return result;
   }
 
   nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
   if (MOZ_UNLIKELY(!timing)) {
     return result;
   }
 
-  result.SetValue(timing->TimeStampToDOMHighRes(aTimeStamp));
+  result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp());
+  return result;
+}
+
+TimeStamp
+AnimationTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const
+{
+  TimeStamp result;
+  nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
+  if (MOZ_UNLIKELY(!timing)) {
+    return result;
+  }
+
+  result = timing->GetNavigationStartTimeStamp() + aTimeDuration;
   return result;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/animation/AnimationTimeline.h
+++ b/dom/animation/AnimationTimeline.h
@@ -28,28 +28,33 @@ public:
   }
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationTimeline)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationTimeline)
 
   nsISupports* GetParentObject() const { return mDocument; }
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
+  // WebIDL API
   Nullable<double> GetCurrentTime() const;
-  mozilla::TimeStamp GetCurrentTimeStamp() const;
+
+  Nullable<TimeDuration> GetCurrentTimeDuration() const;
 
-  Nullable<double> ToTimelineTime(const mozilla::TimeStamp& aTimeStamp) const;
+  Nullable<TimeDuration> ToTimelineTime(const TimeStamp& aTimeStamp) const;
+  TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const;
+
+  TimeStamp GetCurrentTimeStamp() const;
 
 protected:
   virtual ~AnimationTimeline() { }
 
   nsCOMPtr<nsIDocument> mDocument;
 
   // Store the most recently returned value of current time. This is used
   // in cases where we don't have a refresh driver (e.g. because we are in
   // a display:none iframe).
-  mutable mozilla::TimeStamp mLastCurrentTime;
+  mutable TimeStamp mLastCurrentTime;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_AnimationTimeline_h
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationUtils.h
@@ -0,0 +1,29 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/TimeStamp.h"
+#include "mozilla/dom/Nullable.h"
+
+namespace mozilla {
+namespace dom {
+
+class AnimationUtils
+{
+public:
+  static Nullable<double>
+    TimeDurationToDouble(const Nullable<TimeDuration>& aTime)
+  {
+    Nullable<double> result;
+
+    if (!aTime.IsNull()) {
+      result.SetValue(aTime.Value().ToMilliseconds());
+    }
+
+    return result;
+  }
+};
+
+} // namespace dom
+} // namespace mozilla
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -346,17 +346,17 @@ 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->mStartTime + timing.mDelay;
+  animation->startTime() = aPlayer->Timeline()->ToTimeStamp(aPlayer->mStartTime.Value() + timing.mDelay);
   animation->duration() = timing.mIterationDuration;
   animation->iterationCount() = timing.mIterationCount;
   animation->direction() = timing.mDirection;
   animation->property() = aProperty;
   animation->data() = aData;
 
   dom::Animation* anim = aPlayer->GetSource();
   for (size_t propIdx = 0;
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -313,17 +313,17 @@ nsAnimationManager::CheckAnimationRule(n
           } else if (oldPlayer->IsPaused() && !newPlayer->IsPaused()) {
             const TimeStamp& now = timeline->GetCurrentTimeStamp();
             if (!now.IsNull()) {
               // FIXME: Once we store the start time and pause start as
               // offsets (not timestamps) we should be able to update the
               // start time to something more appropriate when now IsNull.
               // Handle change in pause state by adjusting start time to
               // unpause.
-              oldPlayer->mStartTime += now - oldPlayer->mHoldTime;
+              oldPlayer->mStartTime.SetValue(now + oldPlayer->mStartTime.Value() - oldPlayer->mHoldTime);
             }
             oldPlayer->mHoldTime = TimeStamp();
           }
           oldPlayer->mPlayState = newPlayer->mPlayState;
 
           // Replace new animation with the (updated) old one and remove the
           // old one from the array so we don't try to match it any more.
           //
@@ -449,17 +449,17 @@ nsAnimationManager::BuildAnimations(nsSt
     timing.mIterationCount = src.GetIterationCount();
     timing.mDirection = src.GetDirection();
     timing.mFillMode = src.GetFillMode();
 
     nsRefPtr<Animation> destAnim =
       new Animation(mPresContext->Document(), timing, src.GetName());
     dest->SetSource(destAnim);
 
-    dest->mStartTime = now;
+    dest->mStartTime = aTimeline->GetCurrentTimeDuration();
     dest->mPlayState = src.GetPlayState();
     if (dest->IsPaused()) {
       dest->mHoldTime = now;
     } else {
       dest->mHoldTime = TimeStamp();
     }
 
     // While current drafts of css3-animations say that later keyframes
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -525,17 +525,17 @@ nsTransitionManager::ConsiderStartingTra
   AnimationPropertySegment& segment = *prop.mSegments.AppendElement();
   segment.mFromValue = startValue;
   segment.mToValue = endValue;
   segment.mFromKey = 0;
   segment.mToKey = 1;
   segment.mTimingFunction.Init(tf);
 
   nsRefPtr<dom::AnimationPlayer> player = new dom::AnimationPlayer(timeline);
-  player->mStartTime = timeline->GetCurrentTimeStamp();
+  player->mStartTime = timeline->GetCurrentTimeDuration();
   player->SetSource(pt);
 
   if (!aElementTransitions) {
     aElementTransitions =
       GetElementTransitions(aElement, aNewStyleContext->GetPseudoType(),
                             true);
     if (!aElementTransitions) {
       NS_WARNING("allocating CommonAnimationManager failed");