mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1299937 - Part 3: Implement haptic pulse for OpenVR controller; r=kip,qdot
MozReview-Commit-ID: TUIbJpyng4 --HG-- extra : rebase_source : e449c85d0e8f9a64a63929d1211dbca3fed8a4b6
This commit is contained in:
parent
49b8854fd8
commit
3905da3aea
@ -146,6 +146,7 @@ VRDisplayHost::CheckClearDisplayInfoDirty()
|
||||
}
|
||||
|
||||
VRControllerHost::VRControllerHost(VRDeviceType aType)
|
||||
: mVibrateIndex(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(VRControllerHost);
|
||||
mControllerInfo.mType = aType;
|
||||
@ -193,3 +194,14 @@ VRControllerHost::GetHand()
|
||||
return mControllerInfo.mHand;
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerHost::SetVibrateIndex(uint64_t aIndex)
|
||||
{
|
||||
mVibrateIndex = aIndex;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
VRControllerHost::GetVibrateIndex()
|
||||
{
|
||||
return mVibrateIndex;
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ public:
|
||||
void SetPose(const dom::GamepadPoseState& aPose);
|
||||
const dom::GamepadPoseState& GetPose();
|
||||
dom::GamepadHand GetHand();
|
||||
void SetVibrateIndex(uint64_t aIndex);
|
||||
uint64_t GetVibrateIndex();
|
||||
|
||||
protected:
|
||||
explicit VRControllerHost(VRDeviceType aType);
|
||||
@ -101,6 +103,7 @@ protected:
|
||||
VRControllerInfo mControllerInfo;
|
||||
// The current button pressed bit of button mask.
|
||||
uint64_t mButtonPressed;
|
||||
uint64_t mVibrateIndex;
|
||||
dom::GamepadPoseState mPose;
|
||||
};
|
||||
|
||||
|
@ -423,5 +423,15 @@ VRManager::NotifyGamepadChange(const T& aInfo)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRManager::VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration)
|
||||
{
|
||||
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
|
||||
mManagers[i]->VibrateHaptic(aControllerIdx, aHapticIndex,
|
||||
aIntensity, aDuration);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
RefPtr<gfx::VRControllerHost> GetController(const uint32_t& aControllerID);
|
||||
void GetVRControllerInfo(nsTArray<VRControllerInfo>& aControllerInfo);
|
||||
void CreateVRTestSystem();
|
||||
void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration);
|
||||
|
||||
protected:
|
||||
VRManager();
|
||||
|
@ -67,7 +67,8 @@ VRSystemManager::AddGamepad(const VRControllerInfo& controllerInfo)
|
||||
controllerInfo.GetHand(),
|
||||
dom::GamepadServiceType::VR,
|
||||
controllerInfo.GetNumButtons(),
|
||||
controllerInfo.GetNumAxes());
|
||||
controllerInfo.GetNumAxes(),
|
||||
controllerInfo.GetNumHaptics());
|
||||
|
||||
VRManager* vm = VRManager::Get();
|
||||
MOZ_ASSERT(vm);
|
||||
|
@ -214,6 +214,7 @@ struct VRControllerInfo
|
||||
dom::GamepadHand GetHand() const { return mHand; }
|
||||
uint32_t GetNumButtons() const { return mNumButtons; }
|
||||
uint32_t GetNumAxes() const { return mNumAxes; }
|
||||
uint32_t GetNumHaptics() const { return mNumHaptics; }
|
||||
|
||||
uint32_t mControllerID;
|
||||
VRDeviceType mType;
|
||||
@ -222,6 +223,7 @@ struct VRControllerInfo
|
||||
dom::GamepadHand mHand;
|
||||
uint32_t mNumButtons;
|
||||
uint32_t mNumAxes;
|
||||
uint32_t mNumHaptics;
|
||||
|
||||
bool operator==(const VRControllerInfo& other) const {
|
||||
return mType == other.mType &&
|
||||
@ -230,7 +232,8 @@ struct VRControllerInfo
|
||||
mMappingType == other.mMappingType &&
|
||||
mHand == other.mHand &&
|
||||
mNumButtons == other.mNumButtons &&
|
||||
mNumAxes == other.mNumAxes;
|
||||
mNumAxes == other.mNumAxes &&
|
||||
mNumHaptics == other.mNumHaptics;
|
||||
}
|
||||
|
||||
bool operator!=(const VRControllerInfo& other) const {
|
||||
@ -256,6 +259,9 @@ public:
|
||||
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
|
||||
virtual void ScanForControllers() = 0;
|
||||
virtual void RemoveControllers() = 0;
|
||||
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration, uint32_t aPromiseID) = 0;
|
||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) = 0;
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, double aValue);
|
||||
void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
|
||||
void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
|
||||
|
@ -542,6 +542,20 @@ VRSystemManagerOSVR::HandleInput()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOSVR::VibrateHaptic(uint32_t aControllerIdx,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOSVR::StopVibrateHaptic(uint32_t aControllerIdx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOSVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
|
||||
{
|
||||
|
@ -73,6 +73,9 @@ public:
|
||||
aControllerResult) override;
|
||||
virtual void ScanForControllers() override;
|
||||
virtual void RemoveControllers() override;
|
||||
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration, uint32_t aPromiseID) override;
|
||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
|
||||
|
||||
protected:
|
||||
VRSystemManagerOSVR()
|
||||
|
@ -912,7 +912,8 @@ VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand)
|
||||
|
||||
mControllerInfo.mNumButtons = kNumOculusButton;
|
||||
mControllerInfo.mNumAxes = static_cast<uint32_t>(
|
||||
OculusControllerAxisType::NumVRControllerAxisType);;
|
||||
OculusControllerAxisType::NumVRControllerAxisType);
|
||||
mControllerInfo.mNumHaptics = kNumOculusHaptcs;
|
||||
}
|
||||
|
||||
float
|
||||
@ -1254,6 +1255,21 @@ VRSystemManagerOculus::HandlePoseTracking(uint32_t aControllerIdx,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOculus::VibrateHaptic(uint32_t aControllerIdx,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID)
|
||||
{
|
||||
// TODO: Bug 1305892
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOculus::StopVibrateHaptic(uint32_t aControllerIdx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOculus::GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
||||
aControllerResult)
|
||||
|
@ -129,6 +129,9 @@ public:
|
||||
aControllerResult) override;
|
||||
virtual void ScanForControllers() override;
|
||||
virtual void RemoveControllers() override;
|
||||
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration, uint32_t aPromiseID) override;
|
||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
|
||||
|
||||
protected:
|
||||
VRSystemManagerOculus()
|
||||
|
@ -59,6 +59,8 @@ static pfn_VR_GetGenericInterface vr_GetGenericInterface = nullptr;
|
||||
#define BTN_MASK_FROM_ID(_id) \
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::_id)
|
||||
|
||||
static const uint32_t kNumOpenVRHaptcs = 1;
|
||||
|
||||
|
||||
bool
|
||||
LoadOpenVRRuntime()
|
||||
@ -392,6 +394,8 @@ VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aNumButt
|
||||
uint32_t aNumAxes)
|
||||
: VRControllerHost(VRDeviceType::OpenVR)
|
||||
, mTrigger(0)
|
||||
, mVibrateThread(nullptr)
|
||||
, mIsVibrating(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
|
||||
mControllerInfo.mControllerName.AssignLiteral("OpenVR Gamepad");
|
||||
@ -399,10 +403,16 @@ VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aNumButt
|
||||
mControllerInfo.mHand = aHand;
|
||||
mControllerInfo.mNumButtons = aNumButtons;
|
||||
mControllerInfo.mNumAxes = aNumAxes;
|
||||
mControllerInfo.mNumHaptics = kNumOpenVRHaptcs;
|
||||
}
|
||||
|
||||
VRControllerOpenVR::~VRControllerOpenVR()
|
||||
{
|
||||
if (mVibrateThread) {
|
||||
mVibrateThread->Shutdown();
|
||||
mVibrateThread = nullptr;
|
||||
}
|
||||
|
||||
MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
|
||||
}
|
||||
|
||||
@ -430,6 +440,75 @@ VRControllerOpenVR::GetTrigger()
|
||||
return mTrigger;
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerOpenVR::UpdateVibrateHaptic(vr::IVRSystem* aVRSystem,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint64_t aVibrateIndex,
|
||||
uint32_t aPromiseID)
|
||||
{
|
||||
// UpdateVibrateHaptic() only can be called by mVibrateThread
|
||||
MOZ_ASSERT(mVibrateThread == NS_GetCurrentThread());
|
||||
// Avoid the previous vibrate event to override the new one.
|
||||
if (mVibrateIndex != aVibrateIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
double duration = (aIntensity == 0) ? 0 : aDuration;
|
||||
// We expect OpenVR to vibrate for 5 ms, but we found it only response the
|
||||
// commend ~ 3.9 ms. For duration time longer than 3.9 ms, we separate them
|
||||
// to a loop of 3.9 ms for make users feel that is a continuous events.
|
||||
uint32_t microSec = (duration < 3.9 ? duration : 3.9) * 1000 * aIntensity;
|
||||
aVRSystem->TriggerHapticPulse(GetTrackedIndex(),
|
||||
aHapticIndex, microSec);
|
||||
|
||||
// In OpenVR spec, it mentions TriggerHapticPulse() may not trigger another haptic pulse
|
||||
// on this controller and axis combination for 5ms.
|
||||
const double kVibrateRate = 5.0;
|
||||
if (duration >= kVibrateRate) {
|
||||
MOZ_ASSERT(mVibrateThread);
|
||||
|
||||
RefPtr<Runnable> runnable =
|
||||
NewRunnableMethod<vr::IVRSystem*, uint32_t, double, double, uint64_t, uint32_t>
|
||||
(this, &VRControllerOpenVR::UpdateVibrateHaptic, aVRSystem,
|
||||
aHapticIndex, aIntensity, duration - kVibrateRate, aVibrateIndex, aPromiseID);
|
||||
NS_DelayedDispatchToCurrentThread(runnable.forget(), kVibrateRate);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerOpenVR::VibrateHaptic(vr::IVRSystem* aVRSystem,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID)
|
||||
{
|
||||
// Spinning up the haptics thread at the first haptics call.
|
||||
if (!mVibrateThread) {
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(mVibrateThread));
|
||||
MOZ_ASSERT(mVibrateThread);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(false, "Failed to create async thread.");
|
||||
}
|
||||
}
|
||||
++mVibrateIndex;
|
||||
|
||||
mIsVibrating = true;
|
||||
RefPtr<Runnable> runnable =
|
||||
NewRunnableMethod<vr::IVRSystem*, uint32_t, double, double, uint64_t, uint32_t>
|
||||
(this, &VRControllerOpenVR::UpdateVibrateHaptic, aVRSystem,
|
||||
aHapticIndex, aIntensity, aDuration, mVibrateIndex, aPromiseID);
|
||||
mVibrateThread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerOpenVR::StopVibrateHaptic()
|
||||
{
|
||||
mIsVibrating = false;
|
||||
}
|
||||
|
||||
VRSystemManagerOpenVR::VRSystemManagerOpenVR()
|
||||
: mVRSystem(nullptr)
|
||||
, mOpenVRInstalled(false)
|
||||
@ -744,12 +823,47 @@ VRSystemManagerOpenVR::HandlePoseTracking(uint32_t aControllerIdx,
|
||||
const GamepadPoseState& aPose,
|
||||
VRControllerHost* aController)
|
||||
{
|
||||
MOZ_ASSERT(aController);
|
||||
if (aPose != aController->GetPose()) {
|
||||
aController->SetPose(aPose);
|
||||
NewPoseState(aControllerIdx, aPose);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOpenVR::VibrateHaptic(uint32_t aControllerIdx,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID)
|
||||
{
|
||||
// mVRSystem is available after VRDisplay is created
|
||||
// at GetHMDs().
|
||||
if (!mVRSystem) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<impl::VRControllerOpenVR> controller = mOpenVRController[aControllerIdx];
|
||||
MOZ_ASSERT(controller);
|
||||
|
||||
controller->VibrateHaptic(mVRSystem, aHapticIndex, aIntensity, aDuration, aPromiseID);
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOpenVR::StopVibrateHaptic(uint32_t aControllerIdx)
|
||||
{
|
||||
// mVRSystem is available after VRDisplay is created
|
||||
// at GetHMDs().
|
||||
if (!mVRSystem) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<impl::VRControllerOpenVR> controller = mOpenVRController[aControllerIdx];
|
||||
MOZ_ASSERT(controller);
|
||||
|
||||
controller->StopVibrateHaptic();
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOpenVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
|
||||
{
|
||||
@ -888,3 +1002,4 @@ VRSystemManagerOpenVR::RemoveControllers()
|
||||
mOpenVRController.Clear();
|
||||
mControllerCount = 0;
|
||||
}
|
||||
|
||||
|
@ -77,14 +77,29 @@ public:
|
||||
uint32_t GetTrackedIndex();
|
||||
void SetTrigger(float aValue);
|
||||
float GetTrigger();
|
||||
void VibrateHaptic(vr::IVRSystem* aVRSystem,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID);
|
||||
void StopVibrateHaptic();
|
||||
|
||||
protected:
|
||||
virtual ~VRControllerOpenVR();
|
||||
|
||||
private:
|
||||
void UpdateVibrateHaptic(vr::IVRSystem* aVRSystem,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint64_t aVibrateIndex,
|
||||
uint32_t aPromiseID);
|
||||
|
||||
// The index of tracked devices from vr::IVRSystem.
|
||||
uint32_t mTrackedIndex;
|
||||
float mTrigger;
|
||||
nsCOMPtr<nsIThread> mVibrateThread;
|
||||
bool mIsVibrating;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
@ -103,6 +118,12 @@ public:
|
||||
aControllerResult) override;
|
||||
virtual void ScanForControllers() override;
|
||||
virtual void RemoveControllers() override;
|
||||
virtual void VibrateHaptic(uint32_t aControllerIdx,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID) override;
|
||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
|
||||
|
||||
protected:
|
||||
VRSystemManagerOpenVR();
|
||||
|
@ -39,6 +39,8 @@ static const uint32_t kPuppetAxes[] = {
|
||||
static const uint32_t kNumPuppetAxis = sizeof(kPuppetAxes) /
|
||||
sizeof(uint32_t);
|
||||
|
||||
static const uint32_t kNumPuppetHaptcs = 1;
|
||||
|
||||
VRDisplayPuppet::VRDisplayPuppet()
|
||||
: VRDisplayHost(VRDeviceType::Puppet)
|
||||
, mIsPresenting(false)
|
||||
@ -236,6 +238,7 @@ VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand)
|
||||
mControllerInfo.mHand = aHand;
|
||||
mControllerInfo.mNumButtons = kNumPuppetButtonMask;
|
||||
mControllerInfo.mNumAxes = kNumPuppetAxis;
|
||||
mControllerInfo.mNumHaptics = kNumPuppetHaptcs;
|
||||
}
|
||||
|
||||
VRControllerPuppet::~VRControllerPuppet()
|
||||
@ -418,6 +421,20 @@ VRSystemManagerPuppet::HandlePoseTracking(uint32_t aControllerIdx,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerPuppet::VibrateHaptic(uint32_t aControllerIdx,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerPuppet::StopVibrateHaptic(uint32_t aControllerIdx)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerPuppet::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
|
||||
{
|
||||
|
@ -95,6 +95,12 @@ public:
|
||||
aControllerResult) override;
|
||||
virtual void ScanForControllers() override;
|
||||
virtual void RemoveControllers() override;
|
||||
virtual void VibrateHaptic(uint32_t aControllerIdx,
|
||||
uint32_t aHapticIndex,
|
||||
double aIntensity,
|
||||
double aDuration,
|
||||
uint32_t aPromiseID) override;
|
||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
|
||||
|
||||
protected:
|
||||
VRSystemManagerPuppet();
|
||||
|
@ -54,11 +54,15 @@ parent:
|
||||
|
||||
async ControllerListenerAdded();
|
||||
async ControllerListenerRemoved();
|
||||
async VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration);
|
||||
|
||||
async CreateVRTestSystem();
|
||||
async CreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID);
|
||||
async CreateVRServiceTestController(nsCString aID, uint32_t aPromiseID);
|
||||
async SetDisplayInfoToMockDisplay(uint32_t aDeviceID, VRDisplayInfo aDisplayInfo);
|
||||
async SetSensorStateToMockDisplay(uint32_t aDeviceID, VRHMDSensorState aSensorState);
|
||||
|
||||
async NewButtonEventToMockController(uint32_t aDeviceID, long aButton,
|
||||
bool aPressed);
|
||||
async NewAxisMoveEventToMockController(uint32_t aDeviceID, long aAxis,
|
||||
|
@ -438,6 +438,18 @@ VRManagerParent::RecvNewPoseMoveToMockController(const uint32_t& aDeviceID,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
VRManagerParent::RecvVibrateHaptic(const uint32_t& aControllerIdx,
|
||||
const uint32_t& aHapticIndex,
|
||||
const double& aIntensity,
|
||||
const double& aDuration)
|
||||
{
|
||||
VRManager* vm = VRManager::Get();
|
||||
vm->VibrateHaptic(aControllerIdx, aHapticIndex, aIntensity,
|
||||
aDuration);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool
|
||||
VRManagerParent::SendGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
|
||||
{
|
||||
|
@ -91,6 +91,8 @@ protected:
|
||||
virtual mozilla::ipc::IPCResult RecvSetHaveEventListener(const bool& aHaveEventListener) override;
|
||||
virtual mozilla::ipc::IPCResult RecvControllerListenerAdded() override;
|
||||
virtual mozilla::ipc::IPCResult RecvControllerListenerRemoved() override;
|
||||
virtual mozilla::ipc::IPCResult RecvVibrateHaptic(const uint32_t& aControllerIdx, const uint32_t& aHapticIndex,
|
||||
const double& aIntensity, const double& aDuration) override;
|
||||
virtual mozilla::ipc::IPCResult RecvCreateVRTestSystem() override;
|
||||
virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID) override;
|
||||
virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID) override;
|
||||
|
Loading…
Reference in New Issue
Block a user