Bug 1271002. Notify right away after getting the first frame of an animated image. r=seth
authorTimothy Nikkel <tnikkel@gmail.com>
Fri, 13 May 2016 21:32:21 -0500
changeset 336435 962463926b903521f4872a4e810da4eb20d7ad6c
parent 336434 db473770c2eb45fb5fe70342571f7152f44a00fb
child 336436 cdc7ecf62c5df89e32ed69a5a17e4fd89ee22170
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersseth
bugs1271002
milestone49.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 1271002. Notify right away after getting the first frame of an animated image. r=seth The decoding loop in Decoder::Decode only pauses to report progress when it runs out of bytes to decode. So for long animated images where the network is keeping up with decoding it will be a relatively long time until we deliver the first frame complete notification and corresponding invalidation. In most cases this shouldn't be too expensive as it is just dispatching a runnable to the main thread from the decoding thread.
image/DecodePool.cpp
image/DecodePool.h
image/Decoder.cpp
--- a/image/DecodePool.cpp
+++ b/image/DecodePool.cpp
@@ -464,16 +464,17 @@ DecodePool::Decode(Decoder* aDecoder)
     NotifyDecodeComplete(aDecoder);
   }
 }
 
 void
 DecodePool::NotifyProgress(Decoder* aDecoder)
 {
   MOZ_ASSERT(aDecoder);
+  MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());
 
   if (!NS_IsMainThread() ||
       (aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
     NotifyProgressWorker::Dispatch(aDecoder->GetImage(),
                                    aDecoder->TakeProgress(),
                                    aDecoder->TakeInvalidRect(),
                                    aDecoder->GetSurfaceFlags());
     return;
--- a/image/DecodePool.h
+++ b/image/DecodePool.h
@@ -74,25 +74,29 @@ public:
    * Returns an event target interface to the DecodePool's I/O thread. Callers
    * who want to deliver data to workers on the DecodePool can use this event
    * target.
    *
    * @return An nsIEventTarget interface to the thread pool's I/O thread.
    */
   already_AddRefed<nsIEventTarget> GetIOEventTarget();
 
+  /**
+   * Notify about progress on aDecoder.
+   */
+  void NotifyProgress(Decoder* aDecoder);
+
 private:
   friend class DecodePoolWorker;
 
   DecodePool();
   virtual ~DecodePool();
 
   void Decode(Decoder* aDecoder);
   void NotifyDecodeComplete(Decoder* aDecoder);
-  void NotifyProgress(Decoder* aDecoder);
 
   static StaticRefPtr<DecodePool> sSingleton;
   static uint32_t sNumCores;
 
   RefPtr<DecodePoolImpl>    mImpl;
 
   // mMutex protects mThreads and mIOThread.
   Mutex                         mMutex;
--- a/image/Decoder.cpp
+++ b/image/Decoder.cpp
@@ -444,16 +444,22 @@ Decoder::PostFrameStop(Opacity aFrameOpa
   mProgress |= FLAG_FRAME_COMPLETE;
 
   // If we're not sending partial invalidations, then we send an invalidation
   // here when the first frame is complete.
   if (!ShouldSendPartialInvalidations() && mFrameCount == 1) {
     mInvalidRect.UnionRect(mInvalidRect,
                            gfx::IntRect(gfx::IntPoint(0, 0), GetSize()));
   }
+
+  // If we are going to keep decoding we should notify now about the first frame being done.
+  if (mImage && mFrameCount == 1 && HasAnimation()) {
+    MOZ_ASSERT(HasProgress());
+    DecodePool::Singleton()->NotifyProgress(this);
+  }
 }
 
 void
 Decoder::PostInvalidation(const nsIntRect& aRect,
                           const Maybe<nsIntRect>& aRectAtTargetSize
                             /* = Nothing() */)
 {
   // We should be mid-frame