--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -51,52 +51,18 @@ typedef void * (VR_CALLTYPE * pfn_VR_Get
static pfn_VR_InitInternal vr_InitInternal = nullptr;
static pfn_VR_ShutdownInternal vr_ShutdownInternal = nullptr;
static pfn_VR_IsHmdPresent vr_IsHmdPresent = nullptr;
static pfn_VR_IsRuntimeInstalled vr_IsRuntimeInstalled = nullptr;
static pfn_VR_GetStringForHmdError vr_GetStringForHmdError = nullptr;
static pfn_VR_GetGenericInterface vr_GetGenericInterface = nullptr;
-// EButton_System, EButton_DPad_xx, and EButton_A
-// can not be triggered in Steam Vive in OpenVR SDK 1.0.3.
-// Reminder: changing the order of these buttons may break web content.
-const uint64_t gOpenVRButtonMask[] = {
- // vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_System),
- vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Touchpad),
- vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Trigger),
- // vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_A),
- vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_Grip),
- vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_ApplicationMenu)
- // vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Left),
- // vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Up),
- // vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Right),
- // vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Down)
-};
-
-const uint32_t gNumOpenVRButtonMask = sizeof(gOpenVRButtonMask) /
- sizeof(uint64_t);
-
-enum class VRControllerAxisType : uint16_t {
- TrackpadXAxis,
- TrackpadYAxis,
- Trigger,
- NumVRControllerAxisType
-};
-
-#define VRControllerAxis(aButtonId) (aButtonId - vr::EVRButtonId::k_EButton_Axis0)
-
-const uint32_t gOpenVRAxes[] = {
- VRControllerAxis(vr::EVRButtonId::k_EButton_Axis0),
- VRControllerAxis(vr::EVRButtonId::k_EButton_Axis0),
- VRControllerAxis(vr::EVRButtonId::k_EButton_Axis1)
-};
-
-const uint32_t gNumOpenVRAxis = sizeof(gOpenVRAxes) /
- sizeof(uint32_t);
+#define BTN_MASK_FROM_ID(_id) \
+ vr::ButtonMaskFromId(vr::EVRButtonId::_id)
bool
LoadOpenVRRuntime()
{
static PRLibrary *openvrLib = nullptr;
std::string openvrPath = gfxPrefs::VROpenVRRuntime();
@@ -423,25 +389,27 @@ VRDisplayOpenVR::NotifyVSync()
{
// We update mIsConneced once per frame.
mDisplayInfo.mIsConnected = vr_IsHmdPresent();
// Make sure we respond to OpenVR events even when not presenting
PollEvents();
}
-VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand)
+VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aNumButtons,
+ uint32_t aNumAxes)
: VRControllerHost(VRDeviceType::OpenVR)
+ , mTrigger(0)
{
MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
mControllerInfo.mControllerName.AssignLiteral("OpenVR Gamepad");
mControllerInfo.mMappingType = GamepadMappingType::_empty;
mControllerInfo.mHand = aHand;
- mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
- mControllerInfo.mNumAxes = gNumOpenVRAxis;
+ mControllerInfo.mNumButtons = aNumButtons;
+ mControllerInfo.mNumAxes = aNumAxes;
}
VRControllerOpenVR::~VRControllerOpenVR()
{
MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
}
void
@@ -451,18 +419,31 @@ VRControllerOpenVR::SetTrackedIndex(uint
}
uint32_t
VRControllerOpenVR::GetTrackedIndex()
{
return mTrackedIndex;
}
+void
+VRControllerOpenVR::SetTrigger(float aValue)
+{
+ mTrigger = aValue;
+}
+
+float
+VRControllerOpenVR::GetTrigger()
+{
+ return mTrigger;
+}
+
VRSystemManagerOpenVR::VRSystemManagerOpenVR()
- : mVRSystem(nullptr), mOpenVRInstalled(false)
+ : mVRSystem(nullptr)
+ , mOpenVRInstalled(false)
{
}
/*static*/ already_AddRefed<VRSystemManagerOpenVR>
VRSystemManagerOpenVR::Create()
{
MOZ_ASSERT(NS_IsMainThread());
@@ -554,109 +535,199 @@ VRSystemManagerOpenVR::HandleInput()
// mVRSystem is available after VRDisplay is created
// at GetHMDs().
if (!mVRSystem) {
return;
}
RefPtr<impl::VRControllerOpenVR> controller;
vr::VRControllerState_t state;
- uint32_t axis = 0;
-
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;
controller = mOpenVRController[i];
+ const uint32_t trackedIndex = controller->GetTrackedIndex();
- MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(controller->GetTrackedIndex())
+ MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(trackedIndex)
== vr::TrackedDeviceClass_Controller);
- if (mVRSystem->GetControllerState(controller->GetTrackedIndex(), &state)) {
- HandleButtonPress(controller->GetIndex(), state.ulButtonPressed);
-
- axis = static_cast<uint32_t>(VRControllerAxisType::TrackpadXAxis);
- HandleAxisMove(controller->GetIndex(), axis,
- state.rAxis[gOpenVRAxes[axis]].x);
-
- axis = static_cast<uint32_t>(VRControllerAxisType::TrackpadYAxis);
- HandleAxisMove(controller->GetIndex(), axis,
- state.rAxis[gOpenVRAxes[axis]].y);
-
- axis = static_cast<uint32_t>(VRControllerAxisType::Trigger);
- HandleAxisMove(controller->GetIndex(), axis,
- state.rAxis[gOpenVRAxes[axis]].x);
- }
-
- // Start to process pose
- const ::vr::TrackedDevicePose_t& pose = poses[controller->GetTrackedIndex()];
-
- if (pose.bDeviceIsConnected && pose.bPoseIsValid &&
- pose.eTrackingResult == vr::TrackingResult_Running_OK) {
- gfx::Matrix4x4 m;
+ if (mVRSystem->GetControllerState(trackedIndex, &state)) {
+ for (uint32_t j = 0; j < vr::k_unControllerStateAxisCount; ++j) {
+ const uint32_t axisType = mVRSystem->GetInt32TrackedDeviceProperty(
+ trackedIndex,
+ static_cast<vr::TrackedDeviceProperty>(
+ vr::Prop_Axis0Type_Int32 + j));
+ switch (axisType) {
+ case vr::EVRControllerAxisType::k_eControllerAxis_Joystick:
+ case vr::EVRControllerAxisType::k_eControllerAxis_TrackPad:
+ HandleAxisMove(controller->GetIndex(), axisIdx,
+ state.rAxis[j].x);
+ ++axisIdx;
+ HandleAxisMove(controller->GetIndex(), axisIdx,
+ state.rAxis[j].y);
+ ++axisIdx;
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ vr::ButtonMaskFromId(
+ static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ break;
+ case vr::EVRControllerAxisType::k_eControllerAxis_Trigger:
+ HandleTriggerPress(i, buttonIdx,
+ vr::ButtonMaskFromId(
+ static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)),
+ state.rAxis[j].x, state.ulButtonPressed);
+ ++buttonIdx;
+ break;
+ }
+ }
+ MOZ_ASSERT(axisIdx ==
+ controller->GetControllerInfo().GetNumAxes());
- // NOTE! mDeviceToAbsoluteTracking is a 3x4 matrix, not 4x4. But
- // because of its arrangement, we can copy the 12 elements in and
- // then transpose them to the right place. We do this so we can
- // pull out a Quaternion.
- memcpy(&m.components, &pose.mDeviceToAbsoluteTracking, sizeof(float) * 12);
- m.Transpose();
-
- gfx::Quaternion rot;
- rot.SetFromRotationMatrix(m);
- rot.Invert();
+ const uint64_t supportedButtons = mVRSystem->GetUint64TrackedDeviceProperty(
+ trackedIndex, vr::Prop_SupportedButtons_Uint64);
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_A)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_A),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_Grip)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_Grip),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_ApplicationMenu)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_ApplicationMenu),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Left)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_DPad_Left),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Up)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_DPad_Up),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Right)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_DPad_Right),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Down)) {
+ HandleButtonPress(controller->GetIndex(), buttonIdx,
+ BTN_MASK_FROM_ID(k_EButton_DPad_Down),
+ state.ulButtonPressed);
+ ++buttonIdx;
+ }
+ MOZ_ASSERT(buttonIdx ==
+ controller->GetControllerInfo().GetNumButtons());
+ controller->SetButtonPressed(state.ulButtonPressed);
- GamepadPoseState poseState;
- poseState.flags |= GamepadCapabilityFlags::Cap_Orientation;
- poseState.orientation[0] = rot.x;
- poseState.orientation[1] = rot.y;
- poseState.orientation[2] = rot.z;
- poseState.orientation[3] = rot.w;
- poseState.angularVelocity[0] = pose.vAngularVelocity.v[0];
- poseState.angularVelocity[1] = pose.vAngularVelocity.v[1];
- poseState.angularVelocity[2] = pose.vAngularVelocity.v[2];
+ // Start to process pose
+ const ::vr::TrackedDevicePose_t& pose = poses[trackedIndex];
+
+ if (pose.bDeviceIsConnected && pose.bPoseIsValid &&
+ pose.eTrackingResult == vr::TrackingResult_Running_OK) {
+ gfx::Matrix4x4 m;
+
+ // NOTE! mDeviceToAbsoluteTracking is a 3x4 matrix, not 4x4. But
+ // because of its arrangement, we can copy the 12 elements in and
+ // then transpose them to the right place. We do this so we can
+ // pull out a Quaternion.
+ memcpy(&m.components, &pose.mDeviceToAbsoluteTracking, sizeof(float) * 12);
+ m.Transpose();
+
+ gfx::Quaternion rot;
+ rot.SetFromRotationMatrix(m);
+ rot.Invert();
- poseState.flags |= GamepadCapabilityFlags::Cap_Position;
- poseState.position[0] = m._41;
- poseState.position[1] = m._42;
- poseState.position[2] = m._43;
- poseState.linearVelocity[0] = pose.vVelocity.v[0];
- poseState.linearVelocity[1] = pose.vVelocity.v[1];
- poseState.linearVelocity[2] = pose.vVelocity.v[2];
- HandlePoseTracking(controller->GetIndex(), poseState, controller);
+ GamepadPoseState poseState;
+ poseState.flags |= GamepadCapabilityFlags::Cap_Orientation;
+ poseState.orientation[0] = rot.x;
+ poseState.orientation[1] = rot.y;
+ poseState.orientation[2] = rot.z;
+ poseState.orientation[3] = rot.w;
+ poseState.angularVelocity[0] = pose.vAngularVelocity.v[0];
+ poseState.angularVelocity[1] = pose.vAngularVelocity.v[1];
+ poseState.angularVelocity[2] = pose.vAngularVelocity.v[2];
+
+ poseState.flags |= GamepadCapabilityFlags::Cap_Position;
+ poseState.position[0] = m._41;
+ poseState.position[1] = m._42;
+ poseState.position[2] = m._43;
+ poseState.linearVelocity[0] = pose.vVelocity.v[0];
+ poseState.linearVelocity[1] = pose.vVelocity.v[1];
+ poseState.linearVelocity[2] = pose.vVelocity.v[2];
+ HandlePoseTracking(controller->GetIndex(), poseState, controller);
+ }
}
}
}
void
VRSystemManagerOpenVR::HandleButtonPress(uint32_t aControllerIdx,
+ uint32_t aButton,
+ uint64_t aButtonMask,
uint64_t aButtonPressed)
{
- uint64_t buttonMask = 0;
- RefPtr<impl::VRControllerOpenVR> controller;
- controller = mOpenVRController[aControllerIdx];
- uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
+ RefPtr<impl::VRControllerOpenVR> controller(mOpenVRController[aControllerIdx]);
+ MOZ_ASSERT(controller);
+ const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
if (!diff) {
return;
}
- for (uint32_t i = 0; i < gNumOpenVRButtonMask; ++i) {
- buttonMask = gOpenVRButtonMask[i];
+ if (diff & aButtonMask) {
+ // diff & aButtonPressed would be true while a new button press
+ // event, otherwise it is an old press event and needs to notify
+ // the button has been released.
+ NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
+ (aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
+ }
+}
- if (diff & buttonMask) {
- // diff & aButtonPressed would be true while a new button press
- // event, otherwise it is an old press event and needs to notify
- // the button has been released.
- NewButtonEvent(aControllerIdx, i, diff & aButtonPressed);
- }
+void
+VRSystemManagerOpenVR::HandleTriggerPress(uint32_t aControllerIdx,
+ uint32_t aButton,
+ uint64_t aButtonMask,
+ float aValue,
+ uint64_t aButtonPressed)
+{
+ RefPtr<impl::VRControllerOpenVR> controller(mOpenVRController[aControllerIdx]);
+ MOZ_ASSERT(controller);
+ const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
+ const float oldValue = controller->GetTrigger();
+
+ // Avoid sending duplicated events in IPC channels.
+ if ((oldValue != aValue) ||
+ (diff & aButtonMask)) {
+ NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed, aValue);
+ controller->SetTrigger(aValue);
}
-
- controller->SetButtonPressed(aButtonPressed);
}
void
VRSystemManagerOpenVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
float aValue)
{
if (aValue != 0.0f) {
NewAxisMove(aControllerIdx, aAxis, aValue);
@@ -711,42 +782,96 @@ VRSystemManagerOpenVR::ScanForController
continue;
}
trackedIndexArray[newControllerCount] = trackedDevice;
++newControllerCount;
}
if (newControllerCount != mControllerCount) {
- // controller count is changed, removing the existing gamepads first.
+ // The controller count is changed, removing the existing gamepads first.
for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
RemoveGamepad(mOpenVRController[i]->GetIndex());
}
mControllerCount = 0;
mOpenVRController.Clear();
// Re-adding controllers to VRControllerManager.
for (vr::TrackedDeviceIndex_t i = 0; i < newControllerCount; ++i) {
- vr::TrackedDeviceIndex_t trackedDevice = trackedIndexArray[i];
- vr::ETrackedControllerRole role =
- mVRSystem->GetControllerRoleForTrackedDeviceIndex(trackedDevice);
+ const vr::TrackedDeviceIndex_t trackedDevice = trackedIndexArray[i];
+ const vr::ETrackedControllerRole role = mVRSystem->
+ GetControllerRoleForTrackedDeviceIndex(
+ trackedDevice);
GamepadHand hand;
+ uint32_t numButtons = 0;
+ uint32_t numAxes = 0;
switch(role) {
case vr::ETrackedControllerRole::TrackedControllerRole_Invalid:
hand = GamepadHand::_empty;
break;
case vr::ETrackedControllerRole::TrackedControllerRole_LeftHand:
hand = GamepadHand::Left;
break;
case vr::ETrackedControllerRole::TrackedControllerRole_RightHand:
hand = GamepadHand::Right;
break;
}
- RefPtr<VRControllerOpenVR> openVRController = new VRControllerOpenVR(hand);
+
+ // 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;
+ break;
+ }
+ }
+
+ // Scan the buttons that the controllers support
+ const uint64_t supportButtons = mVRSystem->GetUint64TrackedDeviceProperty(
+ trackedDevice, vr::Prop_SupportedButtons_Uint64);
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_A)) {
+ ++numButtons;
+ }
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_Grip)) {
+ ++numButtons;
+ }
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_ApplicationMenu)) {
+ ++numButtons;
+ }
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Left)) {
+ ++numButtons;
+ }
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Up)) {
+ ++numButtons;
+ }
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Right)) {
+ ++numButtons;
+ }
+ if (supportButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Down)) {
+ ++numButtons;
+ }
+
+ RefPtr<VRControllerOpenVR> openVRController =
+ new VRControllerOpenVR(hand, numButtons, numAxes);
openVRController->SetIndex(mControllerCount);
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
@@ -67,25 +67,30 @@ protected:
void UpdateStageParameters();
void PollEvents();
};
class VRControllerOpenVR : public VRControllerHost
{
public:
- explicit VRControllerOpenVR(dom::GamepadHand aHand);
+ explicit VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aNumButtons,
+ uint32_t aNumAxes);
void SetTrackedIndex(uint32_t aTrackedIndex);
uint32_t GetTrackedIndex();
+ void SetTrigger(float aValue);
+ float GetTrigger();
protected:
virtual ~VRControllerOpenVR();
+private:
// The index of tracked devices from vr::IVRSystem.
uint32_t mTrackedIndex;
+ float mTrigger;
};
} // namespace impl
class VRSystemManagerOpenVR : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerOpenVR> Create();
@@ -98,23 +103,30 @@ public:
aControllerResult) override;
virtual void ScanForControllers() override;
virtual void RemoveControllers() override;
protected:
VRSystemManagerOpenVR();
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 HandleTriggerPress(uint32_t aControllerIdx,
+ uint32_t aButton,
+ uint64_t aButtonMask,
+ float aValue,
+ uint64_t aButtonPressed);
+ void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
+ float aValue);
+ void HandlePoseTracking(uint32_t aControllerIdx,
+ const dom::GamepadPoseState& aPose,
+ VRControllerHost* aController);
// there can only be one
RefPtr<impl::VRDisplayOpenVR> mOpenVRHMD;
nsTArray<RefPtr<impl::VRControllerOpenVR>> mOpenVRController;
vr::IVRSystem *mVRSystem;
bool mOpenVRInstalled;
};