Bug 1271002. Notify right away after getting the first frame of an animated image. r=seth
☠☠ backed out by 2a218727e6e6 ☠ ☠
authorTimothy Nikkel <tnikkel@gmail.com>
Fri, 13 May 2016 16:19:55 -0500
changeset 297419 2ac62de7365d1557e3f2f53900f587cf4bc68cd9
parent 297418 e486707bccdc22b916d35a9c4350730d5c0b7d9d
child 297420 0671d2ac18f3b1d5700814b435fdb1121671ddeb
push id30257
push userphilringnalda@gmail.com
push dateSat, 14 May 2016 20:03:55 +0000
treeherdermozilla-central@1665c708ebab [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 (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