Bug 1128223 (Part 3) - Add FLAG_ASYNC_NOTIFY. r=tn a=lmandel
authorSeth Fowler <seth@mozilla.com>
Mon, 02 Feb 2015 21:40:35 -0800
changeset 249864 4626a2f29ca515e19a2f54005d1f1b848bce221f
parent 249863 eba6fc85e742b0efaf5e2e8e7fc03f208fcb1796
child 249865 91694fca2ff839f8a9893654d6342867c513688d
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, lmandel
bugs1128223
milestone37.0a2
Bug 1128223 (Part 3) - Add FLAG_ASYNC_NOTIFY. r=tn a=lmandel
image/public/imgIContainer.idl
image/src/DecodePool.cpp
image/src/RasterImage.cpp
image/src/RasterImage.h
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -64,17 +64,17 @@ native nsIntSizeByVal(nsIntSize);
 
 /**
  * imgIContainer is the interface that represents an image. It allows
  * access to frames as Thebes surfaces. It also allows drawing of images
  * onto Thebes contexts.
  *
  * Internally, imgIContainer also manages animation of images.
  */
-[scriptable, builtinclass, uuid(60e07aae-8500-46c7-b305-9a35ad7e6665)]
+[scriptable, builtinclass, uuid(3a630c1d-3365-4873-bc01-54468decf8c6)]
 interface imgIContainer : nsISupports
 {
   /**
    * The width of the container rectangle.  In the case of any error,
    * zero is returned, and an exception will be thrown.
    */
   readonly attribute int32_t width;
 
@@ -149,16 +149,19 @@ interface imgIContainer : nsISupports
    * FLAG_NONE: Lack of flags.
    *
    * FLAG_SYNC_DECODE: Forces synchronous/non-progressive decode of all
    * available data before the call returns.
    *
    * FLAG_SYNC_DECODE_IF_FAST: Like FLAG_SYNC_DECODE, but requests a sync decode
    * be performed only if ImageLib estimates it can be completed very quickly.
    *
+   * FLAG_ASYNC_NOTIFY: Send notifications asynchronously, even if we decode
+   * synchronously beause of FLAG_SYNC_DECODE or FLAG_SYNC_DECODE_IF_FAST.
+   *
    * FLAG_DECODE_NO_PREMULTIPLY_ALPHA: Do not premultiply alpha if
    * it's not already premultiplied in the image data.
    *
    * FLAG_DECODE_NO_COLORSPACE_CONVERSION: Do not do any colorspace conversion;
    * ignore any embedded profiles, and don't convert to any particular
    * destination space.
    *
    * FLAG_CLAMP: Extend the image to the fill area by clamping image sample
@@ -176,22 +179,23 @@ interface imgIContainer : nsISupports
    * FLAG_BYPASS_SURFACE_CACHE: Forces drawing to happen rather than taking
    * cached rendering from the surface cache. This is used when we are printing,
    * for example, where we want the vector commands from VectorImages to end up
    * in the PDF output rather than a cached rendering at screen resolution.
    */
   const unsigned long FLAG_NONE                            = 0x0;
   const unsigned long FLAG_SYNC_DECODE                     = 0x1;
   const unsigned long FLAG_SYNC_DECODE_IF_FAST             = 0x2;
-  const unsigned long FLAG_DECODE_NO_PREMULTIPLY_ALPHA     = 0x4;
-  const unsigned long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x8;
-  const unsigned long FLAG_CLAMP                           = 0x10;
-  const unsigned long FLAG_HIGH_QUALITY_SCALING            = 0x20;
-  const unsigned long FLAG_WANT_DATA_SURFACE               = 0x40;
-  const unsigned long FLAG_BYPASS_SURFACE_CACHE            = 0x80;
+  const unsigned long FLAG_ASYNC_NOTIFY                    = 0x4;
+  const unsigned long FLAG_DECODE_NO_PREMULTIPLY_ALPHA     = 0x8;
+  const unsigned long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x10;
+  const unsigned long FLAG_CLAMP                           = 0x20;
+  const unsigned long FLAG_HIGH_QUALITY_SCALING            = 0x40;
+  const unsigned long FLAG_WANT_DATA_SURFACE               = 0x80;
+  const unsigned long FLAG_BYPASS_SURFACE_CACHE            = 0x100;
 
   /**
    * A constant specifying the default set of decode flags (i.e., the default
    * values for FLAG_DECODE_*).
    */
   const unsigned long DECODE_FLAGS_DEFAULT = 0;
 
   /**
--- a/image/src/DecodePool.cpp
+++ b/image/src/DecodePool.cpp
@@ -340,17 +340,18 @@ DecodePool::Decode(Decoder* aDecoder)
   }
 }
 
 void
 DecodePool::NotifyProgress(Decoder* aDecoder)
 {
   MOZ_ASSERT(aDecoder);
 
-  if (!NS_IsMainThread()) {
+  if (!NS_IsMainThread() ||
+      (aDecoder->GetFlags() & imgIContainer::FLAG_ASYNC_NOTIFY)) {
     NotifyProgressWorker::Dispatch(aDecoder->GetImage(),
                                    aDecoder->TakeProgress(),
                                    aDecoder->TakeInvalidRect(),
                                    aDecoder->GetDecodeFlags());
     return;
   }
 
   aDecoder->GetImage()->NotifyProgress(aDecoder->TakeProgress(),
@@ -358,17 +359,18 @@ DecodePool::NotifyProgress(Decoder* aDec
                                        aDecoder->GetDecodeFlags());
 }
 
 void
 DecodePool::NotifyDecodeComplete(Decoder* aDecoder)
 {
   MOZ_ASSERT(aDecoder);
 
-  if (!NS_IsMainThread()) {
+  if (!NS_IsMainThread() ||
+      (aDecoder->GetFlags() & imgIContainer::FLAG_ASYNC_NOTIFY)) {
     NotifyDecodeCompleteWorker::Dispatch(aDecoder);
     return;
   }
 
   aDecoder->Finish();
   aDecoder->GetImage()->FinalizeDecoder(aDecoder);
 }
 
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -501,18 +501,17 @@ RasterImage::LookupFrameInternal(uint32_
                                                         DecodeFlags(aFlags),
                                                         aFrameNum),
                                        alternateFlags);
 }
 
 DrawableFrameRef
 RasterImage::LookupFrame(uint32_t aFrameNum,
                          const nsIntSize& aSize,
-                         uint32_t aFlags,
-                         bool aShouldSyncNotify /* = true */)
+                         uint32_t aFlags)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags)
                         ? aSize.ToIntSize()
                         : mSize.ToIntSize();
 
   DrawableFrameRef ref = LookupFrameInternal(aFrameNum, requestedSize, aFlags);
