summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/CompositorBridgeChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/layers/ipc/CompositorBridgeChild.cpp648
1 files changed, 648 insertions, 0 deletions
diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp
new file mode 100644
index 0000000000..72210607e2
--- /dev/null
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -0,0 +1,648 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/layers/CompositorBridgeChild.h"
+#include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/layers/CompositorThread.h"
+#include <stddef.h> // for size_t
+#include "base/task.h" // for NewRunnableMethod, etc
+#include "mozilla/StaticPrefs_layers.h"
+#include "mozilla/layers/CompositorManagerChild.h"
+#include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/APZChild.h"
+#include "mozilla/layers/IAPZCTreeManager.h"
+#include "mozilla/layers/APZCTreeManagerChild.h"
+#include "mozilla/layers/CanvasChild.h"
+#include "mozilla/layers/WebRenderLayerManager.h"
+#include "mozilla/layers/PTextureChild.h"
+#include "mozilla/layers/TextureClient.h" // for TextureClient
+#include "mozilla/layers/TextureClientPool.h" // for TextureClientPool
+#include "mozilla/layers/WebRenderBridgeChild.h"
+#include "mozilla/layers/SyncObject.h" // for SyncObjectClient
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/gfx/GPUProcessManager.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/ipc/Endpoint.h"
+#include "mozilla/mozalloc.h" // for operator new, etc
+#include "mozilla/Telemetry.h"
+#include "gfxConfig.h"
+#include "nsDebug.h" // for NS_WARNING
+#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
+#include "nsTArray.h" // for nsTArray, nsTArray_Impl
+#include "mozilla/dom/BrowserChild.h"
+#include "mozilla/dom/BrowserParent.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/Unused.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/SpinEventLoopUntil.h"
+#include "nsThreadUtils.h"
+#if defined(XP_WIN)
+# include "WinUtils.h"
+#endif
+#include "mozilla/widget/CompositorWidget.h"
+#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
+# include "mozilla/widget/CompositorWidgetChild.h"
+#endif
+#include "VsyncSource.h"
+
+using mozilla::Unused;
+using mozilla::gfx::GPUProcessManager;
+
+namespace mozilla {
+namespace layers {
+
+static int sShmemCreationCounter = 0;
+
+static void ResetShmemCounter() { sShmemCreationCounter = 0; }
+
+static void ShmemAllocated(CompositorBridgeChild* aProtocol) {
+ sShmemCreationCounter++;
+ if (sShmemCreationCounter > 256) {
+ aProtocol->SendSyncWithCompositor();
+ ResetShmemCounter();
+ MOZ_PERFORMANCE_WARNING(
+ "gfx", "The number of shmem allocations is too damn high!");
+ }
+}
+
+static StaticRefPtr<CompositorBridgeChild> sCompositorBridge;
+
+Atomic<int32_t> KnowsCompositor::sSerialCounter(0);
+
+CompositorBridgeChild::CompositorBridgeChild(CompositorManagerChild* aManager)
+ : mCompositorManager(aManager),
+ mIdNamespace(0),
+ mResourceId(0),
+ mCanSend(false),
+ mActorDestroyed(false),
+ mFwdTransactionId(0),
+ mThread(NS_GetCurrentThread()),
+ mProcessToken(0),
+ mSectionAllocator(nullptr) {
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+CompositorBridgeChild::~CompositorBridgeChild() {
+ if (mCanSend) {
+ gfxCriticalError() << "CompositorBridgeChild was not deinitialized";
+ }
+}
+
+bool CompositorBridgeChild::IsSameProcess() const {
+ return OtherPid() == base::GetCurrentProcId();
+}
+
+void CompositorBridgeChild::PrepareFinalDestroy() {
+ // Because of medium high priority DidComposite, we need to repost to
+ // medium high priority queue to ensure the actor is destroyed after possible
+ // pending DidComposite message.
+ nsCOMPtr<nsIRunnable> runnable =
+ NewRunnableMethod("CompositorBridgeChild::AfterDestroy", this,
+ &CompositorBridgeChild::AfterDestroy);
+ NS_DispatchToCurrentThreadQueue(runnable.forget(),
+ EventQueuePriority::MediumHigh);
+}
+
+void CompositorBridgeChild::AfterDestroy() {
+ // Note that we cannot rely upon mCanSend here because we already set that to
+ // false to prevent normal IPDL calls from being made after SendWillClose.
+ // The only time we should not issue Send__delete__ is if the actor is already
+ // destroyed, e.g. the compositor process crashed.
+ if (!mActorDestroyed) {
+ // We saw this send fail quite often with "Channel closing", probably a race
+ // with the other side closing or some event scheduling order.
+ if (GetIPCChannel()->CanSend()) {
+ Send__delete__(this);
+ }
+ mActorDestroyed = true;
+ }
+
+ if (mCanvasChild) {
+ mCanvasChild->Destroy();
+ }
+
+ if (sCompositorBridge == this) {
+ sCompositorBridge = nullptr;
+ }
+}
+
+void CompositorBridgeChild::Destroy() {
+ // This must not be called from the destructor!
+ mTexturesWaitingNotifyNotUsed.clear();
+
+ // Destroying the layer manager may cause all sorts of things to happen, so
+ // let's make sure there is still a reference to keep this alive whatever
+ // happens.
+ RefPtr<CompositorBridgeChild> selfRef = this;
+
+ for (size_t i = 0; i < mTexturePools.Length(); i++) {
+ mTexturePools[i]->Destroy();
+ }
+
+ if (mSectionAllocator) {
+ delete mSectionAllocator;
+ mSectionAllocator = nullptr;
+ }
+
+ if (mLayerManager) {
+ mLayerManager->Destroy();
+ mLayerManager = nullptr;
+ }
+
+ if (!mCanSend) {
+ // We may have already called destroy but still have lingering references
+ // or CompositorBridgeChild::ActorDestroy was called. Ensure that we do our
+ // post destroy clean up no matter what. It is safe to call multiple times.
+ NS_GetCurrentThread()->Dispatch(
+ NewRunnableMethod("CompositorBridgeChild::PrepareFinalDestroy", selfRef,
+ &CompositorBridgeChild::PrepareFinalDestroy));
+ return;
+ }
+
+ AutoTArray<PWebRenderBridgeChild*, 16> wrBridges;
+ ManagedPWebRenderBridgeChild(wrBridges);
+ for (int i = wrBridges.Length() - 1; i >= 0; --i) {
+ RefPtr<WebRenderBridgeChild> wrBridge =
+ static_cast<WebRenderBridgeChild*>(wrBridges[i]);
+ wrBridge->Destroy(/* aIsSync */ false);
+ }
+
+ AutoTArray<PAPZChild*, 16> apzChildren;
+ ManagedPAPZChild(apzChildren);
+ for (PAPZChild* child : apzChildren) {
+ Unused << child->SendDestroy();
+ }
+
+ const ManagedContainer<PTextureChild>& textures = ManagedPTextureChild();
+ for (const auto& key : textures) {
+ RefPtr<TextureClient> texture = TextureClient::AsTextureClient(key);
+
+ if (texture) {
+ texture->Destroy();
+ }
+ }
+
+ // The WillClose message is synchronous, so we know that after it returns
+ // any messages sent by the above code will have been processed on the
+ // other side.
+ SendWillClose();
+ mCanSend = false;
+
+ // We no longer care about unexpected shutdowns, in the remote process case.
+ mProcessToken = 0;
+
+ // The call just made to SendWillClose can result in IPC from the
+ // CompositorBridgeParent to the CompositorBridgeChild (e.g. caused by the
+ // destruction of shared memory). We need to ensure this gets processed by the
+ // CompositorBridgeChild before it gets destroyed. It suffices to ensure that
+ // events already in the thread get processed before the
+ // CompositorBridgeChild is destroyed, so we add a task to the thread to
+ // handle compositor destruction.
+
+ // From now on we can't send any message message.
+ NS_GetCurrentThread()->Dispatch(
+ NewRunnableMethod("CompositorBridgeChild::PrepareFinalDestroy", selfRef,
+ &CompositorBridgeChild::PrepareFinalDestroy));
+}
+
+// static
+void CompositorBridgeChild::ShutDown() {
+ if (sCompositorBridge) {
+ sCompositorBridge->Destroy();
+ SpinEventLoopUntil("CompositorBridgeChild::ShutDown"_ns,
+ [&]() { return !sCompositorBridge; });
+ }
+}
+
+void CompositorBridgeChild::InitForContent(uint32_t aNamespace) {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aNamespace);
+
+ if (RefPtr<CompositorBridgeChild> old = sCompositorBridge.forget()) {
+ // Note that at this point, ActorDestroy may not have been called yet,
+ // meaning mCanSend is still true. In this case we will try to send a
+ // synchronous WillClose message to the parent, and will certainly get
+ // a false result and a MsgDropped processing error. This is okay.
+ old->Destroy();
+ }
+
+ mCanSend = true;
+ mIdNamespace = aNamespace;
+
+ sCompositorBridge = this;
+}
+
+void CompositorBridgeChild::InitForWidget(uint64_t aProcessToken,
+ WebRenderLayerManager* aLayerManager,
+ uint32_t aNamespace) {
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(aProcessToken);
+ MOZ_ASSERT(aLayerManager);
+ MOZ_ASSERT(aNamespace);
+
+ mCanSend = true;
+ mProcessToken = aProcessToken;
+ mLayerManager = aLayerManager;
+ mIdNamespace = aNamespace;
+}
+
+/*static*/
+CompositorBridgeChild* CompositorBridgeChild::Get() {
+ // This is only expected to be used in child processes. While the parent
+ // process does have CompositorBridgeChild instances, it has _multiple_ (one
+ // per window), and therefore there is no global singleton available.
+ MOZ_ASSERT(!XRE_IsParentProcess());
+ return sCompositorBridge;
+}
+
+/* static */
+bool CompositorBridgeChild::CompositorIsInGPUProcess() {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ if (XRE_IsParentProcess()) {
+ return !!GPUProcessManager::Get()->GetGPUChild();
+ }
+
+ MOZ_ASSERT(XRE_IsContentProcess());
+ CompositorBridgeChild* bridge = CompositorBridgeChild::Get();
+ if (!bridge) {
+ return false;
+ }
+
+ return bridge->OtherPid() != dom::ContentChild::GetSingleton()->OtherPid();
+}
+
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvDidComposite(
+ const LayersId& aId, const nsTArray<TransactionId>& aTransactionIds,
+ const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd) {
+ // Hold a reference to keep texture pools alive. See bug 1387799
+ const auto texturePools = mTexturePools.Clone();
+
+ for (const auto& id : aTransactionIds) {
+ if (mLayerManager) {
+ MOZ_ASSERT(!aId.IsValid());
+ MOZ_ASSERT(mLayerManager->GetBackendType() == LayersBackend::LAYERS_WR);
+ // Hold a reference to keep LayerManager alive. See Bug 1242668.
+ RefPtr<WebRenderLayerManager> m = mLayerManager;
+ m->DidComposite(id, aCompositeStart, aCompositeEnd);
+ } else if (aId.IsValid()) {
+ RefPtr<dom::BrowserChild> child = dom::BrowserChild::GetFrom(aId);
+ if (child) {
+ child->DidComposite(id, aCompositeStart, aCompositeEnd);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < texturePools.Length(); i++) {
+ texturePools[i]->ReturnDeferredClients();
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvNotifyFrameStats(
+ nsTArray<FrameStats>&& aFrameStats) {
+ gfxPlatform::GetPlatform()->NotifyFrameStats(std::move(aFrameStats));
+ return IPC_OK();
+}
+
+void CompositorBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
+ if (aWhy == AbnormalShutdown) {
+ // If the parent side runs into a problem then the actor will be destroyed.
+ // There is nothing we can do in the child side, here sets mCanSend as
+ // false.
+ gfxCriticalNote << "CompositorBridgeChild receives IPC close with "
+ "reason=AbnormalShutdown";
+ }
+
+ mCanSend = false;
+ mActorDestroyed = true;
+
+ if (mProcessToken && XRE_IsParentProcess()) {
+ GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
+ }
+}
+
+bool CompositorBridgeChild::SendWillClose() {
+ MOZ_RELEASE_ASSERT(mCanSend);
+ return PCompositorBridgeChild::SendWillClose();
+}
+
+bool CompositorBridgeChild::SendPause() {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendPause();
+}
+
+bool CompositorBridgeChild::SendResume() {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendResume();
+}
+
+bool CompositorBridgeChild::SendResumeAsync() {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendResumeAsync();
+}
+
+bool CompositorBridgeChild::SendAdoptChild(const LayersId& id) {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendAdoptChild(id);
+}
+
+bool CompositorBridgeChild::SendFlushRendering(
+ const wr::RenderReasons& aReasons) {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendFlushRendering(aReasons);
+}
+
+bool CompositorBridgeChild::SendStartFrameTimeRecording(
+ const int32_t& bufferSize, uint32_t* startIndex) {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendStartFrameTimeRecording(bufferSize,
+ startIndex);
+}
+
+bool CompositorBridgeChild::SendStopFrameTimeRecording(
+ const uint32_t& startIndex, nsTArray<float>* intervals) {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::SendStopFrameTimeRecording(startIndex,
+ intervals);
+}
+
+PTextureChild* CompositorBridgeChild::AllocPTextureChild(
+ const SurfaceDescriptor&, ReadLockDescriptor&, const LayersBackend&,
+ const TextureFlags&, const LayersId&, const uint64_t& aSerial,
+ const wr::MaybeExternalImageId& aExternalImageId) {
+ return TextureClient::CreateIPDLActor();
+}
+
+bool CompositorBridgeChild::DeallocPTextureChild(PTextureChild* actor) {
+ return TextureClient::DestroyIPDLActor(actor);
+}
+
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvParentAsyncMessages(
+ nsTArray<AsyncParentMessageData>&& aMessages) {
+ for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
+ const AsyncParentMessageData& message = aMessages[i];
+
+ switch (message.type()) {
+ case AsyncParentMessageData::TOpNotifyNotUsed: {
+ const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
+ NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
+ break;
+ }
+ default:
+ NS_ERROR("unknown AsyncParentMessageData type");
+ return IPC_FAIL_NO_REASON(this);
+ }
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvObserveLayersUpdate(
+ const LayersId& aLayersId, const LayersObserverEpoch& aEpoch,
+ const bool& aActive) {
+ // This message is sent via the window compositor, not the tab compositor -
+ // however it still has a layers id.
+ MOZ_ASSERT(aLayersId.IsValid());
+ MOZ_ASSERT(XRE_IsParentProcess());
+
+ if (RefPtr<dom::BrowserParent> tab =
+ dom::BrowserParent::GetBrowserParentFromLayersId(aLayersId)) {
+ tab->LayerTreeUpdate(aEpoch, aActive);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvCompositorOptionsChanged(
+ const LayersId& aLayersId, const CompositorOptions& aNewOptions) {
+ MOZ_ASSERT(aLayersId.IsValid());
+ MOZ_ASSERT(XRE_IsParentProcess());
+
+ if (RefPtr<dom::BrowserParent> tab =
+ dom::BrowserParent::GetBrowserParentFromLayersId(aLayersId)) {
+ Unused << tab->SendCompositorOptionsChanged(aNewOptions);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult CompositorBridgeChild::RecvNotifyJankedAnimations(
+ const LayersId& aLayersId, nsTArray<uint64_t>&& aJankedAnimations) {
+ if (mLayerManager) {
+ MOZ_ASSERT(!aLayersId.IsValid());
+ mLayerManager->UpdatePartialPrerenderedAnimations(aJankedAnimations);
+ } else if (aLayersId.IsValid()) {
+ RefPtr<dom::BrowserChild> child = dom::BrowserChild::GetFrom(aLayersId);
+ if (child) {
+ child->NotifyJankedAnimations(aJankedAnimations);
+ }
+ }
+
+ return IPC_OK();
+}
+
+void CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(
+ TextureClient* aClient) {
+ if (!aClient) {
+ return;
+ }
+
+ bool waitNotifyNotUsed =
+ aClient->GetFlags() & TextureFlags::RECYCLE ||
+ aClient->GetFlags() & TextureFlags::WAIT_HOST_USAGE_END;
+ if (!waitNotifyNotUsed) {
+ return;
+ }
+
+ aClient->SetLastFwdTransactionId(GetFwdTransactionId());
+ mTexturesWaitingNotifyNotUsed.emplace(aClient->GetSerial(), aClient);
+}
+
+void CompositorBridgeChild::NotifyNotUsed(uint64_t aTextureId,
+ uint64_t aFwdTransactionId) {
+ auto it = mTexturesWaitingNotifyNotUsed.find(aTextureId);
+ if (it != mTexturesWaitingNotifyNotUsed.end()) {
+ if (aFwdTransactionId < it->second->GetLastFwdTransactionId()) {
+ // Released on host side, but client already requested newer use texture.
+ return;
+ }
+ mTexturesWaitingNotifyNotUsed.erase(it);
+ }
+}
+
+void CompositorBridgeChild::CancelWaitForNotifyNotUsed(uint64_t aTextureId) {
+ mTexturesWaitingNotifyNotUsed.erase(aTextureId);
+}
+
+FixedSizeSmallShmemSectionAllocator*
+CompositorBridgeChild::GetTileLockAllocator() {
+ if (!IPCOpen()) {
+ return nullptr;
+ }
+
+ if (!mSectionAllocator) {
+ mSectionAllocator = new FixedSizeSmallShmemSectionAllocator(this);
+ }
+ return mSectionAllocator;
+}
+
+PTextureChild* CompositorBridgeChild::CreateTexture(
+ const SurfaceDescriptor& aSharedData, ReadLockDescriptor&& aReadLock,
+ LayersBackend aLayersBackend, TextureFlags aFlags,
+ const dom::ContentParentId& aContentId, uint64_t aSerial,
+ wr::MaybeExternalImageId& aExternalImageId) {
+ PTextureChild* textureChild =
+ AllocPTextureChild(aSharedData, aReadLock, aLayersBackend, aFlags,
+ LayersId{0} /* FIXME */, aSerial, aExternalImageId);
+
+ return SendPTextureConstructor(
+ textureChild, aSharedData, std::move(aReadLock), aLayersBackend, aFlags,
+ LayersId{0} /* FIXME? */, aSerial, aExternalImageId);
+}
+
+already_AddRefed<CanvasChild> CompositorBridgeChild::GetCanvasChild() {
+ MOZ_ASSERT(gfx::gfxVars::RemoteCanvasEnabled());
+
+ if (CanvasChild::Deactivated()) {
+ return nullptr;
+ }
+
+ if (!mCanvasChild) {
+ ipc::Endpoint<PCanvasParent> parentEndpoint;
+ ipc::Endpoint<PCanvasChild> childEndpoint;
+ nsresult rv = PCanvas::CreateEndpoints(OtherPid(), base::GetCurrentProcId(),
+ &parentEndpoint, &childEndpoint);
+ if (NS_SUCCEEDED(rv)) {
+ Unused << SendInitPCanvasParent(std::move(parentEndpoint));
+ mCanvasChild = new CanvasChild(std::move(childEndpoint));
+ }
+ }
+
+ return do_AddRef(mCanvasChild);
+}
+
+void CompositorBridgeChild::EndCanvasTransaction() {
+ if (mCanvasChild) {
+ mCanvasChild->EndTransaction();
+ if (mCanvasChild->ShouldBeCleanedUp()) {
+ mCanvasChild->Destroy();
+ Unused << SendReleasePCanvasParent();
+ mCanvasChild = nullptr;
+ }
+ }
+}
+
+bool CompositorBridgeChild::AllocUnsafeShmem(size_t aSize, ipc::Shmem* aShmem) {
+ ShmemAllocated(this);
+ return PCompositorBridgeChild::AllocUnsafeShmem(aSize, aShmem);
+}
+
+bool CompositorBridgeChild::AllocShmem(size_t aSize, ipc::Shmem* aShmem) {
+ ShmemAllocated(this);
+ return PCompositorBridgeChild::AllocShmem(aSize, aShmem);
+}
+
+bool CompositorBridgeChild::DeallocShmem(ipc::Shmem& aShmem) {
+ if (!mCanSend) {
+ return false;
+ }
+ return PCompositorBridgeChild::DeallocShmem(aShmem);
+}
+
+widget::PCompositorWidgetChild*
+CompositorBridgeChild::AllocPCompositorWidgetChild(
+ const CompositorWidgetInitData& aInitData) {
+ // We send the constructor manually.
+ MOZ_CRASH("Should not be called");
+ return nullptr;
+}
+
+bool CompositorBridgeChild::DeallocPCompositorWidgetChild(
+ PCompositorWidgetChild* aActor) {
+#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
+ delete aActor;
+ return true;
+#else
+ return false;
+#endif
+}
+
+PAPZCTreeManagerChild* CompositorBridgeChild::AllocPAPZCTreeManagerChild(
+ const LayersId& aLayersId) {
+ APZCTreeManagerChild* child = new APZCTreeManagerChild();
+ child->AddIPDLReference();
+
+ return child;
+}
+
+PAPZChild* CompositorBridgeChild::AllocPAPZChild(const LayersId& aLayersId) {
+ // We send the constructor manually.
+ MOZ_CRASH("Should not be called");
+ return nullptr;
+}
+
+bool CompositorBridgeChild::DeallocPAPZChild(PAPZChild* aActor) {
+ delete aActor;
+ return true;
+}
+
+bool CompositorBridgeChild::DeallocPAPZCTreeManagerChild(
+ PAPZCTreeManagerChild* aActor) {
+ APZCTreeManagerChild* child = static_cast<APZCTreeManagerChild*>(aActor);
+ child->ReleaseIPDLReference();
+ return true;
+}
+
+// -
+
+PWebRenderBridgeChild* CompositorBridgeChild::AllocPWebRenderBridgeChild(
+ const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize&,
+ const WindowKind&) {
+ WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId);
+ child->AddIPDLReference();
+ return child;
+}
+
+bool CompositorBridgeChild::DeallocPWebRenderBridgeChild(
+ PWebRenderBridgeChild* aActor) {
+ WebRenderBridgeChild* child = static_cast<WebRenderBridgeChild*>(aActor);
+ child->ReleaseIPDLReference();
+ return true;
+}
+
+uint64_t CompositorBridgeChild::GetNextResourceId() {
+ ++mResourceId;
+ MOZ_RELEASE_ASSERT(mResourceId != UINT32_MAX);
+
+ uint64_t id = mIdNamespace;
+ id = (id << 32) | mResourceId;
+
+ return id;
+}
+
+wr::MaybeExternalImageId CompositorBridgeChild::GetNextExternalImageId() {
+ return Some(wr::ToExternalImageId(GetNextResourceId()));
+}
+
+wr::PipelineId CompositorBridgeChild::GetNextPipelineId() {
+ return wr::AsPipelineId(GetNextResourceId());
+}
+
+} // namespace layers
+} // namespace mozilla