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
--- 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()) {