зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1852145
- Part 1. Refactor CanvasRenderThread to represent a virtual thread. r=gfx-reviewers,lsalzman
Prior to this patch, CanvasRenderThread represents the concrete thread we would spawn if gfxVars::UseCanvasRenderThread() returned true. CanvasManagerParent was responsible for checking our state and deciding between using the Compositor, Renderer and CanvasRender threads. This patch makes the CanvasRenderThread class represent a virtual thread. It will spawn a CanvasRender thread if necessary. Other classes may use the abstraction to run on the correct thread without having to duplicate the selection logic. Differential Revision: https://phabricator.services.mozilla.com/D187719
This commit is contained in:
Родитель
620833163a
Коммит
f1d22fb2f1
|
@ -13,7 +13,6 @@
|
|||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/webgpu/WebGPUParent.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
|
@ -27,41 +26,21 @@ CanvasManagerParent::ManagerSet CanvasManagerParent::sManagers;
|
|||
|
||||
auto manager = MakeRefPtr<CanvasManagerParent>();
|
||||
|
||||
if (!gfxVars::SupportsThreadsafeGL()) {
|
||||
nsCOMPtr<nsIThread> owningThread;
|
||||
owningThread = wr::RenderThread::GetRenderThread();
|
||||
nsCOMPtr<nsIThread> owningThread =
|
||||
gfx::CanvasRenderThread::GetCanvasRenderThread();
|
||||
MOZ_ASSERT(owningThread);
|
||||
|
||||
owningThread->Dispatch(NewRunnableMethod<Endpoint<PCanvasManagerParent>&&>(
|
||||
"CanvasManagerParent::Bind", manager, &CanvasManagerParent::Bind,
|
||||
std::move(aEndpoint)));
|
||||
} else if (gfxVars::UseCanvasRenderThread()) {
|
||||
nsCOMPtr<nsIThread> owningThread;
|
||||
owningThread = gfx::CanvasRenderThread::GetCanvasRenderThread();
|
||||
MOZ_ASSERT(owningThread);
|
||||
|
||||
owningThread->Dispatch(NewRunnableMethod<Endpoint<PCanvasManagerParent>&&>(
|
||||
"CanvasManagerParent::Bind", manager, &CanvasManagerParent::Bind,
|
||||
std::move(aEndpoint)));
|
||||
} else {
|
||||
manager->Bind(std::move(aEndpoint));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void CanvasManagerParent::Shutdown() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsISerialEventTarget> owningThread;
|
||||
if (!gfxVars::SupportsThreadsafeGL()) {
|
||||
owningThread = wr::RenderThread::GetRenderThread();
|
||||
} else if (gfxVars::UseCanvasRenderThread()) {
|
||||
owningThread = gfx::CanvasRenderThread::GetCanvasRenderThread();
|
||||
} else {
|
||||
owningThread = layers::CompositorThread();
|
||||
}
|
||||
if (!owningThread) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIThread> owningThread =
|
||||
gfx::CanvasRenderThread::GetCanvasRenderThread();
|
||||
MOZ_ASSERT(owningThread);
|
||||
|
||||
NS_DispatchAndSpinEventLoopUntilComplete(
|
||||
"CanvasManagerParent::Shutdown"_ns, owningThread,
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
#include "CanvasRenderThread.h"
|
||||
|
||||
#include "mozilla/BackgroundHangMonitor.h"
|
||||
#include "mozilla/gfx/CanvasManagerParent.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "transport/runnable_utils.h"
|
||||
|
||||
namespace mozilla::gfx {
|
||||
|
@ -17,13 +21,11 @@ static mozilla::BackgroundHangMonitor* sBackgroundHangMonitor;
|
|||
static bool sCanvasRenderThreadEverStarted = false;
|
||||
#endif
|
||||
|
||||
CanvasRenderThread::CanvasRenderThread(RefPtr<nsIThread> aThread)
|
||||
: mThread(std::move(aThread)) {}
|
||||
CanvasRenderThread::CanvasRenderThread(nsCOMPtr<nsIThread>&& aThread,
|
||||
bool aCreatedThread)
|
||||
: mThread(std::move(aThread)), mCreatedThread(aCreatedThread) {}
|
||||
|
||||
CanvasRenderThread::~CanvasRenderThread() {}
|
||||
|
||||
// static
|
||||
CanvasRenderThread* CanvasRenderThread::Get() { return sCanvasRenderThread; }
|
||||
CanvasRenderThread::~CanvasRenderThread() = default;
|
||||
|
||||
// static
|
||||
void CanvasRenderThread::Start() {
|
||||
|
@ -37,6 +39,21 @@ void CanvasRenderThread::Start() {
|
|||
sCanvasRenderThreadEverStarted = true;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
if (!gfxVars::SupportsThreadsafeGL()) {
|
||||
thread = wr::RenderThread::GetRenderThread();
|
||||
MOZ_ASSERT(thread);
|
||||
} else if (!gfxVars::UseCanvasRenderThread()) {
|
||||
thread = layers::CompositorThread();
|
||||
MOZ_ASSERT(thread);
|
||||
}
|
||||
|
||||
if (thread) {
|
||||
sCanvasRenderThread =
|
||||
new CanvasRenderThread(std::move(thread), /* aCreatedThread */ false);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is 4M, which is higher than the default 256K.
|
||||
// Increased with bug 1753349 to accommodate the `chromium/5359` branch of
|
||||
// ANGLE, which has large peak stack usage for some pathological shader
|
||||
|
@ -51,7 +68,6 @@ void CanvasRenderThread::Start() {
|
|||
const uint32_t stackSize =
|
||||
nsIThreadManager::DEFAULT_STACK_SIZE ? 4096 << 10 : 0;
|
||||
|
||||
RefPtr<nsIThread> thread;
|
||||
nsresult rv = NS_NewNamedThread(
|
||||
"CanvasRenderer", getter_AddRefs(thread),
|
||||
NS_NewRunnableFunction(
|
||||
|
@ -75,26 +91,41 @@ void CanvasRenderThread::Start() {
|
|||
}),
|
||||
{.stackSize = stackSize});
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
sCanvasRenderThread = new CanvasRenderThread(thread);
|
||||
sCanvasRenderThread =
|
||||
new CanvasRenderThread(std::move(thread), /* aCreatedThread */ true);
|
||||
}
|
||||
|
||||
// static
|
||||
void CanvasRenderThread::ShutDown() {
|
||||
void CanvasRenderThread::Shutdown() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(sCanvasRenderThread);
|
||||
|
||||
// It is possible we never initialized this thread in the parent process,
|
||||
// because we used the GPU process instead.
|
||||
if (!sCanvasRenderThread) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
return;
|
||||
}
|
||||
|
||||
CanvasManagerParent::Shutdown();
|
||||
|
||||
// Null out sCanvasRenderThread before we enter synchronous Shutdown,
|
||||
// from here on we are to be considered shut down for our consumers.
|
||||
nsCOMPtr<nsIThread> oldThread = sCanvasRenderThread->GetCanvasRenderThread();
|
||||
nsCOMPtr<nsIThread> oldThread;
|
||||
if (sCanvasRenderThread->mCreatedThread) {
|
||||
oldThread = sCanvasRenderThread->GetCanvasRenderThread();
|
||||
MOZ_ASSERT(oldThread);
|
||||
}
|
||||
sCanvasRenderThread = nullptr;
|
||||
|
||||
// We do a synchronous shutdown here while spinning the MT event loop.
|
||||
MOZ_ASSERT(oldThread);
|
||||
// We do a synchronous shutdown here while spinning the MT event loop, but
|
||||
// only if we created a dedicated CanvasRender thread.
|
||||
if (oldThread) {
|
||||
oldThread->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -13,22 +13,28 @@
|
|||
#include "nsISupportsImpl.h"
|
||||
#include "nsThread.h"
|
||||
|
||||
class nsIRunnable;
|
||||
|
||||
namespace mozilla::gfx {
|
||||
|
||||
/**
|
||||
* This class represents the virtual thread for canvas rendering. Depending on
|
||||
* platform requirements and user configuration, canvas rendering may happen on
|
||||
* the Compositor thread, Render thread or the CanvasRender thread.
|
||||
*/
|
||||
class CanvasRenderThread final {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_MAIN_THREAD(
|
||||
CanvasRenderThread)
|
||||
|
||||
public:
|
||||
/// Can be called from any thread, may return nullptr late in shutdown.
|
||||
static CanvasRenderThread* Get();
|
||||
|
||||
/// Can only be called from the main thread, expected to be called at most
|
||||
/// once during a process' lifetime.
|
||||
/// once during a process' lifetime. Must be called after the Compositor and
|
||||
/// Render threads are initialized.
|
||||
static void Start();
|
||||
|
||||
/// Can only be called from the main thread.
|
||||
static void ShutDown();
|
||||
/// Can only be called from the main thread. Must be called before the
|
||||
/// Compositor and Render threads are shutdown.
|
||||
static void Shutdown();
|
||||
|
||||
/// Can be called from any thread.
|
||||
static bool IsInCanvasRenderThread();
|
||||
|
@ -37,12 +43,16 @@ class CanvasRenderThread final {
|
|||
static already_AddRefed<nsIThread> GetCanvasRenderThread();
|
||||
|
||||
private:
|
||||
explicit CanvasRenderThread(RefPtr<nsIThread> aThread);
|
||||
CanvasRenderThread(nsCOMPtr<nsIThread>&& aThread, bool aCreatedThread);
|
||||
~CanvasRenderThread();
|
||||
|
||||
void PostRunnable(already_AddRefed<nsIRunnable> aRunnable);
|
||||
|
||||
RefPtr<nsIThread> const mThread;
|
||||
nsCOMPtr<nsIThread> const mThread;
|
||||
|
||||
// True if mThread points to CanvasRender thread, false if mThread points to
|
||||
// Compositor/Render thread.
|
||||
bool mCreatedThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla::gfx
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "GPUProcessManager.h"
|
||||
#include "gfxGradientCache.h"
|
||||
#include "GfxInfoBase.h"
|
||||
#include "CanvasManagerParent.h"
|
||||
#include "VRGPUChild.h"
|
||||
#include "VRManager.h"
|
||||
#include "VRManagerParent.h"
|
||||
|
@ -378,10 +377,8 @@ mozilla::ipc::IPCResult GPUParent::RecvInit(
|
|||
#endif
|
||||
|
||||
// Make sure to do this *after* we update gfxVars above.
|
||||
if (gfxVars::UseCanvasRenderThread()) {
|
||||
gfx::CanvasRenderThread::Start();
|
||||
}
|
||||
wr::RenderThread::Start(aWrNamespace);
|
||||
gfx::CanvasRenderThread::Start();
|
||||
image::ImageMemoryReporter::InitForWebRender();
|
||||
|
||||
VRManager::ManagerInit();
|
||||
|
@ -700,9 +697,10 @@ void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|||
self->mVsyncBridge = nullptr;
|
||||
}
|
||||
VideoBridgeParent::Shutdown();
|
||||
// This could be running on either the Compositor or the Renderer
|
||||
// thread.
|
||||
CanvasManagerParent::Shutdown();
|
||||
// This could be running on either the Compositor thread, the Renderer
|
||||
// thread, or the dedicated CanvasRender thread, so we need to shutdown
|
||||
// before the former two.
|
||||
CanvasRenderThread::Shutdown();
|
||||
CompositorThreadHolder::Shutdown();
|
||||
RemoteTextureMap::Shutdown();
|
||||
// There is a case that RenderThread exists when gfxVars::UseWebRender()
|
||||
|
@ -711,9 +709,6 @@ void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|||
if (wr::RenderThread::Get()) {
|
||||
wr::RenderThread::ShutDown();
|
||||
}
|
||||
if (gfx::CanvasRenderThread::Get()) {
|
||||
gfx::CanvasRenderThread::ShutDown();
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
if (widget::WinCompositorWindowThread::Get()) {
|
||||
widget::WinCompositorWindowThread::ShutDown();
|
||||
|
|
|
@ -28,7 +28,7 @@ static Atomic<bool> sFinishedCompositorShutDown(false);
|
|||
static mozilla::BackgroundHangMonitor* sBackgroundHangMonitor;
|
||||
static ProfilerThreadId sProfilerThreadId;
|
||||
|
||||
nsISerialEventTarget* CompositorThread() {
|
||||
nsIThread* CompositorThread() {
|
||||
return sCompositorThreadHolder
|
||||
? sCompositorThreadHolder->GetCompositorThread()
|
||||
: nullptr;
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace mozilla::baseprofiler {
|
|||
class BaseProfilerThreadId;
|
||||
}
|
||||
using ProfilerThreadId = mozilla::baseprofiler::BaseProfilerThreadId;
|
||||
class nsISerialEventTarget;
|
||||
class nsIThread;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -26,9 +25,7 @@ class CompositorThreadHolder final {
|
|||
public:
|
||||
CompositorThreadHolder();
|
||||
|
||||
nsISerialEventTarget* GetCompositorThread() const {
|
||||
return mCompositorThread;
|
||||
}
|
||||
nsIThread* GetCompositorThread() const { return mCompositorThread; }
|
||||
|
||||
static CompositorThreadHolder* GetSingleton();
|
||||
|
||||
|
@ -61,7 +58,7 @@ class CompositorThreadHolder final {
|
|||
friend class CompositorBridgeParent;
|
||||
};
|
||||
|
||||
nsISerialEventTarget* CompositorThread();
|
||||
nsIThread* CompositorThread();
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "mozilla/gfx/GPUProcessManager.h"
|
||||
#include "mozilla/gfx/GraphicsMessages.h"
|
||||
#include "mozilla/gfx/CanvasManagerChild.h"
|
||||
#include "mozilla/gfx/CanvasManagerParent.h"
|
||||
#include "mozilla/gfx/CanvasRenderThread.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
@ -1309,14 +1308,15 @@ void gfxPlatform::InitLayersIPC() {
|
|||
#endif
|
||||
if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
|
||||
RemoteTextureMap::Init();
|
||||
if (gfxVars::UseCanvasRenderThread()) {
|
||||
gfx::CanvasRenderThread::Start();
|
||||
}
|
||||
wr::RenderThread::Start(GPUProcessManager::Get()->AllocateNamespace());
|
||||
image::ImageMemoryReporter::InitForWebRender();
|
||||
}
|
||||
|
||||
layers::CompositorThreadHolder::Start();
|
||||
|
||||
if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
|
||||
gfx::CanvasRenderThread::Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1343,8 +1343,10 @@ void gfxPlatform::ShutdownLayersIPC() {
|
|||
gfx::CanvasManagerChild::Shutdown();
|
||||
layers::CompositorManagerChild::Shutdown();
|
||||
layers::ImageBridgeChild::ShutDown();
|
||||
// This could be running on either the Compositor or the Renderer thread.
|
||||
gfx::CanvasManagerParent::Shutdown();
|
||||
// This could be running on either the Compositor thread, the Renderer
|
||||
// thread, or the dedicated CanvasRender thread, so we need to shutdown
|
||||
// before the former two.
|
||||
gfx::CanvasRenderThread::Shutdown();
|
||||
// This has to happen after shutting down the child protocols.
|
||||
layers::CompositorThreadHolder::Shutdown();
|
||||
RemoteTextureMap::Shutdown();
|
||||
|
@ -1363,9 +1365,6 @@ void gfxPlatform::ShutdownLayersIPC() {
|
|||
nsDependentCString(
|
||||
StaticPrefs::GetPrefName_gfx_webrender_blob_tile_size()));
|
||||
}
|
||||
if (gfx::CanvasRenderThread::Get()) {
|
||||
gfx::CanvasRenderThread::ShutDown();
|
||||
}
|
||||
#if defined(XP_WIN)
|
||||
widget::WinWindowOcclusionTracker::ShutDown();
|
||||
#endif
|
||||
|
@ -3851,12 +3850,10 @@ void gfxPlatform::DisableGPUProcess() {
|
|||
}
|
||||
|
||||
RemoteTextureMap::Init();
|
||||
if (gfxVars::UseCanvasRenderThread()) {
|
||||
gfx::CanvasRenderThread::Start();
|
||||
}
|
||||
// We need to initialize the parent process to prepare for WebRender if we
|
||||
// did not end up disabling it, despite losing the GPU process.
|
||||
wr::RenderThread::Start(GPUProcessManager::Get()->AllocateNamespace());
|
||||
gfx::CanvasRenderThread::Start();
|
||||
image::ImageMemoryReporter::InitForWebRender();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче