author | Daosheng Mu <daoshengmu@gmail.com> |
Thu, 16 Mar 2017 15:57:04 +0800 | |
changeset 348322 | 45d7ca77e14763b44ed7d03dd2f2c5d3de87e1c1 |
parent 348321 | 109db936e344c10543191aceb01a81eec1fa9f3f |
child 348323 | 407f363abf4e31585b096a68b4a44ba303f79f9b |
push id | 88187 |
push user | archaeopteryx@coole-files.de |
push date | Sat, 18 Mar 2017 15:27:00 +0000 |
treeherder | mozilla-inbound@0b1d3324cffe [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kip |
bugs | 1346149 |
milestone | 55.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
|
gfx/vr/gfxVROpenVR.cpp | file | annotate | diff | comparison | revisions | |
gfx/vr/gfxVROpenVR.h | file | annotate | diff | comparison | revisions |
--- 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(); @@ -417,25 +383,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 @@ -445,18 +413,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()); @@ -548,109 +529,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); @@ -705,42 +776,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 @@ -66,25 +66,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(); @@ -97,23 +102,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; };