Bug 1404222 Part 6: Update RasterImage to allow us to delay the load event until full decode. draft
authorBrad Werth <bwerth@mozilla.com>
Wed, 14 Feb 2018 14:14:17 -0800
changeset 762263 878db8e338f75ebcb8cd0bef98aaccfe0287be13
parent 762262 5cb784f72082919098591d69d2f338e2cd1751fc
child 762264 57652b4a58adf31ac50e43aee1d6acd3c9fac25b
push id101114
push userbwerth@mozilla.com
push dateThu, 01 Mar 2018 23:33:31 +0000
bugs1404222
milestone60.0a1
Bug 1404222 Part 6: Update RasterImage to allow us to delay the load event until full decode. MozReview-Commit-ID: 6tpO13NzkmP
image/RasterImage.cpp
image/RasterImage.h
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -127,16 +127,17 @@ RasterImage::Init(const char* aMimeType,
   MOZ_ASSERT_IF(aFlags & INIT_FLAG_TRANSIENT,
                 !(aFlags & INIT_FLAG_DISCARDABLE));
 
   // Store initialization data
   mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE);
   mWantFullDecode = !!(aFlags & INIT_FLAG_DECODE_IMMEDIATELY);
   mTransient = !!(aFlags & INIT_FLAG_TRANSIENT);
   mSyncLoad = !!(aFlags & INIT_FLAG_SYNC_LOAD);
+  mDelayLoadEventUntilDecode = !!(aFlags & INIT_FLAG_LOADEVENT_AFTER_DECODE);
 
   // Use the MIME type to select a decoder type, and make sure there *is* a
   // decoder for this MIME type.
   NS_ENSURE_ARG_POINTER(aMimeType);
   mDecoderType = DecoderFactory::GetDecoderType(aMimeType);
   if (mDecoderType == DecoderType::UNKNOWN) {
     return NS_ERROR_FAILURE;
   }
@@ -1770,27 +1771,58 @@ RasterImage::NotifyDecodeComplete(const 
   if (aStatus.mHadError &&
       (!mAnimationState || mAnimationState->KnownFrameCount() == 0)) {
     DoError();
   } else if (aStatus.mWasMetadataDecode && !mHasSize) {
     DoError();
   }
 
   // XXX(aosmond): Can we get this far without mFinished == true?
-  if (aStatus.mFinished && aStatus.mWasMetadataDecode) {
-    // If we were waiting to fire the load event, go ahead and fire it now.
-    if (mLoadProgress) {
-      NotifyForLoadEvent(*mLoadProgress);
-      mLoadProgress = Nothing();
-    }
+  if (aStatus.mFinished) {
+    if (aStatus.mWasMetadataDecode) {
+      // If we're waiting to send the load event, and we can do that
+      // with just the metadata or we aren't requesting the full
+      // decode ourself, send the load event now.
+      if (mLoadProgress &&
+          (!mDelayLoadEventUntilDecode || !mWantFullDecode)) {
+        NotifyForLoadEvent(*mLoadProgress);
+        mLoadProgress = Nothing();
+      }
 
-    // If we were a metadata decode and a full decode was requested, do it.
-    if (mWantFullDecode) {
-      mWantFullDecode = false;
-      RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
+      // If we were a metadata decode and a full decode was requested,
+      // do it.
+      if (mWantFullDecode) {
+        mWantFullDecode = false;
+        RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
+      }
+    } else {
+      // We've decoded fully; if we're still waiting to send the
+      // load event, do it now.
+      if (mLoadProgress) {
+        // If we intentionally delayed until full decode, delay
+        // dispatch of the event itself, since we want to ensure that
+        // whatever needed the decode has time to act on it (reflow,
+        // for example).
+        Progress progress = *mLoadProgress;
+        mLoadProgress = Nothing();
+
+        if (mDelayLoadEventUntilDecode) {
+          // Dispatch the event as a runnable.
+          RefPtr<RasterImage> image = this;
+          nsCOMPtr<nsIRunnable> ev = NS_NewRunnableFunction(
+                                    "RasterImage::NotifyDecodeComplete",
+                                    [=]() -> void {
+            image->NotifyForLoadEvent(progress);
+          });
+          NS_IdleDispatchToCurrentThread(ev.forget());
+        } else {
+          // Run the event directly.
+          NotifyForLoadEvent(progress);
+        }
+      }
     }
   }
 }
 
 void
 RasterImage::ReportDecoderError()
 {
   nsCOMPtr<nsIConsoleService> consoleService =
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -423,16 +423,20 @@ private: // data
   // Whether the animation can stop, due to running out
   // of frames, or no more owning request
   bool                       mAnimationFinished:1;
 
   // Whether, once we are done doing a metadata decode, we should immediately
   // kick off a full decode.
   bool                       mWantFullDecode:1;
 
+  // Whether we should delay our load event until full decode. If false,
+  // load event will fire as soon as size is known.
+  bool                       mDelayLoadEventUntilDecode:1;
+
   TimeStamp mDrawStartTime;
 
 
   //////////////////////////////////////////////////////////////////////////////
   // Scaling.
   //////////////////////////////////////////////////////////////////////////////
 
   // Determines whether we can downscale during decode with the given