tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 3ef34f13f0ae4db66f96da5f2d24a4a36a8f66ef
parent 4d93b3cafc3ada6411954fdf218fffeb5ace9663
Author: Jamie Nicol <jnicol@mozilla.com>
Date:   Fri, 14 Nov 2025 10:47:37 +0000

Bug 1960922 - Obtain reference to CompositorSurfaceManager asynchronously. r=aosmond

GPUProcessHost must obtain a reference to the GPU process'
CompositorSurfaceManager, which requires a round-trip to the IPC
launcher thread in order to interact with GeckoProcessManager.
Currently this is achieved using a synchronous task, which has the
downside of blocking the main thread during startup.

This patch attempts to obtain the reference asynchronously, by
scheduling a task to run on the IPC launcher thread to obtain the
reference from GeckoSurfaceManager, then another back on the main
thread to initialize GPUProcessHost's member variable.

If GPUProcessHost::WaitForLaunch() is called prior to the async
initialization completing, we fall back to the synchronous task
approach.

Differential Revision: https://phabricator.services.mozilla.com/D272309

Diffstat:
Mgfx/ipc/GPUProcessHost.cpp | 68++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mipc/glue/GeckoChildProcessHost.cpp | 4++--
Mipc/glue/GeckoChildProcessHost.h | 2+-
3 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/gfx/ipc/GPUProcessHost.cpp b/gfx/ipc/GPUProcessHost.cpp @@ -79,6 +79,7 @@ bool GPUProcessHost::Launch(geckoargs::ChildProcessArgs aExtraOpts) { } bool GPUProcessHost::WaitForLaunch() { + MOZ_ASSERT(mLaunchPhase != LaunchPhase::Unlaunched); if (mLaunchPhase == LaunchPhase::Complete) { return !!mGPUChild; } @@ -140,30 +141,39 @@ void GPUProcessHost::InitAfterConnect(bool aSucceeded) { DebugOnly<bool> rv = TakeInitialEndpoint().Bind(mGPUChild.get()); MOZ_ASSERT(rv); - mGPUChild->Init()->Then( - GetCurrentSerialEventTarget(), __func__, - [this, liveToken = mLiveToken]( - const GPUChild::InitPromiseType::ResolveOrRejectValue&) { - if (*liveToken) { - this->OnAsyncInitComplete(); - } - }); + nsTArray<RefPtr<GPUChild::InitPromiseType>> initPromises; + initPromises.AppendElement(mGPUChild->Init()); #ifdef MOZ_WIDGET_ANDROID - nsCOMPtr<nsIEventTarget> launcherThread(GetIPCLauncher()); + nsCOMPtr<nsISerialEventTarget> launcherThread(GetIPCLauncher()); MOZ_ASSERT(launcherThread); - layers::SynchronousTask task( - "GeckoProcessManager::GetCompositorSurfaceManager"); - - launcherThread->Dispatch(NS_NewRunnableFunction( - "GeckoProcessManager::GetCompositorSurfaceManager", [&]() { - layers::AutoCompleteTask complete(&task); - mCompositorSurfaceManager = - java::GeckoProcessManager::GetCompositorSurfaceManager(); - })); - - task.Wait(); + RefPtr<GPUChild::InitPromiseType> csmPromise = + InvokeAsync( + launcherThread, __func__, + [] { + java::CompositorSurfaceManager::LocalRef csm = + java::GeckoProcessManager::GetCompositorSurfaceManager(); + return MozPromise<java::CompositorSurfaceManager::GlobalRef, Ok, + true>::CreateAndResolve(csm, __func__); + }) + ->Map(GetCurrentSerialEventTarget(), __func__, + [this, liveToken = mLiveToken]( + java::CompositorSurfaceManager::GlobalRef&& aCsm) { + if (*liveToken) { + mCompositorSurfaceManager = aCsm; + } + return Ok{}; + }); + initPromises.AppendElement(csmPromise); #endif + + GPUChild::InitPromiseType::All(GetCurrentSerialEventTarget(), initPromises) + ->Then(GetCurrentSerialEventTarget(), __func__, + [this, liveToken = mLiveToken]() { + if (*liveToken) { + this->OnAsyncInitComplete(); + } + }); } else { mLaunchPhase = LaunchPhase::Complete; if (mListener) { @@ -187,6 +197,24 @@ bool GPUProcessHost::CompleteInitSynchronously() { const bool result = mGPUChild->EnsureGPUReady(); +#ifdef MOZ_WIDGET_ANDROID + if (!mCompositorSurfaceManager) { + layers::SynchronousTask task( + "GeckoProcessManager::GetCompositorSurfaceManager"); + + nsCOMPtr<nsIEventTarget> launcherThread(GetIPCLauncher()); + MOZ_ASSERT(launcherThread); + launcherThread->Dispatch(NS_NewRunnableFunction( + "GeckoProcessManager::GetCompositorSurfaceManager", [&]() { + layers::AutoCompleteTask complete(&task); + mCompositorSurfaceManager = + java::GeckoProcessManager::GetCompositorSurfaceManager(); + })); + + task.Wait(); + } +#endif + mLaunchPhase = LaunchPhase::Complete; if (mListener) { mListener->OnProcessLaunchComplete(this); diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp @@ -994,7 +994,7 @@ IPCLaunchThreadObserver::Observe(nsISupports* aSubject, const char* aTopic, return rv; } -nsCOMPtr<nsIEventTarget> GetIPCLauncher() { +nsCOMPtr<nsISerialEventTarget> GetIPCLauncher() { StaticMutexAutoLock lock(gIPCLaunchThreadMutex); if (!gIPCLaunchThread) { nsCOMPtr<nsIThread> thread; @@ -1011,7 +1011,7 @@ nsCOMPtr<nsIEventTarget> GetIPCLauncher() { } } - nsCOMPtr<nsIEventTarget> thread = gIPCLaunchThread.get(); + nsCOMPtr<nsISerialEventTarget> thread = gIPCLaunchThread.get(); MOZ_DIAGNOSTIC_ASSERT(thread); return thread; } diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h @@ -315,7 +315,7 @@ class GeckoChildProcessHost : public SupportsWeakPtr, static StaticMutex sMutex; }; -nsCOMPtr<nsIEventTarget> GetIPCLauncher(); +nsCOMPtr<nsISerialEventTarget> GetIPCLauncher(); } /* namespace ipc */ } /* namespace mozilla */