Bug 1561179 - P1: Enable the creation of multiple VideoBridgeParent actors. r=mattwoodrow
authorDan Glastonbury <dan.glastonbury@gmail.com>
Mon, 04 Nov 2019 03:41:45 +0000
changeset 500312 9942990fbff5baf5c76aa811fa43896b5c678d39
parent 500311 3a6ca30f318eaa59284333b04c33244be2f750fe
child 500313 8b9accb338043f9e7cdeb90f77b76927cd19a143
push id36761
push userdvarga@mozilla.com
push dateMon, 04 Nov 2019 09:41:18 +0000
treeherdermozilla-central@5647ec4ba6f2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1561179
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1561179 - P1: Enable the creation of multiple VideoBridgeParent actors. r=mattwoodrow Differential Revision: https://phabricator.services.mozilla.com/D50398
dom/media/ipc/RDDProcessManager.cpp
dom/media/ipc/RemoteDecoderManagerChild.cpp
dom/media/ipc/RemoteDecoderManagerChild.h
gfx/ipc/GfxMessageUtils.h
gfx/layers/client/GPUVideoTextureClient.cpp
gfx/layers/client/TextureClient.cpp
gfx/layers/composite/GPUVideoTextureHost.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/VideoBridgeChild.cpp
gfx/layers/ipc/VideoBridgeChild.h
gfx/layers/ipc/VideoBridgeParent.cpp
gfx/layers/ipc/VideoBridgeParent.h
gfx/layers/ipc/VideoBridgeUtils.h
gfx/layers/moz.build
--- a/dom/media/ipc/RDDProcessManager.cpp
+++ b/dom/media/ipc/RDDProcessManager.cpp
@@ -175,17 +175,17 @@ void RDDProcessManager::OnProcessLaunchC
     DestroyProcess();
     return;
   }
 
   mRDDChild->SendCreateVideoBridgeToParentProcess(std::move(childPipe));
 
   CompositorThreadHolder::Loop()->PostTask(
       NewRunnableFunction("gfx::VideoBridgeParent::Open",
-                          &VideoBridgeParent::Open, std::move(parentPipe)));
+                          &VideoBridgeParent::Open, std::move(parentPipe), VideoBridgeSource::RddProcess));
 
   CrashReporter::AnnotateCrashReport(
       CrashReporter::Annotation::RDDProcessStatus,
       NS_LITERAL_CSTRING("Running"));
 }
 
 void RDDProcessManager::OnProcessUnexpectedShutdown(RDDProcessHost* aHost) {
   MOZ_ASSERT(mProcess && mProcess == aHost);
--- a/dom/media/ipc/RemoteDecoderManagerChild.cpp
+++ b/dom/media/ipc/RemoteDecoderManagerChild.cpp
@@ -150,46 +150,50 @@ PRemoteDecoderChild* RemoteDecoderManage
 
 bool RemoteDecoderManagerChild::DeallocPRemoteDecoderChild(
     PRemoteDecoderChild* actor) {
   RemoteDecoderChild* child = static_cast<RemoteDecoderChild*>(actor);
   child->IPDLActorDestroyed();
   return true;
 }
 
+RemoteDecoderManagerChild::RemoteDecoderManagerChild(
+    layers::VideoBridgeSource aSource)
+    : mSource(aSource) {}
+
 void RemoteDecoderManagerChild::OpenForRDDProcess(
     Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) {
   MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
   // Only create RemoteDecoderManagerChild, bind new endpoint and init
   // ipdl if:
   // 1) haven't init'd sRemoteDecoderManagerChild
   // or
   // 2) if ActorDestroy was called (mCanSend is false) meaning the other
   // end of the ipc channel was torn down
   if (sRemoteDecoderManagerChildForRDDProcess &&
       sRemoteDecoderManagerChildForRDDProcess->mCanSend) {
     return;
   }
   sRemoteDecoderManagerChildForRDDProcess = nullptr;
   if (aEndpoint.IsValid()) {
-    RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild();
+    RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild(VideoBridgeSource::RddProcess);
     if (aEndpoint.Bind(manager)) {
       sRemoteDecoderManagerChildForRDDProcess = manager;
       manager->InitIPDL();
     }
   }
 }
 
 void RemoteDecoderManagerChild::OpenForGPUProcess(
     Endpoint<PRemoteDecoderManagerChild>&& aEndpoint) {
   // Make sure we always dispatch everything in sRecreateTasks, even if we
   // fail since this is as close to being recreated as we will ever be.
   sRemoteDecoderManagerChildForGPUProcess = nullptr;
   if (aEndpoint.IsValid()) {
-    RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild();
+    RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild(VideoBridgeSource::GpuProcess);
     if (aEndpoint.Bind(manager)) {
       sRemoteDecoderManagerChildForGPUProcess = manager;
       manager->InitIPDL();
     }
   }
   for (Runnable* task : *sRecreateTasks) {
     task->Run();
   }
--- a/dom/media/ipc/RemoteDecoderManagerChild.h
+++ b/dom/media/ipc/RemoteDecoderManagerChild.h
@@ -1,16 +1,17 @@
 /* -*- 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/. */
 #ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h
 #define include_dom_media_ipc_RemoteDecoderManagerChild_h
 #include "mozilla/PRemoteDecoderManagerChild.h"
+#include "mozilla/layers/VideoBridgeUtils.h"
 
 namespace mozilla {
 
 class RemoteDecoderManagerChild final : public PRemoteDecoderManagerChild,
                                         public mozilla::ipc::IShmemAllocator {
   friend class PRemoteDecoderManagerChild;
 
  public:
@@ -56,16 +57,17 @@ class RemoteDecoderManagerChild final : 
 
   // Run aTask (on the manager thread) when we next attempt to create a new
   // manager (even if creation fails). Intended to be called from ActorDestroy
   // when we get notified that the old manager is being destroyed. Can only be
   // called from the manager thread.
   void RunWhenGPUProcessRecreated(already_AddRefed<Runnable> aTask);
 
   bool CanSend();
+  layers::VideoBridgeSource GetSource() const { return mSource; }
 
  protected:
   void InitIPDL();
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void ActorDealloc() override;
 
   void HandleFatalError(const char* aMsg) const override;
@@ -76,25 +78,28 @@ class RemoteDecoderManagerChild final : 
       const Maybe<layers::TextureFactoryIdentifier>& aIdentifier,
       bool* aSuccess, nsCString* aErrorDescription);
   bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor);
 
  private:
   // Main thread only
   static void InitializeThread();
 
-  RemoteDecoderManagerChild() = default;
+  explicit RemoteDecoderManagerChild(layers::VideoBridgeSource aSource);
   ~RemoteDecoderManagerChild() = default;
 
   static void OpenForRDDProcess(
       Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
   static void OpenForGPUProcess(
       Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
 
   RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
 
+  // The associated source of this decoder manager
+  layers::VideoBridgeSource mSource;
+
   // Should only ever be accessed on the manager thread.
   bool mCanSend = false;
 };
 
 }  // namespace mozilla
 
 #endif  // include_dom_media_ipc_RemoteDecoderManagerChild_h
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -20,16 +20,17 @@
 #include "gfxTelemetry.h"
 #include "gfxTypes.h"
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/gfx/CrossProcessPaint.h"
 #include "mozilla/gfx/Matrix.h"
 #include "nsRect.h"
 #include "nsRegion.h"
 #include "mozilla/Array.h"
+#include "mozilla/layers/VideoBridgeUtils.h"
 
 #include <stdint.h>
 
 #ifdef _MSC_VER
 #  pragma warning(disable : 4800)
 #endif
 
 namespace mozilla {
--- a/gfx/layers/client/GPUVideoTextureClient.cpp
+++ b/gfx/layers/client/GPUVideoTextureClient.cpp
@@ -11,19 +11,22 @@
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
 
 GPUVideoTextureData::GPUVideoTextureData(RemoteDecoderManagerChild* aManager,
                                          const SurfaceDescriptorGPUVideo& aSD,
                                          const gfx::IntSize& aSize)
-    : mManager(aManager), mSD(aSD), mSize(aSize) {}
+    : mManager(aManager),
+      mSD(aSD), mSize(aSize) {
+  mSD.source() = Some(mManager->GetSource());
+}
 
-GPUVideoTextureData::~GPUVideoTextureData() {}
+      GPUVideoTextureData::~GPUVideoTextureData() {}
 
 bool GPUVideoTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
   aOutDescriptor = mSD;
   return true;
 }
 
 void GPUVideoTextureData::FillInfo(TextureData::Info& aInfo) const {
   aInfo.size = mSize;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -1486,17 +1486,17 @@ void TextureClient::PrintInfo(std::strin
 
 void TextureClient::GPUVideoDesc(SurfaceDescriptorGPUVideo* const aOutDesc) {
   const auto handle = GetSerial();
 
   GPUVideoSubDescriptor subDesc = null_t();
   MOZ_RELEASE_ASSERT(mData);
   mData->GetSubDescriptor(&subDesc);
 
-  *aOutDesc = SurfaceDescriptorGPUVideo(handle, std::move(subDesc));
+  *aOutDesc = SurfaceDescriptorGPUVideo(handle, std::move(subDesc), Nothing());
 }
 
 class MemoryTextureReadLock : public NonBlockingTextureReadLock {
  public:
   MemoryTextureReadLock();
 
   virtual ~MemoryTextureReadLock();
 
--- a/gfx/layers/composite/GPUVideoTextureHost.cpp
+++ b/gfx/layers/composite/GPUVideoTextureHost.cpp
@@ -32,17 +32,17 @@ TextureHost* GPUVideoTextureHost::Ensure
     return mWrappedTextureHost;
   }
 
   // In the future when the RDD process has a PVideoBridge connection,
   // then there might be two VideoBridgeParents (one within the GPU process,
   // one from RDD). We'll need to flag which one to use to lookup our
   // descriptor, or just try both.
   mWrappedTextureHost =
-      VideoBridgeParent::GetSingleton()->LookupTexture(mDescriptor.handle());
+      VideoBridgeParent::GetSingleton(mDescriptor.source())->LookupTexture(mDescriptor.handle());
   return mWrappedTextureHost;
 }
 
 bool GPUVideoTextureHost::Lock() {
   if (!EnsureWrappedTextureHost()) {
     return false;
   }
   return EnsureWrappedTextureHost()->Lock();
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -11,16 +11,17 @@ using mozilla::WindowsHandle from "ipc/I
 using mozilla::gfx::YUVColorSpace from "mozilla/gfx/Types.h";
 using mozilla::gfx::ColorDepth from "mozilla/gfx/Types.h";
 using mozilla::gfx::ColorRange from "mozilla/gfx/Types.h";
 using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
 using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h";
 using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
 using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasic.h";
 using gfxImageFormat from "gfxTypes.h";
+using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUtils.h";
 
 namespace mozilla {
 namespace layers {
 
 struct SurfaceDescriptorFileMapping {
   WindowsHandle handle;
   SurfaceFormat format;
   IntSize size;
@@ -96,16 +97,17 @@ union GPUVideoSubDescriptor {
   SurfaceDescriptorD3D10;
   SurfaceDescriptorDXGIYCbCr;
   null_t;
 };
 
 struct SurfaceDescriptorGPUVideo {
   uint64_t handle;
   GPUVideoSubDescriptor subdesc;
+  MaybeVideoBridgeSource source;
 };
 
 struct RGBDescriptor {
   IntSize size;
   SurfaceFormat format;
   bool hasIntermediateBuffer;
 };
 
--- a/gfx/layers/ipc/VideoBridgeChild.cpp
+++ b/gfx/layers/ipc/VideoBridgeChild.cpp
@@ -20,19 +20,19 @@ void VideoBridgeChild::StartupForGPUProc
   ipc::Endpoint<PVideoBridgeChild> childPipe;
 
   PVideoBridge::CreateEndpoints(base::GetCurrentProcId(),
                                 base::GetCurrentProcId(), &parentPipe,
                                 &childPipe);
 
   VideoBridgeChild::OpenToGPUProcess(std::move(childPipe));
 
-  CompositorThreadHolder::Loop()->PostTask(
-      NewRunnableFunction("gfx::VideoBridgeParent::Open",
-                          &VideoBridgeParent::Open, std::move(parentPipe)));
+  CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
+      "gfx::VideoBridgeParent::Open", &VideoBridgeParent::Open,
+      std::move(parentPipe), VideoBridgeSource::GpuProcess));
 }
 
 void VideoBridgeChild::OpenToParentProcess(
     Endpoint<PVideoBridgeChild>&& aEndpoint) {
   sVideoBridgeToParentProcess = new VideoBridgeChild();
 
   if (!aEndpoint.Bind(sVideoBridgeToParentProcess)) {
     // We can't recover from this.
--- a/gfx/layers/ipc/VideoBridgeChild.h
+++ b/gfx/layers/ipc/VideoBridgeChild.h
@@ -3,16 +3,17 @@
 /* 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/. */
 
 #ifndef MOZILLA_GFX_VIDEOBRIDGECHILD_H
 #define MOZILLA_GFX_VIDEOBRIDGECHILD_H
 
 #include "mozilla/layers/PVideoBridgeChild.h"
+#include "mozilla/layers/VideoBridgeUtils.h"
 #include "ISurfaceAllocator.h"
 #include "TextureForwarder.h"
 
 namespace mozilla {
 namespace layers {
 
 class VideoBridgeChild final : public PVideoBridgeChild,
                                public TextureForwarder {
--- a/gfx/layers/ipc/VideoBridgeParent.cpp
+++ b/gfx/layers/ipc/VideoBridgeParent.cpp
@@ -2,44 +2,75 @@
 /* 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 "VideoBridgeParent.h"
 #include "CompositorThread.h"
 #include "mozilla/layers/TextureHost.h"
+#include "mozilla/layers/VideoBridgeUtils.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::ipc;
 using namespace mozilla::gfx;
 
-static VideoBridgeParent* sVideoBridgeSingleton;
+static VideoBridgeParent* sVideoBridgeFromRddProcess;
+static VideoBridgeParent* sVideoBridgeFromGpuProcess;
 
-VideoBridgeParent::VideoBridgeParent() : mClosed(false) {
+VideoBridgeParent::VideoBridgeParent(VideoBridgeSource aSource)
+    : mClosed(false) {
   mSelfRef = this;
-  sVideoBridgeSingleton = this;
+  switch (aSource) {
+    default:
+      MOZ_CRASH("Unhandled case");
+    case VideoBridgeSource::RddProcess:
+      sVideoBridgeFromRddProcess = this;
+      break;
+    case VideoBridgeSource::GpuProcess:
+      sVideoBridgeFromGpuProcess = this;
+      break;
+  }
   mCompositorThreadRef = CompositorThreadHolder::GetSingleton();
 }
 
-VideoBridgeParent::~VideoBridgeParent() { sVideoBridgeSingleton = nullptr; }
+VideoBridgeParent::~VideoBridgeParent() {
+  if (sVideoBridgeFromRddProcess == this) {
+    sVideoBridgeFromRddProcess = nullptr;
+  }
+  if (sVideoBridgeFromGpuProcess == this) {
+    sVideoBridgeFromGpuProcess = nullptr;
+  }
+}
 
-void VideoBridgeParent::Open(Endpoint<PVideoBridgeParent>&& aEndpoint) {
-  RefPtr<VideoBridgeParent> parent = new VideoBridgeParent();
+void VideoBridgeParent::Open(Endpoint<PVideoBridgeParent>&& aEndpoint,
+                             VideoBridgeSource aSource) {
+  RefPtr<VideoBridgeParent> parent = new VideoBridgeParent(aSource);
   if (!aEndpoint.Bind(parent)) {
     // We can't recover from this.
     MOZ_CRASH("Failed to bind RemoteDecoderManagerParent to endpoint");
   }
 }
 
 /* static */
-VideoBridgeParent* VideoBridgeParent::GetSingleton() {
-  return sVideoBridgeSingleton;
+VideoBridgeParent* VideoBridgeParent::GetSingleton(
+    Maybe<VideoBridgeSource>& aSource) {
+  MOZ_ASSERT(aSource.isSome());
+  switch (aSource.value()) {
+    default:
+      MOZ_CRASH("Unhandled case");
+    case VideoBridgeSource::RddProcess:
+      MOZ_ASSERT(sVideoBridgeFromRddProcess);
+      return sVideoBridgeFromRddProcess;
+    case VideoBridgeSource::GpuProcess:
+      MOZ_ASSERT(sVideoBridgeFromGpuProcess);
+      return sVideoBridgeFromGpuProcess;
+  }
 }
 
 TextureHost* VideoBridgeParent::LookupTexture(uint64_t aSerial) {
   return TextureHost::AsTextureHost(mTextureMap[aSerial]);
 }
 
 void VideoBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
   // Can't alloc/dealloc shmems from now on.
--- a/gfx/layers/ipc/VideoBridgeParent.h
+++ b/gfx/layers/ipc/VideoBridgeParent.h
@@ -8,25 +8,27 @@
 #define gfx_layers_ipc_VideoBridgeParent_h_
 
 #include "mozilla/layers/PVideoBridgeParent.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 
 namespace mozilla {
 namespace layers {
 
+enum class VideoBridgeSource : uint8_t;
 class CompositorThreadHolder;
 
 class VideoBridgeParent final : public PVideoBridgeParent,
                                 public HostIPCAllocator,
                                 public ShmemAllocator {
  public:
   ~VideoBridgeParent();
 
-  static VideoBridgeParent* GetSingleton();
+  static VideoBridgeParent* GetSingleton(Maybe<VideoBridgeSource>& aSource);
+
   TextureHost* LookupTexture(uint64_t aSerial);
 
   // PVideoBridgeParent
   void ActorDestroy(ActorDestroyReason aWhy) override;
   PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
                                       const ReadLockDescriptor& aReadLock,
                                       const LayersBackend& aLayersBackend,
                                       const TextureFlags& aFlags,
@@ -49,20 +51,21 @@ class VideoBridgeParent final : public P
   bool AllocShmem(size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
                   ipc::Shmem* aShmem) override;
 
   bool AllocUnsafeShmem(size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
                         ipc::Shmem* aShmem) override;
 
   void DeallocShmem(ipc::Shmem& aShmem) override;
 
-  static void Open(Endpoint<PVideoBridgeParent>&& aEndpoint);
+  static void Open(Endpoint<PVideoBridgeParent>&& aEndpoint,
+                   VideoBridgeSource aSource);
 
  private:
-  VideoBridgeParent();
+  explicit VideoBridgeParent(VideoBridgeSource aSource);
 
   void ActorDealloc() override;
 
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   RefPtr<VideoBridgeParent> mSelfRef;
   RefPtr<CompositorThreadHolder> mCompositorThreadRef;
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/VideoBridgeUtils.h
@@ -0,0 +1,37 @@
+/* -*- 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/. */
+
+#ifndef IPC_VideoBridgeUtils_h
+#define IPC_VideoBridgeUtils_h
+
+#include "ipc/IPCMessageUtils.h"
+
+namespace mozilla {
+namespace layers {
+
+enum class VideoBridgeSource : uint8_t {
+  RddProcess,
+  GpuProcess,
+  _Count,
+};
+
+typedef Maybe<VideoBridgeSource> MaybeVideoBridgeSource;
+
+}  // namespace layers
+}  // namespace mozilla
+
+namespace IPC {
+
+template <>
+struct ParamTraits<mozilla::layers::VideoBridgeSource>
+    : public ContiguousEnumSerializer<
+          mozilla::layers::VideoBridgeSource,
+          mozilla::layers::VideoBridgeSource::RddProcess,
+          mozilla::layers::VideoBridgeSource::_Count> {};
+
+}  // namespace IPC
+
+#endif  // IPC_VideoBridgeUtils_h
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -210,16 +210,17 @@ EXPORTS.mozilla.layers += [
     'ipc/SharedSurfacesParent.h',
     'ipc/SynchronousTask.h',
     'ipc/TextureForwarder.h',
     'ipc/UiCompositorControllerChild.h',
     'ipc/UiCompositorControllerMessageTypes.h',
     'ipc/UiCompositorControllerParent.h',
     'ipc/VideoBridgeChild.h',
     'ipc/VideoBridgeParent.h',
+    'ipc/VideoBridgeUtils.h',
     'LayerAttributes.h',
     'LayerMetricsWrapper.h',
     'LayersHelpers.h',
     'LayersTypes.h',
     'MemoryPressureObserver.h',
     'mlgpu/LayerManagerMLGPU.h',
     'mlgpu/LayerMLGPU.h',
     'mlgpu/MemoryReportingMLGPU.h',