@@ -521,20 +520,20 @@ RasterImage::LookupFrame(uint32_t aFrame
     // We can't request a decode without knowing our intrinsic size. Give up.
     return DrawableFrameRef();
   }
 
   if (!ref || ref->GetImageSize() != requestedSize) {
     // The OS threw this frame away. We need to redecode if we can.
     MOZ_ASSERT(!mAnim, "Animated frames should be locked");
 
-    WantDecodedFrames(ThebesIntSize(requestedSize), aFlags, aShouldSyncNotify);
+    WantDecodedFrames(ThebesIntSize(requestedSize), aFlags);
 
     // If we can sync decode, we should already have the frame.
-    if ((aFlags & FLAG_SYNC_DECODE) && aShouldSyncNotify) {
+    if (aFlags & FLAG_SYNC_DECODE) {
       ref = LookupFrameInternal(aFrameNum, requestedSize, aFlags);
     }
   }
 
   if (!ref) {
     // We still weren't able to get a frame. Give up.
     return DrawableFrameRef();
   }
@@ -543,18 +542,17 @@ RasterImage::LookupFrame(uint32_t aFrame
     return DrawableFrameRef();
   }
 
   MOZ_ASSERT(!ref || !ref->GetIsPaletted(), "Should not have paletted frame");
 
   // Sync decoding guarantees that we got the frame, but if it's owned by an
   // async decoder that's currently running, the contents of the frame may not
   // be available yet. Make sure we get everything.
-  if (ref && mHasSourceData && aShouldSyncNotify &&
-      (aFlags & FLAG_SYNC_DECODE)) {
+  if (ref && mHasSourceData && (aFlags & FLAG_SYNC_DECODE)) {
     ref->WaitUntilComplete();
   }
 
   return ref;
 }
 
 uint32_t
 RasterImage::GetCurrentFrameIndex() const
@@ -650,31 +648,29 @@ RasterImage::GetFirstFrameDelay()
   if (NS_FAILED(GetAnimated(&animated)) || !animated)
     return -1;
 
   MOZ_ASSERT(mAnim, "Animated images should have a FrameAnimator");
   return mAnim->GetTimeoutForFrame(0);
 }
 
 TemporaryRef<SourceSurface>
