--- a/dom/vr/VRDisplay.cpp
+++ b/dom/vr/VRDisplay.cpp
@@ -280,68 +280,68 @@ VRPose::~VRPose()
mozilla::DropJSObjects(this);
}
void
VRPose::GetPosition(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
- SetFloat32Array(aCx, aRetval, mPosition, mVRState.position, 3,
+ SetFloat32Array(aCx, aRetval, mPosition, mVRState.pose.position, 3,
!mPosition && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position),
aRv);
}
void
VRPose::GetLinearVelocity(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
- SetFloat32Array(aCx, aRetval, mLinearVelocity, mVRState.linearVelocity, 3,
+ SetFloat32Array(aCx, aRetval, mLinearVelocity, mVRState.pose.linearVelocity, 3,
!mLinearVelocity && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position),
aRv);
}
void
VRPose::GetLinearAcceleration(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
- SetFloat32Array(aCx, aRetval, mLinearAcceleration, mVRState.linearAcceleration, 3,
+ SetFloat32Array(aCx, aRetval, mLinearAcceleration, mVRState.pose.linearAcceleration, 3,
!mLinearAcceleration && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_LinearAcceleration),
aRv);
}
void
VRPose::GetOrientation(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
- SetFloat32Array(aCx, aRetval, mOrientation, mVRState.orientation, 4,
+ SetFloat32Array(aCx, aRetval, mOrientation, mVRState.pose.orientation, 4,
!mOrientation && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation),
aRv);
}
void
VRPose::GetAngularVelocity(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
- SetFloat32Array(aCx, aRetval, mAngularVelocity, mVRState.angularVelocity, 3,
+ SetFloat32Array(aCx, aRetval, mAngularVelocity, mVRState.pose.angularVelocity, 3,
!mAngularVelocity && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation),
aRv);
}
void
VRPose::GetAngularAcceleration(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
- SetFloat32Array(aCx, aRetval, mAngularAcceleration, mVRState.angularAcceleration, 3,
+ SetFloat32Array(aCx, aRetval, mAngularAcceleration, mVRState.pose.angularAcceleration, 3,
!mAngularAcceleration && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_AngularAcceleration),
aRv);
}
JSObject*
VRPose::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRPose_Binding::Wrap(aCx, this, aGivenProto);
--- a/dom/vr/VRServiceTest.cpp
+++ b/dom/vr/VRServiceTest.cpp
@@ -90,60 +90,60 @@ VRMockDisplay::SetPose(const Nullable<Fl
VRDisplayCapabilityFlags::Cap_External |
VRDisplayCapabilityFlags::Cap_MountDetection |
VRDisplayCapabilityFlags::Cap_Present;
if (!aOrientation.IsNull()) {
const Float32Array& value = aOrientation.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 4);
- mSensorState.orientation[0] = value.Data()[0];
- mSensorState.orientation[1] = value.Data()[1];
- mSensorState.orientation[2] = value.Data()[2];
- mSensorState.orientation[3] = value.Data()[3];
+ mSensorState.pose.orientation[0] = value.Data()[0];
+ mSensorState.pose.orientation[1] = value.Data()[1];
+ mSensorState.pose.orientation[2] = value.Data()[2];
+ mSensorState.pose.orientation[3] = value.Data()[3];
}
if (!aAngularVelocity.IsNull()) {
const Float32Array& value = aAngularVelocity.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 3);
- mSensorState.angularVelocity[0] = value.Data()[0];
- mSensorState.angularVelocity[1] = value.Data()[1];
- mSensorState.angularVelocity[2] = value.Data()[2];
+ mSensorState.pose.angularVelocity[0] = value.Data()[0];
+ mSensorState.pose.angularVelocity[1] = value.Data()[1];
+ mSensorState.pose.angularVelocity[2] = value.Data()[2];
}
if (!aAngularAcceleration.IsNull()) {
const Float32Array& value = aAngularAcceleration.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 3);
- mSensorState.angularAcceleration[0] = value.Data()[0];
- mSensorState.angularAcceleration[1] = value.Data()[1];
- mSensorState.angularAcceleration[2] = value.Data()[2];
+ mSensorState.pose.angularAcceleration[0] = value.Data()[0];
+ mSensorState.pose.angularAcceleration[1] = value.Data()[1];
+ mSensorState.pose.angularAcceleration[2] = value.Data()[2];
}
if (!aPosition.IsNull()) {
const Float32Array& value = aPosition.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 3);
- mSensorState.position[0] = value.Data()[0];
- mSensorState.position[1] = value.Data()[1];
- mSensorState.position[2] = value.Data()[2];
+ mSensorState.pose.position[0] = value.Data()[0];
+ mSensorState.pose.position[1] = value.Data()[1];
+ mSensorState.pose.position[2] = value.Data()[2];
}
if (!aLinearVelocity.IsNull()) {
const Float32Array& value = aLinearVelocity.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 3);
- mSensorState.linearVelocity[0] = value.Data()[0];
- mSensorState.linearVelocity[1] = value.Data()[1];
- mSensorState.linearVelocity[2] = value.Data()[2];
+ mSensorState.pose.linearVelocity[0] = value.Data()[0];
+ mSensorState.pose.linearVelocity[1] = value.Data()[1];
+ mSensorState.pose.linearVelocity[2] = value.Data()[2];
}
if (!aLinearAcceleration.IsNull()) {
const Float32Array& value = aLinearAcceleration.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 3);
- mSensorState.linearAcceleration[0] = value.Data()[0];
- mSensorState.linearAcceleration[1] = value.Data()[1];
- mSensorState.linearAcceleration[2] = value.Data()[2];
+ mSensorState.pose.linearAcceleration[0] = value.Data()[0];
+ mSensorState.pose.linearAcceleration[1] = value.Data()[1];
+ mSensorState.pose.linearAcceleration[2] = value.Data()[2];
}
}
void
VRMockDisplay::Update()
{
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
--- a/gfx/vr/VRDisplayClient.cpp
+++ b/gfx/vr/VRDisplayClient.cpp
@@ -4,17 +4,20 @@
* 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 "nsIGlobalObject.h"
+#include "nsRefPtrHashtable.h"
#include "nsString.h"
+#include "mozilla/dom/GamepadManager.h"
#include "mozilla/Preferences.h"
#include "mozilla/Unused.h"
#include "nsServiceManagerUtils.h"
#include "nsIScreenManager.h"
#ifdef XP_WIN
#include "../layers/d3d11/CompositorD3D11.h"
#endif
@@ -29,16 +32,17 @@ using namespace mozilla::gfx;
VRDisplayClient::VRDisplayClient(const VRDisplayInfo& aDisplayInfo)
: mDisplayInfo(aDisplayInfo)
, bLastEventWasMounted(false)
, bLastEventWasPresenting(false)
, mPresentationCount(0)
, mLastEventFrameId(0)
, mLastPresentingGeneration(0)
+ , mLastEventControllerState{}
{
MOZ_COUNT_CTOR(VRDisplayClient);
}
VRDisplayClient::~VRDisplayClient() {
MOZ_COUNT_DTOR(VRDisplayClient);
}
@@ -123,16 +127,150 @@ VRDisplayClient::FireEvents()
}
}
// Check if we need to trigger VRDisplay.requestAnimationFrame
if (mLastEventFrameId != mDisplayInfo.mFrameId) {
mLastEventFrameId = mDisplayInfo.mFrameId;
vm->RunFrameRequestCallbacks();
}
+
+ FireGamepadEvents();
+}
+
+void
+VRDisplayClient::FireGamepadEvents()
+{
+ RefPtr<dom::GamepadManager> gamepadManager(dom::GamepadManager::GetService());
+ if (!gamepadManager) {
+ return;
+ }
+ for (int stateIndex=0; stateIndex < kVRControllerMaxCount; stateIndex++) {
+ const VRControllerState& state = mDisplayInfo.mControllerState[stateIndex];
+ const VRControllerState& lastState = mLastEventControllerState[stateIndex];
+ uint32_t gamepadId = mDisplayInfo.mDisplayID * kVRControllerMaxCount + stateIndex;
+ bool bIsNew = false;
+
+ // Send events to notify that controllers are removed
+ if (state.controllerName[0] == '\0') {
+ // Controller is not present
+ if (lastState.controllerName[0] != '\0') {
+ // Controller has been removed
+ dom::GamepadRemoved info;
+ dom::GamepadChangeEventBody body(info);
+ dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR, body);
+ gamepadManager->Update(event);
+ }
+ // Do not process any further events for removed controllers
+ continue;
+ }
+
+ // Send events to notify that new controllers are added
+ if (lastState.controllerName[0] == '\0') {
+ dom::GamepadAdded info(NS_ConvertUTF8toUTF16(state.controllerName),
+ dom::GamepadMappingType::_empty,
+ state.hand,
+ mDisplayInfo.mDisplayID,
+ state.numButtons,
+ state.numAxes,
+ state.numHaptics);
+ dom::GamepadChangeEventBody body(info);
+ dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR, body);
+ gamepadManager->Update(event);
+ bIsNew = true;
+ }
+
+ // Send events for handedness changes
+ if (state.hand != lastState.hand) {
+ dom::GamepadHandInformation info(state.hand);
+ dom::GamepadChangeEventBody body(info);
+ dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR, body);
+ gamepadManager->Update(event);
+ }
+
+ // Send events for axis value changes
+ for (uint32_t axisIndex = 0; axisIndex < state.numAxes; axisIndex++) {
+ if (state.axisValue[axisIndex] != lastState.axisValue[axisIndex]) {
+ dom::GamepadAxisInformation info(axisIndex, state.axisValue[axisIndex]);
+ dom::GamepadChangeEventBody body(info);
+ dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR, body);
+ gamepadManager->Update(event);
+ }
+ }
+
+ // Send events for trigger, touch, and button value changes
+ if (!bIsNew) {
+ // When a new controller is added, we do not emit button events for
+ // the initial state of the inputs.
+ for (uint32_t buttonIndex = 0; buttonIndex < state.numButtons; buttonIndex++) {
+ bool bPressed = (state.buttonPressed & (1ULL << buttonIndex)) != 0;
+ bool bTouched = (state.buttonTouched & (1ULL << buttonIndex)) != 0;
+ bool bLastPressed = (lastState.buttonPressed & (1ULL << buttonIndex)) != 0;
+ bool bLastTouched = (lastState.buttonTouched & (1ULL << buttonIndex)) != 0;
+
+ if (state.triggerValue[buttonIndex] != lastState.triggerValue[buttonIndex] ||
+ bPressed != bLastPressed ||
+ bTouched != bLastTouched) {
+ dom::GamepadButtonInformation info(buttonIndex, state.triggerValue[buttonIndex], bPressed, bTouched);
+ dom::GamepadChangeEventBody body(info);
+ dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR, body);
+ gamepadManager->Update(event);
+ }
+ }
+ }
+
+ // Send events for pose changes
+ // Note that VRPose is asserted to be a POD type so memcmp is safe
+ if (state.flags != lastState.flags ||
+ state.isPositionValid != lastState.isPositionValid ||
+ state.isOrientationValid != lastState.isOrientationValid ||
+ memcmp(&state.pose, &lastState.pose, sizeof(VRPose)) != 0) {
+
+ // Convert pose to GamepadPoseState
+ dom::GamepadPoseState poseState;
+ poseState.Clear();
+ poseState.flags = state.flags;
+
+ // Orientation values
+ poseState.isOrientationValid = state.isOrientationValid;
+ poseState.orientation[0] = state.pose.orientation[0];
+ poseState.orientation[1] = state.pose.orientation[1];
+ poseState.orientation[2] = state.pose.orientation[2];
+ poseState.orientation[3] = state.pose.orientation[3];
+ poseState.angularVelocity[0] = state.pose.angularVelocity[0];
+ poseState.angularVelocity[1] = state.pose.angularVelocity[1];
+ poseState.angularVelocity[2] = state.pose.angularVelocity[2];
+ poseState.angularAcceleration[0] = state.pose.angularAcceleration[0];
+ poseState.angularAcceleration[1] = state.pose.angularAcceleration[1];
+ poseState.angularAcceleration[2] = state.pose.angularAcceleration[2];
+
+ // Position values
+ poseState.isPositionValid = state.isPositionValid;
+ poseState.position[0] = state.pose.position[0];
+ poseState.position[1] = state.pose.position[1];
+ poseState.position[2] = state.pose.position[2];
+ poseState.linearVelocity[0] = state.pose.linearVelocity[0];
+ poseState.linearVelocity[1] = state.pose.linearVelocity[1];
+ poseState.linearVelocity[2] = state.pose.linearVelocity[2];
+ poseState.linearAcceleration[0] = state.pose.linearAcceleration[0];
+ poseState.linearAcceleration[1] = state.pose.linearAcceleration[1];
+ poseState.linearAcceleration[2] = state.pose.linearAcceleration[2];
+
+ // Send the event
+ dom::GamepadPoseInformation info(poseState);
+ dom::GamepadChangeEventBody body(info);
+ dom::GamepadChangeEvent event(gamepadId, dom::GamepadServiceType::VR, body);
+ gamepadManager->Update(event);
+ }
+ }
+
+ // Note that VRControllerState is asserted to be a POD type and memcpy is safe.
+ memcpy(mLastEventControllerState,
+ mDisplayInfo.mControllerState,
+ sizeof(VRControllerState) * kVRControllerMaxCount);
}
VRHMDSensorState
VRDisplayClient::GetSensorState()
{
return mDisplayInfo.GetSensorState();
}
--- a/gfx/vr/VRDisplayClient.h
+++ b/gfx/vr/VRDisplayClient.h
@@ -46,25 +46,30 @@ public:
bool IsPresentationGenerationCurrent() const;
void MakePresentationGenerationCurrent();
protected:
virtual ~VRDisplayClient();
void FireEvents();
+ void FireGamepadEvents();
VRDisplayInfo mDisplayInfo;
bool bLastEventWasMounted;
bool bLastEventWasPresenting;
int mPresentationCount;
uint64_t mLastEventFrameId;
uint32_t mLastPresentingGeneration;
+
+ // Difference between mDisplayInfo.mControllerState and mLastEventControllerState
+ // determines what gamepad events to fire when updated.
+ VRControllerState mLastEventControllerState[kVRControllerMaxCount];
private:
VRSubmitFrameResultInfo mSubmitFrameResult;
};
} // namespace gfx
} // namespace mozilla
#endif /* GFX_VR_DISPLAY_CLIENT_H */
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -347,17 +347,17 @@ VRDisplayHost::CheckClearDisplayInfoDirt
VRControllerHost::VRControllerHost(VRDeviceType aType, dom::GamepadHand aHand,
uint32_t aDisplayID)
: mControllerInfo{}
, mVibrateIndex(0)
{
MOZ_COUNT_CTOR(VRControllerHost);
mControllerInfo.mType = aType;
- mControllerInfo.mControllerState.mHand = aHand;
+ mControllerInfo.mControllerState.hand = aHand;
mControllerInfo.mMappingType = dom::GamepadMappingType::_empty;
mControllerInfo.mDisplayID = aDisplayID;
mControllerInfo.mControllerID = VRSystemManager::AllocateControllerID();
}
VRControllerHost::~VRControllerHost()
{
MOZ_COUNT_DTOR(VRControllerHost);
@@ -367,35 +367,35 @@ const VRControllerInfo&
VRControllerHost::GetControllerInfo() const
{
return mControllerInfo;
}
void
VRControllerHost::SetButtonPressed(uint64_t aBit)
{
- mControllerInfo.mControllerState.mButtonPressed = aBit;
+ mControllerInfo.mControllerState.buttonPressed = aBit;
}
uint64_t
VRControllerHost::GetButtonPressed()
{
- return mControllerInfo.mControllerState.mButtonPressed;
+ return mControllerInfo.mControllerState.buttonPressed;
}
void
VRControllerHost::SetButtonTouched(uint64_t aBit)
{
- mControllerInfo.mControllerState.mButtonTouched = aBit;
+ mControllerInfo.mControllerState.buttonTouched = aBit;
}
uint64_t
VRControllerHost::GetButtonTouched()
{
- return mControllerInfo.mControllerState.mButtonTouched;
+ return mControllerInfo.mControllerState.buttonTouched;
}
void
VRControllerHost::SetPose(const dom::GamepadPoseState& aPose)
{
mPose = aPose;
}
@@ -403,17 +403,17 @@ const dom::GamepadPoseState&
VRControllerHost::GetPose()
{
return mPose;
}
dom::GamepadHand
VRControllerHost::GetHand()
{
- return mControllerInfo.mControllerState.mHand;
+ return mControllerInfo.mControllerState.hand;
}
void
VRControllerHost::SetVibrateIndex(uint64_t aIndex)
{
mVibrateIndex = aIndex;
}
--- a/gfx/vr/external_api/moz_external_vr.h
+++ b/gfx/vr/external_api/moz_external_vr.h
@@ -19,37 +19,38 @@
#if defined(__ANDROID__)
#include <pthread.h>
#endif // defined(__ANDROID__)
namespace mozilla {
#ifdef MOZILLA_INTERNAL_API
namespace dom {
enum class GamepadHand : uint8_t;
+ enum class GamepadCapabilityFlags : uint16_t;
}
#endif // MOZILLA_INTERNAL_API
namespace gfx {
-static const int32_t kVRExternalVersion = 0;
+static const int32_t kVRExternalVersion = 1;
// We assign VR presentations to groups with a bitmask.
// Currently, we will only display either content or chrome.
// Later, we will have more groups to support VR home spaces and
// multitasking environments.
// These values are not exposed to regular content and only affect
// chrome-only API's. They may be changed at any time.
static const uint32_t kVRGroupNone = 0;
static const uint32_t kVRGroupContent = 1 << 0;
static const uint32_t kVRGroupChrome = 1 << 1;
static const uint32_t kVRGroupAll = 0xffffffff;
static const int kVRDisplayNameMaxLen = 256;
static const int kVRControllerNameMaxLen = 256;
static const int kVRControllerMaxCount = 16;
-static const int kVRControllerMaxTriggers = 16;
+static const int kVRControllerMaxButtons = 64;
static const int kVRControllerMaxAxis = 16;
static const int kVRLayerMaxCount = 8;
struct Point3D_POD
{
float x;
float y;
float z;
@@ -71,16 +72,42 @@ struct FloatSize_POD
enum class ControllerHand : uint8_t {
_empty,
Left,
Right,
EndGuard_
};
+enum class ControllerCapabilityFlags : uint16_t {
+ Cap_None = 0,
+ /**
+ * Cap_Position is set if the Gamepad is capable of tracking its position.
+ */
+ Cap_Position = 1 << 1,
+ /**
+ * Cap_Orientation is set if the Gamepad is capable of tracking its orientation.
+ */
+ Cap_Orientation = 1 << 2,
+ /**
+ * Cap_AngularAcceleration is set if the Gamepad is capable of tracking its
+ * angular acceleration.
+ */
+ Cap_AngularAcceleration = 1 << 3,
+ /**
+ * Cap_LinearAcceleration is set if the Gamepad is capable of tracking its
+ * linear acceleration.
+ */
+ Cap_LinearAcceleration = 1 << 4,
+ /**
+ * Cap_All used for validity checking during IPC serialization
+ */
+ Cap_All = (1 << 5) - 1
+};
+
#endif // ifndef MOZILLA_INTERNAL_API
enum class VRDisplayCapabilityFlags : uint16_t {
Cap_None = 0,
/**
* Cap_Position is set if the VRDisplay is capable of tracking its position.
*/
Cap_Position = 1 << 1,
@@ -129,30 +156,35 @@ enum class VRDisplayCapabilityFlags : ui
*/
Cap_All = (1 << 9) - 1
};
#ifdef MOZILLA_INTERNAL_API
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayCapabilityFlags)
#endif // MOZILLA_INTERNAL_API
+struct VRPose
+{
+ float orientation[4];
+ float position[3];
+ float angularVelocity[3];
+ float angularAcceleration[3];
+ float linearVelocity[3];
+ float linearAcceleration[3];
+};
+
struct VRHMDSensorState {
int64_t inputFrameID;
double timestamp;
VRDisplayCapabilityFlags flags;
// These members will only change with inputFrameID:
- float orientation[4];
- float position[3];
+ VRPose pose;
float leftViewMatrix[16];
float rightViewMatrix[16];
- float angularVelocity[3];
- float angularAcceleration[3];
- float linearVelocity[3];
- float linearAcceleration[3];
#ifdef MOZILLA_INTERNAL_API
void Clear() {
memset(this, 0, sizeof(VRHMDSensorState));
}
bool operator==(const VRHMDSensorState& other) const {
@@ -237,32 +269,40 @@ struct VRDisplayState
float mSittingToStandingTransform[16];
uint64_t mLastSubmittedFrameId;
bool mLastSubmittedFrameSuccessful;
uint32_t mPresentingGeneration;
};
struct VRControllerState
{
- char mControllerName[kVRControllerNameMaxLen];
+ char controllerName[kVRControllerNameMaxLen];
#ifdef MOZILLA_INTERNAL_API
- dom::GamepadHand mHand;
+ dom::GamepadHand hand;
#else
- ControllerHand mHand;
+ ControllerHand hand;
#endif
- uint32_t mNumButtons;
- uint32_t mNumAxes;
- uint32_t mNumTriggers;
- uint32_t mNumHaptics;
+ uint32_t numButtons;
+ uint32_t numAxes;
+ uint32_t numHaptics;
// The current button pressed bit of button mask.
- uint64_t mButtonPressed;
+ uint64_t buttonPressed;
// The current button touched bit of button mask.
- uint64_t mButtonTouched;
- float mTriggerValue[kVRControllerMaxTriggers];
- float mAxisValue[kVRControllerMaxAxis];
+ uint64_t buttonTouched;
+ float triggerValue[kVRControllerMaxButtons];
+ float axisValue[kVRControllerMaxAxis];
+
+#ifdef MOZILLA_INTERNAL_API
+ dom::GamepadCapabilityFlags flags;
+#else
+ ControllerCapabilityFlags flags;
+#endif
+ VRPose pose;
+ bool isPositionValid;
+ bool isOrientationValid;
};
struct VRLayerEyeRect
{
float x;
float y;
float width;
float height;
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -184,20 +184,20 @@ VRSystemManager::NewHandChangeEvent(uint
}
void
VRHMDSensorState::CalcViewMatrices(const gfx::Matrix4x4* aHeadToEyeTransforms)
{
gfx::Matrix4x4 matHead;
if (flags & VRDisplayCapabilityFlags::Cap_Orientation) {
- matHead.SetRotationFromQuaternion(gfx::Quaternion(orientation[0], orientation[1],
- orientation[2], orientation[3]));
+ matHead.SetRotationFromQuaternion(gfx::Quaternion(pose.orientation[0], pose.orientation[1],
+ pose.orientation[2], pose.orientation[3]));
}
- matHead.PreTranslate(-position[0], -position[1], -position[2]);
+ matHead.PreTranslate(-pose.position[0], -pose.position[1], -pose.position[2]);
gfx::Matrix4x4 matView = matHead * aHeadToEyeTransforms[VRDisplayState::Eye_Left];
matView.Normalize();
memcpy(leftViewMatrix, matView.components, sizeof(matView.components));
matView = matHead * aHeadToEyeTransforms[VRDisplayState::Eye_Right];
matView.Normalize();
memcpy(rightViewMatrix, matView.components, sizeof(matView.components));
}
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -55,16 +55,17 @@ enum class VRDeviceType : uint16_t {
struct VRDisplayInfo
{
uint32_t mDisplayID;
VRDeviceType mType;
uint32_t mPresentingGroups;
uint32_t mGroupMask;
uint64_t mFrameId;
VRDisplayState mDisplayState;
+ VRControllerState mControllerState[kVRControllerMaxCount];
VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames];
const VRHMDSensorState& GetSensorState() const
{
return mLastSensorState[mFrameId % kVRMaxLatencyFrames];
}
VRDeviceType GetType() const { return mType; }
@@ -84,20 +85,21 @@ struct VRDisplayInfo
uint64_t GetFrameId() const { return mFrameId; }
bool operator==(const VRDisplayInfo& other) const {
for (size_t i = 0; i < kVRMaxLatencyFrames; i++) {
if (mLastSensorState[i] != other.mLastSensorState[i]) {
return false;
}
}
- // Note that mDisplayState is asserted to be a POD type, so memcmp is safe
+ // Note that mDisplayState and mControllerState are asserted to be POD types, so memcmp is safe
return mType == other.mType &&
mDisplayID == other.mDisplayID &&
memcmp(&mDisplayState, &other.mDisplayState, sizeof(VRDisplayState)) == 0 &&
+ memcmp(mControllerState, other.mControllerState, sizeof(VRControllerState) * kVRControllerMaxCount) == 0 &&
mPresentingGroups == other.mPresentingGroups &&
mGroupMask == other.mGroupMask &&
mFrameId == other.mFrameId;
}
bool operator!=(const VRDisplayInfo& other) const {
return !(*this == other);
}
@@ -118,39 +120,36 @@ struct VRSubmitFrameResultInfo
uint32_t mWidth;
uint32_t mHeight;
};
struct VRControllerInfo
{
VRDeviceType GetType() const { return mType; }
uint32_t GetControllerID() const { return mControllerID; }
- const char* GetControllerName() const { return mControllerState.mControllerName; }
+ const char* GetControllerName() const { return mControllerState.controllerName; }
dom::GamepadMappingType GetMappingType() const { return mMappingType; }
uint32_t GetDisplayID() const { return mDisplayID; }
- dom::GamepadHand GetHand() const { return mControllerState.mHand; }
- uint32_t GetNumButtons() const { return mControllerState.mNumButtons; }
- uint32_t GetNumAxes() const { return mControllerState.mNumAxes; }
- uint32_t GetNumHaptics() const { return mControllerState.mNumHaptics; }
+ dom::GamepadHand GetHand() const { return mControllerState.hand; }
+ uint32_t GetNumButtons() const { return mControllerState.numButtons; }
+ uint32_t GetNumAxes() const { return mControllerState.numAxes; }
+ uint32_t GetNumHaptics() const { return mControllerState.numHaptics; }
uint32_t mControllerID;
VRDeviceType mType;
dom::GamepadMappingType mMappingType;
uint32_t mDisplayID;
VRControllerState mControllerState;
bool operator==(const VRControllerInfo& other) const {
+ // Note that mControllerState is asserted to be a POD type, so memcmp is safe
return mType == other.mType &&
mControllerID == other.mControllerID &&
- strncmp(mControllerState.mControllerName, other.mControllerState.mControllerName, kVRControllerNameMaxLen) == 0 &&
+ memcmp(&mControllerState, &other.mControllerState, sizeof(VRControllerState)) == 0 &&
mMappingType == other.mMappingType &&
- mDisplayID == other.mDisplayID &&
- mControllerState.mHand == other.mControllerState.mHand &&
- mControllerState.mNumButtons == other.mControllerState.mNumButtons &&
- mControllerState.mNumAxes == other.mControllerState.mNumAxes &&
- mControllerState.mNumHaptics == other.mControllerState.mNumHaptics;
+ mDisplayID == other.mDisplayID;
}
bool operator!=(const VRControllerInfo& other) const {
return !(*this == other);
}
};
struct VRTelemetry
--- a/gfx/vr/gfxVRExternal.cpp
+++ b/gfx/vr/gfxVRExternal.cpp
@@ -47,56 +47,52 @@ static const char* kShmemName = "/moz.ge
#endif
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::gfx::impl;
using namespace mozilla::layers;
using namespace mozilla::dom;
-static const uint32_t kNumExternalHaptcs = 1;
-
VRDisplayExternal::VRDisplayExternal(const VRDisplayState& aDisplayState)
: VRDisplayHost(VRDeviceType::External)
, mIsPresenting(false)
, mLastSensorState{}
{
MOZ_COUNT_CTOR_INHERITED(VRDisplayExternal, VRDisplayHost);
mDisplayInfo.mDisplayState = aDisplayState;
// default to an identity quaternion
- mLastSensorState.orientation[3] = 1.0f;
+ mLastSensorState.pose.orientation[3] = 1.0f;
}
VRDisplayExternal::~VRDisplayExternal()
{
Destroy();
MOZ_COUNT_DTOR_INHERITED(VRDisplayExternal, VRDisplayHost);
}
void
VRDisplayExternal::Destroy()
{
StopPresentation();
-
- // TODO - Implement
}
void
VRDisplayExternal::ZeroSensor()
{
}
void
VRDisplayExternal::Refresh()
{
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
- manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState);
+ manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState, mDisplayInfo.mControllerState);
}
VRHMDSensorState
VRDisplayExternal::GetSensorState()
{
return mLastSensorState;
}
@@ -216,52 +212,32 @@ VRDisplayExternal::SubmitFrame(const lay
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state);
VRDisplayState displayState;
memset(&displayState, 0, sizeof(VRDisplayState));
while (displayState.mLastSubmittedFrameId < aFrameId) {
- if (manager->PullState(&displayState, &mLastSensorState)) {
+ if (manager->PullState(&displayState, &mLastSensorState, mDisplayInfo.mControllerState)) {
if (!displayState.mIsConnected) {
// Service has shut down or hardware has been disconnected
return false;
}
}
#ifdef XP_WIN
Sleep(0);
#else
sleep(0);
#endif
}
return displayState.mLastSubmittedFrameSuccessful;
}
-VRControllerExternal::VRControllerExternal(dom::GamepadHand aHand, uint32_t aDisplayID,
- uint32_t aNumButtons, uint32_t aNumTriggers,
- uint32_t aNumAxes, const nsCString& aId)
- : VRControllerHost(VRDeviceType::External, aHand, aDisplayID)
-{
- MOZ_COUNT_CTOR_INHERITED(VRControllerExternal, VRControllerHost);
-
- VRControllerState& state = mControllerInfo.mControllerState;
- strncpy(state.mControllerName, aId.BeginReading(), kVRControllerNameMaxLen);
- state.mNumButtons = aNumButtons;
- state.mNumAxes = aNumAxes;
- state.mNumTriggers = aNumTriggers;
- state.mNumHaptics = kNumExternalHaptcs;
-}
-
-VRControllerExternal::~VRControllerExternal()
-{
- MOZ_COUNT_DTOR_INHERITED(VRControllerExternal, VRControllerHost);
-}
-
VRSystemManagerExternal::VRSystemManagerExternal(VRExternalShmem* aAPIShmem /* = nullptr*/)
: mExternalShmem(aAPIShmem)
, mSameProcess(aAPIShmem != nullptr)
{
#if defined(XP_MACOSX)
mShmemFD = 0;
#elif defined(XP_WIN)
mShmemFile = NULL;
@@ -423,17 +399,16 @@ VRSystemManagerExternal::Destroy()
}
void
VRSystemManagerExternal::Shutdown()
{
if (mDisplay) {
mDisplay = nullptr;
}
- RemoveControllers();
CloseShmem();
#if defined(MOZ_WIDGET_ANDROID)
mDoShutdown = false;
#endif
}
void
VRSystemManagerExternal::NotifyVSync()
@@ -503,22 +478,16 @@ VRSystemManagerExternal::GetIsPresenting
VRDisplayInfo displayInfo(mDisplay->GetDisplayInfo());
return displayInfo.GetPresentingGroups() != 0;
}
return false;
}
void
-VRSystemManagerExternal::HandleInput()
-{
- // TODO - Implement This!
-}
-
-void
VRSystemManagerExternal::VibrateHaptic(uint32_t aControllerIdx,
uint32_t aHapticIndex,
double aIntensity,
double aDuration,
const VRManagerPromise& aPromise)
{
// TODO - Implement this
}
@@ -527,63 +496,79 @@ void
VRSystemManagerExternal::StopVibrateHaptic(uint32_t aControllerIdx)
{
// TODO - Implement this
}
void
VRSystemManagerExternal::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
{
+ // Controller updates are handled in VRDisplayClient for VRSystemManagerExternal
aControllerResult.Clear();
- for (uint32_t i = 0; i < mExternalController.Length(); ++i) {
- aControllerResult.AppendElement(mExternalController[i]);
- }
}
void
VRSystemManagerExternal::ScanForControllers()
{
- // TODO - Implement this
+ // Controller updates are handled in VRDisplayClient for VRSystemManagerExternal
+ if (mDisplay) {
+ mDisplay->Refresh();
+ }
+ return;
+}
+
+void
+VRSystemManagerExternal::HandleInput()
+{
+ // Controller updates are handled in VRDisplayClient for VRSystemManagerExternal
+ if (mDisplay) {
+ mDisplay->Refresh();
+ }
+ return;
}
void
VRSystemManagerExternal::RemoveControllers()
{
- // The controller count is changed, removing the existing gamepads first.
- for (uint32_t i = 0; i < mExternalController.Length(); ++i) {
- RemoveGamepad(i);
- }
- mExternalController.Clear();
- mControllerCount = 0;
+ // Controller updates are handled in VRDisplayClient for VRSystemManagerExternal
+ return;
}
bool
-VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState /* = nullptr */)
+VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState,
+ VRHMDSensorState* aSensorState /* = nullptr */,
+ VRControllerState* aControllerState /* = nullptr */)
{
bool success = false;
MOZ_ASSERT(mExternalShmem);
if (mExternalShmem) {
#if defined(MOZ_WIDGET_ANDROID)
if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->systemMutex)) == 0) {
memcpy(aDisplayState, (void*)&(mExternalShmem->state.displayState), sizeof(VRDisplayState));
if (aSensorState) {
memcpy(aSensorState, (void*)&(mExternalShmem->state.sensorState), sizeof(VRHMDSensorState));
}
+ if (aControllerState) {
+ memcpy(aControllerState, (void*)&(mExternalShmem->state.controllerState), sizeof(VRControllerState) * kVRControllerMaxCount);
+ }
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->systemMutex));
mDoShutdown = aDisplayState->shutdown;
success = mExternalShmem->state.enumerationCompleted;
}
#else
VRExternalShmem tmp;
memcpy(&tmp, (void *)mExternalShmem, sizeof(VRExternalShmem));
if (tmp.generationA == tmp.generationB && tmp.generationA != 0 && tmp.generationA != -1 && tmp.state.enumerationCompleted) {
memcpy(aDisplayState, &tmp.state.displayState, sizeof(VRDisplayState));
if (aSensorState) {
memcpy(aSensorState, &tmp.state.sensorState, sizeof(VRHMDSensorState));
}
+ if (aControllerState) {
+ memcpy(aControllerState, (void*)&(mExternalShmem->state.controllerState), sizeof(VRControllerState) * kVRControllerMaxCount);
+ }
success = true;
}
#endif // defined(MOZ_WIDGET_ANDROID)
}
return success;
}
--- a/gfx/vr/gfxVRExternal.h
+++ b/gfx/vr/gfxVRExternal.h
@@ -40,41 +40,31 @@ protected:
bool SubmitFrame(const layers::SurfaceDescriptor& aTexture,
uint64_t aFrameId,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
public:
explicit VRDisplayExternal(const VRDisplayState& aDisplayState);
void Refresh();
+ const VRControllerState& GetLastControllerState(uint32_t aStateIndex) const;
protected:
virtual ~VRDisplayExternal();
void Destroy();
private:
bool PopulateLayerTexture(const layers::SurfaceDescriptor& aTexture,
VRLayerTextureType* aTextureType,
void** aTextureHandle);
VRTelemetry mTelemetry;
bool mIsPresenting;
VRHMDSensorState mLastSensorState;
};
-class VRControllerExternal : public VRControllerHost
-{
-public:
- explicit VRControllerExternal(dom::GamepadHand aHand, uint32_t aDisplayID, uint32_t aNumButtons,
- uint32_t aNumTriggers, uint32_t aNumAxes,
- const nsCString& aId);
-
-protected:
- virtual ~VRControllerExternal();
-};
-
} // namespace impl
class VRSystemManagerExternal : public VRSystemManager
{
public:
static already_AddRefed<VRSystemManagerExternal> Create(VRExternalShmem* aAPIShmem = nullptr);
virtual void Destroy() override;
@@ -90,27 +80,28 @@ public:
virtual void ScanForControllers() override;
virtual void RemoveControllers() override;
virtual void VibrateHaptic(uint32_t aControllerIdx,
uint32_t aHapticIndex,
double aIntensity,
double aDuration,
const VRManagerPromise& aPromise) override;
virtual void StopVibrateHaptic(uint32_t aControllerIdx) override;
- bool PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState = nullptr);
+ bool PullState(VRDisplayState* aDisplayState,
+ VRHMDSensorState* aSensorState = nullptr,
+ VRControllerState* aControllerState = nullptr);
void PushState(VRBrowserState* aBrowserState);
protected:
explicit VRSystemManagerExternal(VRExternalShmem* aAPIShmem = nullptr);
virtual ~VRSystemManagerExternal();
private:
// there can only be one
RefPtr<impl::VRDisplayExternal> mDisplay;
- nsTArray<RefPtr<impl::VRControllerExternal>> mExternalController;
#if defined(XP_MACOSX)
int mShmemFD;
#elif defined(XP_WIN)
HANDLE mShmemFile;
#elif defined(MOZ_WIDGET_ANDROID)
bool mDoShutdown;
bool mExternalStructFailed;
#endif
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -312,32 +312,32 @@ VRDisplayOSVR::GetSensorState()
OSVR_ReturnCode ret =
osvr_GetOrientationState(*m_iface, ×tamp, &orientation);
result.timestamp = timestamp.seconds;
result.inputFrameID = mDisplayInfo.mFrameId;
if (ret == OSVR_RETURN_SUCCESS) {
result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
- result.orientation[0] = orientation.data[1];
- result.orientation[1] = orientation.data[2];
- result.orientation[2] = orientation.data[3];
- result.orientation[3] = orientation.data[0];
+ result.pose.orientation[0] = orientation.data[1];
+ result.pose.orientation[1] = orientation.data[2];
+ result.pose.orientation[2] = orientation.data[3];
+ result.pose.orientation[3] = orientation.data[0];
} else {
// default to an identity quaternion
- result.orientation[3] = 1.0f;
+ result.pose.orientation[3] = 1.0f;
}
OSVR_PositionState position;
ret = osvr_GetPositionState(*m_iface, ×tamp, &position);
if (ret == OSVR_RETURN_SUCCESS) {
result.flags |= VRDisplayCapabilityFlags::Cap_Position;
- result.position[0] = position.data[0];
- result.position[1] = position.data[1];
- result.position[2] = position.data[2];
+ result.pose.position[0] = position.data[0];
+ result.pose.position[1] = position.data[1];
+ result.pose.position[2] = position.data[2];
}
result.CalcViewMatrices(mHeadToEye);
return result;
}
#if defined(XP_WIN)
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -947,17 +947,17 @@ VRDisplayOculus::GetSensorState()
UpdateEyeParameters(headToEyeTransforms);
double predictedFrameTime = 0.0f;
if (gfxPrefs::VRPosePredictionEnabled()) {
// XXX We might need to call ovr_GetPredictedDisplayTime even if we don't use the result.
// If we don't call it, the Oculus driver will spew out many warnings...
predictedFrameTime = ovr_GetPredictedDisplayTime(mSession->Get(), 0);
}
result = GetSensorState(predictedFrameTime);
- result.position[1] -= mEyeHeight;
+ result.pose.position[1] -= mEyeHeight;
result.CalcViewMatrices(headToEyeTransforms);
}
result.inputFrameID = mDisplayInfo.mFrameId;
return result;
}
VRHMDSensorState
@@ -968,51 +968,51 @@ VRDisplayOculus::GetSensorState(double a
ovrTrackingState state = ovr_GetTrackingState(mSession->Get(), absTime, true);
ovrPoseStatef& pose(state.HeadPose);
result.timestamp = pose.TimeInSeconds;
if (state.StatusFlags & ovrStatus_OrientationTracked) {
result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
- result.orientation[0] = pose.ThePose.Orientation.x;
- result.orientation[1] = pose.ThePose.Orientation.y;
- result.orientation[2] = pose.ThePose.Orientation.z;
- result.orientation[3] = pose.ThePose.Orientation.w;
+ result.pose.orientation[0] = pose.ThePose.Orientation.x;
+ result.pose.orientation[1] = pose.ThePose.Orientation.y;
+ result.pose.orientation[2] = pose.ThePose.Orientation.z;
+ result.pose.orientation[3] = pose.ThePose.Orientation.w;
- result.angularVelocity[0] = pose.AngularVelocity.x;
- result.angularVelocity[1] = pose.AngularVelocity.y;
- result.angularVelocity[2] = pose.AngularVelocity.z;
+ result.pose.angularVelocity[0] = pose.AngularVelocity.x;
+ result.pose.angularVelocity[1] = pose.AngularVelocity.y;
+ result.pose.angularVelocity[2] = pose.AngularVelocity.z;
result.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration;
- result.angularAcceleration[0] = pose.AngularAcceleration.x;
- result.angularAcceleration[1] = pose.AngularAcceleration.y;
- result.angularAcceleration[2] = pose.AngularAcceleration.z;
+ result.pose.angularAcceleration[0] = pose.AngularAcceleration.x;
+ result.pose.angularAcceleration[1] = pose.AngularAcceleration.y;
+ result.pose.angularAcceleration[2] = pose.AngularAcceleration.z;
} else {
// default to an identity quaternion
- result.orientation[3] = 1.0f;
+ result.pose.orientation[3] = 1.0f;
}
if (state.StatusFlags & ovrStatus_PositionTracked) {
result.flags |= VRDisplayCapabilityFlags::Cap_Position;
- result.position[0] = pose.ThePose.Position.x;
- result.position[1] = pose.ThePose.Position.y;
- result.position[2] = pose.ThePose.Position.z;
+ result.pose.position[0] = pose.ThePose.Position.x;
+ result.pose.position[1] = pose.ThePose.Position.y;
+ result.pose.position[2] = pose.ThePose.Position.z;
- result.linearVelocity[0] = pose.LinearVelocity.x;
- result.linearVelocity[1] = pose.LinearVelocity.y;
- result.linearVelocity[2] = pose.LinearVelocity.z;
+ result.pose.linearVelocity[0] = pose.LinearVelocity.x;
+ result.pose.linearVelocity[1] = pose.LinearVelocity.y;
+ result.pose.linearVelocity[2] = pose.LinearVelocity.z;
result.flags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
- result.linearAcceleration[0] = pose.LinearAcceleration.x;
- result.linearAcceleration[1] = pose.LinearAcceleration.y;
- result.linearAcceleration[2] = pose.LinearAcceleration.z;
+ result.pose.linearAcceleration[0] = pose.LinearAcceleration.x;
+ result.pose.linearAcceleration[1] = pose.LinearAcceleration.y;
+ result.pose.linearAcceleration[2] = pose.LinearAcceleration.z;
}
result.flags |= VRDisplayCapabilityFlags::Cap_External;
result.flags |= VRDisplayCapabilityFlags::Cap_MountDetection;
result.flags |= VRDisplayCapabilityFlags::Cap_Present;
return result;
}
@@ -1325,27 +1325,27 @@ VRControllerOculus::VRControllerOculus(d
case dom::GamepadHand::Right:
touchID = "Oculus Touch (Right)";
break;
default:
MOZ_ASSERT(false);
break;
}
- strncpy(state.mControllerName, touchID, kVRControllerNameMaxLen);
+ strncpy(state.controllerName, touchID, kVRControllerNameMaxLen);
MOZ_ASSERT(kNumOculusButton ==
static_cast<uint32_t>(OculusLeftControllerButtonType::NumButtonType)
&& kNumOculusButton ==
static_cast<uint32_t>(OculusRightControllerButtonType::NumButtonType));
- state.mNumButtons = kNumOculusButton;
- state.mNumAxes = static_cast<uint32_t>(
+ state.numButtons = kNumOculusButton;
+ state.numAxes = static_cast<uint32_t>(
OculusControllerAxisType::NumVRControllerAxisType);
- state.mNumHaptics = kNumOculusHaptcs;
+ state.numHaptics = kNumOculusHaptcs;
}
float
VRControllerOculus::GetAxisMove(uint32_t aAxis)
{
return mAxisMove[aAxis];
}
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -282,34 +282,34 @@ VRDisplayOpenVR::GetSensorState()
memcpy(&m._11, &pose.mDeviceToAbsoluteTracking, sizeof(pose.mDeviceToAbsoluteTracking));
m.Transpose();
gfx::Quaternion rot;
rot.SetFromRotationMatrix(m);
rot.Invert();
result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
- result.orientation[0] = rot.x;
- result.orientation[1] = rot.y;
- result.orientation[2] = rot.z;
- result.orientation[3] = rot.w;
- result.angularVelocity[0] = pose.vAngularVelocity.v[0];
- result.angularVelocity[1] = pose.vAngularVelocity.v[1];
- result.angularVelocity[2] = pose.vAngularVelocity.v[2];
+ result.pose.orientation[0] = rot.x;
+ result.pose.orientation[1] = rot.y;
+ result.pose.orientation[2] = rot.z;
+ result.pose.orientation[3] = rot.w;
+ result.pose.angularVelocity[0] = pose.vAngularVelocity.v[0];
+ result.pose.angularVelocity[1] = pose.vAngularVelocity.v[1];
+ result.pose.angularVelocity[2] = pose.vAngularVelocity.v[2];
result.flags |= VRDisplayCapabilityFlags::Cap_Position;
- result.position[0] = m._41;
- result.position[1] = m._42;
- result.position[2] = m._43;
- result.linearVelocity[0] = pose.vVelocity.v[0];
- result.linearVelocity[1] = pose.vVelocity.v[1];
- result.linearVelocity[2] = pose.vVelocity.v[2];
+ result.pose.position[0] = m._41;
+ result.pose.position[1] = m._42;
+ result.pose.position[2] = m._43;
+ result.pose.linearVelocity[0] = pose.vVelocity.v[0];
+ result.pose.linearVelocity[1] = pose.vVelocity.v[1];
+ result.pose.linearVelocity[2] = pose.vVelocity.v[2];
} else {
// default to an identity quaternion
- result.orientation[3] = 1.0f;
+ result.pose.orientation[3] = 1.0f;
}
result.CalcViewMatrices(headToEyeTransforms);
result.inputFrameID = mDisplayInfo.mFrameId;
return result;
}
void
@@ -433,21 +433,20 @@ VRControllerOpenVR::VRControllerOpenVR(d
: VRControllerHost(VRDeviceType::OpenVR, aHand, aDisplayID)
, mTrackedIndex(0)
, mVibrateThread(nullptr)
, mIsVibrateStopped(false)
{
MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
VRControllerState& state = mControllerInfo.mControllerState;
- strncpy(state.mControllerName, aId.BeginReading(), kVRControllerNameMaxLen);
- state.mNumButtons = aNumButtons;
- state.mNumAxes = aNumAxes;
- state.mNumTriggers = aNumTriggers;
- state.mNumHaptics = kNumOpenVRHaptcs;
+ strncpy(state.controllerName, aId.BeginReading(), kVRControllerNameMaxLen);
+ state.numButtons = aNumButtons;
+ state.numAxes = aNumAxes;
+ state.numHaptics = kNumOpenVRHaptcs;
}
VRControllerOpenVR::~VRControllerOpenVR()
{
ShutdownVibrateHapticThread();
MOZ_COUNT_DTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
}
@@ -461,41 +460,41 @@ uint32_t
VRControllerOpenVR::GetTrackedIndex()
{
return mTrackedIndex;
}
float
VRControllerOpenVR::GetAxisMove(uint32_t aAxis)
{
- return mControllerInfo.mControllerState.mAxisValue[aAxis];
+ return mControllerInfo.mControllerState.axisValue[aAxis];
}
void
VRControllerOpenVR::SetAxisMove(uint32_t aAxis, float aValue)
{
- mControllerInfo.mControllerState.mAxisValue[aAxis] = aValue;
+ mControllerInfo.mControllerState.axisValue[aAxis] = aValue;
}
void
VRControllerOpenVR::SetTrigger(uint32_t aButton, float aValue)
{
- mControllerInfo.mControllerState.mTriggerValue[aButton] = aValue;
+ mControllerInfo.mControllerState.triggerValue[aButton] = aValue;
}
float
VRControllerOpenVR::GetTrigger(uint32_t aButton)
{
- return mControllerInfo.mControllerState.mTriggerValue[aButton];
+ return mControllerInfo.mControllerState.triggerValue[aButton];
}
void
VRControllerOpenVR::SetHand(dom::GamepadHand aHand)
{
- mControllerInfo.mControllerState.mHand = aHand;
+ mControllerInfo.mControllerState.hand = aHand;
}
void
VRControllerOpenVR::UpdateVibrateHaptic(::vr::IVRSystem* aVRSystem,
uint32_t aHapticIndex,
double aIntensity,
double aDuration,
uint64_t aVibrateIndex,
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -99,31 +99,31 @@ VRDisplayPuppet::VRDisplayPuppet()
state.mSittingToStandingTransform[12] = 0.0f;
state.mSittingToStandingTransform[13] = 0.75f;
state.mSittingToStandingTransform[14] = 0.0f;
state.mSittingToStandingTransform[15] = 1.0f;
gfx::Quaternion rot;
mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
- mSensorState.orientation[0] = rot.x;
- mSensorState.orientation[1] = rot.y;
- mSensorState.orientation[2] = rot.z;
- mSensorState.orientation[3] = rot.w;
- mSensorState.angularVelocity[0] = 0.0f;
- mSensorState.angularVelocity[1] = 0.0f;
- mSensorState.angularVelocity[2] = 0.0f;
+ mSensorState.pose.orientation[0] = rot.x;
+ mSensorState.pose.orientation[1] = rot.y;
+ mSensorState.pose.orientation[2] = rot.z;
+ mSensorState.pose.orientation[3] = rot.w;
+ mSensorState.pose.angularVelocity[0] = 0.0f;
+ mSensorState.pose.angularVelocity[1] = 0.0f;
+ mSensorState.pose.angularVelocity[2] = 0.0f;
mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Position;
- mSensorState.position[0] = 0.0f;
- mSensorState.position[1] = 0.0f;
- mSensorState.position[2] = 0.0f;
- mSensorState.linearVelocity[0] = 0.0f;
- mSensorState.linearVelocity[1] = 0.0f;
- mSensorState.linearVelocity[2] = 0.0f;
+ mSensorState.pose.position[0] = 0.0f;
+ mSensorState.pose.position[1] = 0.0f;
+ mSensorState.pose.position[2] = 0.0f;
+ mSensorState.pose.linearVelocity[0] = 0.0f;
+ mSensorState.pose.linearVelocity[1] = 0.0f;
+ mSensorState.pose.linearVelocity[2] = 0.0f;
}
VRDisplayPuppet::~VRDisplayPuppet()
{
MOZ_COUNT_DTOR_INHERITED(VRDisplayPuppet, VRDisplayLocal);
}
void
@@ -580,20 +580,20 @@ VRDisplayPuppet::Refresh()
VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand, uint32_t aDisplayID)
: VRControllerHost(VRDeviceType::Puppet, aHand, aDisplayID)
, mButtonPressState(0)
, mButtonTouchState(0)
{
MOZ_COUNT_CTOR_INHERITED(VRControllerPuppet, VRControllerHost);
VRControllerState& state = mControllerInfo.mControllerState;
- strncpy(state.mControllerName, "Puppet Gamepad", kVRControllerNameMaxLen);
- state.mNumButtons = kNumPuppetButtonMask;
- state.mNumAxes = kNumPuppetAxis;
- state.mNumHaptics = kNumPuppetHaptcs;
+ strncpy(state.controllerName, "Puppet Gamepad", kVRControllerNameMaxLen);
+ state.numButtons = kNumPuppetButtonMask;
+ state.numAxes = kNumPuppetAxis;
+ state.numHaptics = kNumPuppetHaptcs;
}
VRControllerPuppet::~VRControllerPuppet()
{
MOZ_COUNT_DTOR_INHERITED(VRControllerPuppet, VRControllerHost);
}
void
@@ -667,23 +667,23 @@ const dom::GamepadPoseState&
VRControllerPuppet::GetPoseMoveState()
{
return mPoseState;
}
float
VRControllerPuppet::GetAxisMove(uint32_t aAxis)
{
- return mControllerInfo.mControllerState.mAxisValue[aAxis];
+ return mControllerInfo.mControllerState.axisValue[aAxis];
}
void
VRControllerPuppet::SetAxisMove(uint32_t aAxis, float aValue)
{
- mControllerInfo.mControllerState.mAxisValue[aAxis] = aValue;
+ mControllerInfo.mControllerState.axisValue[aAxis] = aValue;
}
VRSystemManagerPuppet::VRSystemManagerPuppet()
: mPuppetDisplayCount(0)
, mPuppetDisplayInfo{}
, mPuppetDisplaySensorState{}
{
}
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -39,16 +39,17 @@ void ReleaseVRManagerParentSingleton() {
VRManagerChild::VRManagerChild()
: mDisplaysInitialized(false)
, mMessageLoop(MessageLoop::current())
, mFrameRequestCallbackCounter(0)
, mBackend(layers::LayersBackend::LAYERS_NONE)
, mPromiseID(0)
, mVRMockDisplay(nullptr)
+ , mLastControllerState{}
{
MOZ_ASSERT(NS_IsMainThread());
mStartTimeStamp = TimeStamp::Now();
}
VRManagerChild::~VRManagerChild()
{
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -134,16 +134,17 @@ private:
nsTArray<RefPtr<dom::VREventObserver>> mListeners;
layers::LayersBackend mBackend;
RefPtr<layers::SyncObjectClient> mSyncObject;
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList;
uint32_t mPromiseID;
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
RefPtr<dom::VRMockDisplay> mVRMockDisplay;
+ VRControllerState mLastControllerState[kVRControllerMaxCount];
DISALLOW_COPY_AND_ASSIGN(VRManagerChild);
};
} // namespace mozilla
} // namespace gfx
#endif // MOZILLA_GFX_VR_VRMANAGERCHILD_H
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -107,16 +107,19 @@ struct ParamTraits<mozilla::gfx::VRDispl
WriteParam(aMsg, aParam.mDisplayID);
WriteParam(aMsg, aParam.mPresentingGroups);
WriteParam(aMsg, aParam.mGroupMask);
WriteParam(aMsg, aParam.mFrameId);
WriteParam(aMsg, aParam.mDisplayState);
for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) {
WriteParam(aMsg, aParam.mLastSensorState[i]);
}
+ for (int i = 0; i < mozilla::gfx::kVRControllerMaxCount; i++) {
+ WriteParam(aMsg, aParam.mControllerState[i]);
+ }
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
!ReadParam(aMsg, aIter, &(aResult->mDisplayID)) ||
!ReadParam(aMsg, aIter, &(aResult->mPresentingGroups)) ||
!ReadParam(aMsg, aIter, &(aResult->mGroupMask)) ||
@@ -124,31 +127,33 @@ struct ParamTraits<mozilla::gfx::VRDispl
!ReadParam(aMsg, aIter, &(aResult->mDisplayState))) {
return false;
}
for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->mLastSensorState[i]))) {
return false;
}
}
-
+ for (int i = 0; i < mozilla::gfx::kVRControllerMaxCount; i++) {
+ if (!ReadParam(aMsg, aIter, &(aResult->mControllerState[i]))) {
+ return false;
+ }
+ }
return true;
}
};
+
template <>
-struct ParamTraits<mozilla::gfx::VRHMDSensorState>
+struct ParamTraits<mozilla::gfx::VRPose>
{
- typedef mozilla::gfx::VRHMDSensorState paramType;
+ typedef mozilla::gfx::VRPose paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
- WriteParam(aMsg, aParam.timestamp);
- WriteParam(aMsg, aParam.inputFrameID);
- WriteParam(aMsg, aParam.flags);
WriteParam(aMsg, aParam.orientation[0]);
WriteParam(aMsg, aParam.orientation[1]);
WriteParam(aMsg, aParam.orientation[2]);
WriteParam(aMsg, aParam.orientation[3]);
WriteParam(aMsg, aParam.position[0]);
WriteParam(aMsg, aParam.position[1]);
WriteParam(aMsg, aParam.position[2]);
WriteParam(aMsg, aParam.angularVelocity[0]);
@@ -158,30 +163,21 @@ struct ParamTraits<mozilla::gfx::VRHMDSe
WriteParam(aMsg, aParam.angularAcceleration[1]);
WriteParam(aMsg, aParam.angularAcceleration[2]);
WriteParam(aMsg, aParam.linearVelocity[0]);
WriteParam(aMsg, aParam.linearVelocity[1]);
WriteParam(aMsg, aParam.linearVelocity[2]);
WriteParam(aMsg, aParam.linearAcceleration[0]);
WriteParam(aMsg, aParam.linearAcceleration[1]);
WriteParam(aMsg, aParam.linearAcceleration[2]);
- for (int i=0; i < 16; i++) {
- WriteParam(aMsg, aParam.leftViewMatrix[i]);
- }
- for (int i=0; i < 16; i++) {
- WriteParam(aMsg, aParam.rightViewMatrix[i]);
- }
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
- if (!ReadParam(aMsg, aIter, &(aResult->timestamp)) ||
- !ReadParam(aMsg, aIter, &(aResult->inputFrameID)) ||
- !ReadParam(aMsg, aIter, &(aResult->flags)) ||
- !ReadParam(aMsg, aIter, &(aResult->orientation[0])) ||
+ if (!ReadParam(aMsg, aIter, &(aResult->orientation[0])) ||
!ReadParam(aMsg, aIter, &(aResult->orientation[1])) ||
!ReadParam(aMsg, aIter, &(aResult->orientation[2])) ||
!ReadParam(aMsg, aIter, &(aResult->orientation[3])) ||
!ReadParam(aMsg, aIter, &(aResult->position[0])) ||
!ReadParam(aMsg, aIter, &(aResult->position[1])) ||
!ReadParam(aMsg, aIter, &(aResult->position[2])) ||
!ReadParam(aMsg, aIter, &(aResult->angularVelocity[0])) ||
!ReadParam(aMsg, aIter, &(aResult->angularVelocity[1])) ||
@@ -192,16 +188,47 @@ struct ParamTraits<mozilla::gfx::VRHMDSe
!ReadParam(aMsg, aIter, &(aResult->linearVelocity[0])) ||
!ReadParam(aMsg, aIter, &(aResult->linearVelocity[1])) ||
!ReadParam(aMsg, aIter, &(aResult->linearVelocity[2])) ||
!ReadParam(aMsg, aIter, &(aResult->linearAcceleration[0])) ||
!ReadParam(aMsg, aIter, &(aResult->linearAcceleration[1])) ||
!ReadParam(aMsg, aIter, &(aResult->linearAcceleration[2]))) {
return false;
}
+ return true;
+ }
+};
+
+template <>
+struct ParamTraits<mozilla::gfx::VRHMDSensorState>
+{
+ typedef mozilla::gfx::VRHMDSensorState paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, aParam.timestamp);
+ WriteParam(aMsg, aParam.inputFrameID);
+ WriteParam(aMsg, aParam.flags);
+ WriteParam(aMsg, aParam.pose);
+ for (int i=0; i < 16; i++) {
+ WriteParam(aMsg, aParam.leftViewMatrix[i]);
+ }
+ for (int i=0; i < 16; i++) {
+ WriteParam(aMsg, aParam.rightViewMatrix[i]);
+ }
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ if (!ReadParam(aMsg, aIter, &(aResult->timestamp)) ||
+ !ReadParam(aMsg, aIter, &(aResult->inputFrameID)) ||
+ !ReadParam(aMsg, aIter, &(aResult->flags)) ||
+ !ReadParam(aMsg, aIter, &(aResult->pose))) {
+ return false;
+ }
for (int i=0; i < 16; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->leftViewMatrix[i]))) {
return false;
}
}
for (int i=0; i < 16; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->rightViewMatrix[i]))) {
return false;
@@ -241,55 +268,63 @@ struct ParamTraits<mozilla::gfx::VRField
template <>
struct ParamTraits<mozilla::gfx::VRControllerState>
{
typedef mozilla::gfx::VRControllerState paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
nsCString controllerName;
- controllerName.Assign(aParam.mControllerName); // FINDME!! HACK! - Bounds checking?
+ controllerName.Assign(aParam.controllerName); // FINDME!! HACK! - Bounds checking?
WriteParam(aMsg, controllerName);
- WriteParam(aMsg, aParam.mNumButtons);
- WriteParam(aMsg, aParam.mNumAxes);
- WriteParam(aMsg, aParam.mNumTriggers);
- WriteParam(aMsg, aParam.mNumHaptics);
- WriteParam(aMsg, aParam.mButtonPressed);
- WriteParam(aMsg, aParam.mButtonTouched);
+ WriteParam(aMsg, aParam.hand);
+ WriteParam(aMsg, aParam.numButtons);
+ WriteParam(aMsg, aParam.numAxes);
+ WriteParam(aMsg, aParam.numHaptics);
+ WriteParam(aMsg, aParam.buttonPressed);
+ WriteParam(aMsg, aParam.buttonTouched);
+ WriteParam(aMsg, aParam.flags);
+ WriteParam(aMsg, aParam.pose);
+ WriteParam(aMsg, aParam.isPositionValid);
+ WriteParam(aMsg, aParam.isOrientationValid);
for (int i=0; i < mozilla::gfx::kVRControllerMaxAxis; i++) {
- WriteParam(aMsg, aParam.mAxisValue[i]);
+ WriteParam(aMsg, aParam.axisValue[i]);
}
- for (int i=0; i < mozilla::gfx::kVRControllerMaxTriggers; i++) {
- WriteParam(aMsg, aParam.mTriggerValue[i]);
+ for (int i=0; i < mozilla::gfx::kVRControllerMaxButtons; i++) {
+ WriteParam(aMsg, aParam.triggerValue[i]);
}
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
nsCString controllerName;
if (!ReadParam(aMsg, aIter, &(controllerName)) ||
- !ReadParam(aMsg, aIter, &(aResult->mNumButtons)) ||
- !ReadParam(aMsg, aIter, &(aResult->mNumAxes)) ||
- !ReadParam(aMsg, aIter, &(aResult->mNumTriggers)) ||
- !ReadParam(aMsg, aIter, &(aResult->mNumHaptics)) ||
- !ReadParam(aMsg, aIter, &(aResult->mButtonPressed)) ||
- !ReadParam(aMsg, aIter, &(aResult->mButtonTouched))) {
+ !ReadParam(aMsg, aIter, &(aResult->hand)) ||
+ !ReadParam(aMsg, aIter, &(aResult->numButtons)) ||
+ !ReadParam(aMsg, aIter, &(aResult->numAxes)) ||
+ !ReadParam(aMsg, aIter, &(aResult->numHaptics)) ||
+ !ReadParam(aMsg, aIter, &(aResult->buttonPressed)) ||
+ !ReadParam(aMsg, aIter, &(aResult->buttonTouched)) ||
+ !ReadParam(aMsg, aIter, &(aResult->flags)) ||
+ !ReadParam(aMsg, aIter, &(aResult->pose)) ||
+ !ReadParam(aMsg, aIter, &(aResult->isPositionValid)) ||
+ !ReadParam(aMsg, aIter, &(aResult->isOrientationValid))) {
return false;
}
for (int i=0; i < mozilla::gfx::kVRControllerMaxAxis; i++) {
- if (!ReadParam(aMsg, aIter, &(aResult->mAxisValue[i]))) {
+ if (!ReadParam(aMsg, aIter, &(aResult->axisValue[i]))) {
return false;
}
}
- for (int i=0; i < mozilla::gfx::kVRControllerMaxTriggers; i++) {
- if (!ReadParam(aMsg, aIter, &(aResult->mTriggerValue[i]))) {
+ for (int i=0; i < mozilla::gfx::kVRControllerMaxButtons; i++) {
+ if (!ReadParam(aMsg, aIter, &(aResult->triggerValue[i]))) {
return false;
}
}
- strncpy(aResult->mControllerName, controllerName.BeginReading(), mozilla::gfx::kVRControllerNameMaxLen); // FINDME! TODO! HACK! Safe? Better way?
+ strncpy(aResult->controllerName, controllerName.BeginReading(), mozilla::gfx::kVRControllerNameMaxLen); // FINDME! TODO! HACK! Safe? Better way?
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRControllerInfo>
{
--- a/gfx/vr/service/OpenVRSession.cpp
+++ b/gfx/vr/service/OpenVRSession.cpp
@@ -1,55 +1,130 @@
#include "OpenVRSession.h"
+#include "gfxPrefs.h"
#if defined(XP_WIN)
#include <d3d11.h>
#include "mozilla/gfx/DeviceManagerDx.h"
#endif // defined(XP_WIN)
-#if defined(MOZILLA_INTERNAL_API)
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/GamepadBinding.h"
-#endif
#if !defined(M_PI)
#define M_PI 3.14159265358979323846264338327950288
#endif
#define BTN_MASK_FROM_ID(_id) \
::vr::ButtonMaskFromId(vr::EVRButtonId::_id)
+static const uint32_t kNumOpenVRHaptcs = 1;
+
using namespace mozilla::gfx;
namespace mozilla {
namespace gfx {
+namespace {
+
+dom::GamepadHand
+GetControllerHandFromControllerRole(::vr::ETrackedControllerRole aRole)
+{
+ dom::GamepadHand hand;
+
+ switch(aRole) {
+ case ::vr::ETrackedControllerRole::TrackedControllerRole_Invalid:
+ case ::vr::ETrackedControllerRole::TrackedControllerRole_OptOut:
+ hand = dom::GamepadHand::_empty;
+ break;
+ case ::vr::ETrackedControllerRole::TrackedControllerRole_LeftHand:
+ hand = dom::GamepadHand::Left;
+ break;
+ case ::vr::ETrackedControllerRole::TrackedControllerRole_RightHand:
+ hand = dom::GamepadHand::Right;
+ break;
+ default:
+ hand = dom::GamepadHand::_empty;
+ MOZ_ASSERT(false);
+ break;
+ }
+
+ return hand;
+}
+
+
+void
+UpdateButton(VRControllerState& aState, const ::vr::VRControllerState_t& aControllerState, uint32_t aButtonIndex, uint64_t aButtonMask)
+{
+ uint64_t mask = (1ULL << aButtonIndex);
+ if ((aControllerState.ulButtonPressed & aButtonMask) == 0) {
+ // not pressed
+ aState.buttonPressed &= ~mask;
+ aState.triggerValue[aButtonIndex] = 0.0f;
+ } else {
+ // pressed
+ aState.buttonPressed |= mask;
+ aState.triggerValue[aButtonIndex] = 1.0f;
+ }
+ if ((aControllerState.ulButtonTouched & aButtonMask) == 0) {
+ // not touched
+ aState.buttonTouched &= ~mask;
+ } else {
+ // touched
+ aState.buttonTouched |= mask;
+ }
+}
+
+void
+UpdateTrigger(VRControllerState& aState, uint32_t aButtonIndex, float aValue, float aThreshold)
+{
+ // 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.
+ uint64_t mask = (1ULL << aButtonIndex);
+ aState.triggerValue[aButtonIndex] = aValue;
+ if (aValue > aThreshold) {
+ aState.buttonPressed |= mask;
+ aState.buttonTouched |= mask;
+ } else {
+ aState.buttonPressed &= ~mask;
+ aState.buttonTouched &= ~mask;
+ }
+}
+
+}; // anonymous namespace
+
OpenVRSession::OpenVRSession()
: VRSession()
, mVRSystem(nullptr)
, mVRChaperone(nullptr)
, mVRCompositor(nullptr)
+ , mControllerDeviceIndex{0}
, mShouldQuit(false)
+ , mIsWindowsMR(false)
{
}
OpenVRSession::~OpenVRSession()
{
Shutdown();
}
bool
OpenVRSession::Initialize(mozilla::gfx::VRSystemState& aSystemState)
{
if (mVRSystem != nullptr) {
// Already initialized
return true;
}
+ if (!::vr::VR_IsRuntimeInstalled()) {
+ return false;
+ }
if (!::vr::VR_IsHmdPresent()) {
- fprintf(stderr, "No HMD detected, VR_IsHmdPresent returned false.\n");
return false;
}
::vr::HmdError err;
::vr::VR_Init(&err, ::vr::EVRApplicationType::VRApplication_Scene);
if (err) {
return false;
@@ -138,131 +213,131 @@ OpenVRSession::InitState(VRSystemState&
}
uint32_t w, h;
mVRSystem->GetRecommendedRenderTargetSize(&w, &h);
state.mEyeResolution.width = w;
state.mEyeResolution.height = h;
// default to an identity quaternion
- aSystemState.sensorState.orientation[3] = 1.0f;
+ aSystemState.sensorState.pose.orientation[3] = 1.0f;
UpdateStageParameters(state);
- UpdateEyeParameters(state);
+ UpdateEyeParameters(aSystemState);
VRHMDSensorState& sensorState = aSystemState.sensorState;
sensorState.flags = (VRDisplayCapabilityFlags)(
(int)VRDisplayCapabilityFlags::Cap_Orientation |
(int)VRDisplayCapabilityFlags::Cap_Position);
- sensorState.orientation[3] = 1.0f; // Default to an identity quaternion
+ sensorState.pose.orientation[3] = 1.0f; // Default to an identity quaternion
return true;
}
void
-OpenVRSession::UpdateStageParameters(VRDisplayState& state)
+OpenVRSession::UpdateStageParameters(VRDisplayState& aState)
{
float sizeX = 0.0f;
float sizeZ = 0.0f;
if (mVRChaperone->GetPlayAreaSize(&sizeX, &sizeZ)) {
::vr::HmdMatrix34_t t = mVRSystem->GetSeatedZeroPoseToStandingAbsoluteTrackingPose();
- state.mStageSize.width = sizeX;
- state.mStageSize.height = sizeZ;
+ aState.mStageSize.width = sizeX;
+ aState.mStageSize.height = sizeZ;
- state.mSittingToStandingTransform[0] = t.m[0][0];
- state.mSittingToStandingTransform[1] = t.m[1][0];
- state.mSittingToStandingTransform[2] = t.m[2][0];
- state.mSittingToStandingTransform[3] = 0.0f;
+ aState.mSittingToStandingTransform[0] = t.m[0][0];
+ aState.mSittingToStandingTransform[1] = t.m[1][0];
+ aState.mSittingToStandingTransform[2] = t.m[2][0];
+ aState.mSittingToStandingTransform[3] = 0.0f;
- state.mSittingToStandingTransform[4] = t.m[0][1];
- state.mSittingToStandingTransform[5] = t.m[1][1];
- state.mSittingToStandingTransform[6] = t.m[2][1];
- state.mSittingToStandingTransform[7] = 0.0f;
+ aState.mSittingToStandingTransform[4] = t.m[0][1];
+ aState.mSittingToStandingTransform[5] = t.m[1][1];
+ aState.mSittingToStandingTransform[6] = t.m[2][1];
+ aState.mSittingToStandingTransform[7] = 0.0f;
- state.mSittingToStandingTransform[8] = t.m[0][2];
- state.mSittingToStandingTransform[9] = t.m[1][2];
- state.mSittingToStandingTransform[10] = t.m[2][2];
- state.mSittingToStandingTransform[11] = 0.0f;
+ aState.mSittingToStandingTransform[8] = t.m[0][2];
+ aState.mSittingToStandingTransform[9] = t.m[1][2];
+ aState.mSittingToStandingTransform[10] = t.m[2][2];
+ aState.mSittingToStandingTransform[11] = 0.0f;
- state.mSittingToStandingTransform[12] = t.m[0][3];
- state.mSittingToStandingTransform[13] = t.m[1][3];
- state.mSittingToStandingTransform[14] = t.m[2][3];
- state.mSittingToStandingTransform[15] = 1.0f;
+ aState.mSittingToStandingTransform[12] = t.m[0][3];
+ aState.mSittingToStandingTransform[13] = t.m[1][3];
+ aState.mSittingToStandingTransform[14] = t.m[2][3];
+ aState.mSittingToStandingTransform[15] = 1.0f;
} else {
// If we fail, fall back to reasonable defaults.
// 1m x 1m space, 0.75m high in seated position
-
- state.mStageSize.width = 1.0f;
- state.mStageSize.height = 1.0f;
+ aState.mStageSize.width = 1.0f;
+ aState.mStageSize.height = 1.0f;
- state.mSittingToStandingTransform[0] = 1.0f;
- state.mSittingToStandingTransform[1] = 0.0f;
- state.mSittingToStandingTransform[2] = 0.0f;
- state.mSittingToStandingTransform[3] = 0.0f;
+ aState.mSittingToStandingTransform[0] = 1.0f;
+ aState.mSittingToStandingTransform[1] = 0.0f;
+ aState.mSittingToStandingTransform[2] = 0.0f;
+ aState.mSittingToStandingTransform[3] = 0.0f;
- state.mSittingToStandingTransform[4] = 0.0f;
- state.mSittingToStandingTransform[5] = 1.0f;
- state.mSittingToStandingTransform[6] = 0.0f;
- state.mSittingToStandingTransform[7] = 0.0f;
+ aState.mSittingToStandingTransform[4] = 0.0f;
+ aState.mSittingToStandingTransform[5] = 1.0f;
+ aState.mSittingToStandingTransform[6] = 0.0f;
+ aState.mSittingToStandingTransform[7] = 0.0f;
- state.mSittingToStandingTransform[8] = 0.0f;
- state.mSittingToStandingTransform[9] = 0.0f;
- state.mSittingToStandingTransform[10] = 1.0f;
- state.mSittingToStandingTransform[11] = 0.0f;
+ aState.mSittingToStandingTransform[8] = 0.0f;
+ aState.mSittingToStandingTransform[9] = 0.0f;
+ aState.mSittingToStandingTransform[10] = 1.0f;
+ aState.mSittingToStandingTransform[11] = 0.0f;
- state.mSittingToStandingTransform[12] = 0.0f;
- state.mSittingToStandingTransform[13] = 0.75f;
- state.mSittingToStandingTransform[14] = 0.0f;
- state.mSittingToStandingTransform[15] = 1.0f;
+ aState.mSittingToStandingTransform[12] = 0.0f;
+ aState.mSittingToStandingTransform[13] = 0.75f;
+ aState.mSittingToStandingTransform[14] = 0.0f;
+ aState.mSittingToStandingTransform[15] = 1.0f;
}
}
void
-OpenVRSession::UpdateEyeParameters(VRDisplayState& state, gfx::Matrix4x4* headToEyeTransforms /* = nullptr */)
+OpenVRSession::UpdateEyeParameters(VRSystemState& aState)
{
+ // This must be called every frame in order to
+ // account for continuous adjustments to ipd.
+ gfx::Matrix4x4 headToEyeTransforms[2];
+
for (uint32_t eye = 0; eye < 2; ++eye) {
::vr::HmdMatrix34_t eyeToHead = mVRSystem->GetEyeToHeadTransform(static_cast<::vr::Hmd_Eye>(eye));
- state.mEyeTranslation[eye].x = eyeToHead.m[0][3];
- state.mEyeTranslation[eye].y = eyeToHead.m[1][3];
- state.mEyeTranslation[eye].z = eyeToHead.m[2][3];
+ aState.displayState.mEyeTranslation[eye].x = eyeToHead.m[0][3];
+ aState.displayState.mEyeTranslation[eye].y = eyeToHead.m[1][3];
+ aState.displayState.mEyeTranslation[eye].z = eyeToHead.m[2][3];
float left, right, up, down;
mVRSystem->GetProjectionRaw(static_cast<::vr::Hmd_Eye>(eye), &left, &right, &up, &down);
- state.mEyeFOV[eye].upDegrees = atan(-up) * 180.0 / M_PI;
- state.mEyeFOV[eye].rightDegrees = atan(right) * 180.0 / M_PI;
- state.mEyeFOV[eye].downDegrees = atan(down) * 180.0 / M_PI;
- state.mEyeFOV[eye].leftDegrees = atan(-left) * 180.0 / M_PI;
+ aState.displayState.mEyeFOV[eye].upDegrees = atan(-up) * 180.0 / M_PI;
+ aState.displayState.mEyeFOV[eye].rightDegrees = atan(right) * 180.0 / M_PI;
+ aState.displayState.mEyeFOV[eye].downDegrees = atan(down) * 180.0 / M_PI;
+ aState.displayState.mEyeFOV[eye].leftDegrees = atan(-left) * 180.0 / M_PI;
- if (headToEyeTransforms) {
- Matrix4x4 pose;
- // NOTE! eyeToHead.m 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.
- memcpy(&pose._11, &eyeToHead.m, sizeof(eyeToHead.m));
- pose.Transpose();
- pose.Invert();
- headToEyeTransforms[eye] = pose;
- }
+ Matrix4x4 pose;
+ // NOTE! eyeToHead.m 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.
+ memcpy(&pose._11, &eyeToHead.m, sizeof(eyeToHead.m));
+ pose.Transpose();
+ pose.Invert();
+ headToEyeTransforms[eye] = pose;
}
+ aState.sensorState.CalcViewMatrices(headToEyeTransforms);
}
void
-OpenVRSession::GetSensorState(VRSystemState& state)
+OpenVRSession::UpdateHeadsetPose(VRSystemState& aState)
{
const uint32_t posesSize = ::vr::k_unTrackedDeviceIndex_Hmd + 1;
::vr::TrackedDevicePose_t poses[posesSize];
// Note: We *must* call WaitGetPoses in order for any rendering to happen at all.
mVRCompositor->WaitGetPoses(nullptr, 0, poses, posesSize);
- gfx::Matrix4x4 headToEyeTransforms[2];
- UpdateEyeParameters(state.displayState, headToEyeTransforms);
::vr::Compositor_FrameTiming timing;
timing.m_nSize = sizeof(::vr::Compositor_FrameTiming);
if (mVRCompositor->GetFrameTiming(&timing)) {
- state.sensorState.timestamp = timing.m_flSystemTimeInSeconds;
+ aState.sensorState.timestamp = timing.m_flSystemTimeInSeconds;
} else {
// This should not happen, but log it just in case
fprintf(stderr, "OpenVR - IVRCompositor::GetFrameTiming failed");
}
if (poses[::vr::k_unTrackedDeviceIndex_Hmd].bDeviceIsConnected &&
poses[::vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid &&
poses[::vr::k_unTrackedDeviceIndex_Hmd].eTrackingResult == ::vr::TrackingResult_Running_OK)
@@ -276,49 +351,421 @@ OpenVRSession::GetSensorState(VRSystemSt
// pull out a Quaternion.
memcpy(&m._11, &pose.mDeviceToAbsoluteTracking, sizeof(pose.mDeviceToAbsoluteTracking));
m.Transpose();
gfx::Quaternion rot;
rot.SetFromRotationMatrix(m);
rot.Invert();
- state.sensorState.flags = (VRDisplayCapabilityFlags)((int)state.sensorState.flags | (int)VRDisplayCapabilityFlags::Cap_Orientation);
- state.sensorState.orientation[0] = rot.x;
- state.sensorState.orientation[1] = rot.y;
- state.sensorState.orientation[2] = rot.z;
- state.sensorState.orientation[3] = rot.w;
- state.sensorState.angularVelocity[0] = pose.vAngularVelocity.v[0];
- state.sensorState.angularVelocity[1] = pose.vAngularVelocity.v[1];
- state.sensorState.angularVelocity[2] = pose.vAngularVelocity.v[2];
+ aState.sensorState.flags = (VRDisplayCapabilityFlags)((int)aState.sensorState.flags | (int)VRDisplayCapabilityFlags::Cap_Orientation);
+ aState.sensorState.pose.orientation[0] = rot.x;
+ aState.sensorState.pose.orientation[1] = rot.y;
+ aState.sensorState.pose.orientation[2] = rot.z;
+ aState.sensorState.pose.orientation[3] = rot.w;
+ aState.sensorState.pose.angularVelocity[0] = pose.vAngularVelocity.v[0];
+ aState.sensorState.pose.angularVelocity[1] = pose.vAngularVelocity.v[1];
+ aState.sensorState.pose.angularVelocity[2] = pose.vAngularVelocity.v[2];
+
+ aState.sensorState.flags =(VRDisplayCapabilityFlags)((int)aState.sensorState.flags | (int)VRDisplayCapabilityFlags::Cap_Position);
+ aState.sensorState.pose.position[0] = m._41;
+ aState.sensorState.pose.position[1] = m._42;
+ aState.sensorState.pose.position[2] = m._43;
+ aState.sensorState.pose.linearVelocity[0] = pose.vVelocity.v[0];
+ aState.sensorState.pose.linearVelocity[1] = pose.vVelocity.v[1];
+ aState.sensorState.pose.linearVelocity[2] = pose.vVelocity.v[2];
+ }
+}
+
+void
+OpenVRSession::EnumerateControllers(VRSystemState& aState)
+{
+ MOZ_ASSERT(mVRSystem);
+
+ bool controllerPresent[kVRControllerMaxCount] = { false };
+
+ // Basically, we would have HMDs in the tracked devices,
+ // but we are just interested in the controllers.
+ for (::vr::TrackedDeviceIndex_t trackedDevice = ::vr::k_unTrackedDeviceIndex_Hmd + 1;
+ trackedDevice < ::vr::k_unMaxTrackedDeviceCount; ++trackedDevice) {
+
+ if (!mVRSystem->IsTrackedDeviceConnected(trackedDevice)) {
+ continue;
+ }
+
+ const ::vr::ETrackedDeviceClass deviceType = mVRSystem->
+ GetTrackedDeviceClass(trackedDevice);
+ if (deviceType != ::vr::TrackedDeviceClass_Controller
+ && deviceType != ::vr::TrackedDeviceClass_GenericTracker) {
+ continue;
+ }
+
+ uint32_t stateIndex = 0;
+ uint32_t firstEmptyIndex = kVRControllerMaxCount;
+
+ // Find the existing controller
+ for (stateIndex = 0; stateIndex < kVRControllerMaxCount; stateIndex++) {
+ if (mControllerDeviceIndex[stateIndex] == 0 && firstEmptyIndex == kVRControllerMaxCount) {
+ firstEmptyIndex = stateIndex;
+ }
+ if (mControllerDeviceIndex[stateIndex] == trackedDevice) {
+ break;
+ }
+ }
+ if (stateIndex == kVRControllerMaxCount) {
+ // This is a new controller, let's add it
+ if (firstEmptyIndex == kVRControllerMaxCount) {
+ NS_WARNING("OpenVR - Too many controllers, need to increase kVRControllerMaxCount.");
+ continue;
+ }
+ stateIndex = firstEmptyIndex;
+ mControllerDeviceIndex[stateIndex] = trackedDevice;
+ VRControllerState& controllerState = aState.controllerState[stateIndex];
+ uint32_t numButtons = 0;
+ uint32_t numAxes = 0;
- state.sensorState.flags =(VRDisplayCapabilityFlags)((int)state.sensorState.flags | (int)VRDisplayCapabilityFlags::Cap_Position);
- state.sensorState.position[0] = m._41;
- state.sensorState.position[1] = m._42;
- state.sensorState.position[2] = m._43;
- state.sensorState.linearVelocity[0] = pose.vVelocity.v[0];
- state.sensorState.linearVelocity[1] = pose.vVelocity.v[1];
- state.sensorState.linearVelocity[2] = pose.vVelocity.v[2];
+ // 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:
+ if (j <= 2) {
+ ++numButtons;
+ } 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;
+ }
+ 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;
+ }
+
+ nsCString deviceId;
+ GetControllerDeviceId(deviceType, trackedDevice, deviceId);
+
+ strncpy(controllerState.controllerName, deviceId.BeginReading(), kVRControllerNameMaxLen);
+ controllerState.numButtons = numButtons;
+ controllerState.numAxes = numAxes;
+ controllerState.numHaptics = kNumOpenVRHaptcs;
+
+ // If the Windows MR controller doesn't has the amount
+ // of buttons or axes as our expectation, switching off
+ // the workaround for Windows MR.
+ if (mIsWindowsMR && (numAxes < 4 || numButtons < 5)) {
+ mIsWindowsMR = false;
+ NS_WARNING("OpenVR - Switching off Windows MR mode.");
+ }
+ }
+ controllerPresent[stateIndex] = true;
}
-
- state.sensorState.CalcViewMatrices(headToEyeTransforms);
- state.sensorState.inputFrameID++;
+ // Clear out entries for disconnected controllers
+ for (uint32_t stateIndex = 0; stateIndex < kVRControllerMaxCount; stateIndex++) {
+ if (!controllerPresent[stateIndex] && mControllerDeviceIndex[stateIndex] != 0) {
+ mControllerDeviceIndex[stateIndex] = 0;
+ memset(&aState.controllerState[stateIndex], 0, sizeof(VRControllerState));
+ }
+ }
}
void
-OpenVRSession::GetControllerState(VRSystemState &state)
+OpenVRSession::UpdateControllerButtons(VRSystemState& aState)
{
- // TODO - Implement
+ MOZ_ASSERT(mVRSystem);
+
+ // Compared to Edge, we have a wrong implementation for the vertical axis value.
+ // In order to not affect the current VR content, we add a workaround for yAxis.
+ const float yAxisInvert = (mIsWindowsMR) ? -1.0f : 1.0f;
+ const float triggerThreshold = gfxPrefs::VRControllerTriggerThreshold();
+
+ for (uint32_t stateIndex = 0; stateIndex < kVRControllerMaxCount; stateIndex++) {
+ ::vr::TrackedDeviceIndex_t trackedDevice = mControllerDeviceIndex[stateIndex];
+ if (trackedDevice == 0) {
+ continue;
+ }
+ VRControllerState& controllerState = aState.controllerState[stateIndex];
+ const ::vr::ETrackedControllerRole role = mVRSystem->
+ GetControllerRoleForTrackedDeviceIndex(
+ trackedDevice);
+ dom::GamepadHand hand = GetControllerHandFromControllerRole(role);
+ controllerState.hand = hand;
+
+ ::vr::VRControllerState_t vrControllerState;
+ if (mVRSystem->GetControllerState(trackedDevice, &vrControllerState, sizeof(vrControllerState))) {
+ uint32_t axisIdx = 0;
+ uint32_t buttonIdx = 0;
+ for (uint32_t j = 0; j < ::vr::k_unControllerStateAxisCount; ++j) {
+ const uint32_t axisType = mVRSystem->GetInt32TrackedDeviceProperty(
+ trackedDevice,
+ static_cast<::vr::TrackedDeviceProperty>(
+ ::vr::Prop_Axis0Type_Int32 + j));
+ switch (axisType) {
+ case ::vr::EVRControllerAxisType::k_eControllerAxis_Joystick:
+ case ::vr::EVRControllerAxisType::k_eControllerAxis_TrackPad:
+ {
+ if (mIsWindowsMR) {
+ // Adjust the input mapping for Windows MR which has
+ // different order.
+ axisIdx = (axisIdx == 0) ? 2 : 0;
+ buttonIdx = (buttonIdx == 0) ? 4 : 0;
+ }
+
+ controllerState.axisValue[axisIdx] = vrControllerState.rAxis[j].x;
+ ++axisIdx;
+ controllerState.axisValue[axisIdx] = vrControllerState.rAxis[j].y * yAxisInvert;
+ ++axisIdx;
+ uint64_t buttonMask = ::vr::ButtonMaskFromId(
+ static_cast<::vr::EVRButtonId>(::vr::k_EButton_Axis0 + j));
+
+ UpdateButton(controllerState, vrControllerState, buttonIdx, buttonMask);
+ ++buttonIdx;
+
+ if (mIsWindowsMR) {
+ axisIdx = (axisIdx == 4) ? 2 : 4;
+ buttonIdx = (buttonIdx == 5) ? 1 : 2;
+ }
+ break;
+ }
+ case vr::EVRControllerAxisType::k_eControllerAxis_Trigger:
+ {
+ if (j <= 2) {
+ UpdateTrigger(controllerState, buttonIdx, vrControllerState.rAxis[j].x, triggerThreshold);
+ ++buttonIdx;
+ } else {
+ // For SteamVR Knuckles.
+ UpdateTrigger(controllerState, buttonIdx, vrControllerState.rAxis[j].x, triggerThreshold);
+ ++buttonIdx;
+ UpdateTrigger(controllerState, buttonIdx, vrControllerState.rAxis[j].y, triggerThreshold);
+ ++buttonIdx;
+ }
+ break;
+ }
+ }
+ }
+
+ const uint64_t supportedButtons = mVRSystem->GetUint64TrackedDeviceProperty(
+ trackedDevice, ::vr::Prop_SupportedButtons_Uint64);
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_A)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_A));
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_Grip)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_Grip));
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_ApplicationMenu)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_ApplicationMenu));
+ ++buttonIdx;
+ }
+ if (mIsWindowsMR) {
+ // button 4 in Windows MR has already been assigned
+ // to k_eControllerAxis_TrackPad.
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Left)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_DPad_Left));
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Up)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_DPad_Up));
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Right)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_DPad_Right));
+ ++buttonIdx;
+ }
+ if (supportedButtons &
+ BTN_MASK_FROM_ID(k_EButton_DPad_Down)) {
+ UpdateButton(controllerState, vrControllerState, buttonIdx, BTN_MASK_FROM_ID(k_EButton_DPad_Down));
+ ++buttonIdx;
+ }
+ }
+ }
+}
+
+void
+OpenVRSession::UpdateControllerPoses(VRSystemState& aState)
+{
+ MOZ_ASSERT(mVRSystem);
+
+ ::vr::TrackedDevicePose_t poses[::vr::k_unMaxTrackedDeviceCount];
+ mVRSystem->GetDeviceToAbsoluteTrackingPose(::vr::TrackingUniverseSeated, 0.0f,
+ poses, ::vr::k_unMaxTrackedDeviceCount);
+
+ for (uint32_t stateIndex = 0; stateIndex < kVRControllerMaxCount; stateIndex++) {
+ ::vr::TrackedDeviceIndex_t trackedDevice = mControllerDeviceIndex[stateIndex];
+ if (trackedDevice == 0) {
+ continue;
+ }
+ VRControllerState& controllerState = aState.controllerState[stateIndex];
+ const ::vr::TrackedDevicePose_t& pose = poses[trackedDevice];
+
+ if (pose.bDeviceIsConnected) {
+ controllerState.flags = (dom::GamepadCapabilityFlags::Cap_Orientation |
+ dom::GamepadCapabilityFlags::Cap_Position);
+ } else {
+ controllerState.flags = dom::GamepadCapabilityFlags::Cap_None;
+ }
+ if (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(pose.mDeviceToAbsoluteTracking));
+ m.Transpose();
+
+ gfx::Quaternion rot;
+ rot.SetFromRotationMatrix(m);
+ rot.Invert();
+
+ controllerState.pose.orientation[0] = rot.x;
+ controllerState.pose.orientation[1] = rot.y;
+ controllerState.pose.orientation[2] = rot.z;
+ controllerState.pose.orientation[3] = rot.w;
+ controllerState.pose.angularVelocity[0] = pose.vAngularVelocity.v[0];
+ controllerState.pose.angularVelocity[1] = pose.vAngularVelocity.v[1];
+ controllerState.pose.angularVelocity[2] = pose.vAngularVelocity.v[2];
+ controllerState.pose.angularAcceleration[0] = 0.0f;
+ controllerState.pose.angularAcceleration[1] = 0.0f;
+ controllerState.pose.angularAcceleration[2] = 0.0f;
+ controllerState.isOrientationValid = true;
+
+ controllerState.pose.position[0] = m._41;
+ controllerState.pose.position[1] = m._42;
+ controllerState.pose.position[2] = m._43;
+ controllerState.pose.linearVelocity[0] = pose.vVelocity.v[0];
+ controllerState.pose.linearVelocity[1] = pose.vVelocity.v[1];
+ controllerState.pose.linearVelocity[2] = pose.vVelocity.v[2];
+ controllerState.pose.linearAcceleration[0] = 0.0f;
+ controllerState.pose.linearAcceleration[1] = 0.0f;
+ controllerState.pose.linearAcceleration[2] = 0.0f;
+ controllerState.isPositionValid = true;
+ } else {
+ controllerState.isOrientationValid = false;
+ controllerState.isPositionValid = false;
+ }
+ }
+}
+
+void
+OpenVRSession::GetControllerDeviceId(::vr::ETrackedDeviceClass aDeviceType,
+ ::vr::TrackedDeviceIndex_t aDeviceIndex,
+ nsCString& aId)
+{
+ switch (aDeviceType) {
+ case ::vr::TrackedDeviceClass_Controller:
+ {
+ ::vr::ETrackedPropertyError err;
+ uint32_t requiredBufferLen;
+ bool isFound = false;
+ char charBuf[128];
+ requiredBufferLen = mVRSystem->GetStringTrackedDeviceProperty(aDeviceIndex,
+ ::vr::Prop_RenderModelName_String, charBuf, 128, &err);
+ if (requiredBufferLen > 128) {
+ MOZ_CRASH("Larger than the buffer size.");
+ }
+ MOZ_ASSERT(requiredBufferLen && err == ::vr::TrackedProp_Success);
+ nsCString deviceId(charBuf);
+ if (deviceId.Find("knuckles") != kNotFound) {
+ aId.AssignLiteral("OpenVR Knuckles");
+ isFound = true;
+ }
+ requiredBufferLen = mVRSystem->GetStringTrackedDeviceProperty(aDeviceIndex,
+ ::vr::Prop_SerialNumber_String, charBuf, 128, &err);
+ if (requiredBufferLen > 128) {
+ MOZ_CRASH("Larger than the buffer size.");
+ }
+ MOZ_ASSERT(requiredBufferLen && err == ::vr::TrackedProp_Success);
+ deviceId.Assign(charBuf);
+ if (deviceId.Find("MRSOURCE") != kNotFound) {
+ aId.AssignLiteral("Spatial Controller (Spatial Interaction Source) ");
+ mIsWindowsMR = true;
+ isFound = true;
+ }
+ if (!isFound) {
+ aId.AssignLiteral("OpenVR Gamepad");
+ }
+ break;
+ }
+ case ::vr::TrackedDeviceClass_GenericTracker:
+ {
+ aId.AssignLiteral("OpenVR Tracker");
+ break;
+ }
+ default:
+ MOZ_ASSERT(false);
+ break;
+ }
}
void
OpenVRSession::StartFrame(mozilla::gfx::VRSystemState& aSystemState)
{
- GetSensorState(aSystemState);
- GetControllerState(aSystemState);
+ UpdateHeadsetPose(aSystemState);
+ UpdateEyeParameters(aSystemState);
+ EnumerateControllers(aSystemState);
+ UpdateControllerButtons(aSystemState);
+ UpdateControllerPoses(aSystemState);
+ aSystemState.sensorState.inputFrameID++;
}
bool
OpenVRSession::ShouldQuit() const
{
return mShouldQuit;
}
--- a/gfx/vr/service/OpenVRSession.h
+++ b/gfx/vr/service/OpenVRSession.h
@@ -37,29 +37,36 @@ public:
void StopPresentation() override;
bool SubmitFrame(const mozilla::gfx::VRLayer_Stereo_Immersive& aLayer) override;
private:
// OpenVR State
::vr::IVRSystem* mVRSystem = nullptr;
::vr::IVRChaperone* mVRChaperone = nullptr;
::vr::IVRCompositor* mVRCompositor = nullptr;
+ ::vr::TrackedDeviceIndex_t mControllerDeviceIndex[kVRControllerMaxCount];
bool mShouldQuit;
+ bool mIsWindowsMR;
bool InitState(mozilla::gfx::VRSystemState& aSystemState);
- void UpdateStageParameters(mozilla::gfx::VRDisplayState& state);
- void UpdateEyeParameters(mozilla::gfx::VRDisplayState& state, gfx::Matrix4x4* headToEyeTransforms = nullptr);
- void GetSensorState(mozilla::gfx::VRSystemState& state);
- void GetControllerState(VRSystemState &state);
+ void UpdateStageParameters(mozilla::gfx::VRDisplayState& aState);
+ void UpdateEyeParameters(mozilla::gfx::VRSystemState& aState);
+ void UpdateHeadsetPose(mozilla::gfx::VRSystemState& aState);
+ void EnumerateControllers(VRSystemState& aState);
+ void UpdateControllerPoses(VRSystemState& aState);
+ void UpdateControllerButtons(VRSystemState& aState);
bool SubmitFrame(void* aTextureHandle,
::vr::ETextureType aTextureType,
const VRLayerEyeRect& aLeftEyeRect,
const VRLayerEyeRect& aRightEyeRect);
#if defined(XP_WIN)
bool CreateD3DObjects();
#endif
+ void GetControllerDeviceId(::vr::ETrackedDeviceClass aDeviceType,
+ ::vr::TrackedDeviceIndex_t aDeviceIndex,
+ nsCString& aId);
};
} // namespace mozilla
} // namespace gfx
#endif // GFX_VR_SERVICE_OPENVRSESSION_H