Bug 1332989 - Using VRSystemManager to manage vr displays and controllers; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 24 Jan 2017 17:49:11 +0800
changeset 466078 b920a35cb14558f2f2db99fcdcec06b156e091a3
parent 464990 5a4412474c63e1d9e66036d603ac42e9cb2b9150
child 543311 a2bb0b5f91d165c2fefef8f4b0521649712a32bf
push id42781
push userbmo:dmu@mozilla.com
push dateWed, 25 Jan 2017 07:00:28 +0000
reviewerskip
bugs1332989
milestone54.0a1
Bug 1332989 - Using VRSystemManager to manage vr displays and controllers; r?kip MozReview-Commit-ID: 7M1ihvCpU9g
gfx/vr/VRDisplayHost.cpp
gfx/vr/VRManager.cpp
gfx/vr/VRManager.h
gfx/vr/gfxVR.cpp
gfx/vr/gfxVR.h
gfx/vr/gfxVROSVR.cpp
gfx/vr/gfxVROSVR.h
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
gfx/vr/gfxVROpenVR.cpp
gfx/vr/gfxVROpenVR.h
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -19,17 +19,17 @@ using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 VRDisplayHost::VRDisplayHost(VRDeviceType aType)
   : mInputFrameID(0)
 {
   MOZ_COUNT_CTOR(VRDisplayHost);
   mDisplayInfo.mType = aType;
-  mDisplayInfo.mDisplayID = VRDisplayManager::AllocateDisplayID();
+  mDisplayInfo.mDisplayID = VRSystemManager::AllocateDisplayID();
   mDisplayInfo.mIsPresenting = false;
 
   for (int i = 0; i < kMaxLatencyFrames; i++) {
     mLastSensorState[i].Clear();
   }
 }
 
 VRDisplayHost::~VRDisplayHost()
@@ -144,17 +144,17 @@ VRDisplayHost::CheckClearDisplayInfoDirt
   mLastUpdateDisplayInfo = mDisplayInfo;
   return true;
 }
 
 VRControllerHost::VRControllerHost(VRDeviceType aType)
 {
   MOZ_COUNT_CTOR(VRControllerHost);
   mControllerInfo.mType = aType;
-  mControllerInfo.mControllerID = VRDisplayManager::AllocateDisplayID();
+  mControllerInfo.mControllerID = VRSystemManager::AllocateDisplayID();
 }
 
 VRControllerHost::~VRControllerHost()
 {
   MOZ_COUNT_DTOR(VRControllerHost);
 }
 
 const VRControllerInfo&
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -46,18 +46,17 @@ VRManager::ManagerInit()
 }
 
 VRManager::VRManager()
   : mInitialized(false)
 {
   MOZ_COUNT_CTOR(VRManager);
   MOZ_ASSERT(sVRManagerSingleton == nullptr);
 
-  RefPtr<VRDisplayManager> mgr;
-  RefPtr<VRControllerManager> controllerMgr;
+  RefPtr<VRSystemManager> mgr;
 
   /**
    * We must add the VRDisplayManager's to mManagers in a careful order to
    * ensure that we don't detect the same VRDisplay from multiple API's.
    *
    * Oculus comes first, as it will only enumerate Oculus HMD's and is the
    * native interface for Oculus HMD's.
    *
@@ -65,35 +64,31 @@ VRManager::VRManager()
    * which is the most common HMD at this time.
    *
    * OSVR will be used if Oculus SDK and OpenVR don't detect any HMDS,
    * to support everyone else.
    */
 
 #if defined(XP_WIN)
   // The Oculus runtime is supported only on Windows
-  mgr = VRDisplayManagerOculus::Create();
+  mgr = VRSystemManagerOculus::Create();
   if (mgr) {
     mManagers.AppendElement(mgr);
   }
 #endif
 
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
   // OpenVR is cross platform compatible
-  mgr = VRDisplayManagerOpenVR::Create();
+  mgr = VRSystemManagerOpenVR::Create();
   if (mgr) {
     mManagers.AppendElement(mgr);
-    controllerMgr = VRControllerManagerOpenVR::Create();
-    if (controllerMgr) {
-      mControllerManagers.AppendElement(controllerMgr);
-    }
   }
 
   // OSVR is cross platform compatible
-  mgr = VRDisplayManagerOSVR::Create();
+  mgr = VRSystemManagerOSVR::Create();
   if (mgr) {
       mManagers.AppendElement(mgr);
   }
 #endif
   // Enable gamepad extensions while VR is enabled.
   // Preference only can be set at the Parent process.
   if (XRE_IsParentProcess() && gfxPrefs::VREnabled()) {
     Preferences::SetBool("dom.gamepad.extensions.enabled", true);
@@ -106,37 +101,31 @@ VRManager::~VRManager()
   MOZ_ASSERT(!mInitialized);
   MOZ_COUNT_DTOR(VRManager);
 }
 
 void
 VRManager::Destroy()
 {
   mVRDisplays.Clear();
+  mVRControllers.Clear();
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->Destroy();
   }
 
-  mVRControllers.Clear();
-  for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
-    mControllerManagers[i]->Destroy();
-  }
   mInitialized = false;
 }
 
 void
 VRManager::Init()
 {
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->Init();
   }
 
