Bug 1390755 - Reorder functions in PaintThread and CompositorBridgeChild. r?mchang
MozReview-Commit-ID: 26Cbc9S0Zls
--- 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();