Bug 926048. Part 3. Correctly check if we are at the end of an animated image. r=edwin
authorTimothy Nikkel <tnikkel@gmail.com>
Tue, 01 Mar 2016 22:34:40 -0600
changeset 336070 68dd453ec527500a44e25164d4f433526610c8ab
parent 336069 2b3a42aa606a417915f4eac3690b6add47a582b1
child 336071 bddda82562e9007b8f76f887628a4a02d4b225f8
push id11963
push userbenj@benj.me
push dateWed, 02 Mar 2016 09:46:33 +0000
Bug 926048. Part 3. Correctly check if we are at the end of an animated image. r=edwin mImage->GetNumFrames() is the current number of decoded frames (that the RasterImage knows about), so it only represents the last frame of the animation if we are done decoding. If we are not fully decoded, and we are on the last decoded frame, just stay on the last decoded frame. When more frames get decoded (or we determine that we are the last frame of the animation) we will advance. One might expect that if |nextFrameIndex == mImage->GetNumFrames()| then |GetRawFrame(nextFrameIndex)| would return a null surface. But that is not the case because the decoding thread can insert frames into the surface cache that the RasterImage hasn't acknowledged yet (because it has to do so on the main thread, which we are currently running on). This is why moving animated images to the surface cache is likely the cause of this bug. This introduces an issue that is explained in, and fixed by the next patch.
--- a/image/FrameAnimator.cpp
+++ b/image/FrameAnimator.cpp
@@ -97,16 +97,23 @@ FrameAnimator::AdvanceFrame(TimeStamp aT
     // Uh oh, the frame we want to show is currently being decoded (partial)
     // Wait until the next refresh driver tick and try again
     return ret;
   // If we're done decoding the next frame, go ahead and display it now and
   // reinit with the next frame's delay time.
   if (mImage->GetNumFrames() == nextFrameIndex) {
+    // We can only accurately determine if we are at the end of the loop if we are
+    // done decoding, otherwise we don't know how many frames there will be.
+    if (!mDoneDecoding) {
+      // We've already advanced to the last decoded frame, nothing more we can do.
+      return ret;
+    }
     // End of an animation loop...
     // If we are not looping forever, initialize the loop counter
     if (mLoopRemainingCount < 0 && LoopCount() >= 0) {
       mLoopRemainingCount = LoopCount();
     // If animation mode is "loop once", or we're at end of loop counter,