-  for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
-    mControllerManagers[i]->Init();
-  }
   mInitialized = true;
 }
 
 /* static */VRManager*
 VRManager::Get()
 {
   MOZ_ASSERT(sVRManagerSingleton != nullptr);
 
@@ -204,18 +193,18 @@ VRManager::NotifyVsync(const TimeStamp& 
       }
     }
   }
 }
 
 void
 VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
 {
-  for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
-    mControllerManagers[i]->HandleInput();
+  for (uint32_t i = 0; i < mManagers.Length(); ++i) {
+    mManagers[i]->HandleInput();
   }
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     Unused << iter.Get()->GetKey()->SendNotifyVRVSync(aDisplayID);
   }
 }
 
 void
 VRManager::RefreshVRDisplays(bool aMustDispatch)
@@ -338,19 +327,19 @@ VRManager::GetVRControllerInfo(nsTArray<
 
 void
 VRManager::RefreshVRControllers()
 {
   nsTArray<RefPtr<gfx::VRControllerHost>> controllers;
 
   ScanForControllers();
 
-  for (uint32_t i = 0; i < mControllerManagers.Length()
+  for (uint32_t i = 0; i < mManagers.Length()
       && controllers.Length() == 0; ++i) {
-    mControllerManagers[i]->GetControllers(controllers);
+    mManagers[i]->GetControllers(controllers);
   }
 
   bool controllerInfoChanged = false;
 
   if (controllers.Length() != mVRControllers.Count()) {
     // Catch cases where VR controllers has been removed
     controllerInfoChanged = true;
   }
@@ -370,26 +359,26 @@ VRManager::RefreshVRControllers()
                          controller);
     }
   }
 }
 
 void
 VRManager::ScanForControllers()
 {
-  for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
-    mControllerManagers[i]->ScanForDevices();
+  for (uint32_t i = 0; i < mManagers.Length(); ++i) {
+    mManagers[i]->ScanForControllers();
   }
 }
 
 void
 VRManager::RemoveControllers()
 {
-  for (uint32_t i = 0; i < mControllerManagers.Length(); ++i) {
-    mControllerManagers[i]->RemoveDevices();
+  for (uint32_t i = 0; i < mManagers.Length(); ++i) {
+    mManagers[i]->RemoveControllers();
   }
   mVRControllers.Clear();
 }
 
 template<class T>
 void
 VRManager::NotifyGamepadChange(const T& aInfo)
 {
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -17,17 +17,16 @@ namespace mozilla {
 namespace layers {
 class TextureHost;
 }
 namespace gfx {
 
 class VRLayerParent;
 class VRManagerParent;
 class VRDisplayHost;
-class VRControllerManager;
 
 class VRManager
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::gfx::VRManager)
 
 public:
   static void ManagerInit();
   static VRManager* Get();
@@ -61,21 +60,18 @@ private:
   void Destroy();
 
   void DispatchVRDisplayInfoUpdate();
   void RefreshVRControllers();
 
   typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
   VRManagerParentSet mVRManagerParents;
 
-  typedef nsTArray<RefPtr<VRDisplayManager>> VRDisplayManagerArray;
-  VRDisplayManagerArray mManagers;
-
-  typedef nsTArray<RefPtr<VRControllerManager>> VRControllerManagerArray;
-  VRControllerManagerArray mControllerManagers;
+  typedef nsTArray<RefPtr<VRSystemManager>> VRSystemManagerArray;
+  VRSystemManagerArray mManagers;
 
   typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRDisplayHost> VRDisplayHostHashMap;
   VRDisplayHostHashMap mVRDisplays;
 
   typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRControllerHost> VRControllerHostHashMap;
   VRControllerHostHashMap mVRControllers;
 
   Atomic<bool> mInitialized;
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -11,21 +11,20 @@
 
 #ifndef M_PI
 # define M_PI 3.14159265358979323846
 #endif
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
-Atomic<uint32_t> VRDisplayManager::sDisplayBase(0);
-Atomic<uint32_t> VRControllerManager::sControllerBase(0);
+Atomic<uint32_t> VRSystemManager::sDisplayBase(0);
 
 /* static */ uint32_t
-VRDisplayManager::AllocateDisplayID()
+VRSystemManager::AllocateDisplayID()
 {
   return ++sDisplayBase;
 }
 
 Matrix4x4
 VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
                                          bool rightHanded) const
 {
@@ -54,72 +53,66 @@ VRFieldOfView::ConstructProjectionMatrix
   m[3*4+2] = (zFar * zNear) / (zNear - zFar);
 
   m[2*4+3] = handednessScale;
   m[3*4+3] = 0.0f;
 
   return mobj;
 }
 
-/* static */ uint32_t
-VRControllerManager::AllocateControllerID()
-{
-  return ++sControllerBase;
-}
-
 void
-VRControllerManager::AddGamepad(const char* aID, dom::GamepadMappingType aMapping,
-                                dom::GamepadHand aHand, uint32_t aNumButtons, uint32_t aNumAxes)
+VRSystemManager::AddGamepad(const char* aID, dom::GamepadMappingType aMapping,
+                            dom::GamepadHand aHand, uint32_t aNumButtons, uint32_t aNumAxes)
 {
   dom::GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), mControllerCount,
                      aMapping, aHand, dom::GamepadServiceType::VR, aNumButtons,
                      aNumAxes);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
   vm->NotifyGamepadChange<dom::GamepadAdded>(a);
 }
 
 void
-VRControllerManager::RemoveGamepad(uint32_t aIndex)
+VRSystemManager::RemoveGamepad(uint32_t aIndex)
 {
   dom::GamepadRemoved a(aIndex, dom::GamepadServiceType::VR);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
   vm->NotifyGamepadChange<dom::GamepadRemoved>(a);
 }
 
 void
