Bug 1430038 - (wip)Part 5: grefPref for VR process; draft
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 31 Jul 2018 14:31:41 -0700
changeset 824862 9508e15b61fbf39e89ad9ce087c63a23336b7b1e
parent 823606 ddb303a718a7847e11e2d85b4627a0ffdfc0c43a
push id118016
push userbmo:dmu@mozilla.com
push dateTue, 31 Jul 2018 21:33:10 +0000
bugs1430038
milestone63.0a1
Bug 1430038 - (wip)Part 5: grefPref for VR process; MozReview-Commit-ID: CLeVL7m5uXg
gfx/ipc/GraphicsMessages.ipdlh
gfx/ipc/PGPU.ipdl
gfx/thebes/gfxPrefs.cpp
gfx/vr/VRManager.cpp
gfx/vr/ipc/PVR.ipdl
gfx/vr/ipc/VRChild.cpp
gfx/vr/ipc/VRChild.h
gfx/vr/ipc/VRContentParent.cpp
gfx/vr/ipc/VRContentParent.h
gfx/vr/ipc/VRParent.cpp
gfx/vr/ipc/VRParent.h
gfx/vr/ipc/VRProcessChild.cpp
gfx/vr/ipc/VRProcessManager.cpp
gfx/vr/ipc/VRProcessManager.h
gfx/vr/ipc/VRProcessParent.cpp
toolkit/xre/nsAppRunner.cpp
xpcom/build/nsXULAppAPI.h
--- a/gfx/ipc/GraphicsMessages.ipdlh
+++ b/gfx/ipc/GraphicsMessages.ipdlh
@@ -10,16 +10,29 @@ using struct mozilla::null_t from "ipc/I
 using mozilla::gfx::FeatureStatus from "gfxTelemetry.h";
 using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
 using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
 using gfxImageFormat from "mozilla/gfx/Types.h";
 
 namespace mozilla {
 namespace gfx {
 
+union GfxPrefValue {
+  bool;
+  int32_t;
+  uint32_t;
+  float;
+  nsCString;
+};
+
+struct GfxPrefSetting {
+  int32_t index;
+  GfxPrefValue value;
+};
+
 struct D3D11DeviceStatus
 {
   bool isWARP;
   bool textureSharingWorks;
   uint32_t featureLevel;
   DxgiAdapterDesc adapter;
   int32_t sequenceNumber;
   bool useNV12;
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -25,29 +25,16 @@ using mozilla::Telemetry::ChildEventData
 using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
 using mozilla::gfx::Feature from "gfxFeature.h";
 using mozilla::gfx::Fallback from "gfxFallback.h";
 using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h";
 
 namespace mozilla {
 namespace gfx {
 
-union GfxPrefValue {
-  bool;
-  int32_t;
-  uint32_t;
-  float;
-  nsCString;
-};
-
-struct GfxPrefSetting {
-  int32_t index;
-  GfxPrefValue value;
-};
-
 struct LayerTreeIdMapping {
   LayersId layersId;
   ProcessId ownerId;
 };
 
 // This protocol allows the UI process to talk to the GPU process. There is one
 // instance of this protocol, with the GPUParent living on the main thread of
 // the GPU process and the GPUChild living on the main thread of the UI process.
--- a/gfx/thebes/gfxPrefs.cpp
+++ b/gfx/thebes/gfxPrefs.cpp
@@ -8,16 +8,18 @@
 #include "MainThreadUtils.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/gfx/GPUChild.h"
 #include "mozilla/gfx/GPUProcessManager.h"
+#include "VRProcessManager.h"
+#include "VRChild.h"
 
 using namespace mozilla;
 
 nsTArray<gfxPrefs::Pref*>* gfxPrefs::sGfxPrefList = nullptr;
 gfxPrefs* gfxPrefs::sInstance = nullptr;
 bool gfxPrefs::sInstanceHasBeenDestroyed = false;
 
 gfxPrefs&
@@ -87,16 +89,24 @@ gfxPrefs::Pref::OnChange()
 {
   if (auto gpm = gfx::GPUProcessManager::Get()) {
     if (gfx::GPUChild* gpu = gpm->GetGPUChild()) {
       GfxPrefValue value;
       GetLiveValue(&value);
       Unused << gpu->SendUpdatePref(gfx::GfxPrefSetting(mIndex, value));
     }
   }
+  if (auto vpm = gfx::VRProcessManager::Get()) {
+    if (gfx::VRChild* vr = vpm->GetVRChild()) {
+      GfxPrefValue value;
+      GetLiveValue(&value);
+      printf_stderr("gfxPrefs::VR::OnChange()... \n");
+      Unused << vr->SendUpdatePref(gfx::GfxPrefSetting(mIndex, value));
+    }
+  }
   FireChangeCallback();
 }
 
 void
 gfxPrefs::Pref::FireChangeCallback()
 {
   if (mChangeCallback) {
     GfxPrefValue value;
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -86,51 +86,54 @@ VRManager::VRManager()
   // if (gfxPrefs::VRProcessEnabled()) {
   //   ipc::Endpoint<PVRContentChild> vrContentBridge;
   //   VRProcessManager* vpm = VRProcessManager::Get();
   //   bool opened = vpm->CreateContentBridges(OtherId(), &vrContentBridge);
   //   MOZ_ASSERT(opened);
 
   //   Unused << SendInitVR(std::move(vrContentBridge));
   // }
-  if (!gfxPrefs::VRProcessEnabled()) {
+  //gfxPrefs::VRProcessEnabled()
+  if (XRE_IsVRProcess() && gfxPrefs::VRProcessEnabled()) {
     mVRService = VRService::Create();
     if (mVRService) {
       mExternalManager = VRSystemManagerExternal::Create(mVRService->GetAPIShmem());
     }
     if (mExternalManager) {
       mManagers.AppendElement(mExternalManager);
     }
   }
 #endif
 
-  if (!mExternalManager) {
+  // Test: mark it for testing
+  /*if (!mExternalManager) {
     mExternalManager = VRSystemManagerExternal::Create();
     if (mExternalManager) {
       mManagers.AppendElement(mExternalManager);
     }
-  }
+  }*/
 
 #if defined(XP_WIN)
   if (!mVRService) {
     // The Oculus runtime is supported only on Windows
     mgr = VRSystemManagerOculus::Create();
     if (mgr) {
       mManagers.AppendElement(mgr);
     }
   }
 #endif
 
 #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
   if (!mVRService) {
+    // Test: mark it for testing
     // OpenVR is cross platform compatible
-    mgr = VRSystemManagerOpenVR::Create();
-    if (mgr) {
-      mManagers.AppendElement(mgr);
-    }
+    // mgr = VRSystemManagerOpenVR::Create();
+    // if (mgr) {
+    //   mManagers.AppendElement(mgr);
+    // }
 
     // OSVR is cross platform compatible
     mgr = VRSystemManagerOSVR::Create();
     if (mgr) {
         mManagers.AppendElement(mgr);
     }
   } // !mVRService
 #endif
@@ -230,17 +233,17 @@ VRManager::UpdateRequestedDevices()
  * VRManager::NotifyVsync must be called on every 2d vsync (usually at 60hz).
  * This must be called even when no WebVR site is active.
  * If we don't have a 2d display attached to the system, we can call this
  * at the VR display's native refresh rate.
  **/
 void
 VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
 {
-  MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
+ // MOZ_ASSERT(VRListenerThreadHolder::IsInVRListenerThread());
   UpdateRequestedDevices();
 
   for (const auto& manager : mManagers) {
     manager->NotifyVSync();
   }
 
   // We must continually refresh the VR display enumeration to check
   // for events that we must fire such as Window.onvrdisplayconnect
--- a/gfx/vr/ipc/PVR.ipdl
+++ b/gfx/vr/ipc/PVR.ipdl
@@ -1,26 +1,28 @@
 /* -*- 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 class mozilla::TimeStamp from "mozilla/TimeStamp.h";
+using mozilla::TimeStamp from "mozilla/TimeStamp.h";
 
+include GraphicsMessages;
 include protocol PVRContent;
 
 namespace mozilla {
 namespace gfx {
 
 async protocol PVR
 {
-
 parent:
   async NewContentVRManager(Endpoint<PVRContentParent> endpoint);
-  async InitVRManager(Endpoint<PVRContentParent> endpoint);
-  async NotifyVsync(TimeStamp vsyncTimeStamp);
+  async Init(GfxPrefSetting[] prefs);
+  async NotifyVsync(TimeStamp aVsyncTimestamp);
+
+  async UpdatePref(GfxPrefSetting pref);
 
 child:
   async ObserveVsync();
 };
 
 } // namespace gfx
 } // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/ipc/VRChild.cpp
+++ b/gfx/vr/ipc/VRChild.cpp
@@ -26,16 +26,39 @@ VRChild::VRChild(VRProcessParent* aHost,
 
 void
 VRChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   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));
+  }
+
+  SendInit(prefs);
+}
+
 mozilla::ipc::IPCResult
 VRChild::RecvObserveVsync()
 {
   // Setup vsync observe.
   mVsyncDispatcher->SetVRVsyncObserver(mVsyncObserver);
   return IPC_OK();
 }
 
--- a/gfx/vr/ipc/VRChild.h
+++ b/gfx/vr/ipc/VRChild.h
@@ -40,16 +40,17 @@ class VRChild final : public PVRChild {
 
 public:
   explicit VRChild(VRProcessParent* aHost,
                    RefPtr<VRVsyncDispatcher> aVsyncDispatcher,
                    RefPtr<VRVsyncObserver> aVsyncObserver);
   ~VRChild() = default;
 
   static void Destroy(UniquePtr<VRChild>&& aChild);
+  void Init();
 
 protected:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   virtual mozilla::ipc::IPCResult RecvObserveVsync() override;
 
 private:
   VRProcessParent* mHost;
   RefPtr<VRVsyncDispatcher> mVsyncDispatcher;
--- a/gfx/vr/ipc/VRContentParent.cpp
+++ b/gfx/vr/ipc/VRContentParent.cpp
@@ -57,24 +57,24 @@ VRContentParent::Bind(Endpoint<PVRConten
 {
   if (!aEndpoint.Bind(this)) {
     return;
   }
 
   mSelfRef = this;
 }
 
-bool
-VRContentParent::CreateForVRProcess(Endpoint<PVRContentParent>&& aEndpoint)
-{
-  RefPtr<VRContentParent> vcp = new VRContentParent(aEndpoint.OtherPid());
-  MessageLoop::current()->PostTask(
-    NewRunnableMethod<Endpoint<PVRContentParent>&&>(
-    "gfx::VRContentParent::Bind",
-    vcp,
-    &VRContentParent::Bind,
-    std::move(aEndpoint)));
+// bool
+// VRContentParent::CreateForVRProcess(Endpoint<PVRContentParent>&& aEndpoint)
+// {
+//   RefPtr<VRContentParent> vcp = new VRContentParent(aEndpoint.OtherPid());
+//   MessageLoop::current()->PostTask(
+//     NewRunnableMethod<Endpoint<PVRContentParent>&&>(
+//     "gfx::VRContentParent::Bind",
+//     vcp,
+//     &VRContentParent::Bind,
+//     std::move(aEndpoint)));
 
-  return true;
-}
+//   return true;
+// }
 
 } // namespace gfx
 } // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/ipc/VRContentParent.h
+++ b/gfx/vr/ipc/VRContentParent.h
@@ -15,24 +15,24 @@ namespace gfx {
 class VRContentParent final : public PVRContentParent {
    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRContentParent)
 
 public:
   explicit VRContentParent(ProcessId aChildProcessId);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
-  static bool CreateForVRProcess(Endpoint<PVRContentParent>&& aEndpoint);
+ // static bool CreateForVRProcess(Endpoint<PVRContentParent>&& aEndpoint);
   static bool CreateForContent(Endpoint<PVRContentParent>&& aEndpoint);
 
 protected:
   ~VRContentParent() {}
 
   // Test: To confirm the ipc channel works
-  virtual mozilla::ipc::IPCResult RecvSend() override { printf_stderr("rrrrrrrrrrrrr");
+  virtual mozilla::ipc::IPCResult RecvSend() override {
     this->SendReply();
     return IPC_OK();
   }
 
   void Bind(Endpoint<PVRContentParent>&& aEndpoint);
 
 private:
   void DeferredDestroy();
--- a/gfx/vr/ipc/VRParent.cpp
+++ b/gfx/vr/ipc/VRParent.cpp
@@ -1,17 +1,20 @@
 /* -*- 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 "VRContentParent.h"
+#include "VRManager.h"
+#include "gfxConfig.h"
 
+#include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ipc/ProcessChild.h"
 
 
 namespace mozilla {
 namespace gfx {
 
 using namespace ipc;
 
@@ -24,28 +27,58 @@ mozilla::ipc::IPCResult
 VRParent::RecvNewContentVRManager(Endpoint<PVRContentParent>&& aEndpoint)
 {
   if (!VRContentParent::CreateForContent(std::move(aEndpoint))) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
+// mozilla::ipc::IPCResult
+// VRParent::RecvInitVRManager(nsTArray<GfxPrefSetting>&& prefs,
+//                             Endpoint<PVRContentParent>&& aEndpoint)
+// {
+//   const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
+//   for (auto& setting : prefs) {
+//     gfxPrefs::Pref* pref = globalPrefs[setting.index()];
+//     pref->SetCachedValue(setting.value());
+//   }
+
+//   VRContentParent::CreateForVRProcess(std::move(aEndpoint));
+//   return IPC_OK();
+// }
+
 mozilla::ipc::IPCResult
-VRParent::RecvInitVRManager(Endpoint<PVRContentParent>&& aEndpoint)
+VRParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs)
 {
-  VRContentParent::CreateForVRProcess(std::move(aEndpoint));
+  const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
+  for (auto& setting : prefs) {
+    gfxPrefs::Pref* pref = globalPrefs[setting.index()];
+    pref->SetCachedValue(setting.value());
+  }
+
+  VRManager::ManagerInit();
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-VRParent::RecvNotifyVsync(const TimeStamp& aVsyncTimeStamp)
+VRParent::RecvNotifyVsync(const TimeStamp& aVsyncTimestamp)
 {
-  TimeStamp test = aVsyncTimeStamp;
- // MOZ_ASSERT(false);
+  VRManager* vm = VRManager::Get();
+  vm->NotifyVsync(aVsyncTimestamp);
+  
+  bool b =  gfxPrefs::VRProcessEnabled();
+  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();
 }
 
 void
 VRParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (AbnormalShutdown == aWhy) {
     NS_WARNING("Shutting down VR process early due to a crash!");
@@ -56,32 +89,53 @@ VRParent::ActorDestroy(ActorDestroyReaso
 }
 
 bool
 VRParent::Init(base::ProcessId aParentPid,
                const char* aParentBuildID,
                MessageLoop* aIOLoop,
                IPC::Channel* aChannel)
 {
-   // Now it's safe to start IPC.
+  // 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.
+  printf_stderr("ensure gfxpref().");
   gfxPrefs::GetSingleton();
+  // gfxConfig::Init(); //
+  // gfxVars::Initialize(); //
+
+ // bool s = gfxPrefs::SingletonExists();
+ // printf_stderr("end ensure gfxpref(). %d\n", s);
+ // printf_stderr("VRProcessEnabled gfxpref(). %d\n", gfxPrefs::VRProcessEnabled());
+  
+// #if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
+//   // Create VR service.
+//   mVRService = VRService::Create();
+//   if (mVRService) {
+//     mExternalManager = VRSystemManagerExternal::Create(mVRService->GetAPIShmem());
+//   }
+//   // if (mExternalManager) {
+//   //   mManagers.AppendElement(mExternalManager);
+//   // }
+// #endif // defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
 
   // Sending reply msg to the parent process.
   SendObserveVsync();
+
+  printf_stderr("VRParent::Init.....\n");
   return true;
 }
 
 } // namespace gfx
 } // namespace mozilla
\ No newline at end of file
--- a/gfx/vr/ipc/VRParent.h
+++ b/gfx/vr/ipc/VRParent.h
@@ -8,33 +8,40 @@
 #define GFX_VR_PARENT_H
 
 #include "mozilla/gfx/PVRParent.h"
 
 namespace mozilla {
 namespace gfx {
 
 class VRContentParent;
+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 RecvNewContentVRManager(Endpoint<PVRContentParent>&& aEndpoint) override;
-  virtual mozilla::ipc::IPCResult RecvInitVRManager(Endpoint<PVRContentParent>&& aEndpoint) override;
-  virtual mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& aVsyncTimeStamp) override;
+  virtual mozilla::ipc::IPCResult RecvInit(nsTArray<GfxPrefSetting>&& prefs) override;
+  virtual mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& aVsyncTimestamp) override;
+  virtual mozilla::ipc::IPCResult RecvUpdatePref(const GfxPrefSetting& setting) override;
 
 private:
   VRContentParent* mVRContent;
-
+  
+  RefPtr<VRSystemManagerExternal> mExternalManager;
+#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_PARENT_H
\ No newline at end of file
--- a/gfx/vr/ipc/VRProcessChild.cpp
+++ b/gfx/vr/ipc/VRProcessChild.cpp
@@ -11,18 +11,16 @@
 #include "mozilla/sandboxTarget.h"
 #endif
 
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using mozilla::ipc::IOThreadChild;
 
-// We need to a scheduler to notify its self.
-
 
 VRProcessChild::VRProcessChild(ProcessId aParentPid)
   : ProcessChild(aParentPid)
 #if defined(aParentPid)
   , mVR(nullptr)
 #endif
 {
 }
@@ -45,27 +43,16 @@ VRProcessChild::Init(int aArgc, char* aA
       parentBuildID = aArgv[i + 1];
     }
   }
 
   mVR.Init(ParentPid(), parentBuildID,
            IOThreadChild::message_loop(),
            IOThreadChild::channel());
 
-#if defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
-  // Create VR service.
-  mVRService = VRService::Create();
-  if (mVRService) {
-    mExternalManager = VRSystemManagerExternal::Create(mVRService->GetAPIShmem());
-  }
-  // if (mExternalManager) {
-  //   mManagers.AppendElement(mExternalManager);
-  // }
-#endif // defined(XP_WIN) || defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID))
-
   return true;
 }
 
 void
 VRProcessChild::CleanUp()
 {
   NS_ShutdownXPCOM(nullptr);
 }
\ No newline at end of file
--- a/gfx/vr/ipc/VRProcessManager.cpp
+++ b/gfx/vr/ipc/VRProcessManager.cpp
@@ -159,10 +159,16 @@ 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
--- a/gfx/vr/ipc/VRProcessManager.h
+++ b/gfx/vr/ipc/VRProcessManager.h
@@ -9,16 +9,17 @@
 
 namespace mozilla {
 namespace gfx {
 
 class VRProcessParent;
 class VRManagerChild;
 class VRContentChild;
 class PVRContentChild;
+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();
@@ -28,17 +29,17 @@ public:
 
   // If not using a VR process, launch a new VR process asynchronously.
   void LaunchVRProcess();
   void DestroyProcess();
 
   bool CreateContentBridges(base::ProcessId aOtherProcess,
                             mozilla::ipc::Endpoint<PVRContentChild>* aOutVRBridge);
 
-  VRProcessParent* mProcess;
+  VRChild* GetVRChild();
 
 private:
   VRProcessManager();
 
   bool CreateContentVRManager(base::ProcessId aOtherProcess,
                               mozilla::ipc::Endpoint<PVRContentChild>* aOutEndpoint);
   void OnXPCOMShutdown();
   void CleanShutdown();
@@ -56,14 +57,15 @@ private:
   protected:
     ~Observer() {}
 
     VRProcessManager* mManager;
   };
   friend class Observer;
 
   RefPtr<Observer> mObserver;
+  VRProcessParent* mProcess;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // GFX_VR_PROCESS_MANAGER_H
--- a/gfx/vr/ipc/VRProcessParent.cpp
+++ b/gfx/vr/ipc/VRProcessParent.cpp
@@ -139,16 +139,18 @@ VRProcessParent::InitAfterConnect(bool a
     RefPtr<VRVsyncDispatcher> dispatcher = new VRVsyncDispatcher(); //aWidget->GetVRVsyncDispatcher();
     RefPtr<VRVsyncObserver> observer = new VRVsyncObserver();
     
     mVRChild = MakeUnique<VRChild>(this, dispatcher, observer);
 
     DebugOnly<bool> rv =
       mVRChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
     MOZ_ASSERT(rv);
+
+    mVRChild->Init();
   }
 }
 
 void
 VRProcessParent::KillHard(const char* aReason)
 {
   ProcessHandle handle = GetChildProcessHandle();
   if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER, false)) {
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -5093,16 +5093,22 @@ XRE_GetProcessType()
 }
 
 bool
 XRE_IsGPUProcess()
 {
   return XRE_GetProcessType() == GeckoProcessType_GPU;
 }
 
+bool
+XRE_IsVRProcess()
+{
+  return XRE_GetProcessType() == GeckoProcessType_VR;
+}
+
 /**
  * Returns true in the e10s parent process and in the main process when e10s
  * is disabled.
  */
 bool
 XRE_IsParentProcess()
 {
   return XRE_GetProcessType() == GeckoProcessType_Default;
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -462,16 +462,19 @@ XRE_API(bool,
 
 XRE_API(bool,
         XRE_IsContentProcess, ())
 
 XRE_API(bool,
         XRE_IsGPUProcess, ())
 
 XRE_API(bool,
+        XRE_IsVRProcess, ())
+
+XRE_API(bool,
         XRE_IsPluginProcess, ())
 
 /**
  * Returns true if the appshell should run its own native event loop. Returns
  * false if we should rely solely on the Gecko event loop.
  */
 XRE_API(bool,
         XRE_UseNativeEventProcessing, ())