Bug 1130707 - Make decode-on-draw-only image notifications more robust. r=tn
authorSeth Fowler <seth@mozilla.com>
Mon, 09 Feb 2015 23:50:30 -0800
changeset 228251 a48321b8bd00f78e5d377c6a5cde201f391c66bc
parent 228250 f97eece7bdb6712fe9033c65c2b6d48ae10719a4
child 228252 88682971f399b5bc1d7bdc7d51fe622d8119bccd
push id55374
push usermfowler@mozilla.com
push dateTue, 10 Feb 2015 07:50:52 +0000
treeherdermozilla-inbound@88682971f399 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1130707
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1130707 - Make decode-on-draw-only image notifications more robust. r=tn
image/src/RasterImage.cpp
image/src/RasterImage.h
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -257,17 +257,16 @@ RasterImage::RasterImage(ProgressTracker
   mDecodeCount(0),
   mRequestedSampleSize(0),
 #ifdef DEBUG
   mFramesNotified(0),
 #endif
   mSourceBuffer(new SourceBuffer()),
   mFrameCount(0),
   mHasSize(false),
-  mBlockedOnload(false),
   mDecodeOnDraw(false),
   mTransient(false),
   mDiscardable(false),
   mHasSourceData(false),
   mHasBeenDecoded(false),
   mPendingAnimation(false),
   mAnimationFinished(false),
   mWantFullDecode(false)
@@ -1154,59 +1153,60 @@ RasterImage::OnImageDataComplete(nsIRequ
 
   MOZ_ASSERT(mHasSize || mError, "Need to know size before firing load event");
   MOZ_ASSERT(!mHasSize ||
              (mProgressTracker->GetProgress() & FLAG_SIZE_AVAILABLE),
              "Should have notified that the size is available if we have it");
 
   Progress loadProgress = LoadCompleteProgress(aLastPart, mError, finalStatus);
 
-  if (mBlockedOnload) {
+  if (mDecodeOnDraw) {
     // For decode-on-draw images, we want to send notifications as if we've
     // already finished decoding. Otherwise some observers will never even try
-    // to draw.
-    MOZ_ASSERT(mDecodeOnDraw, "Blocked onload but not decode-on-draw");
-    loadProgress |= FLAG_FRAME_COMPLETE |
+    // to draw. (We may have already sent some of these notifications from
+    // NotifyForDecodeOnDrawOnly(), but ProgressTracker will ensure no duplicate
+    // notifications get sent.)
+    loadProgress |= FLAG_ONLOAD_BLOCKED |
+                    FLAG_DECODE_STARTED |
+                    FLAG_FRAME_COMPLETE |
                     FLAG_DECODE_COMPLETE |
                     FLAG_ONLOAD_UNBLOCKED;
   }
 
   // Notify our listeners, which will fire this image's load event.
   NotifyProgress(loadProgress);
 
   return finalStatus;
 }
 
 void
-RasterImage::BlockOnloadForDecodeOnDraw()
+RasterImage::NotifyForDecodeOnDrawOnly()
 {
-  if (mHasSourceData) {
-    // OnImageDataComplete got called before we got to run. No point in blocking
-    // onload now.
-    return;
+  if (!NS_IsMainThread()) {
+    nsCOMPtr<nsIRunnable> runnable =
+      NS_NewRunnableMethod(this, &RasterImage::NotifyForDecodeOnDrawOnly);
+    NS_DispatchToMainThread(runnable);
   }
 
-  // Block onload. We'll unblock it in OnImageDataComplete.
-  mBlockedOnload = true;
   NotifyProgress(FLAG_DECODE_STARTED | FLAG_ONLOAD_BLOCKED);
 }
 
 nsresult
 RasterImage::OnImageDataAvailable(nsIRequest*,
                                   nsISupports*,
                                   nsIInputStream* aInStr,
                                   uint64_t aOffset,
                                   uint32_t aCount)
 {
   nsresult rv;
 
   if (MOZ_UNLIKELY(mDecodeOnDraw && aOffset == 0)) {
-    nsCOMPtr<nsIRunnable> runnable =
-      NS_NewRunnableMethod(this, &RasterImage::BlockOnloadForDecodeOnDraw);
-    NS_DispatchToMainThread(runnable);
+    // If we're a decode-on-draw image, send notifications as if we've just
+    // started decoding.
+    NotifyForDecodeOnDrawOnly();
   }
 
   // WriteToSourceBuffer always consumes everything it gets if it doesn't run
   // out of memory.
   uint32_t bytesRead;
   rv = aInStr->ReadSegments(WriteToSourceBuffer, this, aCount, &bytesRead);
 
   MOZ_ASSERT(bytesRead == aCount || HasError() || NS_FAILED(rv),
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -242,17 +242,17 @@ public:
                                         nsIInputStream* aInStr,
                                         uint64_t aSourceOffset,
                                         uint32_t aCount) MOZ_OVERRIDE;
   virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
                                        nsISupports* aContext,
                                        nsresult aStatus,
                                        bool aLastPart) MOZ_OVERRIDE;
 
-  void BlockOnloadForDecodeOnDraw();
+  void NotifyForDecodeOnDrawOnly();
 
   /**
    * A hint of the number of bytes of source data that the image contains. If
    * called early on, this can help reduce copying and reallocations by
    * appropriately preallocating the source data buffer.
    *
    * We take this approach rather than having the source data management code do
    * something more complicated (like chunklisting) because HTTP is by far the
@@ -388,17 +388,16 @@ private: // data
   // The source data for this image.
   nsRefPtr<SourceBuffer>     mSourceBuffer;
 
   // The number of frames this image has.
   uint32_t                   mFrameCount;
 
   // Boolean flags (clustered together to conserve space):
   bool                       mHasSize:1;       // Has SetSize() been called?
-  bool                       mBlockedOnload:1; // Did send BLOCK_ONLOAD?
   bool                       mDecodeOnDraw:1;  // Decoding on draw?
   bool                       mTransient:1;     // Is the image short-lived?
   bool                       mDiscardable:1;   // Is container discardable?
   bool                       mHasSourceData:1; // Do we have source data?
   bool                       mHasBeenDecoded:1; // Decoded at least once?
   bool                       mDownscaleDuringDecode:1;
 
   // Whether we're waiting to start animation. If we get a StartAnimation() call