Bug 1288040 (Part 8) - Return a FrameTimeout value from FrameAnimator::GetSingleLoopTime(). r=edwin
authorSeth Fowler <mark.seth.fowler@gmail.com>
Tue, 19 Jul 2016 15:48:37 -0700
changeset 305962 b6b8a4bc9168e7f0422c6bf612776a875ea32dc6
parent 305961 76ad9c12237689a490d756def046bd6e4b8901ac
child 305963 ec558fefe42f16f4f8e1c0345762d9f59facd49b
push id30474
push usercbook@mozilla.com
push dateThu, 21 Jul 2016 14:25:10 +0000
treeherdermozilla-central@6b180266ac16 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin
bugs1288040
milestone50.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 1288040 (Part 8) - Return a FrameTimeout value from FrameAnimator::GetSingleLoopTime(). r=edwin
image/FrameAnimator.cpp
image/FrameAnimator.h
--- a/image/FrameAnimator.cpp
+++ b/image/FrameAnimator.cpp
@@ -74,43 +74,43 @@ AnimationState::GetFirstFrameRefreshArea
   return mFirstFrameRefreshArea;
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // FrameAnimator implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
-int32_t
+FrameTimeout
 FrameAnimator::GetSingleLoopTime(AnimationState& aState) const
 {
   // If we aren't done decoding, we don't know the image's full play time.
   if (!aState.mDoneDecoding) {
-    return -1;
+    return FrameTimeout::Forever();
   }
 
-  // If we're not looping, a single loop time has no meaning
+  // If we're not looping, a single loop time has no meaning.
   if (aState.mAnimationMode != imgIContainer::kNormalAnimMode) {
-    return -1;
+    return FrameTimeout::Forever();
   }
 
-  int32_t looptime = 0;
+  // Add up the timeouts of all the frames.
+  FrameTimeout loopTime = FrameTimeout::Zero();
   for (uint32_t i = 0; i < mImage->GetNumFrames(); ++i) {
-    FrameTimeout timeout = GetTimeoutForFrame(i);
-    if (timeout == FrameTimeout::Forever()) {
-      // If we have a frame that never times out, we're probably in an error
-      // case, but let's handle it more gracefully.
-      NS_WARNING("Infinite frame timeout - how did this happen?");
-      return -1;
-    }
-
-    looptime += timeout.AsMilliseconds();
+    loopTime += GetTimeoutForFrame(i);
   }
 
-  return looptime;
+  if (loopTime == FrameTimeout::Forever()) {
+    // We have at least one frame that never times out. This may be an error,
+    // but we'll try to handle it gracefully.
+    // XXX(seth): I don't think this is actually ever an error.
+    NS_WARNING("Infinite frame timeout - how did this happen?");
+  }
+
+  return loopTime;
 }
 
 TimeStamp
 FrameAnimator::GetCurrentImgFrameEndTime(AnimationState& aState) const
 {
   TimeStamp currentFrameTime = aState.mCurrentAnimationFrameTime;
   FrameTimeout timeout = GetTimeoutForFrame(aState.mCurrentAnimationFrameIndex);
 
@@ -232,29 +232,26 @@ FrameAnimator::AdvanceFrame(AnimationSta
     nextFrame->SetCompositingFailed(false);
   }
 
   aState.mCurrentAnimationFrameTime = GetCurrentImgFrameEndTime(aState);
 
   // If we can get closer to the current time by a multiple of the image's loop
   // time, we should. We need to be done decoding in order to know the full loop
   // time though!
-  int32_t loopTime = GetSingleLoopTime(aState);
-  if (loopTime > 0) {
-    // We shouldn't be advancing by a whole loop unless we are decoded and know
-    // what a full loop actually is. GetSingleLoopTime should return -1 so this
-    // never happens.
-    MOZ_ASSERT(aState.mDoneDecoding);
+  FrameTimeout loopTime = GetSingleLoopTime(aState);
+  if (loopTime != FrameTimeout::Forever()) {
     TimeDuration delay = aTime - aState.mCurrentAnimationFrameTime;
-    if (delay.ToMilliseconds() > loopTime) {
+    if (delay.ToMilliseconds() > loopTime.AsMilliseconds()) {
       // Explicitly use integer division to get the floor of the number of
       // loops.
-      uint64_t loops = static_cast<uint64_t>(delay.ToMilliseconds()) / loopTime;
+      uint64_t loops = static_cast<uint64_t>(delay.ToMilliseconds())
+                     / loopTime.AsMilliseconds();
       aState.mCurrentAnimationFrameTime +=
-        TimeDuration::FromMilliseconds(loops * loopTime);
+        TimeDuration::FromMilliseconds(loops * loopTime.AsMilliseconds());
     }
   }
 
   // Set currentAnimationFrameIndex at the last possible moment
   aState.mCurrentAnimationFrameIndex = nextFrameIndex;
 
   // If we're here, we successfully advanced the frame.
   ret.frameAdvanced = true;
--- a/image/FrameAnimator.h
+++ b/image/FrameAnimator.h
@@ -206,23 +206,21 @@ private: // methods
   RefreshResult AdvanceFrame(AnimationState& aState, TimeStamp aTime);
 
   /**
    * Get the @aIndex-th frame in the frame index, ignoring results of blending.
    */
   RawAccessFrameRef GetRawFrame(uint32_t aFrameNum) const;
 
   /**
-   * Gets the length of a single loop of this image, in milliseconds.
-   *
-   * If this image is not finished decoding, is not animated, or it is animated
-   * but does not loop, returns -1. Can return 0 in the case of an animated
-   * image that has a 0ms delay between its frames and does not loop.
+   * @return the length of a single loop of this image, as a FrameTimeout value
+   * in milliseconds. If this image is not finished decoding, is not animated,
+   * or it is animated but does not loop, returns FrameTimeout::Forever().
    */
-  int32_t GetSingleLoopTime(AnimationState& aState) const;
+  FrameTimeout GetSingleLoopTime(AnimationState& aState) const;
 
   /// @return the given frame's timeout.
   FrameTimeout GetTimeoutForFrame(uint32_t aFrameNum) const;
 
   /**
    * Get the time the frame we're currently displaying is supposed to end.
    *
    * In the error case, returns an "infinity" timestamp.