Wait for image decode notifications from reftest harnesses. draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 09 Jul 2018 14:36:03 +0200
changeset 815640 2ba47b6d669b72f1b9ad3ef8d66c2d26471a6673
parent 815639 be7fe241f910dd73e76e4e25919cdc247678bb2b
child 815641 19efac2b69ea32f475d77f76d0d4a1362fa1a75f
push id115591
push userbmo:emilio@crisal.io
push dateMon, 09 Jul 2018 16:15:39 +0000
milestone63.0a1
Wait for image decode notifications from reftest harnesses. MozReview-Commit-ID: 1GZDOU40BCq
image/DecodePool.h
image/IDecodingTask.cpp
image/IDecodingTask.h
image/moz.build
layout/base/nsPresContext.cpp
--- a/image/DecodePool.h
+++ b/image/DecodePool.h
@@ -54,16 +54,39 @@ public:
   /// @return the number of processor cores we have available. This is not the
   /// same as the number of decoding threads we're actually using.
   static uint32_t NumberOfCores();
 
   /// True if the DecodePool is being shutdown. This may only be called by
   /// threads from the pool to check if they should keep working or not.
   bool IsShuttingDown() const;
 
+  /// Whether there are any outstanding image decoding tasks that haven't
+  /// notified yet via IDecodingTask::NotifyDecodeComplete.
+  ///
+  /// This is intended to only be used for the reftest instrumentation.
+  ///
+  /// This could end up being positive on shutdown if we drop any task on the
+  /// floor, but that's completely fine.
+  bool HasOutstandingDecodingNotifications() const
+  {
+    return mOutstandingNotifications > 0;
+  }
+
+  void DecodingTaskCreated()
+  {
+    ++mOutstandingNotifications;
+  }
+
+  void DecodingTaskNotified()
+  {
+    MOZ_ASSERT(mOutstandingNotifications);
+    --mOutstandingNotifications;
+  }
+
   /// Ask the DecodePool to run @aTask asynchronously and return immediately.
   void AsyncRun(IDecodingTask* aTask);
 
   /**
    * Run @aTask synchronously if the task would prefer it. It's up to the task
    * itself to make this decision; @see IDecodingTask::ShouldPreferSyncRun(). If
    * @aTask doesn't prefer it, just run @aTask asynchronously and return
    * immediately.
@@ -92,16 +115,18 @@ private:
   friend class DecodePoolWorker;
 
   DecodePool();
   virtual ~DecodePool();
 
   static StaticRefPtr<DecodePool> sSingleton;
   static uint32_t sNumCores;
 
+  Atomic<uint32_t, Relaxed> mOutstandingNotifications;
+
   RefPtr<DecodePoolImpl> mImpl;
 
   // mMutex protects mIOThread.
   Mutex                         mMutex;
   nsCOMPtr<nsIThread>           mIOThread;
 };
 
 } // namespace image
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -16,16 +16,21 @@
 #include "mozilla/SystemGroup.h"
 
 namespace mozilla {
 
 using gfx::IntRect;
 
 namespace image {
 
+IDecodingTask::IDecodingTask()
+{
+  DecodePool::Singleton()->DecodingTaskCreated();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Helpers for sending notifications to the image associated with a decoder.
 ///////////////////////////////////////////////////////////////////////////////
 
 void
 IDecodingTask::EnsureHasEventTarget(NotNull<RasterImage*> aImage)
 {
   if (!mEventTarget) {
@@ -114,27 +119,29 @@ IDecodingTask::NotifyDecodeComplete(NotN
   DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
   SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
 
   // Synchronously notify if we can.
   if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
     aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
                                  invalidRect, frameCount, decoderFlags,
                                  surfaceFlags);
+    DecodePool::Singleton()->DecodingTaskNotified();
     return;
   }
 
   // We're forced to notify asynchronously.
   NotNull<RefPtr<RasterImage>> image = aImage;
   mEventTarget->Dispatch(NS_NewRunnableFunction(
                            "IDecodingTask::NotifyDecodeComplete",
                            [=]() -> void {
     image->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
                                 invalidRect, frameCount, decoderFlags,
                                 surfaceFlags);
+    DecodePool::Singleton()->DecodingTaskNotified();
   }), NS_DISPATCH_NORMAL);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // IDecodingTask implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
--- a/image/IDecodingTask.h
+++ b/image/IDecodingTask.h
@@ -45,17 +45,19 @@ public:
   /// @return a priority hint that DecodePool can use when scheduling this task.
   virtual TaskPriority Priority() const = 0;
 
   /// A default implementation of IResumable which resubmits the task to the
   /// DecodePool. Subclasses can override this if they need different behavior.
   void Resume() override;
 
 protected:
-  virtual ~IDecodingTask() { }
+  IDecodingTask();
+
+  virtual ~IDecodingTask() = default;
 
   /// Notify @aImage of @aDecoder's progress.
   void NotifyProgress(NotNull<RasterImage*> aImage,
                       NotNull<Decoder*> aDecoder);
 
   /// Notify @aImage that @aDecoder has finished.
   void NotifyDecodeComplete(NotNull<RasterImage*> aImage,
                             NotNull<Decoder*> aDecoder);
--- a/image/moz.build
+++ b/image/moz.build
@@ -33,16 +33,17 @@ XPIDL_SOURCES += [
     'imgIScriptedNotificationObserver.idl',
     'imgITools.idl',
     'nsIIconURI.idl',
 ]
 
 XPIDL_MODULE = 'imglib2'
 
 EXPORTS += [
+    'DecodePool.h',
     'FrameTimeout.h',
     'ImageCacheKey.h',
     'ImageLogging.h',
     'ImageMetadata.h',
     'ImageOps.h',
     'ImageRegion.h',
     'ImgDrawResult.h',
     'imgLoader.h',
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* a presentation of a document, part 1 */
 
 #include "nsPresContext.h"
 
+#include "DecodePool.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Encoding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 
 #include "base/basictypes.h"
 
@@ -134,23 +135,29 @@ nsPresContext::MakeColorPref(const nsStr
 
 bool
 nsPresContext::IsDOMPaintEventPending()
 {
   if (!mTransactions.IsEmpty()) {
     return true;
   }
   nsRootPresContext* drpc = GetRootPresContext();
-  if (drpc && drpc->mRefreshDriver->ViewManagerFlushIsPending()) {
+  if (!drpc) {
+    return false;
+  }
+
+  if (drpc->mRefreshDriver->ViewManagerFlushIsPending() ||
+      DecodePool::Singleton()->HasOutstandingDecodingNotifications()) {
     // Since we're promising that there will be a MozAfterPaint event
     // fired, we record an empty invalidation in case display list
     // invalidation doesn't invalidate anything further.
     NotifyInvalidation(drpc->mRefreshDriver->LastTransactionId().Next(), nsRect(0, 0, 0, 0));
     return true;
   }
+
   return false;
 }
 
 void
 nsPresContext::PrefChangedCallback(const char* aPrefName, void* instance_data)
 {
   RefPtr<nsPresContext>  presContext =
     static_cast<nsPresContext*>(instance_data);