Bug 1430038 - Part 2: launch VR process and communicate with GPU process; r?kip, jimm draft
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 07 Aug 2018 11:20:34 -0700
changeset 827382 401b81d450ba648d982b8e433834e5f728bd8803
parent 827381 a482d83c6702316ded19add6eb8a2c55857425d1
child 827383 31128466ace0b3cbc76c09530db66f6c429c3455
child 830256 2a78cd6b8f86f9ef9fc106df415ce20c431de943
push id118524
push userbmo:dmu@mozilla.com
push dateTue, 07 Aug 2018 23:12:13 +0000
reviewerskip, jimm
bugs1430038
milestone63.0a1
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
@@ -465,17 +465,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;