diff --git a/gfx/layers/PaintThread.cpp b/gfx/layers/PaintThread.cpp index 1914858959de..68b86544e320 100644 --- a/gfx/layers/PaintThread.cpp +++ b/gfx/layers/PaintThread.cpp @@ -6,10 +6,7 @@ #include "PaintThread.h" -#include "base/task.h" -#include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/gfx/2D.h" -#include "mozilla/Preferences.h" #include "mozilla/SyncRunnable.h" namespace mozilla { @@ -18,8 +15,6 @@ namespace layers { using namespace gfx; StaticAutoPtr PaintThread::sSingleton; -StaticRefPtr PaintThread::sThread; -PlatformThreadId PaintThread::sThreadId; void PaintThread::Release() @@ -35,25 +30,24 @@ void PaintThread::InitOnPaintThread() { MOZ_ASSERT(!NS_IsMainThread()); - sThreadId = PlatformThread::CurrentId(); + mThreadId = PlatformThread::CurrentId(); } bool PaintThread::Init() { MOZ_ASSERT(NS_IsMainThread()); + nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(mThread)); - RefPtr thread; - nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(thread)); if (NS_FAILED(rv)) { return false; } - sThread = thread; nsCOMPtr paintInitTask = NewRunnableMethod("PaintThread::InitOnPaintThread", this, &PaintThread::InitOnPaintThread); - SyncRunnable::DispatchToThread(sThread, paintInitTask); + + SyncRunnable::DispatchToThread(PaintThread::sSingleton->mThread, paintInitTask); return true; } @@ -75,83 +69,49 @@ PaintThread::Get() return PaintThread::sSingleton.get(); } -void -DestroyPaintThread(UniquePtr&& pt) -{ - MOZ_ASSERT(PaintThread::IsOnPaintThread()); - pt->ShutdownOnPaintThread(); -} - /* static */ void PaintThread::Shutdown() { - MOZ_ASSERT(NS_IsMainThread()); - - UniquePtr pt(sSingleton.forget()); - if (!pt) { + if (!PaintThread::sSingleton) { return; } - sThread->Dispatch(NewRunnableFunction(DestroyPaintThread, Move(pt))); - sThread->Shutdown(); - sThread = nullptr; + PaintThread::sSingleton->ShutdownImpl(); + PaintThread::sSingleton = nullptr; } void -PaintThread::ShutdownOnPaintThread() +PaintThread::ShutdownImpl() { - MOZ_ASSERT(IsOnPaintThread()); + MOZ_ASSERT(NS_IsMainThread()); + PaintThread::sSingleton->mThread->AsyncShutdown(); } -/* static */ bool +bool PaintThread::IsOnPaintThread() { - return sThreadId == PlatformThread::CurrentId(); -} - -void -PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge, - gfx::DrawTargetCapture* aCapture, - gfx::DrawTarget* aTarget) -{ - MOZ_ASSERT(IsOnPaintThread()); - - // Draw all the things into the actual dest target. - aTarget->DrawCapturedDT(aCapture, Matrix()); - - if (aBridge) { - aBridge->NotifyFinishedAsyncPaint(); - } + MOZ_ASSERT(mThread); + return PlatformThread::CurrentId() == mThreadId; } void PaintThread::PaintContents(DrawTargetCapture* aCapture, DrawTarget* aTarget) { - MOZ_ASSERT(NS_IsMainThread()); + if (!IsOnPaintThread()) { + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr paintTask = + NewRunnableMethod("PaintThread::PaintContents", + this, + &PaintThread::PaintContents, + aCapture, aTarget); - // 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 cbc; - if (!gfxPrefs::LayersOMTPForceSync()) { - cbc = CompositorBridgeChild::Get(); - cbc->NotifyBeginAsyncPaint(); + SyncRunnable::DispatchToThread(mThread, paintTask); + return; } - RefPtr capture(aCapture); - RefPtr target(aTarget); - RefPtr task = NS_NewRunnableFunction("PaintThread::PaintContents", - [=, this]() -> void - { - PaintContentsAsync(cbc, capture, target); - }); - - if (cbc) { - sThread->Dispatch(task.forget()); - } else { - SyncRunnable::DispatchToThread(sThread, task); - } + // Draw all the things into the actual dest target. + aTarget->DrawCapturedDT(aCapture, Matrix()); } } // namespace layers diff --git a/gfx/layers/PaintThread.h b/gfx/layers/PaintThread.h index 4d7bc0a46284..813e8a663b5d 100644 --- a/gfx/layers/PaintThread.h +++ b/gfx/layers/PaintThread.h @@ -9,7 +9,6 @@ #include "base/platform_thread.h" #include "mozilla/StaticPtr.h" -#include "mozilla/UniquePtr.h" #include "nsThreadUtils.h" namespace mozilla { @@ -20,19 +19,14 @@ class DrawTargetCapture; namespace layers { -class CompositorBridgeChild; - class PaintThread final { - friend void DestroyPaintThread(UniquePtr&& aPaintThread); - public: static void Start(); static void Shutdown(); static PaintThread* Get(); void PaintContents(gfx::DrawTargetCapture* aCapture, gfx::DrawTarget* aTarget); - // Sync Runnables need threads to be ref counted, // But this thread lives through the whole process. // We're only temporarily using sync runnables so @@ -40,23 +34,18 @@ public: void Release(); void AddRef(); - // Helper for asserts. - static bool IsOnPaintThread(); - private: + bool IsOnPaintThread(); bool Init(); - void ShutdownOnPaintThread(); + void ShutdownImpl(); void InitOnPaintThread(); - void PaintContentsAsync(CompositorBridgeChild* aBridge, - gfx::DrawTargetCapture* aCapture, - gfx::DrawTarget* aTarget); static StaticAutoPtr sSingleton; - static StaticRefPtr sThread; - static PlatformThreadId sThreadId; + RefPtr mThread; + PlatformThreadId mThreadId; }; } // namespace layers } // namespace mozilla -#endif +#endif \ No newline at end of file diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index 8a18e32d9dd5..fd50db920144 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -226,9 +226,6 @@ ClientLayerManager::CreateReadbackLayer() bool ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) { - // Wait for any previous async paints to complete before starting to paint again. - GetCompositorBridgeChild()->FlushAsyncPaints(); - MOZ_ASSERT(mForwarder, "ClientLayerManager::BeginTransaction without forwarder"); if (!mForwarder->IPCOpen()) { gfxCriticalNote << "ClientLayerManager::BeginTransaction with IPC channel down. GPU process may have died."; diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp index b8c8e0efacb6..ab6582c1e0a4 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -19,7 +19,6 @@ #include "mozilla/layers/IAPZCTreeManager.h" #include "mozilla/layers/APZCTreeManagerChild.h" #include "mozilla/layers/LayerTransactionChild.h" -#include "mozilla/layers/PaintThread.h" #include "mozilla/layers/PLayerTransactionChild.h" #include "mozilla/layers/PTextureChild.h" #include "mozilla/layers/TextureClient.h"// for TextureClient @@ -90,9 +89,6 @@ CompositorBridgeChild::CompositorBridgeChild(CompositorManagerChild *aManager) , mMessageLoop(MessageLoop::current()) , mProcessToken(0) , mSectionAllocator(nullptr) - , mPaintLock("CompositorBridgeChild.mPaintLock") - , mOutstandingAsyncPaints(0) - , mIsWaitingForPaint(false) { MOZ_ASSERT(NS_IsMainThread()); } @@ -546,20 +542,8 @@ CompositorBridgeChild::ActorDestroy(ActorDestroyReason aWhy) gfxCriticalNote << "Receive IPC close with reason=AbnormalShutdown"; } - { - // We take the lock to update these fields, since they are read from the - // paint thread. We don't need the lock to init them, since that happens - // on the main thread before the paint thread can ever grab a reference - // to the CompositorBridge object. - // - // Note that it is useful to take this lock for one other reason: It also - // tells us whether GetIPCChannel is safe to call. If we access the IPC - // channel within this lock, when mCanSend is true, then we know it has not - // been zapped by IPDL. - MonitorAutoLock lock(mPaintLock); - mCanSend = false; - mActorDestroyed = true; - } + mCanSend = false; + mActorDestroyed = true; if (mProcessToken && XRE_IsParentProcess()) { GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken); @@ -1130,86 +1114,6 @@ CompositorBridgeChild::GetNextPipelineId() return wr::AsPipelineId(GetNextResourceId()); } -void -CompositorBridgeChild::NotifyBeginAsyncPaint() -{ - 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 - // incorrect rendering or IPDL deadlocks. - MOZ_ASSERT(!mIsWaitingForPaint); - - mOutstandingAsyncPaints++; -} - -void -CompositorBridgeChild::NotifyFinishedAsyncPaint() -{ - MOZ_ASSERT(PaintThread::IsOnPaintThread()); - - MonitorAutoLock lock(mPaintLock); - - mOutstandingAsyncPaints--; - - // It's possible that we painted so fast that the main thread never reached - // the code that starts delaying messages. If so, mIsWaitingForPaint will be - // false, and we can safely return. - if (mIsWaitingForPaint && mOutstandingAsyncPaints == 0) { - ResumeIPCAfterAsyncPaint(); - - // 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) { - 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); - - mIsWaitingForPaint = false; - - // It's also possible that the channel has shut down already. - if (!mCanSend || mActorDestroyed) { - return; - } - - GetIPCChannel()->StopPostponingSends(); -} - -void -CompositorBridgeChild::FlushAsyncPaints() -{ - MOZ_ASSERT(NS_IsMainThread()); - - MonitorAutoLock lock(mPaintLock); - while (mIsWaitingForPaint) { - lock.Wait(); - } -} - } // namespace layers } // namespace mozilla + diff --git a/gfx/layers/ipc/CompositorBridgeChild.h b/gfx/layers/ipc/CompositorBridgeChild.h index be1529cbd2ac..f5ebe2c2c4d6 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.h +++ b/gfx/layers/ipc/CompositorBridgeChild.h @@ -10,7 +10,6 @@ #include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 #include "mozilla/Attributes.h" // for override -#include "mozilla/Monitor.h" #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/layers/PCompositorBridgeChild.h" #include "mozilla/layers/TextureForwarder.h" // for TextureForwarder @@ -221,33 +220,10 @@ public: 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(); - - // Must only be called from the paint thread. Notifies the CompositorBridge - // that the paint thread has finished an asynchronous paint request. - void NotifyFinishedAsyncPaint(); - - // 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(); - 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(); - void AfterDestroy(); virtual PLayerTransactionChild* @@ -352,20 +328,6 @@ private: uint64_t mProcessToken; FixedSizeSmallShmemSectionAllocator* mSectionAllocator; - - // Off-Main-Thread Painting state. This covers access to the OMTP-related - // state below. - Monitor mPaintLock; - - // Contains the number of outstanding asynchronous paints tied to a - // PLayerTransaction on this bridge. This is R/W on both the main and paint - // threads, and must be accessed within the paint lock. - size_t mOutstandingAsyncPaints; - - // True if this CompositorBridge is currently delaying its messages until the - // paint thread completes. This is R/W on both the main and paint threads, and - // must be accessed within the paint lock. - bool mIsWaitingForPaint; }; } // namespace layers diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index d587b0c2c8dc..337aff46bab4 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -764,10 +764,6 @@ ShadowLayerForwarder::EndTransaction(const nsIntRegion& aRegionToClear, } } - // We delay at the last possible minute, to give the paint thread a chance to - // finish. If it does we don't have to delay messages at all. - GetCompositorBridgeChild()->PostponeMessagesIfAsyncPainting(); - MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction...")); RenderTraceScope rendertrace3("Forward Transaction", "000093"); if (!mShadowManager->SendUpdate(info)) { diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index e99d61e1b51b..117d457133ad 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -585,7 +585,6 @@ private: DECL_GFX_PREF(Once, "layers.mlgpu.enable-container-resizing", AdvancedLayersEnableContainerResizing, bool, true); DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false); DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1); - DECL_GFX_PREF(Live, "layers.omtp.force-sync", LayersOMTPForceSync, bool, true); DECL_GFX_PREF(Live, "layers.orientation.sync.timeout", OrientationSyncMillis, uint32_t, (uint32_t)0); DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false); DECL_GFX_PREF(Live, "layers.progressive-paint", ProgressivePaint, bool, false); diff --git a/xpcom/base/StaticPtr.h b/xpcom/base/StaticPtr.h index e64a9413e59f..f2c820a93937 100644 --- a/xpcom/base/StaticPtr.h +++ b/xpcom/base/StaticPtr.h @@ -67,13 +67,6 @@ public: T& operator*() const { return *get(); } - T* forget() - { - T* temp = mRawPtr; - mRawPtr = nullptr; - return temp; - } - private: // Disallow copy constructor, but only in debug mode. We only define // a default constructor in debug mode (see above); if we declared