diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 50fa33c78633..375de5542542 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -320,6 +320,7 @@ RasterImage::RasterImage(ProgressTracker* aProgressTracker, #endif mDecodingMonitor("RasterImage Decoding Monitor"), mDecoder(nullptr), + mDecodeStatus(DecodeStatus::INACTIVE), mNotifyProgress(NoProgress), mNotifying(false), mHasSize(false), @@ -1665,7 +1666,6 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus, bo { ReentrantMonitorAutoEnter lock(mDecodingMonitor); FinishedSomeDecoding(eShutdownIntent_Done, - nullptr, LoadCompleteProgress(aLastPart, mError, finalStatus)); } @@ -1732,7 +1732,7 @@ RasterImage::OnNewSourceData() mHasSourceData = false; mHasSize = false; mWantFullDecode = true; - mDecodeRequest = nullptr; + mDecodeStatus = DecodeStatus::INACTIVE; if (mAnim) { mAnim->SetDoneDecoding(false); @@ -1833,7 +1833,7 @@ RasterImage::Discard(bool force) if (mProgressTracker) mProgressTracker->OnDiscard(); - mDecodeRequest = nullptr; + mDecodeStatus = DecodeStatus::INACTIVE; if (force) DiscardTracker::Remove(&mDiscardTrackerNode); @@ -1953,9 +1953,6 @@ RasterImage::InitDecoder(bool aDoSizeDecode) } // Initialize the decoder - if (!mDecodeRequest) { - mDecodeRequest = new DecodeRequest(this); - } mDecoder->SetSizeDecode(aDoSizeDecode); mDecoder->SetDecodeFlags(mFrameDecodeFlags); if (!aDoSizeDecode) { @@ -2168,8 +2165,7 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType) } // If the image is waiting for decode work to be notified, go ahead and do that. - if (mDecodeRequest && - mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE && + if (mDecodeStatus == DecodeStatus::WORK_DONE && aDecodeType == SYNCHRONOUS_NOTIFY) { ReentrantMonitorAutoEnter lock(mDecodingMonitor); nsresult rv = FinishedSomeDecoding(); @@ -2205,9 +2201,7 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType) // we need to repeat the following three checks after getting the lock. // If the image is waiting for decode work to be notified, go ahead and do that. - if (mDecodeRequest && - mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE && - aDecodeType != ASYNCHRONOUS) { + if (mDecodeStatus == DecodeStatus::WORK_DONE && aDecodeType != ASYNCHRONOUS) { nsresult rv = FinishedSomeDecoding(); CONTAINER_ENSURE_SUCCESS(rv); } @@ -2292,12 +2286,10 @@ RasterImage::SyncDecode() ReentrantMonitorAutoEnter lock(mDecodingMonitor); - if (mDecodeRequest) { - // If the image is waiting for decode work to be notified, go ahead and do that. - if (mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) { - nsresult rv = FinishedSomeDecoding(); - CONTAINER_ENSURE_SUCCESS(rv); - } + // If the image is waiting for decode work to be notified, go ahead and do that. + if (mDecodeStatus == DecodeStatus::WORK_DONE) { + nsresult rv = FinishedSomeDecoding(); + CONTAINER_ENSURE_SUCCESS(rv); } nsresult rv; @@ -2894,20 +2886,12 @@ RasterImage::RequestDecodeIfNeeded(nsresult aStatus, nsresult RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_Done */, - DecodeRequest* aRequest /* = nullptr */, Progress aProgress /* = NoProgress */) { MOZ_ASSERT(NS_IsMainThread()); mDecodingMonitor.AssertCurrentThreadIn(); - nsRefPtr request; - if (aRequest) { - request = aRequest; - } else { - request = mDecodeRequest; - } - // Ensure that, if the decoder is the last reference to the image, we don't // destroy it by destroying the decoder. nsRefPtr image(this); @@ -2942,7 +2926,7 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D wasSize = decoder->IsSizeDecode(); // Do some telemetry if this isn't a size decode. - if (request && !wasSize) { + if (!wasSize) { Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME, int32_t(decoder->DecodeTime().ToMicroseconds())); @@ -3140,15 +3124,15 @@ RasterImage::DecodePool::RequestDecode(RasterImage* aImg) // If we're currently waiting on a new frame for this image, we can't do any // decoding. if (!aImg->mDecoder->NeedsNewFrame()) { - if (aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_PENDING || - aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_ACTIVE) { + if (aImg->mDecodeStatus == DecodeStatus::PENDING || + aImg->mDecodeStatus == DecodeStatus::ACTIVE) { // The image is already in our list of images to decode, or currently being // decoded, so we don't have to do anything else. return; } - aImg->mDecodeRequest->mRequestStatus = DecodeRequest::REQUEST_PENDING; - nsRefPtr job = new DecodeJob(aImg->mDecodeRequest, aImg); + aImg->mDecodeStatus = DecodeStatus::PENDING; + nsRefPtr job = new DecodeJob(aImg); MutexAutoLock threadPoolLock(mThreadPoolMutex); if (!gfxPrefs::ImageMTDecodingEnabled() || !mThreadPool) { @@ -3165,11 +3149,9 @@ RasterImage::DecodePool::DecodeABitOf(RasterImage* aImg, DecodeStrategy aStrateg MOZ_ASSERT(NS_IsMainThread()); aImg->mDecodingMonitor.AssertCurrentThreadIn(); - if (aImg->mDecodeRequest) { - // If the image is waiting for decode work to be notified, go ahead and do that. - if (aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) { - aImg->FinishedSomeDecoding(); - } + // If the image is waiting for decode work to be notified, go ahead and do that. + if (aImg->mDecodeStatus == DecodeStatus::WORK_DONE) { + aImg->FinishedSomeDecoding(); } DecodeSomeOfImage(aImg, aStrategy); @@ -3199,9 +3181,7 @@ RasterImage::DecodePool::StopDecoding(RasterImage* aImg) // If we haven't got a decode request, we're not currently decoding. (Having // a decode request doesn't imply we *are* decoding, though.) - if (aImg->mDecodeRequest) { - aImg->mDecodeRequest->mRequestStatus = DecodeRequest::REQUEST_STOPPED; - } + aImg->mDecodeStatus = DecodeStatus::STOPPED; } NS_IMETHODIMP @@ -3210,14 +3190,14 @@ RasterImage::DecodePool::DecodeJob::Run() ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor); // If we were interrupted, we shouldn't do any work. - if (mRequest->mRequestStatus == DecodeRequest::REQUEST_STOPPED) { - DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest); + if (mImage->mDecodeStatus == DecodeStatus::STOPPED) { + DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage); return NS_OK; } // If someone came along and synchronously decoded us, there's nothing for us to do. if (!mImage->mDecoder || mImage->IsDecodeFinished()) { - DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest); + DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage); return NS_OK; } @@ -3228,7 +3208,7 @@ RasterImage::DecodePool::DecodeJob::Run() return NS_OK; } - mRequest->mRequestStatus = DecodeRequest::REQUEST_ACTIVE; + mImage->mDecodeStatus = DecodeStatus::ACTIVE; size_t oldByteCount = mImage->mDecoder->BytesDecoded(); @@ -3247,7 +3227,7 @@ RasterImage::DecodePool::DecodeJob::Run() size_t bytesDecoded = mImage->mDecoder->BytesDecoded() - oldByteCount; - mRequest->mRequestStatus = DecodeRequest::REQUEST_WORK_DONE; + mImage->mDecodeStatus = DecodeStatus::WORK_DONE; // If the decoder needs a new frame, enqueue an event to get it; that event // will enqueue another decode request when it's done. @@ -3265,7 +3245,7 @@ RasterImage::DecodePool::DecodeJob::Run() DecodePool::Singleton()->RequestDecode(mImage); } else { // Nothing more for us to do - let everyone know what happened. - DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest); + DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage); } return NS_OK; @@ -3293,14 +3273,12 @@ RasterImage::DecodePool::DecodeUntilSizeAvailable(RasterImage* aImg) MOZ_ASSERT(NS_IsMainThread()); ReentrantMonitorAutoEnter lock(aImg->mDecodingMonitor); - if (aImg->mDecodeRequest) { - // If the image is waiting for decode work to be notified, go ahead and do that. - if (aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) { - nsresult rv = aImg->FinishedSomeDecoding(); - if (NS_FAILED(rv)) { - aImg->DoError(); - return rv; - } + // If the image is waiting for decode work to be notified, go ahead and do that. + if (aImg->mDecodeStatus == DecodeStatus::WORK_DONE) { + nsresult rv = aImg->FinishedSomeDecoding(); + if (NS_FAILED(rv)) { + aImg->DoError(); + return rv; } } @@ -3411,17 +3389,16 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg, return NS_OK; } -RasterImage::DecodeDoneWorker::DecodeDoneWorker(RasterImage* image, DecodeRequest* request) - : mImage(image) - , mRequest(request) -{} +RasterImage::DecodeDoneWorker::DecodeDoneWorker(RasterImage* aImage) + : mImage(aImage) +{ } void -RasterImage::DecodeDoneWorker::NotifyFinishedSomeDecoding(RasterImage* image, DecodeRequest* request) +RasterImage::DecodeDoneWorker::NotifyFinishedSomeDecoding(RasterImage* aImage) { - image->mDecodingMonitor.AssertCurrentThreadIn(); + aImage->mDecodingMonitor.AssertCurrentThreadIn(); - nsCOMPtr worker = new DecodeDoneWorker(image, request); + nsCOMPtr worker = new DecodeDoneWorker(aImage); NS_DispatchToMainThread(worker); } @@ -3431,7 +3408,7 @@ RasterImage::DecodeDoneWorker::Run() MOZ_ASSERT(NS_IsMainThread()); ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor); - mImage->FinishedSomeDecoding(eShutdownIntent_Done, mRequest); + mImage->FinishedSomeDecoding(eShutdownIntent_Done); return NS_OK; } diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index 3f63f6e73872..ba74f8f45f39 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -33,6 +33,7 @@ #include "mozilla/Mutex.h" #include "mozilla/ReentrantMonitor.h" #include "mozilla/TimeStamp.h" +#include "mozilla/TypedEnum.h" #include "mozilla/StaticPtr.h" #include "mozilla/WeakPtr.h" #include "mozilla/UniquePtr.h" @@ -136,6 +137,14 @@ class Decoder; class FrameAnimator; class ScaleRunner; +MOZ_BEGIN_ENUM_CLASS(DecodeStatus, uint8_t) + INACTIVE, + PENDING, + ACTIVE, + WORK_DONE, + STOPPED +MOZ_END_ENUM_CLASS(DecodeStatus) + class RasterImage MOZ_FINAL : public ImageResource , public nsIProperties , public SupportsWeakPtr @@ -306,39 +315,7 @@ public: eShutdownIntent_AllCount = 3 }; - // Decode strategy - private: - nsresult OnImageDataCompleteCore(nsIRequest* aRequest, nsISupports*, nsresult aStatus); - - /** - * Each RasterImage has a pointer to one or zero heap-allocated - * DecodeRequests. - */ - struct DecodeRequest - { - explicit DecodeRequest(RasterImage* aImage) - : mImage(aImage) - , mRequestStatus(REQUEST_INACTIVE) - { } - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecodeRequest) - - RasterImage* mImage; - - enum DecodeRequestStatus - { - REQUEST_INACTIVE, - REQUEST_PENDING, - REQUEST_ACTIVE, - REQUEST_WORK_DONE, - REQUEST_STOPPED - } mRequestStatus; - - private: - ~DecodeRequest() {} - }; - /* * DecodePool is a singleton class we use when decoding large images. * @@ -426,18 +403,14 @@ private: class DecodeJob : public nsRunnable { public: - DecodeJob(DecodeRequest* aRequest, RasterImage* aImg) - : mRequest(aRequest) - , mImage(aImg) - {} + DecodeJob(RasterImage* aImage) : mImage(aImage) { } - NS_IMETHOD Run(); + NS_IMETHOD Run() MOZ_OVERRIDE; protected: virtual ~DecodeJob(); private: - nsRefPtr mRequest; nsRefPtr mImage; }; @@ -460,17 +433,14 @@ private: * Ensures the decode state accumulated by the decoding process gets * applied to the image. */ - static void NotifyFinishedSomeDecoding(RasterImage* image, DecodeRequest* request); + static void NotifyFinishedSomeDecoding(RasterImage* aImage); NS_IMETHOD Run(); - private: /* methods */ - DecodeDoneWorker(RasterImage* image, DecodeRequest* request); - - private: /* members */ + private: + DecodeDoneWorker(RasterImage* aImage); nsRefPtr mImage; - nsRefPtr mRequest; }; class FrameNeededWorker : public nsRunnable @@ -481,7 +451,7 @@ private: * decoder that it needs a new frame to be allocated on the main thread. * * Dispatches an event to do so, which will further dispatch a - * DecodeRequest event to continue decoding. + * RequestDecode event to continue decoding. */ static void GetNewFrame(RasterImage* image); @@ -496,7 +466,6 @@ private: }; nsresult FinishedSomeDecoding(eShutdownIntent intent = eShutdownIntent_Done, - DecodeRequest* request = nullptr, Progress aProgress = NoProgress); void DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef, @@ -621,7 +590,7 @@ private: // data // Decoder and friends nsRefPtr mDecoder; - nsRefPtr mDecodeRequest; + DecodeStatus mDecodeStatus; // END LOCKED MEMBER VARIABLES // Notification state. Used to avoid recursive notifications.