-VRControllerManager::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
-                                    bool aPressed)
+VRSystemManager::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
+                                bool aPressed)
 {
   dom::GamepadButtonInformation a(aIndex, dom::GamepadServiceType::VR,
                                   aButton, aPressed, aPressed ? 1.0L : 0.0L);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
   vm->NotifyGamepadChange<dom::GamepadButtonInformation>(a);
 }
 
 void
-VRControllerManager::NewAxisMove(uint32_t aIndex, uint32_t aAxis,
-                                 double aValue)
+VRSystemManager::NewAxisMove(uint32_t aIndex, uint32_t aAxis,
+                             double aValue)
 {
   dom::GamepadAxisInformation a(aIndex, dom::GamepadServiceType::VR,
                                 aAxis, aValue);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
   vm->NotifyGamepadChange<dom::GamepadAxisInformation>(a);
 }
 
 void
-VRControllerManager::NewPoseState(uint32_t aIndex,
-                                  const dom::GamepadPoseState& aPose)
+VRSystemManager::NewPoseState(uint32_t aIndex,
+                              const dom::GamepadPoseState& aPose)
 {
   dom::GamepadPoseInformation a(aIndex, dom::GamepadServiceType::VR,
                                 aPose);
 
   VRManager* vm = VRManager::Get();
   MOZ_ASSERT(vm);
   vm->NotifyGamepadChange<dom::GamepadPoseInformation>(a);
 }
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -191,33 +191,54 @@ struct VRHMDSensorState {
   float linearVelocity[3];
   float linearAcceleration[3];
 
   void Clear() {
     memset(this, 0, sizeof(VRHMDSensorState));
   }
 };
 
-class VRDisplayManager {
+class VRSystemManager {
 public:
   static uint32_t AllocateDisplayID();
 
 protected:
   static Atomic<uint32_t> sDisplayBase;
 
 public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayManager)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRSystemManager)
 
   virtual bool Init() = 0;
   virtual void Destroy() = 0;
   virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) = 0;
+  virtual void HandleInput() = 0;
+  virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
+  virtual void ScanForControllers() = 0;
+  virtual void RemoveControllers() = 0;
+  void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
+  void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
+  void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
+  void AddGamepad(const char* aID, dom::GamepadMappingType aMapping,
+                  dom::GamepadHand aHand, uint32_t aNumButtons, uint32_t aNumAxes);
+  void RemoveGamepad(uint32_t aIndex);
 
 protected:
-  VRDisplayManager() { }
-  virtual ~VRDisplayManager() { }
+  VRSystemManager() : mControllerCount(0) { }
+  virtual ~VRSystemManager() { }
+
+  uint32_t mControllerCount;
+
+private:
+  virtual void HandleButtonPress(uint32_t aControllerIdx,
+                                 uint64_t aButtonPressed) = 0;
+  virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                              float aValue) = 0;
+  virtual void HandlePoseTracking(uint32_t aControllerIdx,
+                                  const dom::GamepadPoseState& aPose,
+                                  VRControllerHost* aController) = 0;
 };
 
 struct VRControllerInfo
 {
   VRDeviceType GetType() const { return mType; }
   uint32_t GetControllerID() const { return mControllerID; }
   const nsCString& GetControllerName() const { return mControllerName; }
   dom::GamepadMappingType GetMappingType() const { return mMappingType; }
@@ -240,48 +261,12 @@ struct VRControllerInfo
            mNumAxes == other.mNumAxes;
   }
 
   bool operator!=(const VRControllerInfo& other) const {
     return !(*this == other);
   }
 };
 
-class VRControllerManager {
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRControllerManager)
-
-  static uint32_t AllocateControllerID();
-  virtual bool Init() = 0;
-  virtual void Destroy() = 0;
-  virtual void HandleInput() = 0;
-  virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
-  virtual void ScanForDevices() = 0;
-  virtual void RemoveDevices() = 0;
-  void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
-  void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
-  void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
-  void AddGamepad(const char* aID, dom::GamepadMappingType aMapping,
-                  dom::GamepadHand aHand, uint32_t aNumButtons, uint32_t aNumAxes);
-  void RemoveGamepad(uint32_t aIndex);
-
-protected:
-  VRControllerManager() : mInstalled(false), mControllerCount(0) {}
-  virtual ~VRControllerManager() {}
-
-  bool mInstalled;
-  uint32_t mControllerCount;
-  static Atomic<uint32_t> sControllerBase;
-
-private:
-  virtual void HandleButtonPress(uint32_t aControllerIdx,
-                                 uint64_t aButtonPressed) = 0;
-  virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
-                              float aValue) = 0;
-  virtual void HandlePoseTracking(uint32_t aControllerIdx,
-                                  const dom::GamepadPoseState& aPose,
-                                  VRControllerHost* aController) = 0;
-};
-
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* GFX_VR_H */
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -16,23 +16,27 @@
 
 #ifdef XP_WIN
 #include "../layers/d3d11/CompositorD3D11.h"
 #include "../layers/d3d11/TextureD3D11.h"
 #endif
 
 #include "gfxVROSVR.h"
 
