Bug 1393392 P8 - report telemetry while a decoder being normally closed; draft
authorKaku Kuo <kaku@mozilla.com>
Thu, 24 Aug 2017 10:44:13 +0800
changeset 652826 237b778ff2be0861528aeeea6b9c0c6e62725e35
parent 652825 708b0ee70a73e6df5ac3929b3467a375fc6ef2b7
child 728188 329b22182fbb8a6c6722c578471c4819a385d965
push id76161
push userbmo:kaku@mozilla.com
push dateFri, 25 Aug 2017 08:18:23 +0000
bugs1393392
milestone57.0a1
Bug 1393392 P8 - report telemetry while a decoder being normally closed; Add a ReportTelemetry() method to MediaDataDecoder. While we're shutting down a decoder in MFR, we call this method to report telemetry. We also override this method at RemoteVideoDecoder as we need to distinguish a remote decoder is closed normally or due to GPU process crashing. MozReview-Commit-ID: IFzKTC5gglm
dom/media/MediaFormatReader.cpp
dom/media/ipc/RemoteVideoDecoder.cpp
dom/media/ipc/RemoteVideoDecoder.h
dom/media/platforms/PlatformDecoderModule.cpp
dom/media/platforms/PlatformDecoderModule.h
dom/media/platforms/moz.build
dom/media/platforms/wrappers/H264Converter.h
dom/media/platforms/wrappers/MediaDataDecoderProxy.cpp
dom/media/platforms/wrappers/MediaDataDecoderProxy.h
gfx/ipc/GPUProcessManager.cpp
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -566,16 +566,20 @@ public:
     RefPtr<MediaDataDecoder> decoder = mDecoder.forget();
     RefPtr<Token> token = mToken.forget();
     return decoder->Shutdown()->Then(
       AbstractThread::GetCurrent(), __func__,
       [token]() {
         return ShutdownPromise::CreateAndResolve(true, __func__);
       });
   }
+  void ReportTelemetry() const override
+  {
+    mDecoder->ReportTelemetry();
+  }
 
 private:
   RefPtr<MediaDataDecoder> mDecoder;
   RefPtr<Token> mToken;
 };
 
 void
 MediaFormatReader::DecoderFactory::RunStage(Data& aData)
@@ -1179,16 +1183,21 @@ void
 MediaFormatReader::ShutdownDecoder(TrackType aTrack)
 {
   LOGV("%s", TrackTypeToStr(aTrack));
 
   // Shut down the pending decoder if any.
   mDecoderFactory->ShutdownDecoder(aTrack);
 
   auto& decoder = GetDecoderData(aTrack);
+
+  if (aTrack == TrackType::kVideoTrack && decoder.mDecoder) {
+    decoder.mDecoder->ReportTelemetry();
+  }
+
   // Flush the decoder if necessary.
   decoder.Flush();
   // Shut down the decoder if any.
   decoder.ShutdownDecoder();
 }
 
 RefPtr<ShutdownPromise>
 MediaFormatReader::TearDownDecoders()
--- a/dom/media/ipc/RemoteVideoDecoder.cpp
+++ b/dom/media/ipc/RemoteVideoDecoder.cpp
@@ -1,24 +1,32 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* 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 "RemoteVideoDecoder.h"
 #include "VideoDecoderChild.h"
 #include "VideoDecoderManagerChild.h"
