Bug 1305889 - Part 3: Enumerate Oculus Touch Controllers; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Mon, 06 Feb 2017 16:13:33 +0800
changeset 479594 697f94824270304bb13327c69eab829d8303164e
parent 479239 61d1b580a647979bc704b68df8d26f72acbd0804
child 544740 43987bddc6afdb0c823fe6d2a2f05046dcc729fa
push id44314
push userbmo:dmu@mozilla.com
push dateTue, 07 Feb 2017 01:49:21 +0000
reviewerskip
bugs1305889
milestone54.0a1
Bug 1305889 - Part 3: Enumerate Oculus Touch Controllers; r?kip MozReview-Commit-ID: Ep57r4hxrRt
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
gfx/vr/gfxVROpenVR.cpp
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -116,16 +116,33 @@ static pfn_ovr_GetMirrorTextureBufferGL 
 #else
 #define BUILD_BITS 32
 #endif
 
 #define OVR_PRODUCT_VERSION 1
 #define OVR_MAJOR_VERSION   1
 #define OVR_MINOR_VERSION   10
 
+static const ovrButton kOculusTouchLButton[] = {
+  ovrButton_X,
+  ovrButton_Y,
+  ovrButton_LThumb
+};
+
+static const ovrButton kOculusTouchRButton[] = {
+  ovrButton_A,
+  ovrButton_B,
+  ovrButton_RThumb
+};
+
+static const uint32_t kNumOculusButton = sizeof(kOculusTouchLButton) /
+                                         sizeof(ovrButton);
+static const uint32_t kNumOculusAxis = 2;
+static const uint32_t kNumOculusHaptcs = 0;  // TODO: Bug 1305892
+
 static bool
 InitializeOculusCAPI()
 {
   static PRLibrary *ovrlib = nullptr;
 
   if (!ovrlib) {
     nsTArray<nsCString> libSearchPaths;
     nsCString libName;
@@ -620,142 +637,16 @@ VRDisplayOculus::StopPresentation()
   ovr_SubmitFrame(mSession, 0, nullptr, nullptr, 0);
 
   if (mTextureSet) {
     ovr_DestroyTextureSwapChain(mSession, mTextureSet);
     mTextureSet = nullptr;
   }
 }
 
-/*static*/ already_AddRefed<VRSystemManagerOculus>
-VRSystemManagerOculus::Create()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!gfxPrefs::VREnabled() || !gfxPrefs::VROculusEnabled())
-  {
-    return nullptr;
-  }
-
-  if (!InitializeOculusCAPI()) {
-    return nullptr;
-  }
-
-  RefPtr<VRSystemManagerOculus> manager = new VRSystemManagerOculus();
-  return manager.forget();
-}
-
-bool
-VRSystemManagerOculus::Init()
-{
-  if (!mOculusInitialized) {
-    nsIThread* thread = nullptr;
-    NS_GetCurrentThread(&thread);
-    mOculusThread = already_AddRefed<nsIThread>(thread);
-
-    ovrInitParams params;
-    memset(&params, 0, sizeof(params));
-    params.Flags = ovrInit_RequestVersion;
-    params.RequestedMinorVersion = OVR_MINOR_VERSION;
-    params.LogCallback = nullptr;
-    params.ConnectionTimeoutMS = 0;
-
-    ovrResult orv = ovr_Initialize(&params);
-
-    if (orv == ovrSuccess) {
-      mOculusInitialized = true;
-    }
-  }
-
-  return mOculusInitialized;
-}
-
-void
-VRSystemManagerOculus::Destroy()
-{
-  if (mOculusInitialized) {
-    MOZ_ASSERT(NS_GetCurrentThread() == mOculusThread);
-    mOculusThread = nullptr;
-
-    mHMDInfo = nullptr;
-
-    ovr_Shutdown();
-    mOculusInitialized = false;
-  }
-}
-
-void
-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
-  ovrHmdDesc desc = ovr_GetHmdDesc(NULL);
-  if (desc.Type == ovrHmd_None) {
-    // 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();
@@ -935,10 +826,237 @@ VRDisplayOculus::SubmitFrame(TextureSour
 }
 
 void
 VRDisplayOculus::NotifyVSync()
 {
   ovrSessionStatus sessionStatus;
   ovrResult ovr = ovr_GetSessionStatus(mSession, &sessionStatus);
   mDisplayInfo.mIsConnected = (ovr == ovrSuccess && sessionStatus.HmdPresent);
-  mDisplayInfo.mIsMounted = (ovr == ovrSuccess && sessionStatus.HmdMounted);
+}
+
+VRControllerOculus::VRControllerOculus()
+  : VRControllerHost(VRDeviceType::Oculus)
+{
+  MOZ_COUNT_CTOR_INHERITED(VRControllerOculus, VRControllerHost);
+  mControllerInfo.mControllerName.AssignLiteral("Oculus Touch Controller");
+  mControllerInfo.mMappingType = GamepadMappingType::_empty;
+  mControllerInfo.mHand = GamepadHand::_empty;
+  mControllerInfo.mNumButtons = kNumOculusButton;
+  mControllerInfo.mNumAxes = kNumOculusAxis;
+}
+
+VRControllerOculus::~VRControllerOculus()
+{
+  MOZ_COUNT_DTOR_INHERITED(VRControllerOculus, VRControllerHost);
+}
+
+/*static*/ already_AddRefed<VRSystemManagerOculus>
+VRSystemManagerOculus::Create()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!gfxPrefs::VREnabled() || !gfxPrefs::VROculusEnabled())
+  {
+    return nullptr;
+  }
+
+  if (!InitializeOculusCAPI()) {
+    return nullptr;
+  }
+
+  RefPtr<VRSystemManagerOculus> manager = new VRSystemManagerOculus();
+  return manager.forget();
+}
+
+bool
+VRSystemManagerOculus::Init()
+{
+  if (!mOculusInitialized) {
+    nsIThread* thread = nullptr;
+    NS_GetCurrentThread(&thread);
+    mOculusThread = already_AddRefed<nsIThread>(thread);
+
+    ovrInitParams params;
+    memset(&params, 0, sizeof(params));
+    params.Flags = ovrInit_RequestVersion;
+    params.RequestedMinorVersion = OVR_MINOR_VERSION;
+    params.LogCallback = nullptr;
+    params.ConnectionTimeoutMS = 0;
+
+    ovrResult orv = ovr_Initialize(&params);
+
+    if (orv == ovrSuccess) {
+      mOculusInitialized = true;
+    }
+  }
+
+  return mOculusInitialized;
+}
+
+void
+VRSystemManagerOculus::Destroy()
+{
+  if (mOculusInitialized) {
+    MOZ_ASSERT(NS_GetCurrentThread() == mOculusThread);
+    mOculusThread = nullptr;
+    mSession = nullptr;
+    mHMDInfo = nullptr;
+
+    ovr_Shutdown();
+    mOculusInitialized = false;
+  }
+}
+
+void
+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
+  ovrHmdDesc desc = ovr_GetHmdDesc(NULL);
+  if (desc.Type == ovrHmd_None) {
+    // 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()
+{
+   // mSession is available after VRDisplay is created
+  // at GetHMDs().
+  if (!mSession) {
+    return;
+  }
+
+  RefPtr<impl::VRControllerOculus> controller;
+  ovrInputState inputState;
+  bool hasInputState = ovr_GetInputState(mSession, ovrControllerType_Touch,
+                                         &inputState) == ovrSuccess;
+
+  if (!hasInputState) {
+    return;
+  }
+
+  for (uint32_t i = 0; i < mOculusController.Length(); ++i) {
+    controller = mOculusController[i];
+    HandleButtonPress(controller->GetIndex(), inputState.Buttons);
+  }
+}
+
+void
+VRSystemManagerOculus::HandleButtonPress(uint32_t aControllerIdx,
+                                         uint64_t aButtonPressed)
+{
+  // TODO: Bug 1305890
+}
+
+void
+VRSystemManagerOculus::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                                      float aValue)
+{
+  // TODO: Bug 1305890
+}
+
+void
+VRSystemManagerOculus::HandlePoseTracking(uint32_t aControllerIdx,
+                                          const GamepadPoseState& aPose,
+                                          VRControllerHost* aController)
+{
+  // TODO: Bug 1305891
+}
+
+void
+VRSystemManagerOculus::GetControllers(nsTArray<RefPtr<VRControllerHost>>&
+                                      aControllerResult)
+{
+  if (!mOculusInitialized) {
+    return;
+  }
+
+  aControllerResult.Clear();
+  for (uint32_t i = 0; i < mOculusController.Length(); ++i) {
+    aControllerResult.AppendElement(mOculusController[i]);
+  }
+}
+
+void
+VRSystemManagerOculus::ScanForControllers()
+{
+  // mSession is available after VRDisplay is created
+  // at GetHMDs().
+  if (!mSession) {
+    return;
+  }
+
+  ovrInputState inputState;
+  bool hasInputState = ovr_GetInputState(mSession, ovrControllerType_Touch,
+                                         &inputState) == ovrSuccess;
+  ovrControllerType activeControllerArray[2];
+  uint32_t newControllerCount = 0;
+
+  if (inputState.ControllerType & ovrControllerType_LTouch) {
+    activeControllerArray[newControllerCount] = ovrControllerType_LTouch;
+    ++newControllerCount;
+  }
+
+  if (inputState.ControllerType & ovrControllerType_RTouch) {
+    activeControllerArray[newControllerCount] = ovrControllerType_RTouch;
+    ++newControllerCount;
+  }
+
+  if (newControllerCount != mControllerCount) {
+    // controller count is changed, removing the existing gamepads first.
+    for (uint32_t i = 0; i < mOculusController.Length(); ++i) {
+      RemoveGamepad(mOculusController[i]->GetIndex());
+    }
+
+    mControllerCount = 0;
+    mOculusController.Clear();
+
+    // Re-adding controllers to VRControllerManager.
+    for (uint32_t i = 0; i < newControllerCount; ++i) {
+      GamepadHand hand;
+
+      switch (activeControllerArray[i]) {
+        case ovrControllerType::ovrControllerType_LTouch:
+          hand = GamepadHand::Left;
+          break;
+        case ovrControllerType::ovrControllerType_RTouch:
+          hand = GamepadHand::Right;
+          break;
+      }
+      RefPtr<VRControllerOculus> oculusController = new VRControllerOculus();
+      oculusController->SetIndex(mControllerCount);
+      oculusController->SetHand(hand);
+      mOculusController.AppendElement(oculusController);
+
+      // Not already present, add it.
+      AddGamepad(oculusController->GetControllerInfo());
+      ++mControllerCount;
+    }
+  }
+}
+
+void
+VRSystemManagerOculus::RemoveControllers()
+{
+  mOculusController.Clear();
+  mControllerCount = 0;
+}
\ No newline at end of file
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -81,16 +81,25 @@ protected:
   bool UpdateConstantBuffers();
 
   struct Vertex
   {
     float position[2];
   };
 };
 
