Bug 1390755 - Reorder functions in PaintThread and CompositorBridgeChild. r?mchang draft
authorRyan Hunt <rhunt@eqrion.net>
Wed, 16 Aug 2017 16:53:15 -0500
changeset 647727 20d32e850cecd8f2f14b9b91ecd4a19f9e725bf8
parent 647726 ac47d49d456a122889f2d0cd4ebbad39cccd6058
child 726624 1e26a73ff5ae11bce1c9cc544a668b40e4f037df
push id74530
push userrhunt@eqrion.net
push dateWed, 16 Aug 2017 22:00:00 +0000
reviewersmchang
bugs1390755
milestone57.0a1
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,39 +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();
-}
-
-void
-DestroyPaintThread(UniquePtr<PaintThread>&& pt)
-{
-  MOZ_ASSERT(PaintThread::IsOnPaintThread());
-  pt->ShutdownOnPaintThread();
+  MOZ_ASSERT(!NS_IsMainThread());
+  sThreadId = PlatformThread::CurrentId();
 }
 
 /* static */ void
 PaintThread::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   UniquePtr<PaintThread> pt(sSingleton.forget());
@@ -128,28 +114,76 @@ PaintThread::Shutdown()
   }
 
   sThread->Dispatch(NewRunnableFunction(DestroyPaintThread, Move(pt)));
   sThread->Shutdown();
   sThread = nullptr;
 }
 
 void
+DestroyPaintThread(UniquePtr<PaintThread>&& pt)
+{
+  MOZ_ASSERT(PaintThread::IsOnPaintThread());
+  pt->ShutdownOnPaintThread();
+}
+
+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,31 +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);
-
-  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);
 
@@ -1254,23 +1253,24 @@ 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);
+
+  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();