Bug 1346149 - Part 2: Adjust Oculus Touch button and axis mapping; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Thu, 16 Mar 2017 15:54:00 +0800
changeset 499882 990bedc31131de673d401f1a3bb2f52d0027a3b0
parent 499872 566885933b411f8254e58fc31464de92834c7369
child 499883 5b64c110de6137eb89d45ad1c870fe168865e81d
child 500329 260ba99b1d0b062adbcf6ab7349346b986edf47d
child 500332 4e55483dc568cc0021e686d309baffbca0be8b55
push id49572
push userbmo:dmu@mozilla.com
push dateThu, 16 Mar 2017 10:33:23 +0000
reviewerskip
bugs1346149
milestone55.0a1
Bug 1346149 - Part 2: Adjust Oculus Touch button and axis mapping; r?kip MozReview-Commit-ID: H9FxkG0S5OL
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -116,32 +116,42 @@ 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_LThumb,
-  ovrButton_X,
-  ovrButton_Y
+enum class OculusLeftControllerButtonType : uint16_t {
+  LThumb,
+  IndexTrigger,
+  HandTrigger,
+  Button_X,
+  Button_Y,
+  LThumbRest,
+  NumButtonType
 };
 
-static const ovrButton kOculusTouchRButton[] = {
-  ovrButton_RThumb,
-  ovrButton_A,
-  ovrButton_B,
+enum class OculusRightControllerButtonType : uint16_t {
+  RThumb,
+  IndexTrigger,
+  HandTrigger,
+  Button_A,
+  Button_B,
+  RThumbRest,
+  NumButtonType
 };
 
-static const uint32_t kNumOculusButton = sizeof(kOculusTouchLButton) /
-                                         sizeof(ovrButton);
+static const uint32_t kNumOculusButton = static_cast<uint32_t>
+                                         (OculusLeftControllerButtonType::
+                                         NumButtonType);
 static const uint32_t kNumOculusHaptcs = 0;  // TODO: Bug 1305892
 
+
 static bool
 InitializeOculusCAPI()
 {
   static PRLibrary *ovrlib = nullptr;
 
   if (!ovrlib) {
     nsTArray<nsCString> libSearchPaths;
     nsCString libName;
@@ -829,16 +839,18 @@ VRDisplayOculus::NotifyVSync()
 {
   ovrSessionStatus sessionStatus;
   ovrResult ovr = ovr_GetSessionStatus(mSession, &sessionStatus);
   mDisplayInfo.mIsConnected = (ovr == ovrSuccess && sessionStatus.HmdPresent);
 }
 
 VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand)
   : VRControllerHost(VRDeviceType::Oculus)
+  , mIndexTrigger(0.0f)
+  , mHandTrigger(0.0f)
 {
   MOZ_COUNT_CTOR_INHERITED(VRControllerOculus, VRControllerHost);
 
   char* touchID = "";
   switch (aHand) {
     case dom::GamepadHand::Left:
       touchID = "Oculus Touch (Left)";
       break;
@@ -847,16 +859,22 @@ VRControllerOculus::VRControllerOculus(d
       break;
     default:
       MOZ_ASSERT(false);
       break;
   }
   mControllerInfo.mControllerName = touchID;
   mControllerInfo.mMappingType = GamepadMappingType::_empty;
   mControllerInfo.mHand = aHand;
+
+  MOZ_ASSERT(kNumOculusButton ==
+             static_cast<uint32_t>(OculusLeftControllerButtonType::NumButtonType)
+             && kNumOculusButton ==
+             static_cast<uint32_t>(OculusRightControllerButtonType::NumButtonType));
+
   mControllerInfo.mNumButtons = kNumOculusButton;
   mControllerInfo.mNumAxes = static_cast<uint32_t>(
                              OculusControllerAxisType::NumVRControllerAxisType);;
 }
 
 float
 VRControllerOculus::GetAxisMove(uint32_t aAxis)
 {
@@ -864,16 +882,40 @@ VRControllerOculus::GetAxisMove(uint32_t
 }
 
 void
 VRControllerOculus::SetAxisMove(uint32_t aAxis, float aValue)
 {
   mAxisMove[aAxis] = aValue;
 }
 
+float
+VRControllerOculus::GetIndexTrigger()
+{
+  return mIndexTrigger;
+}
+
+void
+VRControllerOculus::SetIndexTrigger(float aValue)
+{
+  mIndexTrigger = aValue;
+}
+
+float
+VRControllerOculus::GetHandTrigger()
+{
+  return mHandTrigger;
+}
+
+void
+VRControllerOculus::SetHandTrigger(float aValue)
+{
+  mHandTrigger = aValue;
+}
+
 VRControllerOculus::~VRControllerOculus()
 {
   MOZ_COUNT_DTOR_INHERITED(VRControllerOculus, VRControllerHost);
 }
 
 /*static*/ already_AddRefed<VRSystemManagerOculus>
 VRSystemManagerOculus::Create()
 {
@@ -968,44 +1010,75 @@ VRSystemManagerOculus::HandleInput()
   // at GetHMDs().
   if (!mSession) {
     return;
   }
 
   RefPtr<impl::VRControllerOculus> controller;
   ovrInputState inputState;
   uint32_t axis = 0;
-  bool hasInputState = ovr_GetInputState(mSession, ovrControllerType_Touch,
-                                         &inputState) == ovrSuccess;
+  const 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(i, inputState.Buttons);
+    const GamepadHand hand = controller->GetHand();
+    const uint32_t handIdx = static_cast<uint32_t>(hand) - 1;
+    uint32_t buttonIdx = 0;
 
-    axis = static_cast<uint32_t>(OculusControllerAxisType::IndexTrigger);
-    HandleAxisMove(i, axis, inputState.IndexTrigger[i]);
-
-    axis = static_cast<uint32_t>(OculusControllerAxisType::HandTrigger);
-    HandleAxisMove(i, axis, inputState.HandTrigger[i]);
+    switch (hand) {
+      case dom::GamepadHand::Left:
+        HandleButtonPress(i, buttonIdx, ovrButton_LThumb, inputState.Buttons);
+        ++buttonIdx;
+        HandleTriggerPress(i, buttonIdx, inputState.IndexTrigger[handIdx]);
+        ++buttonIdx;
+        HandleTriggerPress(i, buttonIdx, inputState.HandTrigger[handIdx]);
+        ++buttonIdx;
+        HandleButtonPress(i, buttonIdx, ovrButton_X, inputState.Buttons);
+        ++buttonIdx;
+        HandleButtonPress(i, buttonIdx, ovrButton_Y, inputState.Buttons);
+        ++buttonIdx;
+        HandleTouchEvent(i, buttonIdx, ovrTouch_LThumbRest, inputState.Touches);
+        ++buttonIdx;
+        break;
+      case dom::GamepadHand::Right:
+        HandleButtonPress(i, buttonIdx, ovrButton_RThumb, inputState.Buttons);
+        ++buttonIdx;
+        HandleTriggerPress(i, buttonIdx, inputState.IndexTrigger[handIdx]);
+        ++buttonIdx;
+        HandleTriggerPress(i, buttonIdx, inputState.HandTrigger[handIdx]);
+        ++buttonIdx;
+        HandleButtonPress(i, buttonIdx, ovrButton_A, inputState.Buttons);
+        ++buttonIdx;
+        HandleButtonPress(i, buttonIdx, ovrButton_B, inputState.Buttons);
+        ++buttonIdx;
+        HandleTouchEvent(i, buttonIdx, ovrTouch_RThumbRest, inputState.Touches);
+        ++buttonIdx;
+        break;
+      default:
+        MOZ_ASSERT(false);
+        break;
+    }
+    controller->SetButtonPressed(inputState.Buttons);
 
     axis = static_cast<uint32_t>(OculusControllerAxisType::ThumbstickXAxis);
     HandleAxisMove(i, axis, inputState.Thumbstick[i].x);
 
     axis = static_cast<uint32_t>(OculusControllerAxisType::ThumbstickYAxis);
     HandleAxisMove(i, axis, -inputState.Thumbstick[i].y);
 
     // Start to process pose
     ovrTrackingState state = ovr_GetTrackingState(mSession, 0.0, false);
     // HandPoses is ordered by ovrControllerType_LTouch and ovrControllerType_RTouch,
     // therefore, we can't get its state by the index of mOculusController.
-    const uint32_t handIdx = static_cast<uint32_t>(controller->GetHand()) - 1;
+
     ovrPoseStatef& pose(state.HandPoses[handIdx]);
     GamepadPoseState poseState;
 
     if (state.HandStatusFlags[handIdx] & ovrStatus_OrientationTracked) {
       poseState.flags |= GamepadCapabilityFlags::Cap_Orientation;
       poseState.orientation[0] = pose.ThePose.Orientation.x;
       poseState.orientation[1] = pose.ThePose.Orientation.y;
       poseState.orientation[2] = pose.ThePose.Orientation.z;
@@ -1034,45 +1107,67 @@ VRSystemManagerOculus::HandleInput()
       poseState.linearAcceleration[2] = pose.LinearAcceleration.z;
     }
     HandlePoseTracking(i, poseState, controller);
   }
 }
 
 void
 VRSystemManagerOculus::HandleButtonPress(uint32_t aControllerIdx,
+                                         uint32_t aButton,
+                                         uint64_t aButtonMask,
                                          uint64_t aButtonPressed)
 {
-  MOZ_ASSERT(sizeof(kOculusTouchLButton) / sizeof(ovrButton) ==
-             sizeof(kOculusTouchRButton) / sizeof(ovrButton));
+  RefPtr<impl::VRControllerOculus> controller(mOculusController[aControllerIdx]);
+  MOZ_ASSERT(controller);
+  const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
 
+  if (diff & aButtonMask) {
+    NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
+                   (aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
+  }
+}
+
+void
+VRSystemManagerOculus::HandleTriggerPress(uint32_t aControllerIdx, uint32_t aButton,
+                                          float aValue)
+{
   RefPtr<impl::VRControllerOculus> controller(mOculusController[aControllerIdx]);
   MOZ_ASSERT(controller);
-  GamepadHand hand = controller->GetHand();
-  uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
-  uint32_t buttonMask = 0;
+  const uint32_t indexTrigger = static_cast<const uint32_t>
+                                (OculusLeftControllerButtonType::IndexTrigger);
+  const uint32_t handTrigger =  static_cast<const uint32_t>
+                                (OculusLeftControllerButtonType::HandTrigger);
+  float oldValue = 0.0f;
 
-  for (uint32_t i = 0; i < kNumOculusButton; ++i) {
-    switch (hand) {
-      case dom::GamepadHand::Left:
-        buttonMask = kOculusTouchLButton[i];
-        break;
-      case dom::GamepadHand::Right:
-        buttonMask = kOculusTouchRButton[i];
-        break;
-      default:
-        MOZ_ASSERT(false);
-        break;
+  // Avoid sending duplicated events in IPC channels.
+  if (aButton == indexTrigger) {
+    oldValue = controller->GetIndexTrigger();
+    if (oldValue == aValue) {
+      return;
     }
-    if (diff & buttonMask) {
-      NewButtonEvent(aControllerIdx, i, diff & aButtonPressed);
+    controller->SetIndexTrigger(aValue);
+  } else if (aButton == handTrigger) {
+    oldValue = controller->GetHandTrigger();
+    if (oldValue == aValue) {
+      return;
     }
+    controller->SetHandTrigger(aValue);
+  } else {
+    MOZ_ASSERT(false, "We only support indexTrigger and handTrigger in Oculus.");
   }
 
-  controller->SetButtonPressed(aButtonPressed);
+  NewButtonEvent(aControllerIdx, aButton, aValue > 0.1f, aValue);
+}
+
+void
+VRSystemManagerOculus::HandleTouchEvent(uint32_t aControllerIdx, uint32_t aButton,
+                                        uint64_t aTouchMask, uint64_t aTouched)
+{
+  // TODO: Bug 1336003
 }
 
 void
 VRSystemManagerOculus::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
                                       float aValue)
 {
   RefPtr<impl::VRControllerOculus> controller(mOculusController[aControllerIdx]);
   MOZ_ASSERT(controller);
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -25,18 +25,16 @@ struct VertexShaderConstants;
 struct PixelShaderConstants;
 }
 namespace gfx {
 namespace impl {
 
 enum class OculusControllerAxisType : uint16_t {
   ThumbstickXAxis,
   ThumbstickYAxis,
-  IndexTrigger,
-  HandTrigger,
   NumVRControllerAxisType
 };
 
 class VRDisplayOculus : public VRDisplayHost
 {
 public:
   virtual void NotifyVSync() override;
   virtual VRHMDSensorState GetSensorState() override;
@@ -95,21 +93,29 @@ protected:
 };
 
 class VRControllerOculus : public VRControllerHost
 {
 public:
   explicit VRControllerOculus(dom::GamepadHand aHand);
   float GetAxisMove(uint32_t aAxis);
   void SetAxisMove(uint32_t aAxis, float aValue);
+  float GetIndexTrigger();
+  void SetIndexTrigger(float aValue);
+  float GetHandTrigger();
+  void SetHandTrigger(float aValue);
 
 protected:
   virtual ~VRControllerOculus();
+
+private:
   float mAxisMove[static_cast<uint32_t>(
                   OculusControllerAxisType::NumVRControllerAxisType)];
+  float mIndexTrigger;
+  float mHandTrigger;
 };
 
 } // namespace impl
 
 class VRSystemManagerOculus : public VRSystemManager
 {
 public:
   static already_AddRefed<VRSystemManagerOculus> Create();
@@ -123,23 +129,29 @@ public:
   virtual void RemoveControllers() override;
 
 protected:
   VRSystemManagerOculus()
     : 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;
+  void HandleButtonPress(uint32_t aControllerIdx,
+                         uint32_t aButton,
+                         uint64_t aButtonMask,
+                         uint64_t aButtonPressed);
+  void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+                      float aValue);
+  void HandlePoseTracking(uint32_t aControllerIdx,
+                          const dom::GamepadPoseState& aPose,
+                          VRControllerHost* aController);
+  void HandleTriggerPress(uint32_t aControllerIdx, uint32_t aButton,
+                          float aValue);
+  void HandleTouchEvent(uint32_t aControllerIdx, uint32_t aButton,
+                        uint64_t aTouchMask, uint64_t aTouched);
 
   RefPtr<impl::VRDisplayOculus> mHMDInfo;
   nsTArray<RefPtr<impl::VRControllerOculus>> mOculusController;
   RefPtr<nsIThread> mOculusThread;
   ovrSession mSession;
   bool mOculusInitialized;
 };