From b63799e1894caae2048873a820460dd92311216f Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Sat, 10 Jan 2015 20:47:38 -0800 Subject: [PATCH] Bug 1118092 - Manage invalidation policy directly in the image decoder. r=tn --- image/decoders/nsICODecoder.cpp | 2 ++ image/src/Decoder.cpp | 16 +++++++++++++--- image/src/Decoder.h | 19 +++++++++++++++++++ image/src/RasterImage.cpp | 11 +---------- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/image/decoders/nsICODecoder.cpp b/image/decoders/nsICODecoder.cpp index 92b6f9e9274..fa447bf8a31 100644 --- a/image/decoders/nsICODecoder.cpp +++ b/image/decoders/nsICODecoder.cpp @@ -345,6 +345,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount) if (mIsPNG) { mContainedDecoder = new nsPNGDecoder(mImage); mContainedDecoder->SetSizeDecode(IsSizeDecode()); + mContainedDecoder->SetSendPartialInvalidations(mSendPartialInvalidations); mContainedDecoder->Init(); if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE)) { return; @@ -421,6 +422,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount) mContainedDecoder = bmpDecoder; bmpDecoder->SetUseAlphaData(true); mContainedDecoder->SetSizeDecode(IsSizeDecode()); + mContainedDecoder->SetSendPartialInvalidations(mSendPartialInvalidations); mContainedDecoder->Init(); // The ICO format when containing a BMP does not include the 14 byte diff --git a/image/src/Decoder.cpp b/image/src/Decoder.cpp index 92a247e078c..7080dd92433 100644 --- a/image/src/Decoder.cpp +++ b/image/src/Decoder.cpp @@ -28,6 +28,7 @@ Decoder::Decoder(RasterImage &aImage) , mChunkCount(0) , mDecodeFlags(0) , mBytesDecoded(0) + , mSendPartialInvalidations(false) , mDecodeDone(false) , mDataError(false) , mFrameCount(0) @@ -364,6 +365,12 @@ Decoder::PostFrameStop(Opacity aFrameOpacity /* = Opacity::TRANSPARENT */, mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout, aBlendMethod); mProgress |= FLAG_FRAME_COMPLETE | FLAG_ONLOAD_UNBLOCKED; + + // If we're not sending partial invalidations, then we send an invalidation + // here when the first frame is complete. + if (!mSendPartialInvalidations && !mIsAnimated) { + mInvalidRect.UnionRect(mInvalidRect, mCurrentFrame->GetRect()); + } } void @@ -373,9 +380,12 @@ Decoder::PostInvalidation(nsIntRect& aRect) NS_ABORT_IF_FALSE(mInFrame, "Can't invalidate when not mid-frame!"); NS_ABORT_IF_FALSE(mCurrentFrame, "Can't invalidate when not mid-frame!"); - // Account for the new region - mInvalidRect.UnionRect(mInvalidRect, aRect); - mCurrentFrame->ImageUpdated(aRect); + // Record this invalidation, unless we're not sending partial invalidations + // or we're past the first frame. + if (mSendPartialInvalidations && !mIsAnimated) { + mInvalidRect.UnionRect(mInvalidRect, aRect); + mCurrentFrame->ImageUpdated(aRect); + } } void diff --git a/image/src/Decoder.h b/image/src/Decoder.h index 92ad646f5c4..dffb30b395a 100644 --- a/image/src/Decoder.h +++ b/image/src/Decoder.h @@ -92,6 +92,24 @@ public: mSizeDecode = aSizeDecode; } + /** + * Set whether should send partial invalidations. + * + * If @aSend is true, we'll send partial invalidations when decoding the first + * frame of the image, so image notifications observers will be able to + * gradually draw in the image as it downloads. + * + * If @aSend is false (the default), we'll only send an invalidation when we + * complete the first frame. + * + * This must be called before Init() is called. + */ + void SetSendPartialInvalidations(bool aSend) + { + MOZ_ASSERT(!mInitialized, "Shouldn't be initialized yet"); + mSendPartialInvalidations = aSend; + } + size_t BytesDecoded() const { return mBytesDecoded; } // The amount of time we've spent inside Write() so far for this decoder. @@ -262,6 +280,7 @@ protected: uint32_t mDecodeFlags; size_t mBytesDecoded; + bool mSendPartialInvalidations; bool mDecodeDone; bool mDataError; diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index b0778b10505..74c05873c9c 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -1505,6 +1505,7 @@ RasterImage::InitDecoder(bool aDoSizeDecode) // Initialize the decoder mDecoder->SetSizeDecode(aDoSizeDecode); mDecoder->SetDecodeFlags(mFrameDecodeFlags); + mDecoder->SetSendPartialInvalidations(!mHasBeenDecoded); mDecoder->Init(); CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError()); @@ -2407,16 +2408,6 @@ RasterImage::FinishedSomeDecoding(ShutdownReason aReason /* = ShutdownReason::DO } } - if (GetCurrentFrameIndex() > 0) { - // Don't send invalidations for animated frames after the first; let - // RequestRefresh take care of that. - invalidRect = nsIntRect(); - } - if (mHasBeenDecoded && !invalidRect.IsEmpty()) { - // Don't send partial invalidations if we've been decoded before. - invalidRect = mDecoded ? GetFirstFrameRect() - : nsIntRect(); - } if (!invalidRect.IsEmpty() && wasDefaultFlags) { // Update our image container since we're invalidating. UpdateImageContainer();