tor-browser

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

commit 9cc6b78dc079e599d2f5f2ab9b4824045f4b3027
parent a9a9ba3d6c4ddbaf1fa8cf9cba76e683df975d31
Author: Andrew Osmond <aosmond@gmail.com>
Date:   Fri, 24 Oct 2025 19:34:29 +0000

Bug 1996352 - Refactor GPUProcessManager::AllocateAndConnectLayerTreeId to simplify/clarify. r=gfx-reviewers,bradwerth

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

Diffstat:
Mgfx/ipc/GPUProcessManager.cpp | 55++++++++++++++++++++++++++-----------------------------
Mgfx/ipc/GPUProcessManager.h | 7+++----
Mgfx/layers/ipc/LayerTreeOwnerTracker.cpp | 17++++++++++++++---
3 files changed, 43 insertions(+), 36 deletions(-)

diff --git a/gfx/ipc/GPUProcessManager.cpp b/gfx/ipc/GPUProcessManager.cpp @@ -1592,23 +1592,6 @@ nsresult GPUProcessManager::EnsureVideoBridge( return NS_OK; } -void GPUProcessManager::MapLayerTreeId(LayersId aLayersId, - base::ProcessId aOwningId) { - if (NS_WARN_IF(NS_FAILED(EnsureGPUReady()))) { - return; - } - - if (mGPUChild) { - mGPUChild->SendAddLayerTreeIdMapping( - LayerTreeIdMapping(aLayersId, aOwningId)); - } - - // Must do this *after* the call to EnsureGPUReady, so that if the - // process is launched as a result then it is initialized without this - // LayersId, meaning it can be successfully mapped. - LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId); -} - void GPUProcessManager::UnmapLayerTreeId(LayersId aLayersId, base::ProcessId aOwningId) { // If the GPU process is down, but not disabled, there is no need to relaunch @@ -1673,26 +1656,40 @@ uint32_t GPUProcessManager::AllocateNamespace() { bool GPUProcessManager::AllocateAndConnectLayerTreeId( PCompositorBridgeChild* aCompositorBridge, base::ProcessId aOtherPid, LayersId* aOutLayersId, CompositorOptions* aOutCompositorOptions) { + MOZ_ASSERT(aOutLayersId); + LayersId layersId = AllocateLayerTreeId(); *aOutLayersId = layersId; - if (!mGPUChild || !aCompositorBridge) { - // If we're not remoting to another process, or there is no compositor, - // then we'll send at most one message. In this case we can just keep - // the old behavior of making sure the mapping occurs, and maybe sending - // a creation notification. - MapLayerTreeId(layersId, aOtherPid); - if (!aCompositorBridge) { - return false; + // We always map the layer ID in the parent process so that we can recover + // from GPU process crashes. In that case, the tree will be shared with the + // new GPU process at initialization. + LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid); + + if (NS_WARN_IF(NS_FAILED(EnsureGPUReady()))) { + return false; + } + + // If we have a CompositorBridgeChild, then we need to call + // CompositorBridgeParent::NotifyChildCreated. If this is in the GPU process, + // we can combine it with LayerTreeOwnerTracker::Map to minimize IPC. + // messages. + if (aCompositorBridge) { + if (mGPUChild) { + return aCompositorBridge->SendMapAndNotifyChildCreated( + layersId, aOtherPid, aOutCompositorOptions); } return aCompositorBridge->SendNotifyChildCreated(layersId, aOutCompositorOptions); } - // Use the combined message path. - LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid); - return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid, - aOutCompositorOptions); + // If we don't have a CompositorBridgeChild, we just need to call + // LayerTreeOwnerTracker::Map in the compositing process. + if (mGPUChild) { + mGPUChild->SendAddLayerTreeIdMapping( + LayerTreeIdMapping(layersId, aOtherPid)); + } + return false; } void GPUProcessManager::EnsureVsyncIOThread() { diff --git a/gfx/ipc/GPUProcessManager.h b/gfx/ipc/GPUProcessManager.h @@ -132,10 +132,6 @@ class GPUProcessManager final : public GPUProcessHost::Listener { mozilla::ipc::EndpointProcInfo aOtherProcess); #endif - // Maps the layer tree and process together so that aOwningPID is allowed - // to access aLayersId across process. - void MapLayerTreeId(LayersId aLayersId, base::ProcessId aOwningId); - // Release compositor-thread resources referred to by |aID|. // // Must run on the content main thread. @@ -159,6 +155,9 @@ class GPUProcessManager final : public GPUProcessHost::Listener { // null, the connect operation will not be performed, but an ID will still be // allocated. This must be called from the browser main thread. // + // It also maps the layer tree and process together so that aOwningPID is + // allowed to access aLayersId across process. + // // Note that a layer tree id is always allocated, even if this returns false. bool AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge, base::ProcessId aOtherPid, diff --git a/gfx/layers/ipc/LayerTreeOwnerTracker.cpp b/gfx/layers/ipc/LayerTreeOwnerTracker.cpp @@ -35,15 +35,26 @@ void LayerTreeOwnerTracker::Map(LayersId aLayersId, MutexAutoLock lock(mLayerIdsLock); // Add the mapping to the list - mLayerIds[aLayersId] = aProcessId; + const auto i = mLayerIds.insert({aLayersId, aProcessId}); + MOZ_ASSERT(i.second, "Mapping already used layers ID!"); + (void)i; } void LayerTreeOwnerTracker::Unmap(LayersId aLayersId, base::ProcessId aProcessId) { MutexAutoLock lock(mLayerIdsLock); - MOZ_ASSERT(mLayerIds[aLayersId] == aProcessId); - mLayerIds.erase(aLayersId); + auto i = mLayerIds.find(aLayersId); + if (i == mLayerIds.end()) { + return; + } + + if (NS_WARN_IF(i->second != aProcessId)) { + MOZ_ASSERT_UNREACHABLE("Unmapping layers ID for another process!"); + return; + } + + mLayerIds.erase(i); } bool LayerTreeOwnerTracker::IsMapped(LayersId aLayersId,