+#include "mozilla/dom/GamepadEventTypes.h"
+#include "mozilla/dom/GamepadBinding.h"
+
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
 #endif
 
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 using namespace mozilla::gfx::impl;
+using namespace mozilla::dom;
 
 namespace {
 // need to typedef functions that will be used in the code below
 extern "C" {
 typedef OSVR_ClientContext (*pfn_osvrClientInit)(
   const char applicationIdentifier[], uint32_t flags);
 typedef OSVR_ReturnCode (*pfn_osvrClientShutdown)(OSVR_ClientContext ctx);
 typedef OSVR_ReturnCode (*pfn_osvrClientUpdate)(OSVR_ClientContext ctx);
@@ -344,33 +348,33 @@ VRDisplayOSVR::StartPresentation()
 }
 
 void
 VRDisplayOSVR::StopPresentation()
 {
   // XXX Add code to end VR Presentation
 }
 
-already_AddRefed<VRDisplayManagerOSVR>
-VRDisplayManagerOSVR::Create()
+already_AddRefed<VRSystemManagerOSVR>
+VRSystemManagerOSVR::Create()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gfxPrefs::VREnabled() || !gfxPrefs::VROSVREnabled()) {
     return nullptr;
   }
   if (!LoadOSVRRuntime()) {
     return nullptr;
   }
-  RefPtr<VRDisplayManagerOSVR> manager = new VRDisplayManagerOSVR();
+  RefPtr<VRSystemManagerOSVR> manager = new VRSystemManagerOSVR();
   return manager.forget();
 }
 
 void
-VRDisplayManagerOSVR::CheckOSVRStatus()
+VRSystemManagerOSVR::CheckOSVRStatus()
 {
   if (mOSVRInitialized) {
     return;
   }
 
   // client context must be initialized first
   InitializeClientContext();
 
@@ -384,17 +388,17 @@ VRDisplayManagerOSVR::CheckOSVRStatus()
   // OSVR is fully initialized now
   if (mClientContextInitialized && mDisplayConfigInitialized &&
       mInterfaceInitialized) {
     mOSVRInitialized = true;
   }
 }
 
 void
-VRDisplayManagerOSVR::InitializeClientContext()
+VRSystemManagerOSVR::InitializeClientContext()
 {
   // already initialized
   if (mClientContextInitialized) {
     return;
   }
 
   // first time creating
   if (!m_ctx) {
@@ -413,34 +417,34 @@ VRDisplayManagerOSVR::InitializeClientCo
     osvr_ClientUpdate(m_ctx);
     if (OSVR_RETURN_SUCCESS == osvr_ClientCheckStatus(m_ctx)) {
       mClientContextInitialized = true;
     }
   }
 }
 
 void
-VRDisplayManagerOSVR::InitializeInterface()
+VRSystemManagerOSVR::InitializeInterface()
 {
   // already initialized
   if (mInterfaceInitialized) {
     return;
   }
   //Client context must be initialized before getting interface
   if (mClientContextInitialized) {
     // m_iface will remain nullptr if no interface is returned
     if (OSVR_RETURN_SUCCESS ==
         osvr_ClientGetInterface(m_ctx, "/me/head", &m_iface)) {
       mInterfaceInitialized = true;
     }
   }
 }
 
 void
-VRDisplayManagerOSVR::InitializeDisplay()
+VRSystemManagerOSVR::InitializeDisplay()
 {
   // display is fully configured
   if (mDisplayConfigInitialized) {
     return;
   }
 
   //Client context must be initialized before getting interface
   if (mClientContextInitialized) {
@@ -465,17 +469,17 @@ VRDisplayManagerOSVR::InitializeDisplay(
       if (OSVR_RETURN_SUCCESS == osvr_ClientCheckDisplayStartup(m_display)) {
         mDisplayConfigInitialized = true;
       }
     }
   }
 }
 
 bool
-VRDisplayManagerOSVR::Init()
+VRSystemManagerOSVR::Init()
 {
 
   // OSVR server should be running in the background
   // It would load plugins and take care of detecting HMDs
   if (!mOSVRInitialized) {
     nsIThread* thread = nullptr;
     NS_GetCurrentThread(&thread);
     mOSVRThread = already_AddRefed<nsIThread>(thread);
@@ -489,17 +493,17 @@ VRDisplayManagerOSVR::Init()
     // verify all components are initialized
     CheckOSVRStatus();
   }
 
   return mOSVRInitialized;
 }
 
 void
-VRDisplayManagerOSVR::Destroy()
+VRSystemManagerOSVR::Destroy()
 {
   if (mOSVRInitialized) {
     MOZ_ASSERT(NS_GetCurrentThread() == mOSVRThread);
     mOSVRThread = nullptr;
     mHMDInfo = nullptr;
     mOSVRInitialized = false;
   }
   // client context may not have been initialized
@@ -507,23 +511,62 @@ VRDisplayManagerOSVR::Destroy()
     osvr_ClientFreeDisplay(m_display);
   }
   // osvr checks that m_ctx or m_iface are not null
   osvr_ClientFreeInterface(m_ctx, m_iface);
   osvr_ClientShutdown(m_ctx);
 }
 
 void
-VRDisplayManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
 {
   // make sure context, interface and display are initialized
   CheckOSVRStatus();
 
   if (!mOSVRInitialized) {
     return;
   }
 
   mHMDInfo = new VRDisplayOSVR(&m_ctx, &m_iface, &m_display);
 
   if (mHMDInfo) {
     aHMDResult.AppendElement(mHMDInfo);
   }
 }