-RasterImage::CopyFrame(uint32_t aWhichFrame,
-                       uint32_t aFlags,
-                       bool aShouldSyncNotify /* = true */)
+RasterImage::CopyFrame(uint32_t aWhichFrame, uint32_t aFlags)
 {
   if (aWhichFrame > FRAME_MAX_VALUE)
     return nullptr;
 
   if (mError)
     return nullptr;
 
   // Get the frame. If it's not there, it's probably the caller's fault for
   // not waiting for the data to be loaded from the network or not passing
   // FLAG_SYNC_DECODE
-  DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
-                                          mSize, aFlags, aShouldSyncNotify);
+  DrawableFrameRef frameRef =
+    LookupFrame(GetRequestedFrameIndex(aWhichFrame), mSize, aFlags);
   if (!frameRef) {
     // The OS threw this frame away and we couldn't redecode it right now.
     return nullptr;
   }
 
   // Create a 32-bit image surface of our size, but draw using the frame's
   // rect, implicitly padding the frame out to the image's size.
 
@@ -722,33 +718,31 @@ RasterImage::CopyFrame(uint32_t aWhichFr
 NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 RasterImage::GetFrame(uint32_t aWhichFrame,
                       uint32_t aFlags)
 {
   return GetFrameInternal(aWhichFrame, aFlags);
 }
 
 TemporaryRef<SourceSurface>
-RasterImage::GetFrameInternal(uint32_t aWhichFrame,
-                              uint32_t aFlags,
-                              bool aShouldSyncNotify /* = true */)
+RasterImage::GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags)
 {
   MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
 
   if (aWhichFrame > FRAME_MAX_VALUE)
     return nullptr;
 
   if (mError)
     return nullptr;
 
   // Get the frame. If it's not there, it's probably the caller's fault for
   // not waiting for the data to be loaded from the network or not passing
   // FLAG_SYNC_DECODE
-  DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame),
-                                          mSize, aFlags, aShouldSyncNotify);
+  DrawableFrameRef frameRef =
+    LookupFrame(GetRequestedFrameIndex(aWhichFrame), mSize, aFlags);
   if (!frameRef) {
     // The OS threw this frame away and we couldn't redecode it.
     return nullptr;
   }
 
   // If this frame covers the entire image, we can just reuse its existing
   // surface.
   RefPtr<SourceSurface> frameSurf;
@@ -757,30 +751,30 @@ RasterImage::GetFrameInternal(uint32_t a
       frameRect.width == mSize.width &&
       frameRect.height == mSize.height) {
     frameSurf = frameRef->GetSurface();
   }
 
   // The image doesn't have a usable surface because it's been optimized away or
   // because it's a partial update frame from an animation. Create one.
   if (!frameSurf) {
-    frameSurf = CopyFrame(aWhichFrame, aFlags, aShouldSyncNotify);
+    frameSurf = CopyFrame(aWhichFrame, aFlags);
   }
 
   return frameSurf;
 }
 
 already_AddRefed<layers::Image>
 RasterImage::GetCurrentImage(ImageContainer* aContainer)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aContainer);
 
   RefPtr<SourceSurface> surface =
-    GetFrameInternal(FRAME_CURRENT, FLAG_NONE, /* aShouldSyncNotify = */ false);
+    GetFrameInternal(FRAME_CURRENT, FLAG_ASYNC_NOTIFY);
   if (!surface) {
     // The OS threw out some or all of our buffer. We'll need to wait for the
     // redecode (which was automatically triggered by GetFrame) to complete.
     return nullptr;
   }
 
   CairoImage::Data cairoData;
   GetWidth(&cairoData.mSize.width);
@@ -1401,39 +1395,34 @@ RasterImage::CreateDecoder(const Maybe<n
       Telemetry::GetHistogramById(Telemetry::IMAGE_MAX_DECODE_COUNT)->Add(sMaxDecodeCount);
     }
   }
 
   return decoder.forget();
 }
 
 void
