Bug 1430038 - Part 2: launch VR process and communicate with GPU process; r=kip, jimm
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 07 Aug 2018 11:20:34 -0700
changeset 487586 57c32dd4f6e6ac28787e207f6854b9e0ab4ede65
parent 487585 1a61001aaee6db940509579078fa9807fd80b01c
child 487587 2e16db6bbb2106bc2fde665626d0013020651623
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip, jimm
bugs1430038
milestone63.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 1430038 - Part 2: launch VR process and communicate with GPU process; r=kip, jimm Summary: MozReview-Commit-ID: IQZVIYVSCxe Tags: #secure-revision Differential Revision: https://phabricator.services.mozilla.com/D2877 MozReview-Commit-ID: 4sT6fqk7MpT
gfx/vr/VRManager.cpp
gfx/vr/gfxVRExternal.cpp
gfx/vr/gfxVRPuppet.h
gfx/vr/ipc/PVR.ipdl
gfx/vr/ipc/PVRGPU.ipdl
gfx/vr/ipc/VRChild.cpp
gfx/vr/ipc/VRChild.h
gfx/vr/ipc/VRGPUChild.cpp
gfx/vr/ipc/VRGPUChild.h
gfx/vr/ipc/VRGPUParent.cpp
gfx/vr/ipc/VRGPUParent.h
gfx/vr/ipc/VRParent.cpp
gfx/vr/ipc/VRParent.h
gfx/vr/ipc/VRProcessChild.cpp
gfx/vr/ipc/VRProcessChild.h
gfx/vr/ipc/VRProcessManager.cpp
gfx/vr/ipc/VRProcessManager.h
gfx/vr/ipc/VRProcessParent.cpp
gfx/vr/ipc/VRProcessParent.h
gfx/vr/moz.build
gfx/vr/service/VRService.h
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -10,16 +10,17 @@
 #include "VRThread.h"
 #include "gfxVR.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/VRDisplay.h"
 #include "mozilla/dom/GamepadEventTypes.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/Unused.h"
+#include "mozilla/gfx/GPUParent.h"
 
 #include "gfxPrefs.h"
 #include "gfxVR.h"
 #include "gfxVRExternal.h"
 #if defined(XP_WIN)
 #include "gfxVROculus.h"
 #endif
 #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
@@ -43,16 +44,18 @@ namespace gfx {
 
 static StaticRefPtr<VRManager> sVRManagerSingleton;
 
 /*static*/ void
 VRManager::ManagerInit()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  // TODO: We should make VRManager::ManagerInit
+  // be called when entering VR content pages.
   if (sVRManagerSingleton == nullptr) {
     sVRManagerSingleton = new VRManager();
     ClearOnShutdown(&sVRManagerSingleton);
   }
 }
 
 VRManager::VRManager()
   : mInitialized(false)
@@ -76,17 +79,23 @@ VRManager::VRManager()
    *
    * OSVR will be used if Oculus SDK and OpenVR don't detect any HMDS,
    * to support everyone else.
    */
 
 #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
   // The VR Service accesses all hardware from a separate process
   // and replaces the other VRSystemManager when enabled.
-  mVRService = VRService::Create();
+  if (!gfxPrefs::VRProcessEnabled()) {
+    mVRService = VRService::Create();
+  } else if (gfxPrefs::VRProcessEnabled() && XRE_IsGPUProcess()) {
+    gfx::GPUParent* gpu = GPUParent::GetSingleton();
+    MOZ_ASSERT(gpu);
+    Unused << gpu->SendCreateVRProcess();
+  }
   if (mVRService) {
     mExternalManager = VRSystemManagerExternal::Create(mVRService->GetAPIShmem());
   }
   if (mExternalManager) {
     mManagers.AppendElement(mExternalManager);
   }
 #endif
 
--- a/gfx/vr/gfxVRExternal.cpp
+++ b/gfx/vr/gfxVRExternal.cpp
@@ -499,17 +499,18 @@ VRSystemManagerExternal::CloseShmem()
 VRSystemManagerExternal::Create(VRExternalShmem* aAPIShmem /* = nullptr*/)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gfxPrefs::VREnabled()) {
     return nullptr;
   }
 
-  if (!gfxPrefs::VRExternalEnabled() && aAPIShmem == nullptr) {
+  if ((!gfxPrefs::VRExternalEnabled() && aAPIShmem == nullptr) ||
+      !XRE_IsGPUProcess()) {
     return nullptr;
   }
 
   RefPtr<VRSystemManagerExternal> manager = new VRSystemManagerExternal(aAPIShmem);
   return manager.forget();
 }
 
 void
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -9,20 +9,28 @@
 
 #include "nsTArray.h"
 #include "mozilla/RefPtr.h"
 #include "nsRefPtrHashtable.h"
 
 #include "gfxVR.h"
 #include "VRDisplayLocal.h"
 