+
+void
+VRSystemManagerOSVR::HandleInput()
+{
+}
+
+void
+VRSystemManagerOSVR::HandleButtonPress(uint32_t aControllerIdx,
+                                       uint64_t aButtonPressed)
+{
+}
+
+void
+VRSystemManagerOSVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                                    float aValue)
+{
+}
+
+void
+VRSystemManagerOSVR::HandlePoseTracking(uint32_t aControllerIdx,
+                                        const GamepadPoseState& aPose,
+                                        VRControllerHost* aController)
+{
+}
+
+void
+VRSystemManagerOSVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
+{
+}
+
+void
+VRSystemManagerOSVR::ScanForControllers()
+{
+}
+
+void
+VRSystemManagerOSVR::RemoveControllers()
+{
+}
--- a/gfx/vr/gfxVROSVR.h
+++ b/gfx/vr/gfxVROSVR.h
@@ -56,26 +56,31 @@ protected:
 
   OSVR_ClientContext* m_ctx;
   OSVR_ClientInterface* m_iface;
   OSVR_DisplayConfig* m_display;
 };
 
 } // namespace impl
 
-class VRDisplayManagerOSVR : public VRDisplayManager
+class VRSystemManagerOSVR : public VRSystemManager
 {
 public:
-  static already_AddRefed<VRDisplayManagerOSVR> Create();
+  static already_AddRefed<VRSystemManagerOSVR> Create();
   virtual bool Init() override;
   virtual void Destroy() override;
   virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
+  virtual void HandleInput() override;
+  virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
+                              aControllerResult) override;
+  virtual void ScanForControllers() override;
+  virtual void RemoveControllers() override;
 
 protected:
-  VRDisplayManagerOSVR()
+  VRSystemManagerOSVR()
     : mOSVRInitialized(false)
     , mClientContextInitialized(false)
     , mDisplayConfigInitialized(false)
     , mInterfaceInitialized(false)
     , m_ctx(nullptr)
     , m_iface(nullptr)
     , m_display(nullptr)
   {
@@ -88,16 +93,23 @@ protected:
   bool mInterfaceInitialized;
   RefPtr<nsIThread> mOSVRThread;
 
   OSVR_ClientContext m_ctx;
   OSVR_ClientInterface m_iface;
   OSVR_DisplayConfig m_display;
 
 private:
+  virtual void HandleButtonPress(uint32_t aControllerIdx,
+                                 uint64_t aButtonPressed) override;
+  virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                              float aValue) override;
+  virtual void HandlePoseTracking(uint32_t aControllerIdx,
+                                  const dom::GamepadPoseState& aPose,
+                                  VRControllerHost* aController) override;
   // check if all components are initialized
   // and if not, it will try to initialize them
   void CheckOSVRStatus();
   void InitializeClientContext();
   void InitializeDisplay();
   void InitializeInterface();
 };
 
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -24,16 +24,19 @@
 #include "mozilla/gfx/Quaternion.h"
 
 #include <d3d11.h>
 #include "CompositorD3D11.h"
 #include "TextureD3D11.h"
 
 #include "gfxVROculus.h"
 
+#include "mozilla/dom/GamepadEventTypes.h"
+#include "mozilla/dom/GamepadBinding.h"
+
 /** XXX The DX11 objects and quad blitting could be encapsulated
  *    into a separate object if either Oculus starts supporting
  *     non-Windows platforms or the blit is needed by other HMD\
  *     drivers.
  *     Alternately, we could remove the extra blit for
  *     Oculus as well with some more refactoring.
  */
 
@@ -44,16 +47,17 @@ extern ShaderBytes sLayerQuadVS;
 #ifndef M_PI
 # define M_PI 3.14159265358979323846
 #endif
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::gfx::impl;
 using namespace mozilla::layers;
+using namespace mozilla::dom;
 
 namespace {
 
 #ifdef OVR_CAPI_LIMITED_MOZILLA
 static pfn_ovr_Initialize ovr_Initialize = nullptr;
 static pfn_ovr_Shutdown ovr_Shutdown = nullptr;
 static pfn_ovr_GetLastErrorInfo ovr_GetLastErrorInfo = nullptr;
 static pfn_ovr_GetVersionString ovr_GetVersionString = nullptr;
@@ -613,36 +617,36 @@ VRDisplayOculus::StopPresentation()
   ovr_SubmitFrame(mSession, 0, nullptr, nullptr, 0);
 
   if (mTextureSet) {
     ovr_DestroyTextureSwapChain(mSession, mTextureSet);
     mTextureSet = nullptr;
   }
 }
 
-/*static*/ already_AddRefed<VRDisplayManagerOculus>
-VRDisplayManagerOculus::Create()
+/*static*/ already_AddRefed<VRSystemManagerOculus>
+VRSystemManagerOculus::Create()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gfxPrefs::VREnabled() || !gfxPrefs::VROculusEnabled())
   {
     return nullptr;
   }
 
   if (!InitializeOculusCAPI()) {
     return nullptr;
   }
 
-  RefPtr<VRDisplayManagerOculus> manager = new VRDisplayManagerOculus();
+  RefPtr<VRSystemManagerOculus> manager = new VRSystemManagerOculus();
   return manager.forget();
 }
 
 bool
-VRDisplayManagerOculus::Init()
+VRSystemManagerOculus::Init()
 {
   if (!mOculusInitialized) {
     nsIThread* thread = nullptr;
     NS_GetCurrentThread(&thread);
     mOculusThread = already_AddRefed<nsIThread>(thread);
 
     ovrInitParams params;
     memset(&params, 0, sizeof(params));
@@ -657,31 +661,31 @@ VRDisplayManagerOculus::Init()
       mOculusInitialized = true;
     }
   }
 
   return mOculusInitialized;
 }
 
 void
