Bug 1390755 - Reorder functions in PaintThread and CompositorBridgeChild. r=mchang
authorRyan Hunt <rhunt@eqrion.net>
Wed, 16 Aug 2017 16:53:15 -0500
changeset 375196 a2b09cf8f6c524abde02b255e856234f23e4a999
parent 375195 5b0eb3f25b7412e3be948bfa95c3d818410944af
child 375197 0cf94aae28707b28ff1fdd27448843af23136e0d
push id93852
push userrhunt@eqrion.net
push dateThu, 17 Aug 2017 05:11:50 +0000
treeherdermozilla-inbound@a2b09cf8f6c5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1390755
milestone57.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 1390755 - Reorder functions in PaintThread and CompositorBridgeChild. r=mchang MozReview-Commit-ID: 26Cbc9S0Zls
gfx/layers/PaintThread.cpp
gfx/layers/PaintThread.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
--- a/gfx/layers/PaintThread.cpp
+++ b/gfx/layers/PaintThread.cpp
@@ -61,21 +61,25 @@ PaintThread::Release()
 {
 }
 
 void
 PaintThread::AddRef()
 {
 }
 
-void
-PaintThread::InitOnPaintThread()
+/* static */ void
+PaintThread::Start()
 {
-  MOZ_ASSERT(!NS_IsMainThread());
-  sThreadId = PlatformThread::CurrentId();
+  PaintThread::sSingleton = new PaintThread();
+
+  if (!PaintThread::sSingleton->Init()) {
+    gfxCriticalNote << "Unable to start paint thread";
+    PaintThread::sSingleton = nullptr;
+  }
 }
 
 bool
 PaintThread::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<nsIThread> thread;
@@ -87,32 +91,21 @@ PaintThread::Init()
 
   nsCOMPtr<nsIRunnable> paintInitTask =
     NewRunnableMethod("PaintThread::InitOnPaintThread",
                       this, &PaintThread::InitOnPaintThread);
   SyncRunnable::DispatchToThread(sThread, paintInitTask);
   return true;
 }
 
-/* static */ void
-PaintThread::Start()
+void
+PaintThread::InitOnPaintThread()
 {
-  PaintThread::sSingleton = new PaintThread();
-
-  if (!PaintThread::sSingleton->Init()) {
-    gfxCriticalNote << "Unable to start paint thread";
-    PaintThread::sSingleton = nullptr;
-  }
-}
-
-/* static */ PaintThread*
-PaintThread::Get()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  return PaintThread::sSingleton.get();
+  MOZ_ASSERT(!NS_IsMainThread());
+  sThreadId = PlatformThread::CurrentId();
 }
 
 void
 DestroyPaintThread(UniquePtr<PaintThread>&& pt)
 {
   MOZ_ASSERT(PaintThread::IsOnPaintThread());
   pt->ShutdownOnPaintThread();
 }
@@ -133,23 +126,64 @@ PaintThread::Shutdown()
 }
 
 void
 PaintThread::ShutdownOnPaintThread()
 {
   MOZ_ASSERT(IsOnPaintThread());
 }
 
+/* static */ PaintThread*
+PaintThread::Get()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  return PaintThread::sSingleton.get();
+}
+
 /* static */ bool
 PaintThread::IsOnPaintThread()
 {
   return sThreadId == PlatformThread::CurrentId();
 }
 
 void
+PaintThread::PaintContents(CapturedPaintState* aState,
+                           PrepDrawTargetForPaintingCallback aCallback)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aState);
+
+  // If painting asynchronously, we need to acquire the compositor bridge which
+  // owns the underlying MessageChannel. Otherwise we leave it null and use
+  // synchronous dispatch.
+  RefPtr<CompositorBridgeChild> cbc;
+  if (!gfxPrefs::LayersOMTPForceSync()) {
+    cbc = CompositorBridgeChild::Get();
+    cbc->NotifyBeginAsyncPaint(aState);
+  }
+  RefPtr<CapturedPaintState> state(aState);
+  RefPtr<DrawTargetCapture> capture(aState->mCapture);
+
+  RefPtr<PaintThread> self = this;
+  RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
+    [self, cbc, capture, state, aCallback]() -> void
+  {
+    self->AsyncPaintContents(cbc,
+                             state,
+                             aCallback);
+  });
+
+  if (cbc) {
+    sThread->Dispatch(task.forget());
+  } else {
+    SyncRunnable::DispatchToThread(sThread, task);
+  }
+}
+
+void
 PaintThread::AsyncPaintContents(CompositorBridgeChild* aBridge,
                                 CapturedPaintState* aState,
                                 PrepDrawTargetForPaintingCallback aCallback)
 {
   MOZ_ASSERT(IsOnPaintThread());
   MOZ_ASSERT(aState);
 
   DrawTarget* target = aState->mTarget;
@@ -237,44 +271,10 @@ PaintThread::AsyncEndLayerTransaction(Co
     aSyncObject->Synchronize();
   }
 
   if (aBridge) {
     aBridge->NotifyFinishedAsyncEndLayerTransaction();
   }
 }
 