+#if defined(XP_WIN)
+#include "CompositorD3D11.h"
+#endif
+
 #if defined(XP_MACOSX)
 class MacIOSurface;
 #endif
 namespace mozilla {
+namespace layers {
+struct VertexShaderConstants;
+struct PixelShaderConstants;
+}
 namespace gfx {
 namespace impl {
 
 class VRDisplayPuppet : public VRDisplayLocal
 {
 public:
   void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);
   void SetSensorState(const VRHMDSensorState& aSensorState);
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/PVR.ipdl
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+using mozilla::TimeStamp from "mozilla/TimeStamp.h";
+
+include GraphicsMessages;
+include protocol PVRGPU;
+
+namespace mozilla {
+namespace gfx {
+
+async protocol PVR
+{
+parent:
+  async NewGPUVRManager(Endpoint<PVRGPUParent> endpoint);
+  async Init(GfxPrefSetting[] prefs, GfxVarUpdate[] vars, DevicePrefs devicePrefs);
+  async NotifyVsync(TimeStamp aVsyncTimestamp);
+
+  async UpdatePref(GfxPrefSetting pref);
+  async UpdateVar(GfxVarUpdate var);
+};
+
+} // namespace gfx
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/PVRGPU.ipdl
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+namespace mozilla {
+namespace gfx {
+
+// IPC for VR-Content process
+async protocol PVRGPU
+{
+parent:
+  async InitVRService(nsCString aId, uint64_t aGPUHandle, uint64_t aVRHandle, uint64_t aShmemFile);
+};
+
+} // gfx
+} // mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRChild.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRChild.h"
+#include "VRProcessParent.h"
+#include "gfxConfig.h"
+
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/SystemGroup.h"
+#include "mozilla/VsyncDispatcher.h"
+
+namespace mozilla {
+namespace gfx {
+
+VRChild::VRChild(VRProcessParent* aHost)
+ : mHost(aHost)
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+}
+
+void
+VRChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  gfxVars::RemoveReceiver(this);
+  mHost->OnChannelClosed();
+  XRE_ShutdownChildProcess();
+}
+
+void
+VRChild::Init()
+{
+  // Build a list of prefs the VR process will need. Note that because we
+  // limit the VR process to prefs contained in gfxPrefs, we can simplify
+  // the message in two ways: one, we only need to send its index in gfxPrefs
+  // rather than its name, and two, we only need to send prefs that don't
+  // have their default value.
+  // Todo: Consider to make our own vrPrefs that we are interested in VR process.
+  nsTArray<GfxPrefSetting> prefs;
+  for (auto pref : gfxPrefs::all()) {
+    if (pref->HasDefaultValue()) {
+      continue;
+    }
+
+    GfxPrefValue value;
+    pref->GetCachedValue(&value);
+    prefs.AppendElement(GfxPrefSetting(pref->Index(), value));
+  }
+  nsTArray<GfxVarUpdate> updates = gfxVars::FetchNonDefaultVars();
+
+  DevicePrefs devicePrefs;
+  devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
+  devicePrefs.d3d11Compositing() = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
+  devicePrefs.oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
+  devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
+  devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
+
+  SendInit(prefs, updates, devicePrefs);
+  gfxVars::AddReceiver(this);
+}
+
+void
+VRChild::OnVarChanged(const GfxVarUpdate& aVar)
+{
+  SendUpdateVar(aVar);
+}
+
+class DeferredDeleteVRChild : public Runnable
+{
+public:
+  explicit DeferredDeleteVRChild(UniquePtr<VRChild>&& aChild)
+    : Runnable("gfx::DeferredDeleteVRChild")
+    , mChild(std::move(aChild))
+  {
+  }
+
+  NS_IMETHODIMP Run() override {
+    return NS_OK;
+  }
+
+private:
+  UniquePtr<VRChild> mChild;
+};
+
+/* static */ void
+VRChild::Destroy(UniquePtr<VRChild>&& aChild)
+{
+  NS_DispatchToMainThread(new DeferredDeleteVRChild(std::move(aChild)));
+}
+
+} // namespace gfx
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRChild.h
@@ -0,0 +1,42 @@
+/* -*- 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 GFX_VR_CHILD_H
+#define GFX_VR_CHILD_H
+
+#include "mozilla/gfx/PVRChild.h"
+#include "mozilla/gfx/gfxVarReceiver.h"
+#include "mozilla/VsyncDispatcher.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRProcessParent;
+class VRChild;
+
+class VRChild final
+ : public PVRChild,
+   public gfxVarReceiver {
+
+public:
+  explicit VRChild(VRProcessParent* aHost);
+  ~VRChild() = default;
+
+  static void Destroy(UniquePtr<VRChild>&& aChild);
+  void Init();
+  virtual void OnVarChanged(const GfxVarUpdate& aVar) override;
+
+protected:
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+private:
+  VRProcessParent* mHost;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif  // GFX_VR_CHILD_H
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRGPUChild.cpp
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRGPUChild.h"
+
+
+namespace mozilla {
+namespace gfx {
+
+static StaticRefPtr<VRGPUChild> sVRGPUChildSingleton;
+
+/* static */ bool
+VRGPUChild::InitForGPUProcess(Endpoint<PVRGPUChild>&& aEndpoint)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!sVRGPUChildSingleton);
+
+  RefPtr<VRGPUChild> child(new VRGPUChild());
+  if (!aEndpoint.Bind(child)) {
+    return false;
+  }
+  sVRGPUChildSingleton = child;
+  return true;
+}
+
+/* static */ bool
+VRGPUChild::IsCreated()
+{
+  return !!sVRGPUChildSingleton;
+}
+
+/* static */ VRGPUChild*
+VRGPUChild::Get()
+{
+  MOZ_ASSERT(IsCreated(), "VRGPUChild haven't initialized yet.");
+  return sVRGPUChildSingleton;
+}
+
+/*static*/ void
+VRGPUChild::DeferredDestroy(RefPtr<VRGPUChild> aVRGPUChild)
+{
+  aVRGPUChild->Close();
+}
+
+/*static*/ void
+VRGPUChild::ShutDown()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (sVRGPUChildSingleton) {
+    sVRGPUChildSingleton->Destroy();
+    sVRGPUChildSingleton = nullptr;
+  }
+}
+
+class DeferredDeleteVRGPUChild : public Runnable
+{
+public:
+  explicit DeferredDeleteVRGPUChild(RefPtr<VRGPUChild> aChild)
+    : Runnable("gfx::DeferredDeleteVRGPUChild")
+    , mChild(std::move(aChild))
+  {
+  }
+
+  NS_IMETHODIMP Run() override {
+    mChild->Close();
+    return NS_OK;
+  }
+
+private:
+  RefPtr<VRGPUChild> mChild;
+};
+
+void
+VRGPUChild::Destroy()
+{
+  // Keep ourselves alive until everything has been shut down
+  RefPtr<VRGPUChild> selfRef = this;
+  NS_DispatchToMainThread(new DeferredDeleteVRGPUChild(this));
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRGPUChild.h
@@ -0,0 +1,39 @@
+/* -*- 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 GFX_VR_GPU_CHILD_H
+#define GFX_VR_GPU_CHILD_H
+
+#include "mozilla/gfx/PVRGPUChild.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRGPUChild final : public PVRGPUChild
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRGPUChild);
+
+  static VRGPUChild* Get();
+  static bool InitForGPUProcess(Endpoint<PVRGPUChild>&& aEndpoint);
+  static bool IsCreated();
+  static void ShutDown();
+
+protected:
+  explicit VRGPUChild() {}
+  ~VRGPUChild() {}
+
+  static void DeferredDestroy(RefPtr<VRGPUChild> aVRManagerChild);
+  void Destroy();
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(VRGPUChild);
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // GFX_VR_GPU_CHILD_H
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRGPUParent.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRGPUParent.h"
+
+#include "mozilla/ipc/ProcessChild.h"
+
+
+namespace mozilla {
+namespace gfx {
+
+using namespace ipc;
+
+
+VRGPUParent::VRGPUParent(ProcessId aChildProcessId)
+{
+  MOZ_COUNT_CTOR(VRGPUParent);
+  MOZ_ASSERT(NS_IsMainThread());
+
+  SetOtherProcessId(aChildProcessId);
+}
+
+void
+VRGPUParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  MessageLoop::current()->PostTask(
+  NewRunnableMethod("gfx::VRGPUParent::DeferredDestroy",
+                     this,
+                     &VRGPUParent::DeferredDestroy));
+}
+
+void
+VRGPUParent::DeferredDestroy()
+{
+  mSelfRef = nullptr;
+}
+
+/* static */ RefPtr<VRGPUParent>
+VRGPUParent::CreateForGPU(Endpoint<PVRGPUParent>&& aEndpoint)
+{
+  RefPtr<VRGPUParent> vcp = new VRGPUParent(aEndpoint.OtherPid());
+  MessageLoop::current()->PostTask(
+    NewRunnableMethod<Endpoint<PVRGPUParent>&&>(
+    "gfx::VRGPUParent::Bind",
+    vcp,
+    &VRGPUParent::Bind,
+    std::move(aEndpoint)));
+
+  return vcp;
+}
+
+void
+VRGPUParent::Bind(Endpoint<PVRGPUParent>&& aEndpoint)
+{
+  if (!aEndpoint.Bind(this)) {
+    return;
+  }
+
+  mSelfRef = this;
+}
+
+mozilla::ipc::IPCResult
+VRGPUParent::RecvInitVRService(const nsCString& aId, const uint64_t& aGPUHandle,
+                               const uint64_t& aVRHandle, const uint64_t& aShmemFile)
+{
+  // TODO: Create duplicate shared memory handle from GPU process.
+  return IPC_OK();
+}
+
+} // namespace gfx
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRGPUParent.h
@@ -0,0 +1,45 @@
+/* -*- 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 GFX_VR_GPU_PARENT_H
+#define GFX_VR_GPU_PARENT_H
+
+#include "mozilla/gfx/PVRGPUParent.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRGPUParent final : public PVRGPUParent {
+   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRGPUParent)
+
+public:
+  explicit VRGPUParent(ProcessId aChildProcessId);
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  static RefPtr<VRGPUParent> CreateForGPU(Endpoint<PVRGPUParent>&& aEndpoint);
+
+protected:
+  ~VRGPUParent() {}
+
+  void Bind(Endpoint<PVRGPUParent>&& aEndpoint);
+  virtual mozilla::ipc::IPCResult RecvInitVRService(const nsCString& aId,
+                                                    const uint64_t& aGPUHandle,
+                                                    const uint64_t& aVRHandle,
+                                                    const uint64_t& aShmemFile) override;
+
+private:
+  void DeferredDestroy();
+
+  RefPtr<VRGPUParent> mSelfRef;
+#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
+  RefPtr<VRService> mVRService;
+#endif
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // GFX_VR_CONTENT_PARENT_H
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRParent.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRParent.h"
+#include "VRGPUParent.h"
+#include "VRManager.h"
+#include "gfxConfig.h"
+
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/ipc/ProcessChild.h"
+
+#if defined(XP_WIN)
+#include "mozilla/gfx/DeviceManagerDx.h"
+#endif
+
+namespace mozilla {
+namespace gfx {
+
+using namespace ipc;
+
+VRParent::VRParent()
+ : mVRGPUParent(nullptr)
+{
+}
+
+mozilla::ipc::IPCResult
+VRParent::RecvNewGPUVRManager(Endpoint<PVRGPUParent>&& aEndpoint)
+{
+  RefPtr<VRGPUParent> vrGPUParent = VRGPUParent::CreateForGPU(std::move(aEndpoint));
+  if (!vrGPUParent) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  mVRGPUParent = std::move(vrGPUParent);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
+                   nsTArray<GfxVarUpdate>&& vars,
+                   const DevicePrefs& devicePrefs)
+{
+  const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
+  for (auto& setting : prefs) {
+    gfxPrefs::Pref* pref = globalPrefs[setting.index()];
+    pref->SetCachedValue(setting.value());
+  }
+  for (const auto& var : vars) {
+    gfxVars::ApplyUpdate(var);
+  }
+
+  // Inherit device preferences.
+  gfxConfig::Inherit(Feature::HW_COMPOSITING, devicePrefs.hwCompositing());
+  gfxConfig::Inherit(Feature::D3D11_COMPOSITING, devicePrefs.d3d11Compositing());
+  gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, devicePrefs.oglCompositing());
+  gfxConfig::Inherit(Feature::ADVANCED_LAYERS, devicePrefs.advancedLayers());
+  gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1());
+
+#if defined(XP_WIN)
+  if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
+    DeviceManagerDx::Get()->CreateCompositorDevices();
+  }
+#endif
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRParent::RecvNotifyVsync(const TimeStamp& aVsyncTimestamp)
+{
+  VRManager* vm = VRManager::Get();
+  vm->NotifyVsync(aVsyncTimestamp);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRParent::RecvUpdatePref(const GfxPrefSetting& setting)
+{
+  gfxPrefs::Pref* pref = gfxPrefs::all()[setting.index()];
+  pref->SetCachedValue(setting.value());
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+VRParent::RecvUpdateVar(const GfxVarUpdate& aUpdate)
+{
+  gfxVars::ApplyUpdate(aUpdate);
+  return IPC_OK();
+}
+
+void
+VRParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  if (AbnormalShutdown == aWhy) {
+    NS_WARNING("Shutting down VR process early due to a crash!");
+    ProcessChild::QuickExit();
+  }
+
+  mVRGPUParent->Close();
+#if defined(XP_WIN)
+  DeviceManagerDx::Shutdown();
+#endif
+  gfxVars::Shutdown();
+  gfxConfig::Shutdown();
+  gfxPrefs::DestroySingleton();
+  XRE_ShutdownChildProcess();
+}
+
+bool
+VRParent::Init(base::ProcessId aParentPid,
+               const char* aParentBuildID,
+               MessageLoop* aIOLoop,
+               IPC::Channel* aChannel)
+{
+  // Now it's safe to start IPC.
+  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+    return false;
+  }
+
+  // This must be checked before any IPDL message, which may hit sentinel
+  // errors due to parent and content processes having different
+  // versions.
+  MessageChannel* channel = GetIPCChannel();
+  if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
+    // We need to quit this process if the buildID doesn't match the parent's.
+    // This can occur when an update occurred in the background.
+    ProcessChild::QuickExit();
+  }
+
+  // Ensure gfxPrefs are initialized.
+  gfxPrefs::GetSingleton();
+  gfxConfig::Init();
+  gfxVars::Initialize();
+#if defined(XP_WIN)
+  DeviceManagerDx::Init();
+#endif
+  return true;
+}
+
+} // namespace gfx
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRParent.h
@@ -0,0 +1,45 @@
+/* -*- 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 GFX_VR_PARENT_H
+#define GFX_VR_PARENT_H
+
+#include "mozilla/gfx/PVRParent.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRGPUParent;
+class VRService;
+class VRSystemManagerExternal;
+
+class VRParent final : public PVRParent {
+
+public:
+  VRParent();
+  bool Init(base::ProcessId aParentPid,
+            const char* aParentBuildID,
+            MessageLoop* aIOLoop,
+            IPC::Channel* aChannel);
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+protected:
+  virtual mozilla::ipc::IPCResult RecvNewGPUVRManager(Endpoint<PVRGPUParent>&& aEndpoint) override;
+  virtual mozilla::ipc::IPCResult RecvInit(nsTArray<GfxPrefSetting>&& prefs,
+                                           nsTArray<GfxVarUpdate>&& vars,
+                                           const DevicePrefs& devicePrefs) override;
+  virtual mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& aVsyncTimestamp) override;
+  virtual mozilla::ipc::IPCResult RecvUpdatePref(const GfxPrefSetting& setting) override;
+  virtual mozilla::ipc::IPCResult RecvUpdateVar(const GfxVarUpdate& pref) override;
+
+private:
+  RefPtr<VRGPUParent> mVRGPUParent;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // GFX_VR_PARENT_H
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRProcessChild.cpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRProcessChild.h"
+
+#include "mozilla/BackgroundHangMonitor.h"
+#include "mozilla/ipc/IOThreadChild.h"
+
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using mozilla::ipc::IOThreadChild;
+
+
+VRProcessChild::VRProcessChild(ProcessId aParentPid)
+  : ProcessChild(aParentPid)
+#if defined(aParentPid)
+  , mVR(nullptr)
+#endif
+{
+}
+
+VRProcessChild::~VRProcessChild()
+{
+}
+
+bool
+VRProcessChild::Init(int aArgc, char* aArgv[])
+{
+  BackgroundHangMonitor::Startup();
+
+  char* parentBuildID = nullptr;
+  for (int i = 1; i < aArgc; i++) {
+    if (strcmp(aArgv[i], "-parentBuildID") == 0) {
+      parentBuildID = aArgv[i + 1];
+    }
+  }
+
+  mVR.Init(ParentPid(), parentBuildID,
+           IOThreadChild::message_loop(),
+           IOThreadChild::channel());
+
+  return true;
+}
+
+void
+VRProcessChild::CleanUp()
+{
+  NS_ShutdownXPCOM(nullptr);
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRProcessChild.h
@@ -0,0 +1,43 @@
+/* -*- 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 GFX_VR_PROCESS_CHILD_H
+#define GFX_VR_PROCESS_CHILD_H
+
+#include "mozilla/ipc/ProcessChild.h"
+#include "VRParent.h"
+
+
+namespace mozilla {
+namespace gfx {
+
+/**
+ * Contains the VRChild object that facilitates IPC communication to/from
+ * the instance of the VR library that is run in this process.
+ */
+class VRProcessChild final : public mozilla::ipc::ProcessChild
+{
+protected:
+  typedef mozilla::ipc::ProcessChild ProcessChild;
+
+public:
+  explicit VRProcessChild(ProcessId aParentPid);
+  ~VRProcessChild();
+
+  // ProcessChild functions.
+  virtual bool Init(int aArgc, char* aArgv[]) override;
+  virtual void CleanUp() override;
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(VRProcessChild);
+
+  VRParent mVR;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* GFX_VR_PROCESS_CHILD_H */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRProcessManager.cpp
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRProcessManager.h"
+
+#include "VRProcessParent.h"
+#include "VRChild.h"
+#include "VRGPUChild.h"
+#include "VRGPUParent.h"
+
+
+namespace mozilla {
+namespace gfx {
+
+static StaticAutoPtr<VRProcessManager> sSingleton;
+
+/* static */ VRProcessManager*
+VRProcessManager::Get()
+{
+  return sSingleton;
+}
+
+/* static */ void
+VRProcessManager::Initialize()
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+  sSingleton = new VRProcessManager();
+}
+
+/* static */ void
+VRProcessManager::Shutdown()
+{
+  sSingleton = nullptr;
+}
+
+VRProcessManager::VRProcessManager()
+ : mProcess(nullptr)
+{
+  MOZ_COUNT_CTOR(VRProcessManager);
+
+  mObserver = new Observer(this);
+  nsContentUtils::RegisterShutdownObserver(mObserver);
+}
+
+VRProcessManager::~VRProcessManager()
+{
+  MOZ_COUNT_DTOR(VRProcessManager);
+
+  DestroyProcess();
+  // The VR process should have already been shut down.
+  MOZ_ASSERT(!mProcess);
+}
+
+void
+VRProcessManager::LaunchVRProcess()
+{
+  if (mProcess) {
+    return;
+  }
+
+  // The subprocess is launched asynchronously, so we wait for a callback to
+  // acquire the IPDL actor.
+  mProcess = new VRProcessParent();
+  if (!mProcess->Launch()) {
+    DisableVRProcess("Failed to launch VR process");
+  }
+}
+
+void
+VRProcessManager::DisableVRProcess(const char* aMessage)
+{
+  if (!gfxPrefs::VRProcessEnabled()) {
+    return;
+  }
+
+  DestroyProcess();
+}
+
+void
+VRProcessManager::DestroyProcess()
+{
+  if (!mProcess) {
+    return;
+  }
+
+  mProcess->Shutdown();
+  mProcess = nullptr;
+}
+
+bool
+VRProcessManager::CreateGPUBridges(base::ProcessId aOtherProcess,
+                                   mozilla::ipc::Endpoint<PVRGPUChild>* aOutVRBridge)
+{
+  if (!CreateGPUVRManager(aOtherProcess, aOutVRBridge)) {
+    return false;
+  }
+  return true;
+}
+
+bool
+VRProcessManager::CreateGPUVRManager(base::ProcessId aOtherProcess,
+                                     mozilla::ipc::Endpoint<PVRGPUChild>* aOutEndpoint)
+{
+  base::ProcessId vrparentPid = mProcess
+                                ? mProcess->OtherPid()  // VR process id.
+                                : base::GetCurrentProcId();
+
+  ipc::Endpoint<PVRGPUParent> vrparentPipe;
+  ipc::Endpoint<PVRGPUChild> vrchildPipe;
+  nsresult rv = PVRGPU::CreateEndpoints(vrparentPid,   // vr process id
+                                        aOtherProcess, // gpu process id
+                                        &vrparentPipe,
+                                        &vrchildPipe);
+
+  if (NS_FAILED(rv)) {
+	  gfxCriticalNote << "Could not create gpu-vr bridge: " << hexa(int(rv));
+	  return false;
+  }
+
+  // Bind vr-gpu pipe to VRParent and make a PVRGPU connection.
+  VRChild* vrChild = mProcess->GetActor();
+  vrChild->SendNewGPUVRManager(std::move(vrparentPipe));
+
+  *aOutEndpoint = std::move(vrchildPipe);
+  return true;
+}
+
+NS_IMPL_ISUPPORTS(VRProcessManager::Observer, nsIObserver);
+
+VRProcessManager::Observer::Observer(VRProcessManager* aManager)
+ : mManager(aManager)
+{
+}
+
+NS_IMETHODIMP
+VRProcessManager::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
+VRProcessManager::CleanShutdown()
+{
+  DestroyProcess();
+}
+
+void
+VRProcessManager::OnXPCOMShutdown()
+{
+  if (mObserver) {
+    nsContentUtils::UnregisterShutdownObserver(mObserver);
+    mObserver = nullptr;
+  }
+
+  CleanShutdown();
+}
+
+VRChild*
+VRProcessManager::GetVRChild()
+{
+  return mProcess->GetActor();
+}
+
+} // namespace gfx
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRProcessManager.h
@@ -0,0 +1,71 @@
+/* -*- 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 GFX_VR_PROCESS_MANAGER_H
+#define GFX_VR_PROCESS_MANAGER_H
+
+
+namespace mozilla {
+namespace gfx {
+
+class VRProcessParent;
+class VRManagerChild;
+class PVRGPUChild;
+class VRChild;
+
+// The VRProcessManager is a singleton responsible for creating VR-bound
+// objects that may live in another process.
+class VRProcessManager final
+{
+public:
+  static VRProcessManager* Get();
+  static void Initialize();
+  static void Shutdown();
+
+  ~VRProcessManager();
+
+  // If not using a VR process, launch a new VR process asynchronously.
+  void LaunchVRProcess();
+  void DestroyProcess();
+
+  bool CreateGPUBridges(base::ProcessId aOtherProcess,
+                        mozilla::ipc::Endpoint<PVRGPUChild>* aOutVRBridge);
+
+  VRChild* GetVRChild();
+
+private:
+  VRProcessManager();
+
+  DISALLOW_COPY_AND_ASSIGN(VRProcessManager);
+
+  bool CreateGPUVRManager(base::ProcessId aOtherProcess,
+                              mozilla::ipc::Endpoint<PVRGPUChild>* aOutEndpoint);
+  void OnXPCOMShutdown();
+  void CleanShutdown();
+
+  // Permanently disable the VR process and record a message why.
+  void DisableVRProcess(const char* aMessage);
+
+  class Observer final : public nsIObserver {
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIOBSERVER
+    explicit Observer(VRProcessManager* aManager);
+
+  protected:
+    ~Observer() {}
+
+    VRProcessManager* mManager;
+  };
+  friend class Observer;
+
+  RefPtr<Observer> mObserver;
+  VRProcessParent* mProcess;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // GFX_VR_PROCESS_MANAGER_H
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRProcessParent.cpp
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRProcessParent.h"
+#include "VRGPUChild.h"
+#include "VRProcessManager.h"
+#include "mozilla/gfx/GPUProcessManager.h"
+#include "mozilla/gfx/GPUChild.h"
+#include "mozilla/ipc/ProtocolTypes.h"
+#include "mozilla/ipc/ProtocolUtils.h"       // for IToplevelProtocol
+#include "mozilla/TimeStamp.h"               // for TimeStamp
+#include "mozilla/Unused.h"
+#include "VRChild.h"
+#include "VRManager.h"
+#include "VRThread.h"
+#include "gfxVRPuppet.h"
+
+#include "nsAppRunner.h"                  // for IToplevelProtocol
+#include "mozilla/ipc/ProtocolUtils.h"
+
+using std::vector;
+using std::string;
+
+using namespace mozilla::ipc;
+
+namespace mozilla {
+namespace gfx {
+
+VRProcessParent::VRProcessParent()
+  : GeckoChildProcessHost(GeckoProcessType_VR),
+    mTaskFactory(this),
+    mChannelClosed(false)
+{
+  MOZ_COUNT_CTOR(VRProcessParent);
+}
+
+VRProcessParent::~VRProcessParent()
+{
+  // Cancel all tasks. We don't want anything triggering after our caller
+  // expects this to go away.
+  {
+    MonitorAutoLock lock(mMonitor);
+    mTaskFactory.RevokeAll();
+  }
+  MOZ_COUNT_DTOR(VRProcessParent);
+}
+
+bool
+VRProcessParent::Launch()
+{
+  mLaunchThread = NS_GetCurrentThread();
+
+  std::vector<std::string> extraArgs;
+  nsCString parentBuildID(mozilla::PlatformBuildID());
+  extraArgs.push_back("-parentBuildID");
+  extraArgs.push_back(parentBuildID.get());
+
+  if (!GeckoChildProcessHost::AsyncLaunch(extraArgs)) {
+    return false;
+  }
+  return true;
+}
+
+void
+VRProcessParent::Shutdown()
+{
+  if (mVRChild) {
+    // The channel might already be closed if we got here unexpectedly.
+    if (!mChannelClosed) {
+      mVRChild->Close();
+    }
+
+#ifndef NS_FREE_PERMANENT_DATA
+    // No need to communicate shutdown, the VR process doesn't need to
+    // communicate anything back.
+    KillHard("NormalShutdown");
+#endif
+
+    // If we're shutting down unexpectedly, we're in the middle of handling an
+    // ActorDestroy for PGPUChild, which is still on the stack. We'll return
+    // back to OnChannelClosed.
+    //
+    // Otherwise, we'll wait for OnChannelClose to be called whenever PGPUChild
+    // acknowledges shutdown.
+    return;
+  }
+
+  DestroyProcess();
+}
+
+static void
+DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
+{
+  XRE_GetIOMessageLoop()->
+    PostTask(mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess));
+}
+
+
+void
+VRProcessParent::DestroyProcess()
+{
+  mLaunchThread->Dispatch(NewRunnableFunction("DestroyProcessRunnable", DelayedDeleteSubprocess, this));
+}
+
+void
+VRProcessParent::InitAfterConnect(bool aSucceeded)
+{
+  if (aSucceeded) {
+    mVRChild = MakeUnique<VRChild>(this);
+
+    DebugOnly<bool> rv =
+      mVRChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
+    MOZ_ASSERT(rv);
+
+    mVRChild->Init();
+
+    // Make vr-gpu process connection
+    GPUChild* gpuChild = GPUProcessManager::Get()->GetGPUChild();
+    MOZ_ASSERT(gpuChild);
+
+    Endpoint<PVRGPUChild> vrGPUBridge;
+    VRProcessManager* vpm = VRProcessManager::Get();
+    DebugOnly<bool> opened = vpm->CreateGPUBridges(gpuChild->OtherPid(), &vrGPUBridge);
+    MOZ_ASSERT(opened);
+
+    Unused << gpuChild->SendInitVR(std::move(vrGPUBridge));
+  }
+}
+
+void
+VRProcessParent::KillHard(const char* aReason)
+{
+  ProcessHandle handle = GetChildProcessHandle();
+  if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER, false)) {
+    NS_WARNING("failed to kill subprocess!");
+  }
+
+  SetAlreadyDead();
+}
+
+void
+VRProcessParent::OnChannelError()
+{
+  MOZ_ASSERT(false, "VR process channel error.");
+}
+
+void
+VRProcessParent::OnChannelConnected(int32_t peer_pid)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  GeckoChildProcessHost::OnChannelConnected(peer_pid);
+
+  // Post a task to the main thread. Take the lock because mTaskFactory is not
+  // thread-safe.
+  RefPtr<Runnable> runnable;
+  {
+    MonitorAutoLock lock(mMonitor);
+    runnable = mTaskFactory.NewRunnableMethod(&VRProcessParent::OnChannelConnectedTask);
+  }
+  NS_DispatchToMainThread(runnable);
+}
+
+void
+VRProcessParent::OnChannelConnectedTask()
+{
+  InitAfterConnect(true);
+}
+
+void
+VRProcessParent::OnChannelErrorTask()
+{
+  MOZ_ASSERT(false, "VR process channel error.");
+}
+
+void
+VRProcessParent::OnChannelClosed()
+{
+  mChannelClosed = true;
+  DestroyProcess();
+
+  // Release the actor.
+  VRChild::Destroy(std::move(mVRChild));
+  MOZ_ASSERT(!mVRChild);
+}
+
+base::ProcessId
+VRProcessParent::OtherPid()
+{
+  return mVRChild->OtherPid();
+}
+
+} // namespace gfx
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ipc/VRProcessParent.h
@@ -0,0 +1,57 @@
+/* -*- 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 GFX_VR_PROCESS_PARENT_H
+#define GFX_VR_PROCESS_PARENT_H
+
+#include "mozilla/UniquePtr.h"
+
+#include "mozilla/ipc/GeckoChildProcessHost.h"
+#include "mozilla/ipc/TaskFactory.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRChild;
+
+class VRProcessParent final : public mozilla::ipc::GeckoChildProcessHost
+{
+public:
+  explicit VRProcessParent();
+  ~VRProcessParent();
+
+  bool Launch();
+  void Shutdown();
+  void DestroyProcess();
+  bool CanShutdown() override { return true; }
+
+  void OnChannelError() override;
+  void OnChannelConnected(int32_t peer_pid) override;
+  void OnChannelConnectedTask();
+  void OnChannelErrorTask();
+  void OnChannelClosed();
+
+  base::ProcessId OtherPid();
+  VRChild* GetActor() const {
+    return mVRChild.get();
+  }
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(VRProcessParent);
+
+  void InitAfterConnect(bool aSucceeded);
+  void KillHard(const char* aReason);
+
+  UniquePtr<VRChild> mVRChild;
+  mozilla::ipc::TaskFactory<VRProcessParent> mTaskFactory;
+  nsCOMPtr<nsIThread> mLaunchThread;
+  bool mChannelClosed;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // ifndef GFX_VR_PROCESS_PARENT_H
\ No newline at end of file
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -2,38 +2,54 @@
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS += [
     'external_api/moz_external_vr.h',
     'gfxVR.h',
+    'gfxVRExternal.h',
+    'ipc/VRChild.h',
+    'ipc/VRGPUChild.h',
+    'ipc/VRGPUParent.h',
     'ipc/VRLayerChild.h',
     'ipc/VRManagerChild.h',
     'ipc/VRManagerParent.h',
     'ipc/VRMessageUtils.h',
+    'ipc/VRParent.h',
+    'ipc/VRProcessChild.h',
+    'ipc/VRProcessManager.h',
+    'ipc/VRProcessParent.h',
     'VRDisplayClient.h',
+    'VRDisplayHost.h',
     'VRDisplayPresentation.h',
     'VRManager.h',
     'VRThread.h',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/gfx/layers/d3d11',
     '/gfx/thebes',
 ]
 
 UNIFIED_SOURCES += [
     'gfxVR.cpp',
+    'ipc/VRChild.cpp',
+    'ipc/VRGPUChild.cpp',
+    'ipc/VRGPUParent.cpp',
     'ipc/VRLayerChild.cpp',
     'ipc/VRLayerParent.cpp',
     'ipc/VRManagerChild.cpp',
     'ipc/VRManagerParent.cpp',
+    'ipc/VRParent.cpp',
+    'ipc/VRProcessChild.cpp',
+    'ipc/VRProcessManager.cpp',
+    'ipc/VRProcessParent.cpp',
     'VRDisplayClient.cpp',
     'VRDisplayPresentation.cpp',
     'VRManager.cpp',
     'VRThread.cpp',
 ]
 
 if CONFIG['OS_TARGET'] != 'Android':
     UNIFIED_SOURCES += [
@@ -64,16 +80,18 @@ if CONFIG['OS_TARGET'] == 'WINNT':
     SOURCES += [
         'gfxVROculus.cpp',
     ]
 
 if CONFIG['OS_TARGET'] == 'Android':
     LOCAL_INCLUDES += ['/widget/android']
 
 IPDL_SOURCES = [
+    'ipc/PVR.ipdl',
+    'ipc/PVRGPU.ipdl',
     'ipc/PVRLayer.ipdl',
     'ipc/PVRManager.ipdl',
 ]
 
 # For building with the real SDK instead of our local hack
 #SOURCES += [
 #    'OVR_CAPI_Util.cpp',
 #    'OVR_CAPIShim.c',
--- a/gfx/vr/service/VRService.h
+++ b/gfx/vr/service/VRService.h
@@ -6,17 +6,16 @@
 
 #ifndef GFX_VR_SERVICE_VRSERVICE_H
 #define GFX_VR_SERVICE_VRSERVICE_H
 
 #include "mozilla/Atomics.h"
 
 #include "moz_external_vr.h"
 
-#include <thread>
 namespace base {
 class Thread;
 } // namespace base
 namespace mozilla {
 namespace gfx {
 
 class VRSession;