-VRDisplayManagerOculus::Destroy()
+VRSystemManagerOculus::Destroy()
 {
   if (mOculusInitialized) {
     MOZ_ASSERT(NS_GetCurrentThread() == mOculusThread);
     mOculusThread = nullptr;
 
     mHMDInfo = nullptr;
 
     ovr_Shutdown();
     mOculusInitialized = false;
   }
 }
 
 void
-VRDisplayManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
 {
   if (!mOculusInitialized) {
     return;
   }
 
   // ovr_Create can be slow when no HMD is present and we wish
   // to keep the same oculus session when possible, so we detect
   // presence of an HMD with ovr_GetHmdDesc before calling ovr_Create
@@ -690,25 +694,65 @@ VRDisplayManagerOculus::GetHMDs(nsTArray
     // No HMD connected.
     mHMDInfo = nullptr;
   } else if (mHMDInfo == nullptr) {
     // HMD Detected
     ovrSession session;
     ovrGraphicsLuid luid;
     ovrResult orv = ovr_Create(&session, &luid);
     if (orv == ovrSuccess) {
+      mSession = session;
       mHMDInfo = new VRDisplayOculus(session);
     }
   }
 
   if (mHMDInfo) {
     aHMDResult.AppendElement(mHMDInfo);
   }
 }
 
+void
+VRSystemManagerOculus::HandleInput()
+{
+}
+
+void
+VRSystemManagerOculus::HandleButtonPress(uint32_t aControllerIdx,
+                                         uint64_t aButtonPressed)
+{
+}
+
+void
+VRSystemManagerOculus::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                                      float aValue)
+{
+}
+
+void
+VRSystemManagerOculus::HandlePoseTracking(uint32_t aControllerIdx,
+                                          const GamepadPoseState& aPose,
+                                          VRControllerHost* aController)
+{
+}
+
+void
+VRSystemManagerOculus::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
+{
+}
+
+void
+VRSystemManagerOculus::ScanForControllers()
+{
+}
+
+void
+VRSystemManagerOculus::RemoveControllers()
+{
+}
+
 already_AddRefed<CompositingRenderTargetD3D11>
 VRDisplayOculus::GetNextRenderTarget()
 {
   int currentRenderTarget = 0;
   DebugOnly<ovrResult> orv = ovr_GetTextureSwapChainCurrentIndex(mSession, mTextureSet, &currentRenderTarget);
   MOZ_ASSERT(orv == ovrSuccess, "ovr_GetTextureSwapChainCurrentIndex failed.");
 
   mRenderTargets[currentRenderTarget]->ClearOnBind();
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -83,29 +83,45 @@ protected:
   struct Vertex
   {
     float position[2];
   };
 };
 
 } // namespace impl
 
-class VRDisplayManagerOculus : public VRDisplayManager
+class VRSystemManagerOculus : public VRSystemManager
 {
 public:
-  static already_AddRefed<VRDisplayManagerOculus> Create();
+  static already_AddRefed<VRSystemManagerOculus> Create();
   virtual bool Init() override;
   virtual void Destroy() override;
   virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
+  virtual void HandleInput() override;
+  virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
+                              aControllerResult) override;
+  virtual void ScanForControllers() override;
+  virtual void RemoveControllers() override;
+
 protected:
-  VRDisplayManagerOculus()
+  VRSystemManagerOculus()
     : mOculusInitialized(false)
   { }
 
+private:
+  virtual void HandleButtonPress(uint32_t aControllerIdx,
+                                 uint64_t aButtonPressed) override;
+  virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                              float aValue) override;
+  virtual void HandlePoseTracking(uint32_t aControllerIdx,
+                                  const dom::GamepadPoseState& aPose,
+                                  VRControllerHost* aController) override;
+
   RefPtr<impl::VRDisplayOculus> mHMDInfo;
+  RefPtr<nsIThread> mOculusThread;
+  ovrSession mSession;
   bool mOculusInitialized;
-  RefPtr<nsIThread> mOculusThread;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* GFX_VR_OCULUS_H */
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -389,64 +389,65 @@ VRDisplayOpenVR::SubmitFrame(TextureSour
 
 void
 VRDisplayOpenVR::NotifyVSync()
 {
   // We update mIsConneced once per frame.
   mDisplayInfo.mIsConnected = vr_IsHmdPresent();
 }
 
-VRDisplayManagerOpenVR::VRDisplayManagerOpenVR()
+VRSystemManagerOpenVR::VRSystemManagerOpenVR()
   : mOpenVRInstalled(false)
 {
 }
 
-/*static*/ already_AddRefed<VRDisplayManagerOpenVR>
-VRDisplayManagerOpenVR::Create()
+/*static*/ already_AddRefed<VRSystemManagerOpenVR>
+VRSystemManagerOpenVR::Create()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!gfxPrefs::VREnabled() || !gfxPrefs::VROpenVREnabled()) {
     return nullptr;
   }
 
   if (!LoadOpenVRRuntime()) {
     return nullptr;
   }
 
-  RefPtr<VRDisplayManagerOpenVR> manager = new VRDisplayManagerOpenVR();
+  RefPtr<VRSystemManagerOpenVR> manager = new VRSystemManagerOpenVR();
   return manager.forget();
 }
 
 bool