+#include "mozilla/dom/VideoDecoderManagerChild.h"
 #include "mozilla/layers/TextureClient.h"
 #include "base/thread.h"
 #include "MediaInfo.h"
 #include "MediaPrefs.h"
 #include "ImageContainer.h"
 #include "mozilla/layers/SynchronousTask.h"
 
 namespace mozilla {
+
+extern void
+ReportUnblacklistingTelemetry(bool isGPUProcessCrashed,
+                              bool isHWDecodingOnGPUProcess,
+                              const nsCString& aD3D11BlacklistedDriver,
+                              const nsCString& aD3D9BlacklistedDriver);
+
 namespace dom {
 
 using base::Thread;
 using namespace ipc;
 using namespace layers;
 using namespace gfx;
 
 RemoteVideoDecoder::RemoteVideoDecoder()
@@ -114,16 +122,34 @@ RemoteVideoDecoder::SetSeekThreshold(con
 }
 
 MediaDataDecoder::ConversionRequired
 RemoteVideoDecoder::NeedsConversion() const
 {
   return mActor->NeedsConversion();
 }
 
+void
+RemoteVideoDecoder::ReportTelemetry() const
+{
+  // CanSend() returning true means the VideoDecoderChild::ActorDestory() has
+  // not been called yet and we are in the normal procedure of deleting a
+  // MediaDataDecoder.
+  // On the other hand, if GPU process crashed, VideoDecoderChild::ActorDestory()
+  // has been called before we get here and CanSend() returns false in this case.
+  // Please be noted that reporting Telemetry about GPU crashing case is done in
+  // GPUProcessManager::OnProcessUnexpectedShutdown().
+  if (mActor->CanSend()) {
+    ReportUnblacklistingTelemetry(false,
+                                  true,
+                                  dom::VideoDecoderManagerChild::D3D11BlacklistedDriver(),
+                                  dom::VideoDecoderManagerChild::D3D9BlacklistedDriver());
+  }
+}
+
 nsresult
 RemoteDecoderModule::Startup()
 {
   if (!VideoDecoderManagerChild::GetManagerThread()) {
     return NS_ERROR_FAILURE;
   }
   return mWrapped->Startup();
 }
--- a/dom/media/ipc/RemoteVideoDecoder.h
+++ b/dom/media/ipc/RemoteVideoDecoder.h
@@ -32,16 +32,17 @@ public:
   RefPtr<DecodePromise> Drain() override;
   RefPtr<FlushPromise> Flush() override;
   RefPtr<ShutdownPromise> Shutdown() override;
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
   void SetSeekThreshold(const media::TimeUnit& aTime) override;
 
   const char* GetDescriptionName() const override { return "RemoteVideoDecoder"; }
   ConversionRequired NeedsConversion() const override;
+  void ReportTelemetry() const override;
 
 private:
   RemoteVideoDecoder();
   ~RemoteVideoDecoder();
 
   // Only ever written to from the reader task queue (during the constructor and
   // destructor when we can guarantee no other threads are accessing it). Only
   // read from the manager thread.
new file mode 100644
--- /dev/null
+++ b/dom/media/platforms/PlatformDecoderModule.cpp
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=99: */
+/* 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 "PlatformDecoderModule.h"
+#include "mozilla/dom/VideoDecoderManagerChild.h"
+#include "mozilla/Telemetry.h"
+
+namespace mozilla {
+
+extern void
+ReportUnblacklistingTelemetry(bool isGPUProcessCrashed,
+                              bool isHWDecodingOnGPUProcess,
+                              const nsCString& aD3D11BlacklistedDriver,
+                              const nsCString& aD3D9BlacklistedDriver);
+
+void
+MediaDataDecoder::ReportTelemetry() const
+{
+  ReportUnblacklistingTelemetry(false,
+                                false,
+                                dom::VideoDecoderManagerChild::D3D11BlacklistedDriver(),
+                                dom::VideoDecoderManagerChild::D3D9BlacklistedDriver());
+}
+
+} // namespace mozilla
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -307,13 +307,15 @@ public:
 
   // Indicates that the decoder requires a specific format.
   // The demuxed data will be converted accordingly before feeding it to
   // Decode().
   virtual ConversionRequired NeedsConversion() const
   {
     return ConversionRequired::kNeedNone;
   }
+
+  virtual void ReportTelemetry() const;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -27,16 +27,17 @@ UNIFIED_SOURCES += [
     'agnostic/DummyMediaDataDecoder.cpp',
     'agnostic/NullDecoderModule.cpp',
     'agnostic/OpusDecoder.cpp',
     'agnostic/TheoraDecoder.cpp',
     'agnostic/VorbisDecoder.cpp',
     'agnostic/VPXDecoder.cpp',
     'agnostic/WAVDecoder.cpp',
     'PDMFactory.cpp',
+    'PlatformDecoderModule.cpp',
     'wrappers/H264Converter.cpp',
     'wrappers/MediaDataDecoderProxy.cpp'
 ]
 
 DIRS += [
     'agnostic/eme',
     'agnostic/gmp',
     'omx'
--- a/dom/media/platforms/wrappers/H264Converter.h
+++ b/dom/media/platforms/wrappers/H264Converter.h
@@ -56,16 +56,23 @@ public:
     if (mDecoder) {
       return mDecoder->NeedsConversion();
     }
     // Default so no conversion is performed.
     return ConversionRequired::kNeedAVCC;
   }
   nsresult GetLastError() const { return mLastError; }
 
+  void ReportTelemetry() const override
+  {
+    if (mDecoder) {
+      mDecoder->ReportTelemetry();
+    }
+  }
+
 private:
   // Will create the required MediaDataDecoder if need AVCC and we have a SPS NAL.
   // Returns NS_ERROR_FAILURE if error is permanent and can't be recovered and
   // will set mError accordingly.
   nsresult CreateDecoder(const VideoInfo& aConfig,
                          DecoderDoctorDiagnostics* aDiagnostics);
   nsresult CreateDecoderAndInit(MediaRawData* aSample);
   nsresult CheckForSPSChange(MediaRawData* aSample);
--- a/dom/media/platforms/wrappers/MediaDataDecoderProxy.cpp
+++ b/dom/media/platforms/wrappers/MediaDataDecoderProxy.cpp
@@ -122,9 +122,16 @@ MediaDataDecoderProxy::SupportDecoderRec
 MediaDataDecoder::ConversionRequired
 MediaDataDecoderProxy::NeedsConversion() const
 {
   MOZ_ASSERT(!mIsShutdown);
 
   return mProxyDecoder->NeedsConversion();
 }
 
+void
+MediaDataDecoderProxy::ReportTelemetry() const
+{
+  MOZ_ASSERT(!mIsShutdown);
+  mProxyDecoder->ReportTelemetry();
+}
+
 } // namespace mozilla
--- a/dom/media/platforms/wrappers/MediaDataDecoderProxy.h
+++ b/dom/media/platforms/wrappers/MediaDataDecoderProxy.h
@@ -46,16 +46,17 @@ public:
   RefPtr<DecodePromise> Drain() override;
   RefPtr<FlushPromise> Flush() override;
   RefPtr<ShutdownPromise> Shutdown() override;
   const char* GetDescriptionName() const override;
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
   void SetSeekThreshold(const media::TimeUnit& aTime) override;
   bool SupportDecoderRecycling() const override;
   ConversionRequired NeedsConversion() const override;
+  void ReportTelemetry() const override;
 
 private:
   RefPtr<MediaDataDecoder> mProxyDecoder;
   RefPtr<AbstractThread> mProxyThread;
 
 #if defined(DEBUG)
   Atomic<bool> mIsShutdown;
 #endif
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -1,1237 +1,1237 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=99: */
-/* 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 "GPUProcessManager.h"
-
-#include "gfxPrefs.h"
-#include "GPUProcessHost.h"
-#include "GPUProcessListener.h"
-#include "mozilla/MemoryReportingProcess.h"
-#include "mozilla/Sprintf.h"
-#include "mozilla/StaticPtr.h"
-#include "mozilla/dom/ContentParent.h"
-#include "mozilla/gfx/gfxVars.h"
-#include "mozilla/layers/APZCTreeManager.h"
-#include "mozilla/layers/APZCTreeManagerChild.h"
-#include "mozilla/layers/CompositorBridgeParent.h"
-#include "mozilla/layers/CompositorManagerChild.h"
-#include "mozilla/layers/CompositorManagerParent.h"
-#include "mozilla/layers/CompositorOptions.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/ImageBridgeParent.h"
-#include "mozilla/layers/InProcessCompositorSession.h"
-#include "mozilla/layers/LayerTreeOwnerTracker.h"
-#include "mozilla/layers/RemoteCompositorSession.h"
-#include "mozilla/widget/PlatformWidgetTypes.h"
-#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
-# include "mozilla/widget/CompositorWidgetChild.h"
-#endif
-#include "nsBaseWidget.h"
-#include "nsContentUtils.h"
-#include "VRManagerChild.h"
-#include "VRManagerParent.h"
-#include "VsyncBridgeChild.h"
-#include "VsyncIOThreadHolder.h"
-#include "VsyncSource.h"
-#include "mozilla/dom/VideoDecoderManagerChild.h"
-#include "mozilla/dom/VideoDecoderManagerParent.h"
-#include "MediaPrefs.h"
-#include "nsPrintfCString.h"
-
-#ifdef MOZ_CRASHREPORTER
-# include "nsExceptionHandler.h"
-#endif
-
-#if defined(MOZ_WIDGET_ANDROID)
-#include "mozilla/widget/AndroidUiThread.h"
-#include "mozilla/layers/UiCompositorControllerChild.h"
-#endif // defined(MOZ_WIDGET_ANDROID)
-
-namespace mozilla {
-
-static void
-ReportUnblacklistingTelemetry(bool isGPUProcessCrashed,
-                              bool isHWDecodingOnGPUProcess,
-                              const nsCString& aD3D11BlacklistedDriver,
-                              const nsCString& aD3D9BlacklistedDriver)
-{
-#ifdef XP_WIN
-  const nsCString& blacklistedDLL = !aD3D11BlacklistedDriver.IsEmpty()
-                                    ? aD3D11BlacklistedDriver
-                                    : aD3D9BlacklistedDriver;
-
-  if (!blacklistedDLL.IsEmpty()) {
-    const uint32_t type = [isHWDecodingOnGPUProcess, isGPUProcessCrashed]() {
-      if (isHWDecodingOnGPUProcess) {
-        if (!isGPUProcessCrashed) {
-          return 0;
-        }
-        else {
-          return 1;
-        }
-      }
-      else {
-        if (!isGPUProcessCrashed) {
-          return 2;
-        }
-        else {
-          return 3;
-        }
-      }
-    }();
-
-    Telemetry::Accumulate(Telemetry::VIDEO_UNBLACKINGLISTING_DXVA_DRIVER_RUNTIME_STATUS,
-                          blacklistedDLL,
-                          type);
-  }
-#endif // XP_WIN
-}
-
-namespace gfx {
-
-using namespace mozilla::layers;
-
-enum class FallbackType : uint32_t
-{
-  NONE = 0,
-  DECODINGDISABLED,
-  DISABLED,
-};
-
-static StaticAutoPtr<GPUProcessManager> sSingleton;
-
-GPUProcessManager*
-GPUProcessManager::Get()
-{
-  return sSingleton;
-}
-
-void
-GPUProcessManager::Initialize()
-{
-  MOZ_ASSERT(XRE_IsParentProcess());
-  sSingleton = new GPUProcessManager();
-}
-
-void
-GPUProcessManager::Shutdown()
-{
-  sSingleton = nullptr;
-}
-
-GPUProcessManager::GPUProcessManager()
- : mTaskFactory(this),
-   mNextNamespace(0),
-   mIdNamespace(0),
-   mResourceId(0),
-   mNumProcessAttempts(0),
-   mDeviceResetCount(0),
-   mProcess(nullptr),
-   mGPUChild(nullptr)
-{
-  MOZ_COUNT_CTOR(GPUProcessManager);
-
-  mIdNamespace = AllocateNamespace();
-  mObserver = new Observer(this);
-  nsContentUtils::RegisterShutdownObserver(mObserver);
-
-  mDeviceResetLastTime = TimeStamp::Now();
-
-  LayerTreeOwnerTracker::Initialize();
-}
-
-GPUProcessManager::~GPUProcessManager()
-{
-  MOZ_COUNT_DTOR(GPUProcessManager);
-
-  LayerTreeOwnerTracker::Shutdown();
-
-  // The GPU process should have already been shut down.
-  MOZ_ASSERT(!mProcess && !mGPUChild);
-
-  // We should have already removed observers.
-  MOZ_ASSERT(!mObserver);
-}
-
-NS_IMPL_ISUPPORTS(GPUProcessManager::Observer, nsIObserver);
-
-GPUProcessManager::Observer::Observer(GPUProcessManager* aManager)
- : mManager(aManager)
-{
-}
-
-NS_IMETHODIMP
-GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
-{
-  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
-    mManager->OnXPCOMShutdown();
-  }
-  return NS_OK;
-}
-
-void
-GPUProcessManager::OnXPCOMShutdown()
-{
-  if (mObserver) {
-    nsContentUtils::UnregisterShutdownObserver(mObserver);
-    mObserver = nullptr;
-  }
-
-  CleanShutdown();
-}
-
-void
-GPUProcessManager::LaunchGPUProcess()
-{
-  if (mProcess) {
-    return;
-  }
-
-  // Start the Vsync I/O thread so can use it as soon as the process launches.
-  EnsureVsyncIOThread();
-
-  mNumProcessAttempts++;
-
-  // The subprocess is launched asynchronously, so we wait for a callback to
-  // acquire the IPDL actor.
-  mProcess = new GPUProcessHost(this);
-  if (!mProcess->Launch()) {
-    DisableGPUProcess("Failed to launch GPU process");
-  }
-}
-
-void
-GPUProcessManager::DisableGPUProcess(const char* aMessage)
-{
-  if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
-    return;
-  }
-
-  gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
-  gfxCriticalNote << aMessage;
-
-  gfxPlatform::NotifyGPUProcessDisabled();
-
-  Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
-                        uint32_t(FallbackType::DISABLED));
-
-  DestroyProcess();
-  ShutdownVsyncIOThread();
-
-  // We may have been in the middle of guaranteeing our various services are
-  // available when one failed. Some callers may fallback to using the same
-  // process equivalent, and we need to make sure those services are setup
-  // correctly. We cannot re-enter DisableGPUProcess from this call because we
-  // know that it is disabled in the config above.
-  EnsureProtocolsReady();
-
-  // If we disable the GPU process during reinitialization after a previous
-  // crash, then we need to tell the content processes again, because they
-  // need to rebind to the UI process.
-  HandleProcessLost();
-}
-
-bool
-GPUProcessManager::EnsureGPUReady()
-{
-  if (mProcess && !mProcess->IsConnected()) {
-    if (!mProcess->WaitForLaunch()) {
-      // If this fails, we should have fired OnProcessLaunchComplete and
-      // removed the process.
-      MOZ_ASSERT(!mProcess && !mGPUChild);
-      return false;
-    }
-  }
-
-  if (mGPUChild && mGPUChild->EnsureGPUReady()) {
-    return true;
-  }
-
-  return false;
-}
-
-void
-GPUProcessManager::EnsureProtocolsReady()
-{
-  EnsureCompositorManagerChild();
-  EnsureImageBridgeChild();
-  EnsureVRManager();
-}
-
-void
-GPUProcessManager::EnsureCompositorManagerChild()
-{
-  base::ProcessId gpuPid = EnsureGPUReady()
-                           ? mGPUChild->OtherPid()
-                           : base::GetCurrentProcId();
-
-  if (CompositorManagerChild::IsInitialized(gpuPid)) {
-    return;
-  }
-
-  if (!EnsureGPUReady()) {
-    CompositorManagerChild::InitSameProcess(AllocateNamespace());
-    return;
-  }
-
-  ipc::Endpoint<PCompositorManagerParent> parentPipe;
-  ipc::Endpoint<PCompositorManagerChild> childPipe;
-  nsresult rv = PCompositorManager::CreateEndpoints(
-    mGPUChild->OtherPid(),
-    base::GetCurrentProcId(),
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    DisableGPUProcess("Failed to create PCompositorManager endpoints");
-    return;
-  }
-
-  mGPUChild->SendInitCompositorManager(Move(parentPipe));
-  CompositorManagerChild::Init(Move(childPipe), AllocateNamespace());
-}
-
-void
-GPUProcessManager::EnsureImageBridgeChild()
-{
-  if (ImageBridgeChild::GetSingleton()) {
-    return;
-  }
-
-  if (!EnsureGPUReady()) {
-    ImageBridgeChild::InitSameProcess(AllocateNamespace());
-    return;
-  }
-
-  ipc::Endpoint<PImageBridgeParent> parentPipe;
-  ipc::Endpoint<PImageBridgeChild> childPipe;
-  nsresult rv = PImageBridge::CreateEndpoints(
-    mGPUChild->OtherPid(),
-    base::GetCurrentProcId(),
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    DisableGPUProcess("Failed to create PImageBridge endpoints");
-    return;
-  }
-
-  mGPUChild->SendInitImageBridge(Move(parentPipe));
-  ImageBridgeChild::InitWithGPUProcess(Move(childPipe), AllocateNamespace());
-}
-
-void
-GPUProcessManager::EnsureVRManager()
-{
-  if (VRManagerChild::IsCreated()) {
-    return;
-  }
-
-  if (!EnsureGPUReady()) {
-    VRManagerChild::InitSameProcess();
-    return;
-  }
-
-  ipc::Endpoint<PVRManagerParent> parentPipe;
-  ipc::Endpoint<PVRManagerChild> childPipe;
-  nsresult rv = PVRManager::CreateEndpoints(
-    mGPUChild->OtherPid(),
-    base::GetCurrentProcId(),
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    DisableGPUProcess("Failed to create PVRManager endpoints");
-    return;
-  }
-
-  mGPUChild->SendInitVRManager(Move(parentPipe));
-  VRManagerChild::InitWithGPUProcess(Move(childPipe));
-}
-
-#if defined(MOZ_WIDGET_ANDROID)
-already_AddRefed<UiCompositorControllerChild>
-GPUProcessManager::CreateUiCompositorController(nsBaseWidget* aWidget, const uint64_t aId)
-{
-  RefPtr<UiCompositorControllerChild> result;
-
-  if (!EnsureGPUReady()) {
-    result = UiCompositorControllerChild::CreateForSameProcess(aId);
-  } else {
-    ipc::Endpoint<PUiCompositorControllerParent> parentPipe;
-    ipc::Endpoint<PUiCompositorControllerChild> childPipe;
-    nsresult rv = PUiCompositorController::CreateEndpoints(
-      mGPUChild->OtherPid(),
-      base::GetCurrentProcId(),
-      &parentPipe,
-      &childPipe);
-    if (NS_FAILED(rv)) {
-      DisableGPUProcess("Failed to create PUiCompositorController endpoints");
-      return nullptr;
-    }
-
-    mGPUChild->SendInitUiCompositorController(aId, Move(parentPipe));
-    result = UiCompositorControllerChild::CreateForGPUProcess(mProcessToken, Move(childPipe));
-  }
-  if (result) {
-    result->SetBaseWidget(aWidget);
-  }
-  return result.forget();
-}
-#endif // defined(MOZ_WIDGET_ANDROID)
-
-void
-GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
-{
-  MOZ_ASSERT(mProcess && mProcess == aHost);
-
-  if (!mProcess->IsConnected()) {
-    DisableGPUProcess("Failed to connect GPU process");
-    return;
-  }
-
-  mGPUChild = mProcess->GetActor();
-  mProcessToken = mProcess->GetProcessToken();
-
-  Endpoint<PVsyncBridgeParent> vsyncParent;
-  Endpoint<PVsyncBridgeChild> vsyncChild;
-  nsresult rv = PVsyncBridge::CreateEndpoints(
-    mGPUChild->OtherPid(),
-    base::GetCurrentProcId(),
-    &vsyncParent,
-    &vsyncChild);
-  if (NS_FAILED(rv)) {
-    DisableGPUProcess("Failed to create PVsyncBridge endpoints");
-    return;
-  }
-
-  mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken, Move(vsyncChild));
-  mGPUChild->SendInitVsyncBridge(Move(vsyncParent));
-
-#ifdef MOZ_CRASHREPORTER
-  CrashReporter::AnnotateCrashReport(
-    NS_LITERAL_CSTRING("GPUProcessStatus"),
-    NS_LITERAL_CSTRING("Running"));
-
-  CrashReporter::AnnotateCrashReport(
-    NS_LITERAL_CSTRING("GPUProcessLaunchCount"),
-    nsPrintfCString("%d", mNumProcessAttempts));
-#endif
-}
-
-static bool
-ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds)
-{
-  // We decide to limit by comparing the amount of resets that have happened
-  // and time since the last reset to two prefs.
-  int32_t timeLimit = gfxPrefs::DeviceResetThresholdMilliseconds();
-  int32_t countLimit = gfxPrefs::DeviceResetLimitCount();
-
-  bool hasTimeLimit = timeLimit >= 0;
-  bool hasCountLimit = countLimit >= 0;
-
-  bool triggeredTime = deltaMilliseconds < timeLimit;
-  bool triggeredCount = count > (uint32_t)countLimit;
-
-  // If we have both prefs set then it needs to trigger both limits,
-  // otherwise we only test the pref that is set or none
-  if (hasTimeLimit && hasCountLimit) {
-    return triggeredTime && triggeredCount;
-  } else if (hasTimeLimit) {
-    return triggeredTime;
-  } else if (hasCountLimit) {
-    return triggeredCount;
-  }
-
-  return false;
-}
-
-void
-GPUProcessManager::ResetCompositors()
-{
-  // Note: this will recreate devices in addition to recreating compositors.
-  // This isn't optimal, but this is only used on linux where acceleration
-  // isn't enabled by default, and this way we don't need a new code path.
-  SimulateDeviceReset();
-}
-
-void
-GPUProcessManager::SimulateDeviceReset()
-{
-  // Make sure we rebuild environment and configuration for accelerated features.
-  gfxPlatform::GetPlatform()->CompositorUpdated();
-
-  if (mProcess) {
-    OnRemoteProcessDeviceReset(mProcess);
-  } else {
-    OnInProcessDeviceReset();
-  }
-}
-
-void
-GPUProcessManager::DisableWebRender()
-{
-  MOZ_ASSERT(gfx::gfxVars::UseWebRender());
-  if (!gfx::gfxVars::UseWebRender()) {
-    return;
-  }
-  // Disable WebRender
-  gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
-    gfx::FeatureStatus::Unavailable,
-    "WebRender initialization failed",
-    NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_INITIALIZE"));
-  gfx::gfxVars::SetUseWebRender(false);
-
-  if (mProcess) {
-    OnRemoteProcessDeviceReset(mProcess);
-  } else {
-    OnInProcessDeviceReset();
-  }
-}
-
-void
-GPUProcessManager::OnInProcessDeviceReset()
-{
-  RebuildInProcessSessions();
-  NotifyListenersOnCompositeDeviceReset();
-}
-
-void
-GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost* aHost)
-{
-  // Detect whether the device is resetting too quickly or too much
-  // indicating that we should give up and use software
-  mDeviceResetCount++;
-
-  auto newTime = TimeStamp::Now();
-  auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
-  mDeviceResetLastTime = newTime;
-
-  if (ShouldLimitDeviceResets(mDeviceResetCount, delta)) {
-    DestroyProcess();
-    DisableGPUProcess("GPU processed experienced too many device resets");
-
-    // Reaches the limited TDR attempts, fallback to software solution.
-    gfxConfig::SetFailed(Feature::HW_COMPOSITING,
-      FeatureStatus::Blocked,
-      "Too many attemps of D3D11 creation, fallback to software solution.");
-    gfxConfig::SetFailed(Feature::D3D11_COMPOSITING,
-      FeatureStatus::Blocked,
-      "Too many attemps of D3D11 creation, fallback to software solution.");
-    gfxConfig::SetFailed(Feature::DIRECT2D,
-      FeatureStatus::Blocked,
-      "Too many attemps of D3D11 creation, fallback to software solution.");
-
-    HandleProcessLost();
-    return;
-  }
-
-  RebuildRemoteSessions();
-  NotifyListenersOnCompositeDeviceReset();
-}
-
-void
-GPUProcessManager::NotifyListenersOnCompositeDeviceReset()
-{
-  for (const auto& listener : mListeners) {
-    listener->OnCompositorDeviceReset();
-  }
-}
-
-void
-GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
-{
-  MOZ_ASSERT(mProcess && mProcess == aHost);
-
-  ReportUnblacklistingTelemetry(true,
-                                mDecodeVideoOnGpuProcess,
-                                mD3D11BlacklistedDriver,
-                                mD3D9BlacklistedDriver);
-
-  CompositorManagerChild::OnGPUProcessLost();
-  DestroyProcess();
-
-  if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
-    char disableMessage[64];
-    SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
-                   mNumProcessAttempts);
-    DisableGPUProcess(disableMessage);
-  } else if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder()) &&
-             mDecodeVideoOnGpuProcess) {
-    mDecodeVideoOnGpuProcess = false;
-    Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
-                                     uint32_t(FallbackType::DECODINGDISABLED));
-    HandleProcessLost();
-  } else {
-    Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
-                                     uint32_t(FallbackType::NONE));
-    HandleProcessLost();
-  }
-}
-
-void
-GPUProcessManager::HandleProcessLost()
-{
-  if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
-    LaunchGPUProcess();
-  }
-
-  // The shutdown and restart sequence for the GPU process is as follows:
-  //
-  //  (1) The GPU process dies. IPDL will enqueue an ActorDestroy message on
-  //      each channel owning a bridge to the GPU process, on the thread
-  //      owning that channel.
-  //
-  //  (2) The first channel to process its ActorDestroy message will post a
-  //      message to the main thread to call NotifyRemoteActorDestroyed on
-  //      the GPUProcessManager, which calls OnProcessUnexpectedShutdown if
-  //      it has not handled shutdown for this process yet.
-  //
-  //  (3) We then notify each widget that its session with the compositor is
-  //      now invalid. The widget is responsible for destroying its layer
-  //      manager and CompositorBridgeChild. Note that at this stage, not
-  //      all actors may have received ActorDestroy yet. CompositorBridgeChild
-  //      may attempt to send messages, and if this happens, it will probably
-  //      report a MsgDropped error. This is okay.
-  //
-  //  (4) At this point, the UI process has a clean slate: no layers should
-  //      exist for the old compositor. We may make a decision on whether or
-  //      not to re-launch the GPU process. Currently, we do not relaunch it,
-  //      and any new compositors will be created in-process and will default
-  //      to software.
-  //
-  //  (5) Next we notify each ContentParent of the lost connection. It will
-  //      request new endpoints from the GPUProcessManager and forward them
-  //      to its ContentChild. The parent-side of these endpoints may come
-  //      from the compositor thread of the UI process, or the compositor
-  //      thread of the GPU process. However, no actual compositors should
-  //      exist yet.
-  //
-  //  (6) Each ContentChild will receive new endpoints. It will destroy its
-  //      Compositor/ImageBridgeChild singletons and recreate them, as well
-  //      as invalidate all retained layers.
-  //
-  //  (7) In addition, each ContentChild will ask each of its TabChildren
-  //      to re-request association with the compositor for the window
-  //      owning the tab. The sequence of calls looks like:
-  //        (a) [CONTENT] ContentChild::RecvReinitRendering
-  //        (b) [CONTENT] TabChild::ReinitRendering
-  //        (c) [CONTENT] TabChild::SendEnsureLayersConnected
-  //        (d)      [UI] TabParent::RecvEnsureLayersConnected
-  //        (e)      [UI] RenderFrameParent::EnsureLayersConnected
-  //        (f)      [UI] CompositorBridgeChild::SendNotifyChildRecreated
-  //
-  //      Note that at step (e), RenderFrameParent will call GetLayerManager
-  //      on the nsIWidget owning the tab. This step ensures that a compositor
-  //      exists for the window. If we decided to launch a new GPU Process,
-  //      at this point we block until the process has launched and we're
-  //      able to create a new window compositor. Otherwise, if compositing
-  //      is now in-process, this will simply create a new
-  //      CompositorBridgeParent in the UI process. If there are multiple tabs
-  //      in the same window, additional tabs will simply return the already-
-  //      established compositor.
-  //
-  //      Finally, this step serves one other crucial function: tabs must be
-  //      associated with a window compositor or else they can't forward
-  //      layer transactions. So this step both ensures that a compositor
-  //      exists, and that the tab can forward layers.
-  //
-  //  (8) Last, if the window had no remote tabs, step (7) will not have
-  //      applied, and the window will not have a new compositor just yet.
-  //      The next refresh tick and paint will ensure that one exists, again
-  //      via nsIWidget::GetLayerManager.
-  RebuildRemoteSessions();
-
-  // Notify content. This will ensure that each content process re-establishes
-  // a connection to the compositor thread (whether it's in-process or in a
-  // newly launched GPU process).
-  for (const auto& listener : mListeners) {
-    listener->OnCompositorUnexpectedShutdown();
-  }
-}
-
-void
-GPUProcessManager::RebuildRemoteSessions()
-{
-  // Build a list of sessions to notify, since notification might delete
-  // entries from the list.
-  nsTArray<RefPtr<RemoteCompositorSession>> sessions;
-  for (auto& session : mRemoteSessions) {
-    sessions.AppendElement(session);
-  }
-
-  // Notify each widget that we have lost the GPU process. This will ensure
-  // that each widget destroys its layer manager and CompositorBridgeChild.
-  for (const auto& session : sessions) {
-    session->NotifySessionLost();
-  }
-}
-
-void
-GPUProcessManager::RebuildInProcessSessions()
-{
-  // Build a list of sessions to notify, since notification might delete
-  // entries from the list.
-  nsTArray<RefPtr<InProcessCompositorSession>> sessions;
-  for (auto& session : mInProcessSessions) {
-    sessions.AppendElement(session);
-  }
-
-  // Notify each widget that we have lost the GPU process. This will ensure
-  // that each widget destroys its layer manager and CompositorBridgeChild.
-  for (const auto& session : sessions) {
-    session->NotifySessionLost();
-  }
-}
-
-void
-GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
-{
-  if (!NS_IsMainThread()) {
-    RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
-      &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
-    NS_DispatchToMainThread(task.forget());
-    return;
-  }
-
-  if (mProcessToken != aProcessToken) {
-    // This token is for an older process; we can safely ignore it.
-    return;
-  }
-
-  // One of the bridged top-level actors for the GPU process has been
-  // prematurely terminated, and we're receiving a notification. This
-  // can happen if the ActorDestroy for a bridged protocol fires
-  // before the ActorDestroy for PGPUChild.
-  OnProcessUnexpectedShutdown(mProcess);
-}
-
-void
-GPUProcessManager::CleanShutdown()
-{
-  DestroyProcess();
-  mVsyncIOThread = nullptr;
-}
-
-void
-GPUProcessManager::KillProcess()
-{
-  if (!mProcess) {
-    return;
-  }
-
-  mProcess->KillProcess();
-}
-
-void
-GPUProcessManager::DestroyProcess()
-{
-  if (!mProcess) {
-    return;
-  }
-
-  mProcess->Shutdown();
-  mProcessToken = 0;
-  mProcess = nullptr;
-  mGPUChild = nullptr;
-  if (mVsyncBridge) {
-    mVsyncBridge->Close();
-    mVsyncBridge = nullptr;
-  }
-
-#ifdef MOZ_CRASHREPORTER
-  CrashReporter::AnnotateCrashReport(
-    NS_LITERAL_CSTRING("GPUProcessStatus"),
-    NS_LITERAL_CSTRING("Destroyed"));
-#endif
-}
-
-already_AddRefed<CompositorSession>
-GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
-                                            LayerManager* aLayerManager,
-                                            CSSToLayoutDeviceScale aScale,
-                                            const CompositorOptions& aOptions,
-                                            bool aUseExternalSurfaceSize,
-                                            const gfx::IntSize& aSurfaceSize,
-                                            bool* aRetryOut)
-{
-  MOZ_ASSERT(aRetryOut);
-
-  uint64_t layerTreeId = AllocateLayerTreeId();
-
-  EnsureProtocolsReady();
-
-  RefPtr<CompositorSession> session;
-
-  if (EnsureGPUReady()) {
-    session = CreateRemoteSession(
-      aWidget,
-      aLayerManager,
-      layerTreeId,
-      aScale,
-      aOptions,
-      aUseExternalSurfaceSize,
-      aSurfaceSize);
-    if (!session) {
-      // We couldn't create a remote compositor, so abort the process.
-      DisableGPUProcess("Failed to create remote compositor");
-      *aRetryOut = true;
-      return nullptr;
-    }
-  } else {
-    session = InProcessCompositorSession::Create(
-      aWidget,
-      aLayerManager,
-      layerTreeId,
-      aScale,
-      aOptions,
-      aUseExternalSurfaceSize,
-      aSurfaceSize,
-      AllocateNamespace());
-  }
-
-#if defined(MOZ_WIDGET_ANDROID)
-  if (session) {
-    // Nothing to do if controller gets a nullptr
-    RefPtr<UiCompositorControllerChild> controller = CreateUiCompositorController(aWidget, session->RootLayerTreeId());
-    session->SetUiCompositorControllerChild(controller);
-  }
-#endif // defined(MOZ_WIDGET_ANDROID)
-
-  *aRetryOut = false;
-  return session.forget();
-}
-
-RefPtr<CompositorSession>
-GPUProcessManager::CreateRemoteSession(nsBaseWidget* aWidget,
-                                       LayerManager* aLayerManager,
-                                       const uint64_t& aRootLayerTreeId,
-                                       CSSToLayoutDeviceScale aScale,
-                                       const CompositorOptions& aOptions,
-                                       bool aUseExternalSurfaceSize,
-                                       const gfx::IntSize& aSurfaceSize)
-{
-#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
-  CompositorWidgetInitData initData;
-  aWidget->GetCompositorWidgetInitData(&initData);
-
-  RefPtr<CompositorBridgeChild> child =
-    CompositorManagerChild::CreateWidgetCompositorBridge(
-      mProcessToken,
-      aLayerManager,
-      AllocateNamespace(),
-      aScale,
-      aOptions,
-      aUseExternalSurfaceSize,
-      aSurfaceSize);
-  if (!child) {
-    gfxCriticalNote << "Failed to create CompositorBridgeChild";
-    return nullptr;
-  }
-
-  RefPtr<CompositorVsyncDispatcher> dispatcher = aWidget->GetCompositorVsyncDispatcher();
-  RefPtr<CompositorWidgetVsyncObserver> observer =
-    new CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
-
-  CompositorWidgetChild* widget = new CompositorWidgetChild(dispatcher, observer);
-  if (!child->SendPCompositorWidgetConstructor(widget, initData)) {
-    return nullptr;
-  }
-  if (!child->SendInitialize(aRootLayerTreeId)) {
-    return nullptr;
-  }
-
-  RefPtr<APZCTreeManagerChild> apz = nullptr;
-  if (aOptions.UseAPZ()) {
-    PAPZCTreeManagerChild* papz = child->SendPAPZCTreeManagerConstructor(0);
-    if (!papz) {
-      return nullptr;
-    }
-    apz = static_cast<APZCTreeManagerChild*>(papz);
-  }
-
-  RefPtr<RemoteCompositorSession> session =
-    new RemoteCompositorSession(aWidget, child, widget, apz, aRootLayerTreeId);
-  return session.forget();
-#else
-  gfxCriticalNote << "Platform does not support out-of-process compositing";
-  return nullptr;
-#endif
-}
-
-bool
-GPUProcessManager::CreateContentBridges(base::ProcessId aOtherProcess,
-                                        ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
-                                        ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
-                                        ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
-                                        ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
-                                        nsTArray<uint32_t>* aNamespaces)
-{
-  if (!CreateContentCompositorManager(aOtherProcess, aOutCompositor) ||
-      !CreateContentImageBridge(aOtherProcess, aOutImageBridge) ||
-      !CreateContentVRManager(aOtherProcess, aOutVRBridge))
-  {
-    return false;
-  }
-  // VideoDeocderManager is only supported in the GPU process, so we allow this to be
-  // fallible.
-  CreateContentVideoDecoderManager(aOtherProcess, aOutVideoManager);
-  // Allocates 3 namespaces(for CompositorManagerChild, CompositorBridgeChild and ImageBridgeChild)
-  aNamespaces->AppendElement(AllocateNamespace());
-  aNamespaces->AppendElement(AllocateNamespace());
-  aNamespaces->AppendElement(AllocateNamespace());
-  return true;
-}
-
-bool
-GPUProcessManager::CreateContentCompositorManager(base::ProcessId aOtherProcess,
-                                                  ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint)
-{
-  ipc::Endpoint<PCompositorManagerParent> parentPipe;
-  ipc::Endpoint<PCompositorManagerChild> childPipe;
-
-  base::ProcessId parentPid = EnsureGPUReady()
-                              ? mGPUChild->OtherPid()
-                              : base::GetCurrentProcId();
-
-  nsresult rv = PCompositorManager::CreateEndpoints(
-    parentPid,
-    aOtherProcess,
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    gfxCriticalNote << "Could not create content compositor manager: " << hexa(int(rv));
-    return false;
-  }
-
-  if (mGPUChild) {
-    mGPUChild->SendNewContentCompositorManager(Move(parentPipe));
-  } else {
-    CompositorManagerParent::Create(Move(parentPipe));
-  }
-
-  *aOutEndpoint = Move(childPipe);
-  return true;
-}
-
-bool
-GPUProcessManager::CreateContentImageBridge(base::ProcessId aOtherProcess,
-                                            ipc::Endpoint<PImageBridgeChild>* aOutEndpoint)
-{
-  EnsureImageBridgeChild();
-
-  base::ProcessId parentPid = EnsureGPUReady()
-                              ? mGPUChild->OtherPid()
-                              : base::GetCurrentProcId();
-
-  ipc::Endpoint<PImageBridgeParent> parentPipe;
-  ipc::Endpoint<PImageBridgeChild> childPipe;
-  nsresult rv = PImageBridge::CreateEndpoints(
-    parentPid,
-    aOtherProcess,
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
-    return false;
-  }
-
-  if (mGPUChild) {
-    mGPUChild->SendNewContentImageBridge(Move(parentPipe));
-  } else {
-    if (!ImageBridgeParent::CreateForContent(Move(parentPipe))) {
-      return false;
-    }
-  }
-
-  *aOutEndpoint = Move(childPipe);
-  return true;
-}
-
-base::ProcessId
-GPUProcessManager::GPUProcessPid()
-{
-  base::ProcessId gpuPid = mGPUChild
-                           ? mGPUChild->OtherPid()
-                           : -1;
-  return gpuPid;
-}
-
-bool
-GPUProcessManager::CreateContentVRManager(base::ProcessId aOtherProcess,
-                                          ipc::Endpoint<PVRManagerChild>* aOutEndpoint)
-{
-  EnsureVRManager();
-
-  base::ProcessId parentPid = EnsureGPUReady()
-                              ? mGPUChild->OtherPid()
-                              : base::GetCurrentProcId();
-
-  ipc::Endpoint<PVRManagerParent> parentPipe;
-  ipc::Endpoint<PVRManagerChild> childPipe;
-  nsresult rv = PVRManager::CreateEndpoints(
-    parentPid,
-    aOtherProcess,
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
-    return false;
-  }
-
-  if (mGPUChild) {
-    mGPUChild->SendNewContentVRManager(Move(parentPipe));
-  } else {
-    if (!VRManagerParent::CreateForContent(Move(parentPipe))) {
-      return false;
-    }
-  }
-
-  *aOutEndpoint = Move(childPipe);
-  return true;
-}
-
-void
-GPUProcessManager::CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
-                                                    ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndpoint)
-{
-  if (!EnsureGPUReady() ||
-      !MediaPrefs::PDMUseGPUDecoder() ||
-      !mDecodeVideoOnGpuProcess) {
-    return;
-  }
-
-  ipc::Endpoint<dom::PVideoDecoderManagerParent> parentPipe;
-  ipc::Endpoint<dom::PVideoDecoderManagerChild> childPipe;
-
-  nsresult rv = dom::PVideoDecoderManager::CreateEndpoints(
-    mGPUChild->OtherPid(),
-    aOtherProcess,
-    &parentPipe,
-    &childPipe);
-  if (NS_FAILED(rv)) {
-    gfxCriticalNote << "Could not create content video decoder: " << hexa(int(rv));
-    return;
-  }
-
-  mGPUChild->SendNewContentVideoDecoderManager(Move(parentPipe));
-
-  *aOutEndpoint = Move(childPipe);
-}
-
-already_AddRefed<IAPZCTreeManager>
-GPUProcessManager::GetAPZCTreeManagerForLayers(uint64_t aLayersId)
-{
-  return CompositorBridgeParent::GetAPZCTreeManager(aLayersId);
-}
-
-void
-GPUProcessManager::MapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
-{
-  LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId);
-
-  if (EnsureGPUReady()) {
-    mGPUChild->SendAddLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
-  }
-}
-
-void
-GPUProcessManager::UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
-{
-  LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
-
-  if (EnsureGPUReady()) {
-    mGPUChild->SendRemoveLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
-    return;
-  }
-  CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
-}
-
-bool
-GPUProcessManager::IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId)
-{
-  return LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, aRequestingId);
-}
-
-uint64_t
-GPUProcessManager::AllocateLayerTreeId()
-{
-  // Allocate tree id by using id namespace.
-  // By it, tree id does not conflict with external image id and
-  // async image pipeline id.
-  MOZ_ASSERT(NS_IsMainThread());
-  ++mResourceId;
-  if (mResourceId == UINT32_MAX) {
-    // Move to next id namespace.
-    mIdNamespace = AllocateNamespace();
-    mResourceId = 1;
-  }
-
-  uint64_t layerTreeId = mIdNamespace;
-  layerTreeId = (layerTreeId << 32) | mResourceId;
-  return layerTreeId;
-}
-
-uint32_t
-GPUProcessManager::AllocateNamespace()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  return ++mNextNamespace;
-}
-
-bool
-GPUProcessManager::AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge,
-                                                 base::ProcessId aOtherPid,
-                                                 uint64_t* aOutLayersId,
-                                                 CompositorOptions* aOutCompositorOptions)
-{
-  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, aOutCompositorOptions);
-  }
-
-  // Use the combined message path.
-  LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
-  return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid, aOutCompositorOptions);
-}
-
-void
-GPUProcessManager::EnsureVsyncIOThread()
-{
-  if (mVsyncIOThread) {
-    return;
-  }
-
-  mVsyncIOThread = new VsyncIOThreadHolder();
-  MOZ_RELEASE_ASSERT(mVsyncIOThread->Start());
-}
-
-void
-GPUProcessManager::ShutdownVsyncIOThread()
-{
-  mVsyncIOThread = nullptr;
-}
-
-void
-GPUProcessManager::RegisterRemoteProcessSession(RemoteCompositorSession* aSession)
-{
-  mRemoteSessions.AppendElement(aSession);
-}
-
-void
-GPUProcessManager::UnregisterRemoteProcessSession(RemoteCompositorSession* aSession)
-{
-  mRemoteSessions.RemoveElement(aSession);
-}
-
-void
-GPUProcessManager::RegisterInProcessSession(InProcessCompositorSession* aSession)
-{
-  mInProcessSessions.AppendElement(aSession);
-}
-
-void
-GPUProcessManager::UnregisterInProcessSession(InProcessCompositorSession* aSession)
-{
-  mInProcessSessions.RemoveElement(aSession);
-}
-
-void
-GPUProcessManager::AddListener(GPUProcessListener* aListener)
-{
-  mListeners.AppendElement(aListener);
-}
-
-void
-GPUProcessManager::RemoveListener(GPUProcessListener* aListener)
-{
-  mListeners.RemoveElement(aListener);
-}
-
-bool
-GPUProcessManager::NotifyGpuObservers(const char* aTopic)
-{
-  if (!EnsureGPUReady()) {
-    return false;
-  }
-  nsCString topic(aTopic);
-  mGPUChild->SendNotifyGpuObservers(topic);
-  return true;
-}
-
-class GPUMemoryReporter : public MemoryReportingProcess
-{
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
-
-  bool IsAlive() const override {
-    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
-      return !!gpm->GetGPUChild();
-    }
-    return false;
-  }
-
-  bool SendRequestMemoryReport(const uint32_t& aGeneration,
-                               const bool& aAnonymize,
-                               const bool& aMinimizeMemoryUsage,
-                               const dom::MaybeFileDesc& aDMDFile) override
-  {
-    GPUChild* child = GetChild();
-    if (!child) {
-      return false;
-    }
-
-    return child->SendRequestMemoryReport(
-      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
-  }
-
-  int32_t Pid() const override {
-    if (GPUChild* child = GetChild()) {
-      return (int32_t)child->OtherPid();
-    }
-    return 0;
-  }
-
-private:
-  GPUChild* GetChild() const {
-    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
-      if (GPUChild* child = gpm->GetGPUChild()) {
-        return child;
-      }
-    }
-    return nullptr;
-  }
-
-protected:
-  ~GPUMemoryReporter() = default;
-};
-
-RefPtr<MemoryReportingProcess>
-GPUProcessManager::GetProcessMemoryReporter()
-{
-  if (!EnsureGPUReady()) {
-    return nullptr;
-  }
-  return new GPUMemoryReporter();
-}
-
-void
-GPUProcessManager::OnSetBlacklistedDrivers(const nsCString& aD3D11Driver,
-                                           const nsCString& aD3D9Driver)
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=99: */
+/* 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 "GPUProcessManager.h"
+
+#include "gfxPrefs.h"
+#include "GPUProcessHost.h"
+#include "GPUProcessListener.h"
+#include "mozilla/MemoryReportingProcess.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/layers/APZCTreeManager.h"
+#include "mozilla/layers/APZCTreeManagerChild.h"
+#include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/layers/CompositorManagerChild.h"
+#include "mozilla/layers/CompositorManagerParent.h"
+#include "mozilla/layers/CompositorOptions.h"
+#include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/ImageBridgeParent.h"
+#include "mozilla/layers/InProcessCompositorSession.h"
+#include "mozilla/layers/LayerTreeOwnerTracker.h"
+#include "mozilla/layers/RemoteCompositorSession.h"
+#include "mozilla/widget/PlatformWidgetTypes.h"
+#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
+# include "mozilla/widget/CompositorWidgetChild.h"
+#endif
+#include "nsBaseWidget.h"
+#include "nsContentUtils.h"
+#include "VRManagerChild.h"
+#include "VRManagerParent.h"
+#include "VsyncBridgeChild.h"
+#include "VsyncIOThreadHolder.h"
+#include "VsyncSource.h"
+#include "mozilla/dom/VideoDecoderManagerChild.h"
+#include "mozilla/dom/VideoDecoderManagerParent.h"
+#include "MediaPrefs.h"
+#include "nsPrintfCString.h"
+
+#ifdef MOZ_CRASHREPORTER
+# include "nsExceptionHandler.h"
+#endif
+
+#if defined(MOZ_WIDGET_ANDROID)
+#include "mozilla/widget/AndroidUiThread.h"
+#include "mozilla/layers/UiCompositorControllerChild.h"
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+namespace mozilla {
+
+void
+ReportUnblacklistingTelemetry(bool isGPUProcessCrashed,
+                              bool isHWDecodingOnGPUProcess,
+                              const nsCString& aD3D11BlacklistedDriver,
+                              const nsCString& aD3D9BlacklistedDriver)
+{
+#ifdef XP_WIN
+  const nsCString& blacklistedDLL = !aD3D11BlacklistedDriver.IsEmpty()
+                                    ? aD3D11BlacklistedDriver
+                                    : aD3D9BlacklistedDriver;
+
+  if (!blacklistedDLL.IsEmpty()) {
+    const uint32_t type = [isHWDecodingOnGPUProcess, isGPUProcessCrashed]() {
+      if (isHWDecodingOnGPUProcess) {
+        if (!isGPUProcessCrashed) {
+          return 0;
+        }
+        else {
+          return 1;
+        }
+      }
+      else {
+        if (!isGPUProcessCrashed) {
+          return 2;
+        }
+        else {
+          return 3;
+        }
+      }
+    }();
+
+    Telemetry::Accumulate(Telemetry::VIDEO_UNBLACKINGLISTING_DXVA_DRIVER_RUNTIME_STATUS,
+                          blacklistedDLL,
+                          type);
+  }
+#endif // XP_WIN
+}
+
+namespace gfx {
+
+using namespace mozilla::layers;
+
+enum class FallbackType : uint32_t
+{
+  NONE = 0,
+  DECODINGDISABLED,
+  DISABLED,
+};
+
+static StaticAutoPtr<GPUProcessManager> sSingleton;
+
+GPUProcessManager*
+GPUProcessManager::Get()
+{
+  return sSingleton;
+}
+
+void
+GPUProcessManager::Initialize()
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+  sSingleton = new GPUProcessManager();
+}
+
+void
+GPUProcessManager::Shutdown()
+{
+  sSingleton = nullptr;
+}
+
+GPUProcessManager::GPUProcessManager()
+ : mTaskFactory(this),
+   mNextNamespace(0),
+   mIdNamespace(0),
+   mResourceId(0),
+   mNumProcessAttempts(0),
+   mDeviceResetCount(0),
+   mProcess(nullptr),
+   mGPUChild(nullptr)
+{
+  MOZ_COUNT_CTOR(GPUProcessManager);
+
+  mIdNamespace = AllocateNamespace();
+  mObserver = new Observer(this);
+  nsContentUtils::RegisterShutdownObserver(mObserver);
+
+  mDeviceResetLastTime = TimeStamp::Now();
+
+  LayerTreeOwnerTracker::Initialize();
+}
+
+GPUProcessManager::~GPUProcessManager()
+{
+  MOZ_COUNT_DTOR(GPUProcessManager);
+
+  LayerTreeOwnerTracker::Shutdown();
+
+  // The GPU process should have already been shut down.
+  MOZ_ASSERT(!mProcess && !mGPUChild);
+
+  // We should have already removed observers.
+  MOZ_ASSERT(!mObserver);
+}
+
+NS_IMPL_ISUPPORTS(GPUProcessManager::Observer, nsIObserver);
+
+GPUProcessManager::Observer::Observer(GPUProcessManager* aManager)
+ : mManager(aManager)
+{
+}
+
+NS_IMETHODIMP
+GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
+{
+  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
+    mManager->OnXPCOMShutdown();
+  }
+  return NS_OK;
+}
+
+void
+GPUProcessManager::OnXPCOMShutdown()
+{
+  if (mObserver) {
+    nsContentUtils::UnregisterShutdownObserver(mObserver);
+    mObserver = nullptr;
+  }
+
+  CleanShutdown();
+}
+
+void
+GPUProcessManager::LaunchGPUProcess()
+{
+  if (mProcess) {
+    return;
+  }
+
+  // Start the Vsync I/O thread so can use it as soon as the process launches.
+  EnsureVsyncIOThread();
+
+  mNumProcessAttempts++;
+
+  // The subprocess is launched asynchronously, so we wait for a callback to
+  // acquire the IPDL actor.
+  mProcess = new GPUProcessHost(this);
+  if (!mProcess->Launch()) {
+    DisableGPUProcess("Failed to launch GPU process");
+  }
+}
+
+void
+GPUProcessManager::DisableGPUProcess(const char* aMessage)
+{
+  if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
+    return;
+  }
+
+  gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
+  gfxCriticalNote << aMessage;
+
+  gfxPlatform::NotifyGPUProcessDisabled();
+
+  Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
+                        uint32_t(FallbackType::DISABLED));
+
+  DestroyProcess();
+  ShutdownVsyncIOThread();
+
+  // We may have been in the middle of guaranteeing our various services are
+  // available when one failed. Some callers may fallback to using the same
+  // process equivalent, and we need to make sure those services are setup
+  // correctly. We cannot re-enter DisableGPUProcess from this call because we
+  // know that it is disabled in the config above.
+  EnsureProtocolsReady();
+
+  // If we disable the GPU process during reinitialization after a previous
+  // crash, then we need to tell the content processes again, because they
+  // need to rebind to the UI process.
+  HandleProcessLost();
+}
+
+bool
+GPUProcessManager::EnsureGPUReady()
+{
+  if (mProcess && !mProcess->IsConnected()) {
+    if (!mProcess->WaitForLaunch()) {
+      // If this fails, we should have fired OnProcessLaunchComplete and
+      // removed the process.
+      MOZ_ASSERT(!mProcess && !mGPUChild);
+      return false;
+    }
+  }
+
+  if (mGPUChild && mGPUChild->EnsureGPUReady()) {
+    return true;
+  }
+
+  return false;
+}
+
+void
+GPUProcessManager::EnsureProtocolsReady()
+{
+  EnsureCompositorManagerChild();
+  EnsureImageBridgeChild();
+  EnsureVRManager();
+}
+
+void
+GPUProcessManager::EnsureCompositorManagerChild()
+{
+  base::ProcessId gpuPid = EnsureGPUReady()
+                           ? mGPUChild->OtherPid()
+                           : base::GetCurrentProcId();
+
+  if (CompositorManagerChild::IsInitialized(gpuPid)) {
+    return;
+  }
+
+  if (!EnsureGPUReady()) {
+    CompositorManagerChild::InitSameProcess(AllocateNamespace());
+    return;
+  }
+
+  ipc::Endpoint<PCompositorManagerParent> parentPipe;
+  ipc::Endpoint<PCompositorManagerChild> childPipe;
+  nsresult rv = PCompositorManager::CreateEndpoints(
+    mGPUChild->OtherPid(),
+    base::GetCurrentProcId(),
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    DisableGPUProcess("Failed to create PCompositorManager endpoints");
+    return;
+  }
+
+  mGPUChild->SendInitCompositorManager(Move(parentPipe));
+  CompositorManagerChild::Init(Move(childPipe), AllocateNamespace());
+}
+
+void
+GPUProcessManager::EnsureImageBridgeChild()
+{
+  if (ImageBridgeChild::GetSingleton()) {
+    return;
+  }
+
+  if (!EnsureGPUReady()) {
+    ImageBridgeChild::InitSameProcess(AllocateNamespace());
+    return;
+  }
+
+  ipc::Endpoint<PImageBridgeParent> parentPipe;
+  ipc::Endpoint<PImageBridgeChild> childPipe;
+  nsresult rv = PImageBridge::CreateEndpoints(
+    mGPUChild->OtherPid(),
+    base::GetCurrentProcId(),
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    DisableGPUProcess("Failed to create PImageBridge endpoints");
+    return;
+  }
+
+  mGPUChild->SendInitImageBridge(Move(parentPipe));
+  ImageBridgeChild::InitWithGPUProcess(Move(childPipe), AllocateNamespace());
+}
+
+void
+GPUProcessManager::EnsureVRManager()
+{
+  if (VRManagerChild::IsCreated()) {
+    return;
+  }
+
+  if (!EnsureGPUReady()) {
+    VRManagerChild::InitSameProcess();
+    return;
+  }
+
+  ipc::Endpoint<PVRManagerParent> parentPipe;
+  ipc::Endpoint<PVRManagerChild> childPipe;
+  nsresult rv = PVRManager::CreateEndpoints(
+    mGPUChild->OtherPid(),
+    base::GetCurrentProcId(),
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    DisableGPUProcess("Failed to create PVRManager endpoints");
+    return;
+  }
+
+  mGPUChild->SendInitVRManager(Move(parentPipe));
+  VRManagerChild::InitWithGPUProcess(Move(childPipe));
+}
+
+#if defined(MOZ_WIDGET_ANDROID)
+already_AddRefed<UiCompositorControllerChild>
+GPUProcessManager::CreateUiCompositorController(nsBaseWidget* aWidget, const uint64_t aId)
+{
+  RefPtr<UiCompositorControllerChild> result;
+
+  if (!EnsureGPUReady()) {
+    result = UiCompositorControllerChild::CreateForSameProcess(aId);
+  } else {
+    ipc::Endpoint<PUiCompositorControllerParent> parentPipe;
+    ipc::Endpoint<PUiCompositorControllerChild> childPipe;
+    nsresult rv = PUiCompositorController::CreateEndpoints(
+      mGPUChild->OtherPid(),
+      base::GetCurrentProcId(),
+      &parentPipe,
+      &childPipe);
+    if (NS_FAILED(rv)) {
+      DisableGPUProcess("Failed to create PUiCompositorController endpoints");
+      return nullptr;
+    }
+
+    mGPUChild->SendInitUiCompositorController(aId, Move(parentPipe));
+    result = UiCompositorControllerChild::CreateForGPUProcess(mProcessToken, Move(childPipe));
+  }
+  if (result) {
+    result->SetBaseWidget(aWidget);
+  }
+  return result.forget();
+}
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+void
+GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
+{
+  MOZ_ASSERT(mProcess && mProcess == aHost);
+
+  if (!mProcess->IsConnected()) {
+    DisableGPUProcess("Failed to connect GPU process");
+    return;
+  }
+
+  mGPUChild = mProcess->GetActor();
+  mProcessToken = mProcess->GetProcessToken();
+
+  Endpoint<PVsyncBridgeParent> vsyncParent;
+  Endpoint<PVsyncBridgeChild> vsyncChild;
+  nsresult rv = PVsyncBridge::CreateEndpoints(
+    mGPUChild->OtherPid(),
+    base::GetCurrentProcId(),
+    &vsyncParent,
+    &vsyncChild);
+  if (NS_FAILED(rv)) {
+    DisableGPUProcess("Failed to create PVsyncBridge endpoints");
+    return;
+  }
+
+  mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken, Move(vsyncChild));
+  mGPUChild->SendInitVsyncBridge(Move(vsyncParent));
+
+#ifdef MOZ_CRASHREPORTER
+  CrashReporter::AnnotateCrashReport(
+    NS_LITERAL_CSTRING("GPUProcessStatus"),
+    NS_LITERAL_CSTRING("Running"));
+
+  CrashReporter::AnnotateCrashReport(
+    NS_LITERAL_CSTRING("GPUProcessLaunchCount"),
+    nsPrintfCString("%d", mNumProcessAttempts));
+#endif
+}
+
+static bool
+ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds)
+{
+  // We decide to limit by comparing the amount of resets that have happened
+  // and time since the last reset to two prefs.
+  int32_t timeLimit = gfxPrefs::DeviceResetThresholdMilliseconds();
+  int32_t countLimit = gfxPrefs::DeviceResetLimitCount();
+
+  bool hasTimeLimit = timeLimit >= 0;
+  bool hasCountLimit = countLimit >= 0;
+
+  bool triggeredTime = deltaMilliseconds < timeLimit;
+  bool triggeredCount = count > (uint32_t)countLimit;
+
+  // If we have both prefs set then it needs to trigger both limits,
+  // otherwise we only test the pref that is set or none
+  if (hasTimeLimit && hasCountLimit) {
+    return triggeredTime && triggeredCount;
+  } else if (hasTimeLimit) {
+    return triggeredTime;
+  } else if (hasCountLimit) {
+    return triggeredCount;
+  }
+
+  return false;
+}
+
+void
+GPUProcessManager::ResetCompositors()
+{
+  // Note: this will recreate devices in addition to recreating compositors.
+  // This isn't optimal, but this is only used on linux where acceleration
+  // isn't enabled by default, and this way we don't need a new code path.
+  SimulateDeviceReset();
+}
+
+void
+GPUProcessManager::SimulateDeviceReset()
+{
+  // Make sure we rebuild environment and configuration for accelerated features.
+  gfxPlatform::GetPlatform()->CompositorUpdated();
+
+  if (mProcess) {
+    OnRemoteProcessDeviceReset(mProcess);
+  } else {
+    OnInProcessDeviceReset();
+  }
+}
+
+void
+GPUProcessManager::DisableWebRender()
+{
+  MOZ_ASSERT(gfx::gfxVars::UseWebRender());
+  if (!gfx::gfxVars::UseWebRender()) {
+    return;
+  }
+  // Disable WebRender
+  gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
+    gfx::FeatureStatus::Unavailable,
+    "WebRender initialization failed",
+    NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_INITIALIZE"));
+  gfx::gfxVars::SetUseWebRender(false);
+
+  if (mProcess) {
+    OnRemoteProcessDeviceReset(mProcess);
+  } else {
+    OnInProcessDeviceReset();
+  }
+}
+
+void
+GPUProcessManager::OnInProcessDeviceReset()
+{
+  RebuildInProcessSessions();
+  NotifyListenersOnCompositeDeviceReset();
+}
+
+void
+GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost* aHost)
+{
+  // Detect whether the device is resetting too quickly or too much
+  // indicating that we should give up and use software
+  mDeviceResetCount++;
+
+  auto newTime = TimeStamp::Now();
+  auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
+  mDeviceResetLastTime = newTime;
+
+  if (ShouldLimitDeviceResets(mDeviceResetCount, delta)) {
+    DestroyProcess();
+    DisableGPUProcess("GPU processed experienced too many device resets");
+
+    // Reaches the limited TDR attempts, fallback to software solution.
+    gfxConfig::SetFailed(Feature::HW_COMPOSITING,
+      FeatureStatus::Blocked,
+      "Too many attemps of D3D11 creation, fallback to software solution.");
+    gfxConfig::SetFailed(Feature::D3D11_COMPOSITING,
+      FeatureStatus::Blocked,
+      "Too many attemps of D3D11 creation, fallback to software solution.");
+    gfxConfig::SetFailed(Feature::DIRECT2D,
+      FeatureStatus::Blocked,
+      "Too many attemps of D3D11 creation, fallback to software solution.");
+
+    HandleProcessLost();
+    return;
+  }
+
+  RebuildRemoteSessions();
+  NotifyListenersOnCompositeDeviceReset();
+}
+
+void
+GPUProcessManager::NotifyListenersOnCompositeDeviceReset()
+{
+  for (const auto& listener : mListeners) {
+    listener->OnCompositorDeviceReset();
+  }
+}
+
+void
+GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
+{
+  MOZ_ASSERT(mProcess && mProcess == aHost);
+
+  ReportUnblacklistingTelemetry(true,
+                                mDecodeVideoOnGpuProcess,
+                                mD3D11BlacklistedDriver,
+                                mD3D9BlacklistedDriver);
+
+  CompositorManagerChild::OnGPUProcessLost();
+  DestroyProcess();
+
+  if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
+    char disableMessage[64];
+    SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
+                   mNumProcessAttempts);
+    DisableGPUProcess(disableMessage);
+  } else if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder()) &&
+             mDecodeVideoOnGpuProcess) {
+    mDecodeVideoOnGpuProcess = false;
+    Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
+                                     uint32_t(FallbackType::DECODINGDISABLED));
+    HandleProcessLost();
+  } else {
+    Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
+                                     uint32_t(FallbackType::NONE));
+    HandleProcessLost();
+  }
+}
+
+void
+GPUProcessManager::HandleProcessLost()
 {
-  mD3D11BlacklistedDriver = aD3D11Driver;
-  mD3D9BlacklistedDriver = aD3D9Driver;
-}
-
-} // namespace gfx
-} // namespace mozilla
+  if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
+    LaunchGPUProcess();
+  }
+
+  // The shutdown and restart sequence for the GPU process is as follows:
+  //
+  //  (1) The GPU process dies. IPDL will enqueue an ActorDestroy message on
+  //      each channel owning a bridge to the GPU process, on the thread
+  //      owning that channel.
+  //
+  //  (2) The first channel to process its ActorDestroy message will post a
+  //      message to the main thread to call NotifyRemoteActorDestroyed on
+  //      the GPUProcessManager, which calls OnProcessUnexpectedShutdown if
+  //      it has not handled shutdown for this process yet.
+  //
+  //  (3) We then notify each widget that its session with the compositor is
+  //      now invalid. The widget is responsible for destroying its layer
+  //      manager and CompositorBridgeChild. Note that at this stage, not
+  //      all actors may have received ActorDestroy yet. CompositorBridgeChild
+  //      may attempt to send messages, and if this happens, it will probably
+  //      report a MsgDropped error. This is okay.
+  //
+  //  (4) At this point, the UI process has a clean slate: no layers should
+  //      exist for the old compositor. We may make a decision on whether or
+  //      not to re-launch the GPU process. Currently, we do not relaunch it,
+  //      and any new compositors will be created in-process and will default
+  //      to software.
+  //
+  //  (5) Next we notify each ContentParent of the lost connection. It will
+  //      request new endpoints from the GPUProcessManager and forward them
+  //      to its ContentChild. The parent-side of these endpoints may come
+  //      from the compositor thread of the UI process, or the compositor
+  //      thread of the GPU process. However, no actual compositors should
+  //      exist yet.
+  //
+  //  (6) Each ContentChild will receive new endpoints. It will destroy its
+  //      Compositor/ImageBridgeChild singletons and recreate them, as well
+  //      as invalidate all retained layers.
+  //
+  //  (7) In addition, each ContentChild will ask each of its TabChildren
+  //      to re-request association with the compositor for the window
+  //      owning the tab. The sequence of calls looks like:
+  //        (a) [CONTENT] ContentChild::RecvReinitRendering
+  //        (b) [CONTENT] TabChild::ReinitRendering
+  //        (c) [CONTENT] TabChild::SendEnsureLayersConnected
+  //        (d)      [UI] TabParent::RecvEnsureLayersConnected
+  //        (e)      [UI] RenderFrameParent::EnsureLayersConnected
+  //        (f)      [UI] CompositorBridgeChild::SendNotifyChildRecreated
+  //
+  //      Note that at step (e), RenderFrameParent will call GetLayerManager
+  //      on the nsIWidget owning the tab. This step ensures that a compositor
+  //      exists for the window. If we decided to launch a new GPU Process,
+  //      at this point we block until the process has launched and we're
+  //      able to create a new window compositor. Otherwise, if compositing
+  //      is now in-process, this will simply create a new
+  //      CompositorBridgeParent in the UI process. If there are multiple tabs
+  //      in the same window, additional tabs will simply return the already-
+  //      established compositor.
+  //
+  //      Finally, this step serves one other crucial function: tabs must be
+  //      associated with a window compositor or else they can't forward
+  //      layer transactions. So this step both ensures that a compositor
+  //      exists, and that the tab can forward layers.
+  //
+  //  (8) Last, if the window had no remote tabs, step (7) will not have
+  //      applied, and the window will not have a new compositor just yet.
+  //      The next refresh tick and paint will ensure that one exists, again
+  //      via nsIWidget::GetLayerManager.
+  RebuildRemoteSessions();
+
+  // Notify content. This will ensure that each content process re-establishes
+  // a connection to the compositor thread (whether it's in-process or in a
+  // newly launched GPU process).
+  for (const auto& listener : mListeners) {
+    listener->OnCompositorUnexpectedShutdown();
+  }
+}
+
+void
+GPUProcessManager::RebuildRemoteSessions()
+{
+  // Build a list of sessions to notify, since notification might delete
+  // entries from the list.
+  nsTArray<RefPtr<RemoteCompositorSession>> sessions;
+  for (auto& session : mRemoteSessions) {
+    sessions.AppendElement(session);
+  }
+
+  // Notify each widget that we have lost the GPU process. This will ensure
+  // that each widget destroys its layer manager and CompositorBridgeChild.
+  for (const auto& session : sessions) {
+    session->NotifySessionLost();
+  }
+}
+
+void
+GPUProcessManager::RebuildInProcessSessions()
+{
+  // Build a list of sessions to notify, since notification might delete
+  // entries from the list.
+  nsTArray<RefPtr<InProcessCompositorSession>> sessions;
+  for (auto& session : mInProcessSessions) {
+    sessions.AppendElement(session);
+  }
+
+  // Notify each widget that we have lost the GPU process. This will ensure
+  // that each widget destroys its layer manager and CompositorBridgeChild.
+  for (const auto& session : sessions) {
+    session->NotifySessionLost();
+  }
+}
+
+void
+GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
+{
+  if (!NS_IsMainThread()) {
+    RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
+      &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
+    NS_DispatchToMainThread(task.forget());
+    return;
+  }
+
+  if (mProcessToken != aProcessToken) {
+    // This token is for an older process; we can safely ignore it.
+    return;
+  }
+
+  // One of the bridged top-level actors for the GPU process has been
+  // prematurely terminated, and we're receiving a notification. This
+  // can happen if the ActorDestroy for a bridged protocol fires
+  // before the ActorDestroy for PGPUChild.
+  OnProcessUnexpectedShutdown(mProcess);
+}
+
+void
+GPUProcessManager::CleanShutdown()
+{
+  DestroyProcess();
+  mVsyncIOThread = nullptr;
+}
+
+void
+GPUProcessManager::KillProcess()
+{
+  if (!mProcess) {
+    return;
+  }
+
+  mProcess->KillProcess();
+}
+
+void
+GPUProcessManager::DestroyProcess()
+{
+  if (!mProcess) {
+    return;
+  }
+
+  mProcess->Shutdown();
+  mProcessToken = 0;
+  mProcess = nullptr;
+  mGPUChild = nullptr;
+  if (mVsyncBridge) {
+    mVsyncBridge->Close();
+    mVsyncBridge = nullptr;
+  }
+
+#ifdef MOZ_CRASHREPORTER
+  CrashReporter::AnnotateCrashReport(
+    NS_LITERAL_CSTRING("GPUProcessStatus"),
+    NS_LITERAL_CSTRING("Destroyed"));
+#endif
+}
+
+already_AddRefed<CompositorSession>
+GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
+                                            LayerManager* aLayerManager,
+                                            CSSToLayoutDeviceScale aScale,
+                                            const CompositorOptions& aOptions,
+                                            bool aUseExternalSurfaceSize,
+                                            const gfx::IntSize& aSurfaceSize,
+                                            bool* aRetryOut)
+{
+  MOZ_ASSERT(aRetryOut);
+
+  uint64_t layerTreeId = AllocateLayerTreeId();
+
+  EnsureProtocolsReady();
+
+  RefPtr<CompositorSession> session;
+
+  if (EnsureGPUReady()) {
+    session = CreateRemoteSession(
+      aWidget,
+      aLayerManager,
+      layerTreeId,
+      aScale,
+      aOptions,
+      aUseExternalSurfaceSize,
+      aSurfaceSize);
+    if (!session) {
+      // We couldn't create a remote compositor, so abort the process.
+      DisableGPUProcess("Failed to create remote compositor");
+      *aRetryOut = true;
+      return nullptr;
+    }
+  } else {
+    session = InProcessCompositorSession::Create(
+      aWidget,
+      aLayerManager,
+      layerTreeId,
+      aScale,
+      aOptions,
+      aUseExternalSurfaceSize,
+      aSurfaceSize,
+      AllocateNamespace());
+  }
+
+#if defined(MOZ_WIDGET_ANDROID)
+  if (session) {
+    // Nothing to do if controller gets a nullptr
+    RefPtr<UiCompositorControllerChild> controller = CreateUiCompositorController(aWidget, session->RootLayerTreeId());
+    session->SetUiCompositorControllerChild(controller);
+  }
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+  *aRetryOut = false;
+  return session.forget();
+}
+
+RefPtr<CompositorSession>
+GPUProcessManager::CreateRemoteSession(nsBaseWidget* aWidget,
+                                       LayerManager* aLayerManager,
+                                       const uint64_t& aRootLayerTreeId,
+                                       CSSToLayoutDeviceScale aScale,
+                                       const CompositorOptions& aOptions,
+                                       bool aUseExternalSurfaceSize,
+                                       const gfx::IntSize& aSurfaceSize)
+{
+#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
+  CompositorWidgetInitData initData;
+  aWidget->GetCompositorWidgetInitData(&initData);
+
+  RefPtr<CompositorBridgeChild> child =
+    CompositorManagerChild::CreateWidgetCompositorBridge(
+      mProcessToken,
+      aLayerManager,
+      AllocateNamespace(),
+      aScale,
+      aOptions,
+      aUseExternalSurfaceSize,
+      aSurfaceSize);
+  if (!child) {
+    gfxCriticalNote << "Failed to create CompositorBridgeChild";
+    return nullptr;
+  }
+
+  RefPtr<CompositorVsyncDispatcher> dispatcher = aWidget->GetCompositorVsyncDispatcher();
+  RefPtr<CompositorWidgetVsyncObserver> observer =
+    new CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
+
+  CompositorWidgetChild* widget = new CompositorWidgetChild(dispatcher, observer);
+  if (!child->SendPCompositorWidgetConstructor(widget, initData)) {
+    return nullptr;
+  }
+  if (!child->SendInitialize(aRootLayerTreeId)) {
+    return nullptr;
+  }
+
+  RefPtr<APZCTreeManagerChild> apz = nullptr;
+  if (aOptions.UseAPZ()) {
+    PAPZCTreeManagerChild* papz = child->SendPAPZCTreeManagerConstructor(0);
+    if (!papz) {
+      return nullptr;
+    }
+    apz = static_cast<APZCTreeManagerChild*>(papz);
+  }
+
+  RefPtr<RemoteCompositorSession> session =
+    new RemoteCompositorSession(aWidget, child, widget, apz, aRootLayerTreeId);
+  return session.forget();
+#else
+  gfxCriticalNote << "Platform does not support out-of-process compositing";
+  return nullptr;
+#endif
+}
+
+bool
+GPUProcessManager::CreateContentBridges(base::ProcessId aOtherProcess,
+                                        ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
+                                        ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
+                                        ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
+                                        ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
+                                        nsTArray<uint32_t>* aNamespaces)
+{
+  if (!CreateContentCompositorManager(aOtherProcess, aOutCompositor) ||
+      !CreateContentImageBridge(aOtherProcess, aOutImageBridge) ||
+      !CreateContentVRManager(aOtherProcess, aOutVRBridge))
+  {
+    return false;
+  }
+  // VideoDeocderManager is only supported in the GPU process, so we allow this to be
+  // fallible.
+  CreateContentVideoDecoderManager(aOtherProcess, aOutVideoManager);
+  // Allocates 3 namespaces(for CompositorManagerChild, CompositorBridgeChild and ImageBridgeChild)
+  aNamespaces->AppendElement(AllocateNamespace());
+  aNamespaces->AppendElement(AllocateNamespace());
+  aNamespaces->AppendElement(AllocateNamespace());
+  return true;
+}
+
+bool
+GPUProcessManager::CreateContentCompositorManager(base::ProcessId aOtherProcess,
+                                                  ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint)
+{
+  ipc::Endpoint<PCompositorManagerParent> parentPipe;
+  ipc::Endpoint<PCompositorManagerChild> childPipe;
+
+  base::ProcessId parentPid = EnsureGPUReady()
+                              ? mGPUChild->OtherPid()
+                              : base::GetCurrentProcId();
+
+  nsresult rv = PCompositorManager::CreateEndpoints(
+    parentPid,
+    aOtherProcess,
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    gfxCriticalNote << "Could not create content compositor manager: " << hexa(int(rv));
+    return false;
+  }
+
+  if (mGPUChild) {
+    mGPUChild->SendNewContentCompositorManager(Move(parentPipe));
+  } else {
+    CompositorManagerParent::Create(Move(parentPipe));
+  }
+
+  *aOutEndpoint = Move(childPipe);
+  return true;
+}
+
+bool
+GPUProcessManager::CreateContentImageBridge(base::ProcessId aOtherProcess,
+                                            ipc::Endpoint<PImageBridgeChild>* aOutEndpoint)
+{
+  EnsureImageBridgeChild();
+
+  base::ProcessId parentPid = EnsureGPUReady()
+                              ? mGPUChild->OtherPid()
+                              : base::GetCurrentProcId();
+
+  ipc::Endpoint<PImageBridgeParent> parentPipe;
+  ipc::Endpoint<PImageBridgeChild> childPipe;
+  nsresult rv = PImageBridge::CreateEndpoints(
+    parentPid,
+    aOtherProcess,
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
+    return false;
+  }
+
+  if (mGPUChild) {
+    mGPUChild->SendNewContentImageBridge(Move(parentPipe));
+  } else {
+    if (!ImageBridgeParent::CreateForContent(Move(parentPipe))) {
+      return false;
+    }
+  }
+
+  *aOutEndpoint = Move(childPipe);
+  return true;
+}
+
+base::ProcessId
+GPUProcessManager::GPUProcessPid()
+{
+  base::ProcessId gpuPid = mGPUChild
+                           ? mGPUChild->OtherPid()
+                           : -1;
+  return gpuPid;
+}
+
+bool
+GPUProcessManager::CreateContentVRManager(base::ProcessId aOtherProcess,
+                                          ipc::Endpoint<PVRManagerChild>* aOutEndpoint)
+{
+  EnsureVRManager();
+
+  base::ProcessId parentPid = EnsureGPUReady()
+                              ? mGPUChild->OtherPid()
+                              : base::GetCurrentProcId();
+
+  ipc::Endpoint<PVRManagerParent> parentPipe;
+  ipc::Endpoint<PVRManagerChild> childPipe;
+  nsresult rv = PVRManager::CreateEndpoints(
+    parentPid,
+    aOtherProcess,
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
+    return false;
+  }
+
+  if (mGPUChild) {
+    mGPUChild->SendNewContentVRManager(Move(parentPipe));
+  } else {
+    if (!VRManagerParent::CreateForContent(Move(parentPipe))) {
+      return false;
+    }
+  }
+
+  *aOutEndpoint = Move(childPipe);
+  return true;
+}
+
+void
+GPUProcessManager::CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
+                                                    ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndpoint)
+{
+  if (!EnsureGPUReady() ||
+      !MediaPrefs::PDMUseGPUDecoder() ||
+      !mDecodeVideoOnGpuProcess) {
+    return;
+  }
+
+  ipc::Endpoint<dom::PVideoDecoderManagerParent> parentPipe;
+  ipc::Endpoint<dom::PVideoDecoderManagerChild> childPipe;
+
+  nsresult rv = dom::PVideoDecoderManager::CreateEndpoints(
+    mGPUChild->OtherPid(),
+    aOtherProcess,
+    &parentPipe,
+    &childPipe);
+  if (NS_FAILED(rv)) {
+    gfxCriticalNote << "Could not create content video decoder: " << hexa(int(rv));
+    return;
+  }
+
+  mGPUChild->SendNewContentVideoDecoderManager(Move(parentPipe));
+
+  *aOutEndpoint = Move(childPipe);
+}
+
+already_AddRefed<IAPZCTreeManager>
+GPUProcessManager::GetAPZCTreeManagerForLayers(uint64_t aLayersId)
+{
+  return CompositorBridgeParent::GetAPZCTreeManager(aLayersId);
+}
+
+void
+GPUProcessManager::MapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
+{
+  LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId);
+
+  if (EnsureGPUReady()) {
+    mGPUChild->SendAddLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
+  }
+}
+
+void
+GPUProcessManager::UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
+{
+  LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
+
+  if (EnsureGPUReady()) {
+    mGPUChild->SendRemoveLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
+    return;
+  }
+  CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
+}
+
+bool
+GPUProcessManager::IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId)
+{
+  return LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, aRequestingId);
+}
+
+uint64_t
+GPUProcessManager::AllocateLayerTreeId()
+{
+  // Allocate tree id by using id namespace.
+  // By it, tree id does not conflict with external image id and
+  // async image pipeline id.
+  MOZ_ASSERT(NS_IsMainThread());
+  ++mResourceId;
+  if (mResourceId == UINT32_MAX) {
+    // Move to next id namespace.
+    mIdNamespace = AllocateNamespace();
+    mResourceId = 1;
+  }
+
+  uint64_t layerTreeId = mIdNamespace;
+  layerTreeId = (layerTreeId << 32) | mResourceId;
+  return layerTreeId;
+}
+
+uint32_t
+GPUProcessManager::AllocateNamespace()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  return ++mNextNamespace;
+}
+
+bool
+GPUProcessManager::AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge,
+                                                 base::ProcessId aOtherPid,
+                                                 uint64_t* aOutLayersId,
+                                                 CompositorOptions* aOutCompositorOptions)
+{
+  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, aOutCompositorOptions);
+  }
+
+  // Use the combined message path.
+  LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
+  return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid, aOutCompositorOptions);
+}
+
+void
+GPUProcessManager::EnsureVsyncIOThread()
+{
+  if (mVsyncIOThread) {
+    return;
+  }
+
+  mVsyncIOThread = new VsyncIOThreadHolder();
+  MOZ_RELEASE_ASSERT(mVsyncIOThread->Start());
+}
+
+void
+GPUProcessManager::ShutdownVsyncIOThread()
+{
+  mVsyncIOThread = nullptr;
+}
+
+void
+GPUProcessManager::RegisterRemoteProcessSession(RemoteCompositorSession* aSession)
+{
+  mRemoteSessions.AppendElement(aSession);
+}
+
+void
+GPUProcessManager::UnregisterRemoteProcessSession(RemoteCompositorSession* aSession)
+{
+  mRemoteSessions.RemoveElement(aSession);
+}
+
+void
+GPUProcessManager::RegisterInProcessSession(InProcessCompositorSession* aSession)
+{
+  mInProcessSessions.AppendElement(aSession);
+}
+
+void
+GPUProcessManager::UnregisterInProcessSession(InProcessCompositorSession* aSession)
+{
+  mInProcessSessions.RemoveElement(aSession);
+}
+
+void
+GPUProcessManager::AddListener(GPUProcessListener* aListener)
+{
+  mListeners.AppendElement(aListener);
+}
+
+void
+GPUProcessManager::RemoveListener(GPUProcessListener* aListener)
+{
+  mListeners.RemoveElement(aListener);
+}
+
+bool
+GPUProcessManager::NotifyGpuObservers(const char* aTopic)
+{
+  if (!EnsureGPUReady()) {
+    return false;
+  }
+  nsCString topic(aTopic);
+  mGPUChild->SendNotifyGpuObservers(topic);
+  return true;
+}
+
+class GPUMemoryReporter : public MemoryReportingProcess
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
+
+  bool IsAlive() const override {
+    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+      return !!gpm->GetGPUChild();
+    }
+    return false;
+  }
+
+  bool SendRequestMemoryReport(const uint32_t& aGeneration,
+                               const bool& aAnonymize,
+                               const bool& aMinimizeMemoryUsage,
+                               const dom::MaybeFileDesc& aDMDFile) override
+  {
+    GPUChild* child = GetChild();
+    if (!child) {
+      return false;
+    }
+
+    return child->SendRequestMemoryReport(
+      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
+  }
+
+  int32_t Pid() const override {
+    if (GPUChild* child = GetChild()) {
+      return (int32_t)child->OtherPid();
+    }
+    return 0;
+  }
+
+private:
+  GPUChild* GetChild() const {
+    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+      if (GPUChild* child = gpm->GetGPUChild()) {
+        return child;
+      }
+    }
+    return nullptr;
+  }
+
+protected:
+  ~GPUMemoryReporter() = default;
+};
+
+RefPtr<MemoryReportingProcess>
+GPUProcessManager::GetProcessMemoryReporter()
+{
+  if (!EnsureGPUReady()) {
+    return nullptr;
+  }
+  return new GPUMemoryReporter();
+}
+
+void
+GPUProcessManager::OnSetBlacklistedDrivers(const nsCString& aD3D11Driver,
+                                           const nsCString& aD3D9Driver)
+{
+  mD3D11BlacklistedDriver = aD3D11Driver;
+  mD3D9BlacklistedDriver = aD3D9Driver;
+}
+
+} // namespace gfx
+} // namespace mozilla