From 91e6c265800e802e890b3ef4d3ba330d8c4ec39e Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Thu, 6 Apr 2017 04:00:36 -0500 Subject: [PATCH] Bug 1353299. Make sure to invalidate when composited frame becomes valid. r=aosmond We draw nothing when the composited frame is invalid, so when we mark it valid we should invalidate. Usually the action that causes the composited frame to be valid will invalidate (ie RequestRefresh). --- image/FrameAnimator.cpp | 22 +++++++++++++++++----- image/FrameAnimator.h | 14 ++++++++------ image/RasterImage.cpp | 18 +++++++++++++++--- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/image/FrameAnimator.cpp b/image/FrameAnimator.cpp index 4b360b00230e2..4602782af9906 100644 --- a/image/FrameAnimator.cpp +++ b/image/FrameAnimator.cpp @@ -25,7 +25,7 @@ namespace image { // AnimationState implementation. /////////////////////////////////////////////////////////////////////////////// -void +const gfx::IntRect AnimationState::UpdateState(bool aAnimationFinished, RasterImage *aImage, const gfx::IntSize& aSize) @@ -36,12 +36,13 @@ AnimationState::UpdateState(bool aAnimationFinished, DefaultSurfaceFlags(), PlaybackType::eAnimated)); - UpdateStateInternal(result, aAnimationFinished); + return UpdateStateInternal(result, aAnimationFinished, aSize); } -void +const gfx::IntRect AnimationState::UpdateStateInternal(LookupResult& aResult, - bool aAnimationFinished) + bool aAnimationFinished, + const gfx::IntSize& aSize) { // Update mDiscarded and mIsCurrentlyDecoded. if (aResult.Type() == MatchType::NOT_FOUND) { @@ -73,6 +74,8 @@ AnimationState::UpdateStateInternal(LookupResult& aResult, } } + gfx::IntRect ret; + // Update the value of mCompositedFrameInvalid. if (mIsCurrentlyDecoded || aAnimationFinished) { // Animated images that have finished their animation (ie because it is a @@ -84,6 +87,10 @@ AnimationState::UpdateStateInternal(LookupResult& aResult, // to do for images that aren't finished animating because before we paint // the refresh driver will call into us to advance to the correct frame, // and that will succeed because we have all the frames. + if (mCompositedFrameInvalid) { + // Invalidate if we are marking the composited frame valid. + ret.SizeTo(aSize); + } mCompositedFrameInvalid = false; } else if (aResult.Type() == MatchType::NOT_FOUND || aResult.Type() == MatchType::PENDING) { @@ -94,6 +101,8 @@ AnimationState::UpdateStateInternal(LookupResult& aResult, } // Otherwise don't change the value of mCompositedFrameInvalid, it will be // updated by RequestRefresh. + + return ret; } void @@ -372,8 +381,11 @@ FrameAnimator::RequestRefresh(AnimationState& aState, DefaultSurfaceFlags(), PlaybackType::eAnimated)); - aState.UpdateStateInternal(result, aAnimationFinished); + ret.mDirtyRect = aState.UpdateStateInternal(result, aAnimationFinished, mSize); if (aState.IsDiscarded() || !result) { + if (!ret.mDirtyRect.IsEmpty()) { + ret.mFrameAdvanced = true; + } return ret; } diff --git a/image/FrameAnimator.h b/image/FrameAnimator.h index 44b5a52e7cac8..bebfbe36b739f 100644 --- a/image/FrameAnimator.h +++ b/image/FrameAnimator.h @@ -42,14 +42,16 @@ class AnimationState /** * Call this whenever a decode completes, a decode starts, or the image is * discarded. It will update the internal state. Specifically mDiscarded, - * mCompositedFrameInvalid, and mIsCurrentlyDecoded. + * mCompositedFrameInvalid, and mIsCurrentlyDecoded. Returns a rect to + * invalidate. */ - void UpdateState(bool aAnimationFinished, - RasterImage *aImage, - const gfx::IntSize& aSize); + const gfx::IntRect UpdateState(bool aAnimationFinished, + RasterImage *aImage, + const gfx::IntSize& aSize); private: - void UpdateStateInternal(LookupResult& aResult, - bool aAnimationFinished); + const gfx::IntRect UpdateStateInternal(LookupResult& aResult, + bool aAnimationFinished, + const gfx::IntSize& aSize); public: /** diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 576beff4a9383..f5d62d6259d1f 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -471,7 +471,9 @@ RasterImage::OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded) if (aAnimatedFramesDiscarded && mAnimationState) { MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable()); - mAnimationState->UpdateState(mAnimationFinished, this, mSize); + gfx::IntRect rect = + mAnimationState->UpdateState(mAnimationFinished, this, mSize); + NotifyProgress(NoProgress, rect); } if (mProgressTracker) { @@ -1084,7 +1086,9 @@ RasterImage::Discard() SurfaceCache::RemoveImage(ImageKey(this)); if (mAnimationState) { - mAnimationState->UpdateState(mAnimationFinished, this, mSize); + gfx::IntRect rect = + mAnimationState->UpdateState(mAnimationFinished, this, mSize); + NotifyProgress(NoProgress, rect); } // Notify that we discarded. @@ -1257,6 +1261,11 @@ RasterImage::Decode(const IntSize& aSize, task = DecoderFactory::CreateAnimationDecoder(mDecoderType, WrapNotNull(this), mSourceBuffer, mSize, decoderFlags, surfaceFlags); + // We may not be able to send an invalidation right here because of async + // notifications but that's not a problem because the first frame + // invalidation (when it comes) will invalidate for us. So we can ignore + // the return value of UpdateState. This also handles the invalidation + // from setting the composited frame as valid below. mAnimationState->UpdateState(mAnimationFinished, this, mSize); // If the animation is finished we can draw right away because we just draw // the final frame all the time from now on. See comment in @@ -1721,7 +1730,10 @@ RasterImage::NotifyDecodeComplete(const DecoderFinalStatus& aStatus, // We've finished a full decode of all animation frames and our AnimationState // has been notified about them all, so let it know not to expect anymore. mAnimationState->NotifyDecodeComplete(); - mAnimationState->UpdateState(mAnimationFinished, this, mSize); + gfx::IntRect rect = mAnimationState->UpdateState(mAnimationFinished, this, mSize); + if (!rect.IsEmpty()) { + NotifyProgress(NoProgress, rect); + } } // Do some telemetry if this isn't a metadata decode.