-VRDisplayManagerOpenVR::Init()
+VRSystemManagerOpenVR::Init()
 {
   if (mOpenVRInstalled)
     return true;
 
   if (!vr_IsRuntimeInstalled())
     return false;
 
   mOpenVRInstalled = true;
   return true;
 }
 
 void
-VRDisplayManagerOpenVR::Destroy()
+VRSystemManagerOpenVR::Destroy()
 {
   if (mOpenVRInstalled) {
     if (mOpenVRHMD) {
       mOpenVRHMD = nullptr;
     }
+    RemoveControllers();
     mOpenVRInstalled = false;
   }
 }
 
 void
-VRDisplayManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
+VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
 {
   if (!mOpenVRInstalled) {
     return;
   }
 
   if (!vr_IsHmdPresent()) {
     if (mOpenVRHMD) {
       mOpenVRHMD = nullptr;
@@ -470,108 +471,27 @@ VRDisplayManagerOpenVR::GetHMDs(nsTArray
       return;
     }
     ::vr::IVRCompositor *compositor = (::vr::IVRCompositor*)vr_GetGenericInterface(::vr::IVRCompositor_Version, &err);
     if (err || !compositor) {
       vr_ShutdownInternal();
       return;
     }
 
+    mVRSystem = system;
     mOpenVRHMD = new VRDisplayOpenVR(system, chaperone, compositor);
   }
 
   if (mOpenVRHMD) {
     aHMDResult.AppendElement(mOpenVRHMD);
   }
 }
 
-VRControllerOpenVR::VRControllerOpenVR()
-  : VRControllerHost(VRDeviceType::OpenVR)
-{
-  MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
-  mControllerInfo.mControllerName.AssignLiteral("OpenVR HMD");
-  mControllerInfo.mMappingType = GamepadMappingType::_empty;
-  mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
-  mControllerInfo.mNumAxes = gNumOpenVRAxis;
-}
-
-VRControllerOpenVR::~VRControllerOpenVR()
-{
-  MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
-}
-
 void
-VRControllerOpenVR::SetTrackedIndex(uint32_t aTrackedIndex)
-{
-  mTrackedIndex = aTrackedIndex;
-}
-
-uint32_t
-VRControllerOpenVR::GetTrackedIndex()
-{
-  return mTrackedIndex;
-}
-
-VRControllerManagerOpenVR::VRControllerManagerOpenVR()
-  : mOpenVRInstalled(false), mVRSystem(nullptr)
-{
-}
-
-VRControllerManagerOpenVR::~VRControllerManagerOpenVR()
-{
-  Destroy();
-}
-
-/*static*/ already_AddRefed<VRControllerManagerOpenVR>
-VRControllerManagerOpenVR::Create()
-{
-  if (!gfxPrefs::VREnabled() || !gfxPrefs::VROpenVREnabled()) {
-    return nullptr;
-  }
-
-  RefPtr<VRControllerManagerOpenVR> manager = new VRControllerManagerOpenVR();
-  return manager.forget();
-}
-
-bool
-VRControllerManagerOpenVR::Init()
-{
-  if (mOpenVRInstalled)
-    return true;
-
-  if (!vr_IsRuntimeInstalled())
-    return false;
-
-  // Loading the OpenVR Runtime
-  vr::EVRInitError err = vr::VRInitError_None;
-
-  vr_InitInternal(&err, vr::VRApplication_Scene);
-  if (err != vr::VRInitError_None) {
-    return false;
-  }
-
-  mVRSystem = (vr::IVRSystem *)vr_GetGenericInterface(vr::IVRSystem_Version, &err);
-  if ((err != vr::VRInitError_None) || !mVRSystem) {
-    vr_ShutdownInternal();
-    return false;
-  }
-
-  mOpenVRInstalled = true;
-  return true;
-}
-
-void
-VRControllerManagerOpenVR::Destroy()
-{
-  RemoveDevices();
-  mOpenVRInstalled = false;
-}
-
-void
-VRControllerManagerOpenVR::HandleInput()
+VRSystemManagerOpenVR::HandleInput()
 {
   RefPtr<impl::VRControllerOpenVR> controller;
   vr::VRControllerState_t state;
   uint32_t axis = 0;
 
   if (!mOpenVRInstalled) {
     return;
   }
@@ -640,18 +560,18 @@ VRControllerManagerOpenVR::HandleInput()
       poseState.linearVelocity[1] = pose.vVelocity.v[1];
       poseState.linearVelocity[2] = pose.vVelocity.v[2];
       HandlePoseTracking(controller->GetIndex(), poseState, controller);
     }
   }
 }
 
 void
-VRControllerManagerOpenVR::HandleButtonPress(uint32_t aControllerIdx,
-                                             uint64_t aButtonPressed)
+VRSystemManagerOpenVR::HandleButtonPress(uint32_t aControllerIdx,
+                                         uint64_t aButtonPressed)
 {
   uint64_t buttonMask = 0;
   RefPtr<impl::VRControllerOpenVR> controller;
   controller = mOpenVRController[aControllerIdx];
   uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
 
   if (!diff) {
     return;
@@ -667,50 +587,50 @@ VRControllerManagerOpenVR::HandleButtonP
       NewButtonEvent(aControllerIdx, i, diff & aButtonPressed);
     }
   }
 
   controller->SetButtonPressed(aButtonPressed);
 }
 
 void
-VRControllerManagerOpenVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
-                                          float aValue)
+VRSystemManagerOpenVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                                      float aValue)
 {
   if (aValue != 0.0f) {
     NewAxisMove(aControllerIdx, aAxis, aValue);
   }
 }
 
 void
-VRControllerManagerOpenVR::HandlePoseTracking(uint32_t aControllerIdx,
-                                              const GamepadPoseState& aPose,
-                                              VRControllerHost* aController)
+VRSystemManagerOpenVR::HandlePoseTracking(uint32_t aControllerIdx,
+                                          const GamepadPoseState& aPose,
+                                          VRControllerHost* aController)
 {
   if (aPose != aController->GetPose()) {
     aController->SetPose(aPose);
     NewPoseState(aControllerIdx, aPose);
   }
 }
 
 void
-VRControllerManagerOpenVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
+VRSystemManagerOpenVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
 {
   if (!mOpenVRInstalled) {
     return;
   }
 
   aControllerResult.Clear();
   for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
     aControllerResult.AppendElement(mOpenVRController[i]);
   }
 }
 
 void
-VRControllerManagerOpenVR::ScanForDevices()
+VRSystemManagerOpenVR::ScanForControllers()
 {
   if (!mVRSystem)
     return;
 
   vr::TrackedDeviceIndex_t trackedIndexArray[vr::k_unMaxTrackedDeviceCount];
   uint32_t newControllerCount = 0;
   // Basically, we would have HMDs in the tracked devices,
   // but we are just interested in the controllers.
@@ -764,13 +684,40 @@ VRControllerManagerOpenVR::ScanForDevice
       AddGamepad("OpenVR Gamepad", GamepadMappingType::_empty,
                  hand, gNumOpenVRButtonMask, gNumOpenVRAxis);
       ++mControllerCount;
     }
   }
 }
 
 void
-VRControllerManagerOpenVR::RemoveDevices()
+VRSystemManagerOpenVR::RemoveControllers()
 {
   mOpenVRController.Clear();
   mControllerCount = 0;
-}
\ No newline at end of file
+}
+
+VRControllerOpenVR::VRControllerOpenVR()
+  : VRControllerHost(VRDeviceType::OpenVR)
+{
+  MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
+  mControllerInfo.mControllerName.AssignLiteral("OpenVR HMD");
+  mControllerInfo.mMappingType = GamepadMappingType::_empty;
+  mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
+  mControllerInfo.mNumAxes = gNumOpenVRAxis;
+}
+
+VRControllerOpenVR::~VRControllerOpenVR()
+{
+  MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
+}
+
+void
+VRControllerOpenVR::SetTrackedIndex(uint32_t aTrackedIndex)
+{
+  mTrackedIndex = aTrackedIndex;
+}
+
+uint32_t
+VRControllerOpenVR::GetTrackedIndex()
+{
+  return mTrackedIndex;
+}
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -63,79 +63,62 @@ protected:
   ::vr::IVRChaperone *mVRChaperone;
   ::vr::IVRCompositor *mVRCompositor;
 
   bool mIsPresenting;
 
   void UpdateStageParameters();
 };
 
-} // namespace impl
-
-class VRDisplayManagerOpenVR : public VRDisplayManager
-{
-public:
-  static already_AddRefed<VRDisplayManagerOpenVR> Create();
-
-  virtual bool Init() override;
-  virtual void Destroy() override;
-  virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
-protected:
-  VRDisplayManagerOpenVR();
-
-  // there can only be one
-  RefPtr<impl::VRDisplayOpenVR> mOpenVRHMD;
-  bool mOpenVRInstalled;
-};
-
-namespace impl {
-
 class VRControllerOpenVR : public VRControllerHost
 {
 public:
   explicit VRControllerOpenVR();
   void SetTrackedIndex(uint32_t aTrackedIndex);
   uint32_t GetTrackedIndex();
 
 protected:
   virtual ~VRControllerOpenVR();
 
   // The index of tracked devices from vr::IVRSystem.
   uint32_t mTrackedIndex;
 };
 
 } // namespace impl
 
-class VRControllerManagerOpenVR : public VRControllerManager
+class VRSystemManagerOpenVR : public VRSystemManager
 {
 public:
-  static already_AddRefed<VRControllerManagerOpenVR> Create();
+  static already_AddRefed<VRSystemManagerOpenVR> Create();
 
   virtual bool Init() override;
   virtual void Destroy() override;
+  virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
   virtual void HandleInput() override;
   virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
                               aControllerResult) override;
-  virtual void ScanForDevices() override;
-  virtual void RemoveDevices() override;
+  virtual void ScanForControllers() override;
+  virtual void RemoveControllers() override;
+
+protected:
+  VRSystemManagerOpenVR();
 
 private:
-  VRControllerManagerOpenVR();
-  ~VRControllerManagerOpenVR();
-
   virtual void HandleButtonPress(uint32_t aControllerIdx,
                                  uint64_t aButtonPressed) override;
   virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
                               float aValue) override;
   virtual void HandlePoseTracking(uint32_t aControllerIdx,
                                   const dom::GamepadPoseState& aPose,
                                   VRControllerHost* aController) override;
 
-  bool mOpenVRInstalled;
+  // there can only be one
+  RefPtr<impl::VRDisplayOpenVR> mOpenVRHMD;
   nsTArray<RefPtr<impl::VRControllerOpenVR>> mOpenVRController;
   vr::IVRSystem *mVRSystem;
+  bool mOpenVRInstalled;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 
 #endif /* GFX_VR_OPENVR_H */