-void
-PaintThread::PaintContents(CapturedPaintState* aState,
-                           PrepDrawTargetForPaintingCallback aCallback)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aState);
-
-  // If painting asynchronously, we need to acquire the compositor bridge which
-  // owns the underlying MessageChannel. Otherwise we leave it null and use
-  // synchronous dispatch.
-  RefPtr<CompositorBridgeChild> cbc;
-  if (!gfxPrefs::LayersOMTPForceSync()) {
-    cbc = CompositorBridgeChild::Get();
-    cbc->NotifyBeginAsyncPaint(aState);
-  }
-  RefPtr<CapturedPaintState> state(aState);
-  RefPtr<DrawTargetCapture> capture(aState->mCapture);
-
-  RefPtr<PaintThread> self = this;
-  RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
-    [self, cbc, capture, state, aCallback]() -> void
-  {
-    self->AsyncPaintContents(cbc,
-                             state,
-                             aCallback);
-  });
-
-  if (cbc) {
-    sThread->Dispatch(task.forget());
-  } else {
-    SyncRunnable::DispatchToThread(sThread, task);
-  }
-}
-
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/PaintThread.h
+++ b/gfx/layers/PaintThread.h
@@ -62,16 +62,20 @@ class CompositorBridgeChild;
 class PaintThread final
 {
   friend void DestroyPaintThread(UniquePtr<PaintThread>&& aPaintThread);
 
 public:
   static void Start();
   static void Shutdown();
   static PaintThread* Get();
+
+  // Helper for asserts.
+  static bool IsOnPaintThread();
+
   void PaintContents(CapturedPaintState* aState,
                      PrepDrawTargetForPaintingCallback aCallback);
 
   // Must be called on the main thread. Signifies that the current
   // batch of CapturedPaintStates* for PaintContents have been recorded
   // and the main thread is finished recording this layer.
   void EndLayer();
 
@@ -85,23 +89,21 @@ public:
 
   // Sync Runnables need threads to be ref counted,
   // But this thread lives through the whole process.
   // We're only temporarily using sync runnables so
   // Override release/addref but don't do anything.
   void Release();
   void AddRef();
 
-  // Helper for asserts.
-  static bool IsOnPaintThread();
-
 private:
   bool Init();
   void ShutdownOnPaintThread();
   void InitOnPaintThread();
+
   void AsyncPaintContents(CompositorBridgeChild* aBridge,
                           CapturedPaintState* aState,
                           PrepDrawTargetForPaintingCallback aCallback);
   void AsyncEndLayer();
   void AsyncEndLayerTransaction(CompositorBridgeChild* aBridge,
                                 SyncObjectClient* aSyncObject);
 
   static StaticAutoPtr<PaintThread> sSingleton;
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -1130,16 +1130,30 @@ CompositorBridgeChild::GetNextExternalIm
 
 wr::PipelineId
 CompositorBridgeChild::GetNextPipelineId()
 {
   return wr::AsPipelineId(GetNextResourceId());
 }
 
 void
+CompositorBridgeChild::FlushAsyncPaints()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  MonitorAutoLock lock(mPaintLock);
+  while (mIsWaitingForPaint) {
+    lock.Wait();
+  }
+
+  // It's now safe to free any TextureClients that were used during painting.
+  mTextureClientsForAsyncPaint.Clear();
+}
+
+void
 CompositorBridgeChild::NotifyBeginAsyncPaint(CapturedPaintState* aState)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   MonitorAutoLock lock(mPaintLock);
 
   // We must not be waiting for paints to complete yet. This would imply we
   // started a new paint without waiting for a previous one, which could lead to
