This means that in RasterImage::LookupFrame when we are asked to do a sync decode (if needed) we use WaitUntilComplete to wait until the frame is finished decoding. But we would actually return after the next progressive pass notified the monitor to wake up. Thus, we would draw a not-fully-decoded image even though the sync decode flag was passed.
The change in FrameAnimator means that we won't draw the next frame in an animated image until all progressive passes of that image are complete. This seems like what we want anyways.
There is one real use of IsImageComplete left, in imgFrame::Draw, where we need to know if the decoded image data covers the whole image frame. (There are a couple of uses of IsImageComplete in asserts.)
The PNG decoder posts the size almost immediately, and later posts transparency (even for non-animated images).
It would be nice to still assert what this assert is intending (that transparency of non-animated images is posted during the metadata decode) but we don't have any easy way of telling when a metadata finishes here.
This is left over from the pre-SurfacePipe code that interacted directly with the Downscaler. It was calculating the size of the surface for the Downscaler to use, and then the Downscaler would handle putting transparent pixels inside that surface (and outside the framerect).
--HG--
extra : rebase_source : aad384fa8589f291254f0a18537a5d6674487182
The testcase has an svg-as-image inside an svg-as-image. At shutdown the viewer of the inner svg-as-image is destroyed (via the shutdown observer) first. Then the outer svg-as-image destroys its viewer which tries to unregister all image requests from the refresh driver. So it unregisters the inner svg-as-image, which calls GetAnimated.
When storing ms, 32 bit ints can hold 2^32/1000/60/60/24 ~= 49 days. It's quite conceivable that someone would leave a tab in the background for 50 days.
GetSingleLoopTime returns -1 on exceptional cases but we used an unsigned int to hold the return value in AdvanceFrame. So the |loopTime > 0| check would succeed. Fortunately the |delay.ToMilliseconds() > loopTime| check would fail because loopTime was MAX_UNIT32, so we didn't do anything incorrect.
http://hg.mozilla.org/mozilla-central/rev/263980931d1b (bug 890743) changed GetSingleLoopTime from returning 0 (and uint32_t) to -1 (and int32_t) on exceptional cases. But the caller of GetSingleLoopTime wasn't updated.
Before the previous patch we would (wrongly) loop through the decoded frames even though we didn't have all of the frames of the animation. This had the beneficial side effect of advancing mCurrentAnimationFrameTime to aTime (the current time). With the previous patch we stop at the last decoded frame and don't advance mCurrentAnimationFrameTime, so it can lag behind. The problem with this is that when we have finished decoding we will then try to catch mCurrentAnimationFrameTime up, and this will jump us to a random point in the animation. So we need to advance mCurrentAnimationFrameTime ourselves.
If we were blocked on network/decoding then displaying the last available decoded frame is the correct frame to be displaying. So we are up to date. So we advance mCurrentAnimationFrameTime to the current time.
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.
http://hg.mozilla.org/mozilla-central/rev/411f18fdffeb (bug 1186796) had a mistake in it.
It changed ImageSurfaceCache::LookupBestMatch to use a for loop instead of using a callback to iterate each entry of the hashtable. The callback was called with the surface key of its entry, and it used the name |aSurfaceKey| for that key. ImageSurfaceCache::LookupBestMatch uses the name |aSurfaceKey| for the key we are looking for. So when the code from the callback was moved into the for loop in ImageSurfaceCache::LookupBestMatch the meaning of |aSurfaceKey| changed, but the code was not updated.