Bug 1382123 - SteamVR Knuckles support in WebVR. r=kip
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 01 Aug 2017 16:36:26 -0400
changeset 420943 2e349fb7c36b7b091ae1786b0acf6a4f35d14923
parent 420942 8bf8ee2bd98c1ce676eac43ffc2ff6f127b06f40
child 420944 b78fd576bdc8d08b630ee3b831352966b90000f2
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskip
bugs1382123
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1382123 - SteamVR Knuckles support in WebVR. r=kip MozReview-Commit-ID: 4dHRkcQcmeL
gfx/vr/VRDisplayHost.cpp
gfx/vr/gfxVROpenVR.cpp
gfx/vr/gfxVROpenVR.h
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -253,17 +253,19 @@ VRDisplayHost::CheckClearDisplayInfoDirt
     return false;
   }
   mLastUpdateDisplayInfo = mDisplayInfo;
   return true;
 }
 
 VRControllerHost::VRControllerHost(VRDeviceType aType, dom::GamepadHand aHand,
                                    uint32_t aDisplayID)
- : mVibrateIndex(0)
+ : mButtonPressed(0)
+ , mButtonTouched(0)
+ , mVibrateIndex(0)
 {
   MOZ_COUNT_CTOR(VRControllerHost);
   mControllerInfo.mType = aType;
   mControllerInfo.mHand = aHand;
   mControllerInfo.mMappingType = dom::GamepadMappingType::_empty;
   mControllerInfo.mDisplayID = aDisplayID;
   mControllerInfo.mControllerID = VRSystemManager::AllocateControllerID();
 }
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -3,17 +3,16 @@
  * 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 <math.h>
 
 #include "prlink.h"
 #include "prenv.h"
 #include "gfxPrefs.h"
-#include "nsString.h"
 #include "mozilla/Preferences.h"
 
 #include "mozilla/gfx/Quaternion.h"
 
 #ifdef XP_WIN
 #include "CompositorD3D11.h"
 #include "TextureD3D11.h"
 #elif defined(XP_MACOSX)
@@ -373,20 +372,20 @@ VRDisplayOpenVR::NotifyVSync()
 
   // Make sure we respond to OpenVR events even when not presenting
   PollEvents();
 
   VRDisplayHost::NotifyVSync();
 }
 
 VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aDisplayID,
-                                       uint32_t aNumButtons, uint32_t aNumAxes,
-                                       ::vr::ETrackedDeviceClass aDeviceType)
+                                       uint32_t aNumButtons, uint32_t aNumTriggers,
+                                       uint32_t aNumAxes, ::vr::ETrackedDeviceClass aDeviceType)
   : VRControllerHost(VRDeviceType::OpenVR, aHand, aDisplayID)