-RasterImage::WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags,
-                               bool aShouldSyncNotify)
+RasterImage::WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags)
 {
   if (mDownscaleDuringDecode) {
     // We're about to decode again, which may mean that some of the previous
     // sizes we've decoded at aren't useful anymore. We can allow them to
     // expire from the cache by unlocking them here. When the decode finishes,
     // it will send an invalidation that will cause all instances of this image
     // to redraw. If this image is locked, any surfaces that are still useful
     // will become locked again when LookupFrame touches them, and the remainder
     // will eventually expire.
     SurfaceCache::UnlockSurfaces(ImageKey(this));
   }
 
   DecodeStrategy strategy = DecodeStrategy::ASYNC;
-
-  if (aShouldSyncNotify) {
-    // We can sync notify, which means we can also sync decode.
-    if (aFlags & FLAG_SYNC_DECODE) {
-      strategy = DecodeStrategy::SYNC_IF_POSSIBLE;
-    } else if (aFlags & FLAG_SYNC_DECODE_IF_FAST) {
-      strategy = DecodeStrategy::SYNC_FOR_SMALL_IMAGES;
-    }
+  if (aFlags & FLAG_SYNC_DECODE) {
+    strategy = DecodeStrategy::SYNC_IF_POSSIBLE;
+  } else if (aFlags & FLAG_SYNC_DECODE_IF_FAST) {
+    strategy = DecodeStrategy::SYNC_FOR_SMALL_IMAGES;
   }
 
   Decode(strategy, Some(aSize), aFlags);
 }
 
 //******************************************************************************
 /* void requestDecode() */
 NS_IMETHODIMP
@@ -1489,22 +1478,17 @@ RasterImage::RequestDecodeForSize(const 
     !mHasBeenDecoded && (aFlags & FLAG_SYNC_DECODE_IF_FAST);
 
   uint32_t flags = shouldSyncDecodeIfFast
                  ? aFlags
                  : aFlags & ~FLAG_SYNC_DECODE_IF_FAST;
 
   // Look up the first frame of the image, which will implicitly start decoding
   // if it's not available right now.
-  // XXX(seth): Passing true for aShouldSyncNotify here has the effect of
-  // synchronously decoding small images, while passing false has the effect of
-  // decoding asynchronously, but that's not obvious from the argument name.
-  // This API needs to be reworked.
-  LookupFrame(0, targetSize, flags,
-              /* aShouldSyncNotify = */ shouldSyncDecodeIfFast);
+  LookupFrame(0, targetSize, flags);
 
   return NS_OK;
 }
 
 bool
 RasterImage::IsDecoded()
 {
   // XXX(seth): We need to get rid of this; it's not reliable.
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -298,29 +298,26 @@ private:
   void DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef,
                                     gfxContext* aContext,
                                     const nsIntSize& aSize,
                                     const ImageRegion& aRegion,
                                     GraphicsFilter aFilter,
                                     uint32_t aFlags);
 
   TemporaryRef<gfx::SourceSurface> CopyFrame(uint32_t aWhichFrame,
-                                             uint32_t aFlags,
-                                             bool aShouldSyncNotify = true);
+                                             uint32_t aFlags);
   TemporaryRef<gfx::SourceSurface> GetFrameInternal(uint32_t aWhichFrame,
-                                                    uint32_t aFlags,
-                                                    bool aShouldSyncNotify = true);
+                                                    uint32_t aFlags);
 
   DrawableFrameRef LookupFrameInternal(uint32_t aFrameNum,
                                        const gfx::IntSize& aSize,
                                        uint32_t aFlags);
   DrawableFrameRef LookupFrame(uint32_t aFrameNum,
                                const nsIntSize& aSize,
-                               uint32_t aFlags,
-                               bool aShouldSyncNotify = true);
+                               uint32_t aFlags);
   uint32_t GetCurrentFrameIndex() const;
   uint32_t GetRequestedFrameIndex(uint32_t aWhichFrame) const;
 
   nsIntRect GetFirstFrameRect();
 
   size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation,
                                                  MallocSizeOf aMallocSizeOf) const;
 
@@ -352,18 +349,17 @@ private:
   /**
    * Creates a new decoder with a target size of @aSize and decode flags
    * specified by @aFlags. If a size decode is desired, pass Nothing() for
    * @aSize.
    */
   already_AddRefed<Decoder> CreateDecoder(const Maybe<nsIntSize>& aSize,
                                           uint32_t aFlags);
 
-  void WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags,
-                         bool aShouldSyncNotify);
+  void WantDecodedFrames(const nsIntSize& aSize, uint32_t aFlags);
 
 private: // data
   nsIntSize                  mSize;
   Orientation                mOrientation;
 
   nsCOMPtr<nsIProperties>   mProperties;
 
   /// If this image is animated, a FrameAnimator which manages its animation.