Bug 1390755 - Notify the paint thread that a layer transaction is completed so it can unblock the main thread. r?mchang draft
authorRyan Hunt <rhunt@eqrion.net>
Wed, 16 Aug 2017 01:04:41 -0500
changeset 647724 1fe2bce0d05a74868c9f08a02deff04eefb1f8be
parent 646672 5ab5511100233277a760550ac509283278a0e3d9
child 647725 bcb0b4e51f42f165bc3ac6c74e7ab2379feee664
push id74530
push userrhunt@eqrion.net
push dateWed, 16 Aug 2017 22:00:00 +0000
reviewersmchang
bugs1390755
milestone57.0a1
Bug 1390755 - Notify the paint thread that a layer transaction is completed so it can unblock the main thread. r?mchang MozReview-Commit-ID: 7kQHWUwek7v
gfx/layers/PaintThread.cpp
gfx/layers/PaintThread.h
gfx/layers/client/ClientLayerManager.cpp
--- a/gfx/layers/PaintThread.cpp
+++ b/gfx/layers/PaintThread.cpp
@@ -197,49 +197,49 @@ PaintThread::EndAsyncPaintingLayer()
   for (size_t i = 0; i < mDrawTargetsToFlush.Length(); i++) {
     mDrawTargetsToFlush[i]->Flush();
   }
 
   mDrawTargetsToFlush.Clear();
 }
 
 void
-PaintThread::SynchronizePaintTextures(SyncObjectClient* aSyncObject)
+PaintThread::FinishedLayerTransaction(SyncObjectClient* aSyncObject)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aSyncObject);
 
   RefPtr<CompositorBridgeChild> cbc;
   if (!gfxPrefs::LayersOMTPForceSync()) {
     cbc = CompositorBridgeChild::Get();
   }
 
   RefPtr<SyncObjectClient> syncObject(aSyncObject);
   RefPtr<PaintThread> self = this;
-  RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::SyncTextureData",
+  RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::EndAsyncLayerTransaction",
     [self, cbc, syncObject]() -> void
   {
-    self->SyncTextureData(cbc, syncObject);
+    self->EndAsyncLayerTransaction(cbc, syncObject);
   });
 
   if (cbc) {
     sThread->Dispatch(task.forget());
   } else {
     SyncRunnable::DispatchToThread(sThread, task);
   }
 }
 
 void
-PaintThread::SyncTextureData(CompositorBridgeChild* aBridge,
-                             SyncObjectClient* aSyncObject)
+PaintThread::EndAsyncLayerTransaction(CompositorBridgeChild* aBridge,
+                                      SyncObjectClient* aSyncObject)
 {
   MOZ_ASSERT(IsOnPaintThread());
-  MOZ_ASSERT(aSyncObject);
 
-  aSyncObject->Synchronize();
+  if (aSyncObject) {
+    aSyncObject->Synchronize();
+  }
 
   if (aBridge) {
     aBridge->NotifyFinishedAsyncPaintTransaction();
   }
 }
 
 void
 PaintThread::PaintContents(CapturedPaintState* aState,
--- a/gfx/layers/PaintThread.h
+++ b/gfx/layers/PaintThread.h
@@ -70,23 +70,23 @@ public:
   void PaintContents(CapturedPaintState* aState,
                      PrepDrawTargetForPaintingCallback aCallback);
 
   // To 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 FinishedLayerBatch();
 
-  // Must be called on the main thread. Tells the paint thread
-  // to schedule a sync textures after all async paints are done.
-  // NOTE: The other paint thread functions are on a per PAINT
-  // or per paint layer basis. This MUST be called at the end
-  // of a layer transaction as multiple paints can occur
-  // with multiple layers. We only have to do this once per transaction.
-  void SynchronizePaintTextures(SyncObjectClient* aSyncObject);
+  // Must be called on the main thread. Signifies that the current
+  // layer tree transaction has been finished and any async paints
+  // for it have been queued on the paint thread. This MUST be called
+  // at the end of a layer transaction as it will be used to do an optional
+  // texture sync and then unblock the main thread if it is waiting to paint
+  // a new frame.
+  void FinishedLayerTransaction(SyncObjectClient* aSyncObject);
 
   // 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();
 
@@ -96,18 +96,18 @@ public:
 private:
   bool Init();
   void ShutdownOnPaintThread();
   void InitOnPaintThread();
   void PaintContentsAsync(CompositorBridgeChild* aBridge,
                           CapturedPaintState* aState,
                           PrepDrawTargetForPaintingCallback aCallback);
   void EndAsyncPaintingLayer();
-  void SyncTextureData(CompositorBridgeChild* aBridge,
-                       SyncObjectClient* aSyncObject);
+  void EndAsyncLayerTransaction(CompositorBridgeChild* aBridge,
+                                SyncObjectClient* aSyncObject);
 
   static StaticAutoPtr<PaintThread> sSingleton;
   static StaticRefPtr<nsIThread> sThread;
   static PlatformThreadId sThreadId;
 
   // This shouldn't be very many elements, so a list should be fine.
   // Should only be accessed on the paint thread.
   nsTArray<RefPtr<gfx::DrawTarget>> mDrawTargetsToFlush;
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -724,25 +724,34 @@ void
 ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
 {
   AutoProfilerTracing tracing("Paint", "ForwardTransaction");
   TimeStamp start = TimeStamp::Now();
 
   // Skip the synchronization for buffer since we also skip the painting during
   // device-reset status. With OMTP, we have to wait for async paints
   // before we synchronize and it's done on the paint thread.
+  SyncObjectClient* syncObject = nullptr;
   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
     if (mForwarder->GetSyncObject() &&
         mForwarder->GetSyncObject()->IsSyncObjectValid()) {
-      if (mTextureSyncOnPaintThread) {
-        // We have to wait for all async paints to finish to do this
-        PaintThread::Get()->SynchronizePaintTextures(mForwarder->GetSyncObject());
-      } else {
-        mForwarder->GetSyncObject()->Synchronize();
-      }
+      syncObject = mForwarder->GetSyncObject();
+    }
+  }
+
+  // If there were async paints queued, then we need to notify the paint thread
+  // that we finished queuing async paints so it can schedule a runnable after
+  // all async painting is finished to do a texture sync and unblock the main
+  // thread if it is waiting before doing a new layer transaction.
+  if (mTextureSyncOnPaintThread) {
+    MOZ_ASSERT(PaintThread::Get());
+    PaintThread::Get()->FinishedLayerTransaction(syncObject);
+  } else {
+    if (syncObject) {
+      syncObject->Synchronize();
     }
   }
 
   mPhase = PHASE_FORWARD;
 
   mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction);
   TimeStamp transactionStart;
   if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) {