-  , mTrigger(0)
+  , mTrigger(aNumTriggers)
   , mAxisMove(aNumAxes)
   , mVibrateThread(nullptr)
   , mIsVibrateStopped(false)
 {
   MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
 
   switch (aDeviceType) {
     case ::vr::TrackedDeviceClass_Controller:
@@ -396,16 +395,17 @@ VRControllerOpenVR::VRControllerOpenVR(d
       mControllerInfo.mControllerName.AssignLiteral("OpenVR Tracker");
       break;
     default:
       MOZ_ASSERT(false);
       break;
   }
 
   mAxisMove.SetLengthAndRetainStorage(aNumAxes);
+  mTrigger.SetLengthAndRetainStorage(aNumTriggers);
   mControllerInfo.mNumButtons = aNumButtons;
   mControllerInfo.mNumAxes = aNumAxes;
   mControllerInfo.mNumHaptics = kNumOpenVRHaptcs;
 }
 
 VRControllerOpenVR::~VRControllerOpenVR()
 {
   if (mVibrateThread) {
@@ -436,25 +436,25 @@ VRControllerOpenVR::GetAxisMove(uint32_t
 
 void
 VRControllerOpenVR::SetAxisMove(uint32_t aAxis, float aValue)
 {
   mAxisMove[aAxis] = aValue;
 }
 
 void
-VRControllerOpenVR::SetTrigger(float aValue)
+VRControllerOpenVR::SetTrigger(uint32_t aButton, float aValue)
 {
-  mTrigger = aValue;
+  mTrigger[aButton] = aValue;
 }
 
 float
-VRControllerOpenVR::GetTrigger()
+VRControllerOpenVR::GetTrigger(uint32_t aButton)
 {
-  return mTrigger;
+  return mTrigger[aButton];
 }
 
 void
 VRControllerOpenVR::SetHand(dom::GamepadHand aHand)
 {
   mControllerInfo.mHand = aHand;
 }
 
@@ -655,16 +655,17 @@ VRSystemManagerOpenVR::HandleInput()
   ::vr::VRControllerState_t state;
   ::vr::TrackedDevicePose_t poses[::vr::k_unMaxTrackedDeviceCount];
   mVRSystem->GetDeviceToAbsoluteTrackingPose(::vr::TrackingUniverseSeated, 0.0f,
                                              poses, ::vr::k_unMaxTrackedDeviceCount);
   // Process OpenVR controller state
   for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
     uint32_t axisIdx = 0;
     uint32_t buttonIdx = 0;
+    uint32_t triggerIdx = 0;
     controller = mOpenVRController[i];
     const uint32_t trackedIndex = controller->GetTrackedIndex();
 
     MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(trackedIndex)
                == ::vr::TrackedDeviceClass_Controller ||
                mVRSystem->GetTrackedDeviceClass(trackedIndex)
                == ::vr::TrackedDeviceClass_GenericTracker);
 
@@ -698,18 +699,28 @@ VRSystemManagerOpenVR::HandleInput()
             ++axisIdx;
             HandleButtonPress(i, buttonIdx,
                               ::vr::ButtonMaskFromId(
                                  static_cast<::vr::EVRButtonId>(::vr::k_EButton_Axis0 + j)),
                                  state.ulButtonPressed, state.ulButtonTouched);
             ++buttonIdx;
             break;
           case vr::EVRControllerAxisType::k_eControllerAxis_Trigger:
-            HandleTriggerPress(i, buttonIdx, state.rAxis[j].x);
-            ++buttonIdx;
+            if (j <= 2) {
+              HandleTriggerPress(i, buttonIdx, triggerIdx, state.rAxis[j].x);
+              ++buttonIdx;
+              ++triggerIdx;
+            } else {
+              HandleTriggerPress(i, buttonIdx, triggerIdx, state.rAxis[j].x);
+              ++buttonIdx;
+              ++triggerIdx;
+              HandleTriggerPress(i, buttonIdx, triggerIdx, state.rAxis[j].y);
+              ++buttonIdx;
+              ++triggerIdx;
+            }
             break;
         }
       }
       MOZ_ASSERT(axisIdx ==
                  controller->GetControllerInfo().GetNumAxes());
 
       const uint64_t supportedButtons = mVRSystem->GetUint64TrackedDeviceProperty(
                                          trackedIndex, ::vr::Prop_SupportedButtons_Uint64);
@@ -838,32 +849,33 @@ VRSystemManagerOpenVR::HandleButtonPress
                    aButtonMask & aButtonTouched,
                    (aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
   }
 }
 
 void
 VRSystemManagerOpenVR::HandleTriggerPress(uint32_t aControllerIdx,
                                           uint32_t aButton,
+                                          uint32_t aTrigger,
                                           float aValue)
 {
   RefPtr<impl::VRControllerOpenVR> controller(mOpenVRController[aControllerIdx]);
   MOZ_ASSERT(controller);
-  const float oldValue = controller->GetTrigger();
+  const float oldValue = controller->GetTrigger(aTrigger);
   // For OpenVR, the threshold value of ButtonPressed and ButtonTouched is 0.55.
   // We prefer to let developers to set their own threshold for the adjustment.
   // Therefore, we don't check ButtonPressed and ButtonTouched with ButtonMask here.
   // we just check the button value is larger than the threshold value or not.
   const float threshold = gfxPrefs::VRControllerTriggerThreshold();
 
   // Avoid sending duplicated events in IPC channels.
   if (oldValue != aValue) {
     NewButtonEvent(aControllerIdx, aButton, aValue > threshold,
                    aValue > threshold, aValue);
-    controller->SetTrigger(aValue);
+    controller->SetTrigger(aTrigger, aValue);
   }
 }
 
 void
 VRSystemManagerOpenVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
                                       float aValue)
 {
   RefPtr<impl::VRControllerOpenVR> controller(mOpenVRController[aControllerIdx]);
@@ -993,31 +1005,49 @@ VRSystemManagerOpenVR::ScanForController
       const ::vr::TrackedDeviceIndex_t trackedDevice = trackedIndexArray[i];
       const ::vr::ETrackedDeviceClass deviceType = mVRSystem->
                                                    GetTrackedDeviceClass(trackedDevice);
       const ::vr::ETrackedControllerRole role = mVRSystem->
                                                 GetControllerRoleForTrackedDeviceIndex(
                                                 trackedDevice);
       const GamepadHand hand = GetGamepadHandFromControllerRole(role);
       uint32_t numButtons = 0;
+      uint32_t numTriggers = 0;
       uint32_t numAxes = 0;
 
       // Scan the axes that the controllers support
       for (uint32_t j = 0; j < ::vr::k_unControllerStateAxisCount; ++j) {
         const uint32_t supportAxis = mVRSystem->GetInt32TrackedDeviceProperty(trackedDevice,
                                       static_cast<vr::TrackedDeviceProperty>(
                                       ::vr::Prop_Axis0Type_Int32 + j));
         switch (supportAxis) {
           case ::vr::EVRControllerAxisType::k_eControllerAxis_Joystick:
           case ::vr::EVRControllerAxisType::k_eControllerAxis_TrackPad:
             numAxes += 2; // It has x and y axes.
             ++numButtons;
             break;
           case ::vr::k_eControllerAxis_Trigger:
-            ++numButtons;
+            if (j <= 2) {
+              ++numButtons;
+              ++numTriggers;
+            } else {
+          #ifdef DEBUG
+              // SteamVR Knuckles is the only special case for using 2D axis values on triggers.
+              ::vr::ETrackedPropertyError err;
+              uint32_t requiredBufferLen;
+              char charBuf[128];
+              requiredBufferLen = mVRSystem->GetStringTrackedDeviceProperty(trackedDevice,
+                                  ::vr::Prop_RenderModelName_String, charBuf, 128, &err);
+              MOZ_ASSERT(requiredBufferLen && err == ::vr::TrackedProp_Success);
+              nsCString deviceId(charBuf);
+              MOZ_ASSERT(deviceId.Find("knuckles") != kNotFound);
+          #endif // #ifdef DEBUG
+              numButtons += 2;
+              numTriggers += 2;
+            }
             break;
         }
       }
 
       // Scan the buttons that the controllers support
       const uint64_t supportButtons = mVRSystem->GetUint64TrackedDeviceProperty(
                                        trackedDevice, ::vr::Prop_SupportedButtons_Uint64);
       if (supportButtons &
@@ -1046,17 +1076,17 @@ VRSystemManagerOpenVR::ScanForController
       }
       if (supportButtons &
           BTN_MASK_FROM_ID(k_EButton_DPad_Down)) {
         ++numButtons;
       }
 
       RefPtr<VRControllerOpenVR> openVRController =
         new VRControllerOpenVR(hand, mOpenVRHMD->GetDisplayInfo().GetDisplayID(),
-                               numButtons, numAxes, deviceType);
+                               numButtons, numTriggers, numAxes, deviceType);
       openVRController->SetTrackedIndex(trackedDevice);
       mOpenVRController.AppendElement(openVRController);
 
       // Not already present, add it.
       AddGamepad(openVRController->GetControllerInfo());
       ++mControllerCount;
     }
   }
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -72,25 +72,25 @@ protected:
                    const IntSize& aSize,
                    const gfx::Rect& aLeftEyeRect,
                    const gfx::Rect& aRightEyeRect);
 };
 
 class VRControllerOpenVR : public VRControllerHost
 {
 public:
-  explicit VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aDisplayID,
-                              uint32_t aNumButtons, uint32_t aNumAxes,
+  explicit VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aDisplayID, uint32_t aNumButtons,
+                              uint32_t aNumTriggers, uint32_t aNumAxes,
                               ::vr::ETrackedDeviceClass aDeviceType);
   void SetTrackedIndex(uint32_t aTrackedIndex);
   uint32_t GetTrackedIndex();
   float GetAxisMove(uint32_t aAxis);
   void SetAxisMove(uint32_t aAxis, float aValue);
