When using the GPU process, combine layer ownership and window mapping into a single IPC message. (
bug 1350660 part 1, r=rhunt, r=billm)
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -864,16 +864,41 @@ GPUProcessManager::IsLayerTreeIdMapped(u
uint64_t
GPUProcessManager::AllocateLayerTreeId()
{
MOZ_ASSERT(NS_IsMainThread());
return ++mNextLayerTreeId;
}
+bool
+GPUProcessManager::AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge,
+ base::ProcessId aOtherPid,
+ uint64_t* aOutLayersId)
+{
+ uint64_t 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;
+ }
+ return aCompositorBridge->SendNotifyChildCreated(layersId);
+ }
+
+ // Use the combined message path.
+ LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
+ return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid);
+}
+
void
GPUProcessManager::EnsureVsyncIOThread()
{
if (mVsyncIOThread) {
return;
}
mVsyncIOThread = new VsyncIOThreadHolder();
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -111,19 +111,28 @@ public:
void UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId);
// Checks to see if aLayersId and aRequestingPID have been mapped by MapLayerTreeId
bool IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId);
// Allocate an ID that can be used to refer to a layer tree and
// associated resources that live only on the compositor thread.
//
- // Must run on the content main thread.
+ // Must run on the browser main thread.
uint64_t AllocateLayerTreeId();
+ // Allocate a layers ID and connect it to a compositor. If the compositor is null,
+ // the connect operation will not be performed, but an ID will still be allocated.
+ // This must be called from the browser main thread.
+ //
+ // Note that a layer tree id is always allocated, even if this returns false.
+ bool AllocateAndConnectLayerTreeId(
+ PCompositorBridgeChild* aCompositorBridge,
+ base::ProcessId aOtherPid,
+ uint64_t* aOutLayersId);
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
void OnProcessDeviceReset(GPUProcessHost* aHost) override;
// Notify the GPUProcessManager that a top-level PGPU protocol has been
// terminated. This may be called from any thread.
void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken);
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1550,16 +1550,30 @@ void
CompositorBridgeParent::NotifyChildCreated(uint64_t aChild)
{
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
sIndirectLayerTrees[aChild].mParent = this;
sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
}
mozilla::ipc::IPCResult
+CompositorBridgeParent::RecvMapAndNotifyChildCreated(const uint64_t& aChild, const base::ProcessId& aOwnerPid)
+{
+ // We only use this message when the remote compositor is in the GPU process.
+ // It is harmless to call it, though.
+ MOZ_ASSERT(XRE_IsGPUProcess());
+
+ LayerTreeOwnerTracker::Get()->Map(aChild, aOwnerPid);
+
+ MonitorAutoLock lock(*sIndirectLayerTreesLock);
+ NotifyChildCreated(aChild);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
{
APZCTreeManagerParent* parent;
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager);
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -184,16 +184,17 @@ public:
const uint64_t& aSeqNo,
bool* aResult,
TextureFactoryIdentifier* aOutIdentifier) override;
virtual mozilla::ipc::IPCResult RecvGetFrameUniformity(FrameUniformityData* aOutData) override;
virtual mozilla::ipc::IPCResult RecvWillClose() override;
virtual mozilla::ipc::IPCResult RecvPause() override;
virtual mozilla::ipc::IPCResult RecvResume() override;
virtual mozilla::ipc::IPCResult RecvNotifyChildCreated(const uint64_t& child) override;
+ virtual mozilla::ipc::IPCResult RecvMapAndNotifyChildCreated(const uint64_t& child, const base::ProcessId& pid) override;
virtual mozilla::ipc::IPCResult RecvNotifyChildRecreated(const uint64_t& child) override;
virtual mozilla::ipc::IPCResult RecvAdoptChild(const uint64_t& child) override;
virtual mozilla::ipc::IPCResult RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
const gfx::IntRect& aRect) override;
virtual mozilla::ipc::IPCResult RecvFlushRendering() override;
virtual mozilla::ipc::IPCResult RecvForcePresent() override;
virtual mozilla::ipc::IPCResult RecvAcknowledgeCompositorUpdate(const uint64_t&, const uint64_t&) override {
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -259,16 +259,24 @@ CrossProcessCompositorBridgeParent::Recv
if (lts->mParent && lts->mCrossProcessParent == this) {
lts->mParent->NotifyChildCreated(child);
return IPC_OK();
}
}
return IPC_FAIL_NO_REASON(this);
}
+mozilla::ipc::IPCResult
+CrossProcessCompositorBridgeParent::RecvMapAndNotifyChildCreated(const uint64_t& child, const base::ProcessId& pid)
+{
+ // This can only be called from the browser process, as the mapping
+ // ensures proper window ownership of layer trees.
+ return IPC_FAIL_NO_REASON(this);
+}
+
void
CrossProcessCompositorBridgeParent::ShadowLayersUpdated(
LayerTransactionParent* aLayerTree,
const TransactionInfo& aInfo,
bool aHitTestUpdate)
{
uint64_t id = aLayerTree->GetId();
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
@@ -51,16 +51,17 @@ public:
bool* aResult,
TextureFactoryIdentifier* aOutIdentifier) override
{ return IPC_FAIL_NO_REASON(this); }
virtual mozilla::ipc::IPCResult RecvWillClose() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvPause() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvResume() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvForceIsFirstPaint() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvNotifyChildCreated(const uint64_t& child) override;
+ virtual mozilla::ipc::IPCResult RecvMapAndNotifyChildCreated(const uint64_t& child, const base::ProcessId& pid) override;
virtual mozilla::ipc::IPCResult RecvNotifyChildRecreated(const uint64_t& child) override { return IPC_FAIL_NO_REASON(this); }
virtual mozilla::ipc::IPCResult RecvAdoptChild(const uint64_t& child) override { return IPC_FAIL_NO_REASON(this); }
virtual mozilla::ipc::IPCResult RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
const gfx::IntRect& aRect) override
{ return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvFlushRendering() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvForcePresent() override { return IPC_OK(); }
virtual mozilla::ipc::IPCResult RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return IPC_OK(); }
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -31,16 +31,17 @@ using mozilla::CSSIntRegion from "Units.
using mozilla::LayoutDeviceIntPoint from "Units.h";
using mozilla::LayoutDeviceIntRegion from "Units.h";
using mozilla::LayoutDeviceIntSize from "Units.h";
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
using class mozilla::layers::FrameUniformityData from "mozilla/layers/FrameUniformityData.h";
using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h";
using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
+using base::ProcessId from "base/process.h";
namespace mozilla {
namespace layers {
/**
* The PCompositorBridge protocol is a top-level protocol for the compositor.
* There is an instance of the protocol for each compositor, plus one for each
@@ -170,16 +171,22 @@ parent:
sync Pause();
sync Resume();
async ForceIsFirstPaint();
// See bug 1316632 comment #33 for why this has to be sync. Otherwise,
// there are ordering issues with SendPLayerTransactionConstructor.
sync NotifyChildCreated(uint64_t id);
+ // This version of NotifyChildCreated also performs a layer tree mapping.
+ //
+ // See bug 1316632 comment #33 for why this has to be sync. Otherwise,
+ // there are ordering issues with SendPLayerTransactionConstructor.
+ sync MapAndNotifyChildCreated(uint64_t id, ProcessId owner);
+
async AdoptChild(uint64_t id);
// Same as NotifyChildCreated, but used when child processes need to
// reassociate layers. This must be synchronous to ensure that the
// association happens before PLayerTransactions are sent over the
// cross-process bridge.
sync NotifyChildRecreated(uint64_t id);
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -987,16 +987,18 @@ description =
[PCompositorBridge::WillClose]
description =
[PCompositorBridge::Pause]
description =
[PCompositorBridge::Resume]
description =
[PCompositorBridge::NotifyChildCreated]
description =
+[PCompositorBridge::MapAndNotifyChildCreated]
+description = bug 1350660
[PCompositorBridge::NotifyChildRecreated]
description =
[PCompositorBridge::MakeSnapshot]
description =
[PCompositorBridge::FlushRendering]
description =
[PCompositorBridge::StartFrameTimeRecording]
description =
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -109,22 +109,28 @@ RenderFrameParent::Init(nsFrameLoader* a
mFrameLoader = aFrameLoader;
RefPtr<LayerManager> lm = GetFrom(mFrameLoader);
mAsyncPanZoomEnabled = lm && lm->AsyncPanZoomEnabled();
TabParent* browser = TabParent::GetFrom(mFrameLoader);
if (XRE_IsParentProcess()) {
+ PCompositorBridgeChild* compositor = nullptr;
+ if (lm) {
+ compositor = lm->GetCompositorBridgeChild();
+ }
+
// Our remote frame will push layers updates to the compositor,
// and we'll keep an indirect reference to that tree.
- browser->Manager()->AsContentParent()->AllocateLayerTreeId(browser, &mLayersId);
- if (lm && lm->GetCompositorBridgeChild()) {
- mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildCreated(mLayersId);
- }
+ GPUProcessManager* gpm = GPUProcessManager::Get();
+ mLayersConnected = gpm->AllocateAndConnectLayerTreeId(
+ compositor,
+ browser->Manager()->AsContentParent()->OtherPid(),
+ &mLayersId);
} else if (XRE_IsContentProcess()) {
ContentChild::GetSingleton()->SendAllocateLayerTreeId(browser->Manager()->ChildID(), browser->GetTabId(), &mLayersId);
mLayersConnected = CompositorBridgeChild::Get()->SendNotifyChildCreated(mLayersId);
}
mInitted = true;
return true;
}