+class VRControllerOculus : public VRControllerHost
+{
+public:
+  explicit VRControllerOculus();
+
+protected:
+  virtual ~VRControllerOculus();
+};
+
 } // namespace impl
 
 class VRSystemManagerOculus : public VRSystemManager
 {
 public:
   static already_AddRefed<VRSystemManagerOculus> Create();
   virtual bool Init() override;
   virtual void Destroy() override;
@@ -98,29 +107,30 @@ public:
   virtual void HandleInput() override;
   virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>&
                               aControllerResult) override;
   virtual void ScanForControllers() override;
   virtual void RemoveControllers() override;
 
 protected:
   VRSystemManagerOculus()
-    : mOculusInitialized(false)
+    : mSession(nullptr), 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;
+  nsTArray<RefPtr<impl::VRControllerOculus>> mOculusController;
   RefPtr<nsIThread> mOculusThread;
   ovrSession mSession;
   bool mOculusInitialized;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -419,17 +419,17 @@ VRDisplayOpenVR::NotifyVSync()
   // Make sure we respond to OpenVR events even when not presenting
   PollEvents();
 }
 
 VRControllerOpenVR::VRControllerOpenVR()
   : VRControllerHost(VRDeviceType::OpenVR)
 {
   MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
-  mControllerInfo.mControllerName.AssignLiteral("OpenVR Gamepad");
+  mControllerInfo.mControllerName.AssignLiteral("OpenVR Controller");
   mControllerInfo.mMappingType = GamepadMappingType::_empty;
   mControllerInfo.mHand = GamepadHand::_empty;
   mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
   mControllerInfo.mNumAxes = gNumOpenVRAxis;
 }
 
 VRControllerOpenVR::~VRControllerOpenVR()
 {