-  void SetTrigger(float aValue);
-  float GetTrigger();
+  void SetTrigger(uint32_t aButton, float aValue);
+  float GetTrigger(uint32_t aButton);
   void SetHand(dom::GamepadHand aHand);
   void VibrateHaptic(::vr::IVRSystem* aVRSystem,
                      uint32_t aHapticIndex,
                      double aIntensity,
                      double aDuration,
                      uint32_t aPromiseID);
   void StopVibrateHaptic();
 
@@ -103,17 +103,17 @@ private:
                            double aIntensity,
                            double aDuration,
                            uint64_t aVibrateIndex,
                            uint32_t aPromiseID);
   void VibrateHapticComplete(uint32_t aPromiseID);
 
   // The index of tracked devices from ::vr::IVRSystem.
   uint32_t mTrackedIndex;
-  float mTrigger;
+  nsTArray<float> mTrigger;
   nsTArray<float> mAxisMove;
   nsCOMPtr<nsIThread> mVibrateThread;
   Atomic<bool> mIsVibrateStopped;
 };
 
 } // namespace impl
 
 class VRSystemManagerOpenVR : public VRSystemManager
@@ -143,16 +143,17 @@ protected:
 private:
   void HandleButtonPress(uint32_t aControllerIdx,
                          uint32_t aButton,
                          uint64_t aButtonMask,
                          uint64_t aButtonPressed,
                          uint64_t aButtonTouched);
   void HandleTriggerPress(uint32_t aControllerIdx,
                           uint32_t aButton,
+                          uint32_t aTrigger,
                           float aValue);
   void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
                       float aValue);
   void HandlePoseTracking(uint32_t aControllerIdx,
                           const dom::GamepadPoseState& aPose,
                           VRControllerHost* aController);
   dom::GamepadHand GetGamepadHandFromControllerRole(
                           ::vr::ETrackedControllerRole aRole);