@@ -1220,33 +1234,16 @@ CompositorBridgeChild::NotifyFinishedAsy
 
     // Notify the main thread in case it's blocking. We do this unconditionally
     // to avoid deadlocking.
     lock.Notify();
   }
 }
 
 void
-CompositorBridgeChild::PostponeMessagesIfAsyncPainting()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  MonitorAutoLock lock(mPaintLock);
-
-  MOZ_ASSERT(!mIsWaitingForPaint);
-
-  // We need to wait for async paints and the async end transaction as
-  // it will do texture synchronization
-  if (mOutstandingAsyncPaints > 0 || mOutstandingAsyncEndTransaction) {
-    mIsWaitingForPaint = true;
-    GetIPCChannel()->BeginPostponingSends();
-  }
-}
-
-void
 CompositorBridgeChild::ResumeIPCAfterAsyncPaint()
 {
   // Note: the caller is responsible for holding the lock.
   mPaintLock.AssertCurrentThreadOwns();
   MOZ_ASSERT(PaintThread::IsOnPaintThread());
   MOZ_ASSERT(mOutstandingAsyncPaints == 0);
   MOZ_ASSERT(mIsWaitingForPaint);
 
@@ -1256,23 +1253,26 @@ CompositorBridgeChild::ResumeIPCAfterAsy
   if (!mCanSend || mActorDestroyed) {
     return;
   }
 
   GetIPCChannel()->StopPostponingSends();
 }
 
 void
-CompositorBridgeChild::FlushAsyncPaints()
+CompositorBridgeChild::PostponeMessagesIfAsyncPainting()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   MonitorAutoLock lock(mPaintLock);
-  while (mIsWaitingForPaint) {
-    lock.Wait();
+
+  MOZ_ASSERT(!mIsWaitingForPaint);
+
+  // We need to wait for async paints and the async end transaction as
+  // it will do texture synchronization
+  if (mOutstandingAsyncPaints > 0 || mOutstandingAsyncEndTransaction) {
+    mIsWaitingForPaint = true;
+    GetIPCChannel()->BeginPostponingSends();
   }
-
-  // It's now safe to free any TextureClients that were used during painting.
-  mTextureClientsForAsyncPaint.Clear();
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -217,45 +217,45 @@ public:
   uint64_t DeviceResetSequenceNumber() const {
     return mDeviceResetSequenceNumber;
   }
 
   wr::MaybeExternalImageId GetNextExternalImageId() override;
 
   wr::PipelineId GetNextPipelineId();
 
-  // Must only be called from the main thread. Notifies the CompositorBridge
-  // that the paint thread is going to begin painting asynchronously.
-  void NotifyBeginAsyncPaint(CapturedPaintState* aState);
-
-  // Must only be called from the main thread. Notifies the CompoistorBridge
-  // that a transaction is about to be sent, and if the paint thread is
-  // currently painting, to begin delaying IPC messages.
-  void PostponeMessagesIfAsyncPainting();
-
   // Must only be called from the main thread. Ensures that any paints from
   // previous frames have been flushed. The main thread blocks until the
   // operation completes.
   void FlushAsyncPaints();
 
+  // Must only be called from the main thread. Notifies the CompositorBridge
+  // that the paint thread is going to begin painting asynchronously.
+  void NotifyBeginAsyncPaint(CapturedPaintState* aState);
+
   // Must only be called from the paint thread. Notifies the CompositorBridge
   // that the paint thread has finished an asynchronous paint request.
   void NotifyFinishedAsyncPaint(CapturedPaintState* aState);
 
   // Must only be called from the main thread. Notifies the CompositorBridge
   // that the paint thread is going to perform texture synchronization at the
   // end of async painting, and should postpone messages if needed until
   // finished.
   void NotifyBeginAsyncEndLayerTransaction();
 
   // Must only be called from the paint thread. Notifies the CompositorBridge
   // that the paint thread has finished all async paints and texture syncs from
   // a given transaction and may resume sending messages.
   void NotifyFinishedAsyncEndLayerTransaction();
 
+  // Must only be called from the main thread. Notifies the CompoistorBridge
+  // that a transaction is about to be sent, and if the paint thread is
+  // currently painting, to begin delaying IPC messages.
+  void PostponeMessagesIfAsyncPainting();
+
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CompositorBridgeChild();
 
   // Must only be called from the paint thread. If the main thread is delaying
   // IPC messages, this forwards all such delayed IPC messages to the I/O thread
   // and resumes IPC.
   void ResumeIPCAfterAsyncPaint();