Bug 868871 - Don't do any invalidation from under RasterImage::GetImageContainer(), which is called while painting. r=seth
authorJoe Drew <joe@drew.ca>
Thu, 09 May 2013 09:36:57 -0400
changeset 138155 98e5c35041c0086535b46e8a159d2445c5973721
parent 138135 4a1cbbb07ce23516c12662db6b154f95439bbca0
child 138156 838eaf27333430933f0d5b33a720c19b0112aeff
push idunknown
push userunknown
push dateunknown
reviewersseth
bugs868871
milestone23.0a1
Bug 868871 - Don't do any invalidation from under RasterImage::GetImageContainer(), which is called while painting. r=seth
image/src/RasterImage.cpp
image/src/RasterImage.h
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -1059,17 +1059,17 @@ RasterImage::GetFrame(uint32_t aWhichFra
 }
 
 already_AddRefed<layers::Image>
 RasterImage::GetCurrentImage()
 {
   if (!mDecoded) {
     // We can't call StartDecoding because that can synchronously notify
     // which can cause DOM modification
-    RequestDecode();
+    RequestDecodeCore(ASYNCHRONOUS);
     return nullptr;
   }
 
   nsRefPtr<gfxASurface> imageSurface;
   nsresult rv = GetFrame(FRAME_CURRENT, FLAG_NONE, getter_AddRefs(imageSurface));
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   if (!imageSurface) {
@@ -2722,24 +2722,24 @@ RasterImage::WantDecodedFrames()
   return StartDecoding();
 }
 
 //******************************************************************************
 /* void requestDecode() */
 NS_IMETHODIMP
 RasterImage::RequestDecode()
 {
-  return RequestDecodeCore(ASYNCHRONOUS);
+  return RequestDecodeCore(SYNCHRONOUS_NOTIFY);
 }
 
 /* void startDecode() */
 NS_IMETHODIMP
 RasterImage::StartDecoding()
 {
-  return RequestDecodeCore(SOMEWHAT_SYNCHRONOUS);
+  return RequestDecodeCore(SYNCHRONOUS_NOTIFY_AND_SOME_DECODE);
 }
 
 
 NS_IMETHODIMP
 RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -2786,17 +2786,18 @@ RasterImage::RequestDecodeCore(RequestDe
       return NS_OK;
     }
   }
 
   MutexAutoLock lock(mDecodingMutex);
 
   // If the image is waiting for decode work to be notified, go ahead and do that.
   if (mDecodeRequest &&
-      mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) {
+      mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&
+      aDecodeType != ASYNCHRONOUS) {
     nsresult rv = FinishedSomeDecoding();
     CONTAINER_ENSURE_SUCCESS(rv);
   }
 
   // If we're fully decoded, we have nothing to do. We need this check after
   // DecodeUntilSizeAvailable and FinishedSomeDecoding because they can result
   // in us finishing an in-progress decode (or kicking off and finishing a
   // synchronous decode if we're already waiting on a full decode).
@@ -2830,17 +2831,17 @@ RasterImage::RequestDecodeCore(RequestDe
 
   // If we've read all the data we have, we're done
   if (mHasSourceData && mBytesDecoded == mSourceData.Length())
     return NS_OK;
 
   // If we can do decoding now, do so.  Small images will decode completely,
   // large images will decode a bit and post themselves to the event loop
   // to finish decoding.
-  if (!mDecoded && !mInDecoder && mHasSourceData && aDecodeType == SOMEWHAT_SYNCHRONOUS) {
+  if (!mDecoded && !mInDecoder && mHasSourceData && aDecodeType == SYNCHRONOUS_NOTIFY_AND_SOME_DECODE) {
     PROFILER_LABEL_PRINTF("RasterImage", "DecodeABitOf", "%s", GetURIString().get());
     mDecoder->SetSynchronous(true);
 
     DecodePool::Singleton()->DecodeABitOf(this);
 
     // DecodeABitOf can destroy mDecoder.
     if (mDecoder) {
       mDecoder->SetSynchronous(false);
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -707,17 +707,18 @@ private:
 
   already_AddRefed<layers::Image> GetCurrentImage();
   void UpdateImageContainer();
 
   void SetInUpdateImageContainer(bool aInUpdate) { mInUpdateImageContainer = aInUpdate; }
   bool IsInUpdateImageContainer() { return mInUpdateImageContainer; }
   enum RequestDecodeType {
       ASYNCHRONOUS,
-      SOMEWHAT_SYNCHRONOUS
+      SYNCHRONOUS_NOTIFY,
+      SYNCHRONOUS_NOTIFY_AND_SOME_DECODE
   };
   NS_IMETHOD RequestDecodeCore(RequestDecodeType aDecodeType);
 
   // We would like to just check if we have a zero lock count, but we can't do
   // that for animated images because in EnsureAnimExists we lock the image and
   // never unlock so that animated images always have their lock count >= 1. In
   // that case we use our animation consumers count as a proxy for lock count.
   bool IsUnlocked() { return (mLockCount == 0 || (mAnim && mAnimationConsumers == 0)); }