From 54898d5d6c408d36b83cea9a2594f382b24abe1d Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Wed, 28 Feb 2018 13:34:52 -0500 Subject: [PATCH] Bug 523950 - Part 5. Pass the currently displayed frame of an animation to its decoder. r=tnikkel When we need to recreate an animated image decoder because it was discarded, the animation may have progressed beyond the first frame. Given that later in the patch series we need FrameAnimator to be driving the decoding more actively, it simplifies its role by making it assume the initial state of the decoder matches its initial state. Passing in the currently displayed frame allows the decoder to advance its frame buffer (and potentially discard unnecessary frames), such that when the animation actually wants to advance as it normally would, the decoder state matches what it would have been if it had never been discarded. --- image/AnimationSurfaceProvider.cpp | 3 ++- image/AnimationSurfaceProvider.h | 3 ++- image/DecoderFactory.cpp | 3 ++- image/RasterImage.cpp | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/image/AnimationSurfaceProvider.cpp b/image/AnimationSurfaceProvider.cpp index 4ed751a93e6f..094d6dce1aea 100644 --- a/image/AnimationSurfaceProvider.cpp +++ b/image/AnimationSurfaceProvider.cpp @@ -17,7 +17,8 @@ namespace image { AnimationSurfaceProvider::AnimationSurfaceProvider(NotNull aImage, const SurfaceKey& aSurfaceKey, - NotNull aDecoder) + NotNull aDecoder, + size_t aCurrentFrame) : ISurfaceProvider(ImageKey(aImage.get()), aSurfaceKey, AvailabilityState::StartAsPlaceholder()) , mImage(aImage.get()) diff --git a/image/AnimationSurfaceProvider.h b/image/AnimationSurfaceProvider.h index 11eae75a3c51..4b291d0c6803 100644 --- a/image/AnimationSurfaceProvider.h +++ b/image/AnimationSurfaceProvider.h @@ -31,7 +31,8 @@ public: AnimationSurfaceProvider(NotNull aImage, const SurfaceKey& aSurfaceKey, - NotNull aDecoder); + NotNull aDecoder, + size_t aCurrentFrame); ////////////////////////////////////////////////////////////////////////////// diff --git a/image/DecoderFactory.cpp b/image/DecoderFactory.cpp index 3341700c0686..f4bdde8600e2 100644 --- a/image/DecoderFactory.cpp +++ b/image/DecoderFactory.cpp @@ -175,6 +175,7 @@ DecoderFactory::CreateAnimationDecoder(DecoderType aType, const IntSize& aIntrinsicSize, DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags, + size_t aCurrentFrame, IDecodingTask** aOutTask) { if (aType == DecoderType::UNKNOWN) { @@ -205,7 +206,7 @@ DecoderFactory::CreateAnimationDecoder(DecoderType aType, SurfaceKey surfaceKey = RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated); auto provider = MakeNotNull>( - aImage, surfaceKey, WrapNotNull(decoder)); + aImage, surfaceKey, WrapNotNull(decoder), aCurrentFrame); // Attempt to insert the surface provider into the surface cache right away so // we won't trigger any more decoders with the same parameters. diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index d1221ad61565..703fcd76a56d 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -1249,9 +1249,11 @@ RasterImage::Decode(const IntSize& aSize, nsresult rv; bool animated = mAnimationState && aPlaybackType == PlaybackType::eAnimated; if (animated) { + size_t currentFrame = mAnimationState->GetCurrentAnimationFrameIndex(); rv = DecoderFactory::CreateAnimationDecoder(mDecoderType, WrapNotNull(this), mSourceBuffer, mSize, decoderFlags, surfaceFlags, + currentFrame, getter_AddRefs(task)); } else { rv = DecoderFactory::CreateDecoder(mDecoderType, WrapNotNull(this),