forked from mirrors/gecko-dev
		
	Bug 1470527 - Implement Controller support for gfxVRExternal and VRServiceOpenVR,r=daoshengmu
MozReview-Commit-ID: I1xHfmAPMxT --HG-- extra : rebase_source : 5d957ff6172f3e730b61878b9067ec506ea4a383 extra : source : 66c97a5d22efc6436aab76756759b9b51517e940
This commit is contained in:
		
							parent
							
								
									12b5f4ebbe
								
							
						
					
					
						commit
						d0b35a2ff4
					
				
					 19 changed files with 981 additions and 333 deletions
				
			
		|  | @ -285,7 +285,7 @@ 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); | ||||
| } | ||||
|  | @ -295,7 +295,7 @@ 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); | ||||
| } | ||||
|  | @ -305,7 +305,7 @@ 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); | ||||
| 
 | ||||
|  | @ -316,7 +316,7 @@ 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); | ||||
| } | ||||
|  | @ -326,7 +326,7 @@ 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); | ||||
| } | ||||
|  | @ -336,7 +336,7 @@ 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); | ||||
| } | ||||
|  |  | |||
|  | @ -95,50 +95,50 @@ VRMockDisplay::SetPose(const Nullable<Float32Array>& aPosition, | |||
|     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]; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,10 @@ | |||
| #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" | ||||
|  | @ -34,6 +37,7 @@ VRDisplayClient::VRDisplayClient(const VRDisplayInfo& aDisplayInfo) | |||
|   , mPresentationCount(0) | ||||
|   , mLastEventFrameId(0) | ||||
|   , mLastPresentingGeneration(0) | ||||
|   , mLastEventControllerState{} | ||||
| { | ||||
|   MOZ_COUNT_CTOR(VRDisplayClient); | ||||
| } | ||||
|  | @ -128,6 +132,140 @@ VRDisplayClient::FireEvents() | |||
|     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 | ||||
|  |  | |||
|  | @ -51,6 +51,7 @@ protected: | |||
|   virtual ~VRDisplayClient(); | ||||
| 
 | ||||
|   void FireEvents(); | ||||
|   void FireGamepadEvents(); | ||||
| 
 | ||||
|   VRDisplayInfo mDisplayInfo; | ||||
| 
 | ||||
|  | @ -60,6 +61,10 @@ protected: | |||
|   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; | ||||
| }; | ||||
|  |  | |||
|  | @ -352,7 +352,7 @@ VRControllerHost::VRControllerHost(VRDeviceType aType, dom::GamepadHand aHand, | |||
| { | ||||
|   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(); | ||||
|  | @ -372,25 +372,25 @@ VRControllerHost::GetControllerInfo() const | |||
| 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 | ||||
|  | @ -408,7 +408,7 @@ VRControllerHost::GetPose() | |||
| dom::GamepadHand | ||||
| VRControllerHost::GetHand() | ||||
| { | ||||
|   return mControllerInfo.mControllerState.mHand; | ||||
|   return mControllerInfo.mControllerState.hand; | ||||
| } | ||||
| 
 | ||||
| void | ||||
|  |  | |||
|  | @ -24,11 +24,12 @@ 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.
 | ||||
|  | @ -44,7 +45,7 @@ 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; | ||||
| 
 | ||||
|  | @ -82,6 +83,32 @@ enum class ControllerHand : uint8_t { | |||
|   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 { | ||||
|  | @ -140,20 +167,25 @@ enum class VRDisplayCapabilityFlags : uint16_t { | |||
| 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 { | ||||
|   uint64_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 | ||||
| 
 | ||||
|  | @ -248,22 +280,30 @@ struct VRDisplayState | |||
| 
 | ||||
| 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 | ||||
|  |  | |||
|  | @ -189,10 +189,10 @@ 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(); | ||||
|  |  | |||
|  | @ -60,6 +60,7 @@ struct VRDisplayInfo | |||
|   uint32_t mGroupMask; | ||||
|   uint64_t mFrameId; | ||||
|   VRDisplayState mDisplayState; | ||||
|   VRControllerState mControllerState[kVRControllerMaxCount]; | ||||
| 
 | ||||
|   VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames]; | ||||
|   const VRHMDSensorState& GetSensorState() const | ||||
|  | @ -89,10 +90,11 @@ struct VRDisplayInfo | |||
|         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; | ||||
|  | @ -123,13 +125,13 @@ 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; | ||||
|  | @ -137,15 +139,12 @@ struct VRControllerInfo | |||
|   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 { | ||||
|  |  | |||
|  | @ -52,8 +52,6 @@ using namespace mozilla::gfx::impl; | |||
| using namespace mozilla::layers; | ||||
| using namespace mozilla::dom; | ||||
| 
 | ||||
| static const uint32_t kNumExternalHaptcs = 1; | ||||
| 
 | ||||
| int VRDisplayExternal::sPushIndex = 0; | ||||
| 
 | ||||
| VRDisplayExternal::VRDisplayExternal(const VRDisplayState& aDisplayState) | ||||
|  | @ -65,7 +63,7 @@ VRDisplayExternal::VRDisplayExternal(const VRDisplayState& aDisplayState) | |||
|   mDisplayInfo.mDisplayState = aDisplayState; | ||||
| 
 | ||||
|   // default to an identity quaternion
 | ||||
|   mLastSensorState.orientation[3] = 1.0f; | ||||
|   mLastSensorState.pose.orientation[3] = 1.0f; | ||||
| } | ||||
| 
 | ||||
| VRDisplayExternal::~VRDisplayExternal() | ||||
|  | @ -78,8 +76,6 @@ void | |||
| VRDisplayExternal::Destroy() | ||||
| { | ||||
|   StopPresentation(); | ||||
| 
 | ||||
|   // TODO - Implement
 | ||||
| } | ||||
| 
 | ||||
| void | ||||
|  | @ -93,7 +89,7 @@ VRDisplayExternal::Refresh() | |||
|   VRManager *vm = VRManager::Get(); | ||||
|   VRSystemManagerExternal* manager = vm->GetExternalManager(); | ||||
| 
 | ||||
|   manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState); | ||||
|   manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState, mDisplayInfo.mControllerState); | ||||
| } | ||||
| 
 | ||||
| VRHMDSensorState | ||||
|  | @ -238,7 +234,7 @@ VRDisplayExternal::SubmitFrame(const layers::SurfaceDescriptor& aTexture, | |||
|   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; | ||||
|  | @ -254,26 +250,6 @@ VRDisplayExternal::SubmitFrame(const layers::SurfaceDescriptor& aTexture, | |||
|   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) | ||||
| #if !defined(MOZ_WIDGET_ANDROID) | ||||
|  | @ -458,7 +434,6 @@ VRSystemManagerExternal::Shutdown() | |||
|   if (mDisplay) { | ||||
|     mDisplay = nullptr; | ||||
|   } | ||||
|   RemoveControllers(); | ||||
|   CloseShmem(); | ||||
| #if defined(MOZ_WIDGET_ANDROID) | ||||
|   mDoShutdown = false; | ||||
|  | @ -537,12 +512,6 @@ VRSystemManagerExternal::GetIsPresenting() | |||
|   return false; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| VRSystemManagerExternal::HandleInput() | ||||
| { | ||||
|   // TODO - Implement This!
 | ||||
| } | ||||
| 
 | ||||
| void | ||||
| VRSystemManagerExternal::VibrateHaptic(uint32_t aControllerIdx, | ||||
|                                       uint32_t aHapticIndex, | ||||
|  | @ -562,31 +531,40 @@ VRSystemManagerExternal::StopVibrateHaptic(uint32_t aControllerIdx) | |||
| 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
 | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState /* = nullptr */) | ||||
| VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, | ||||
|                                    VRHMDSensorState* aSensorState /* = nullptr */, | ||||
|                                    VRControllerState* aControllerState /* = nullptr */) | ||||
| { | ||||
|   bool success = false; | ||||
|   MOZ_ASSERT(mExternalShmem); | ||||
|  | @ -597,6 +575,9 @@ VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorSta | |||
|       if (aSensorState) { | ||||
|         memcpy(aSensorState, (void*)&(mExternalShmem->state.sensorState), sizeof(VRHMDSensorState)); | ||||
|       } | ||||
|       if (aControllerState) { | ||||
|         memcpy(aControllerState, (void*)&(mExternalShmem->state.controllerState), sizeof(VRControllerState) * kVRControllerMaxCount); | ||||
|       } | ||||
|       success = mExternalShmem->state.enumerationCompleted; | ||||
|       pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->systemMutex)); | ||||
|       mDoShutdown = aDisplayState->shutdown; | ||||
|  | @ -609,6 +590,9 @@ VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorSta | |||
|       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)
 | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ protected: | |||
| public: | ||||
|   explicit VRDisplayExternal(const VRDisplayState& aDisplayState); | ||||
|   void Refresh(); | ||||
|   const VRControllerState& GetLastControllerState(uint32_t aStateIndex) const; | ||||
| protected: | ||||
|   virtual ~VRDisplayExternal(); | ||||
|   void Destroy(); | ||||
|  | @ -60,17 +61,6 @@ private: | |||
|   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 | ||||
|  | @ -96,7 +86,9 @@ public: | |||
|                              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, const bool aNotifyCond = false); | ||||
| 
 | ||||
| protected: | ||||
|  | @ -106,7 +98,6 @@ protected: | |||
| 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) | ||||
|  |  | |||
|  | @ -317,22 +317,22 @@ VRDisplayOSVR::GetSensorState() | |||
| 
 | ||||
|   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); | ||||
|  |  | |||
|  | @ -952,7 +952,7 @@ VRDisplayOculus::GetSensorState() | |||
|       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; | ||||
|  | @ -973,41 +973,41 @@ VRDisplayOculus::GetSensorState(double absTime) | |||
|   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; | ||||
|  | @ -1330,17 +1330,17 @@ VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand, uint32_t aDisplay | |||
|       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 | ||||
|  |  | |||
|  | @ -287,24 +287,24 @@ VRDisplayOpenVR::GetSensorState() | |||
|     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); | ||||
|  | @ -438,11 +438,10 @@ VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aDisplay | |||
|   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() | ||||
|  | @ -466,31 +465,31 @@ VRControllerOpenVR::GetTrackedIndex() | |||
| 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 | ||||
|  |  | |||
|  | @ -104,21 +104,21 @@ VRDisplayPuppet::VRDisplayPuppet() | |||
|   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() | ||||
|  | @ -585,10 +585,10 @@ VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand, uint32_t aDisplay | |||
| { | ||||
|   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() | ||||
|  | @ -672,13 +672,13 @@ VRControllerPuppet::GetPoseMoveState() | |||
| 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() | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ VRManagerChild::VRManagerChild() | |||
|   , mBackend(layers::LayersBackend::LAYERS_NONE) | ||||
|   , mPromiseID(0) | ||||
|   , mVRMockDisplay(nullptr) | ||||
|   , mLastControllerState{} | ||||
| { | ||||
|   MOZ_ASSERT(NS_IsMainThread()); | ||||
| 
 | ||||
|  |  | |||
|  | @ -139,6 +139,7 @@ private: | |||
|   uint32_t mPromiseID; | ||||
|   nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList; | ||||
|   RefPtr<dom::VRMockDisplay> mVRMockDisplay; | ||||
|   VRControllerState mLastControllerState[kVRControllerMaxCount]; | ||||
| 
 | ||||
|   DISALLOW_COPY_AND_ASSIGN(VRManagerChild); | ||||
| }; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #define mozilla_gfx_vr_VRMessageUtils_h | ||||
| 
 | ||||
| #include "ipc/IPCMessageUtils.h" | ||||
| #include "mozilla/ArrayUtils.h" | ||||
| #include "mozilla/GfxMessageUtils.h" | ||||
| #include "VRManager.h" | ||||
| 
 | ||||
|  | @ -109,9 +110,12 @@ struct ParamTraits<mozilla::gfx::VRDisplayInfo> | |||
|     WriteParam(aMsg, aParam.mGroupMask); | ||||
|     WriteParam(aMsg, aParam.mFrameId); | ||||
|     WriteParam(aMsg, aParam.mDisplayState); | ||||
|     for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) { | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aParam.mLastSensorState); i++) { | ||||
|       WriteParam(aMsg, aParam.mLastSensorState[i]); | ||||
|     } | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aParam.mControllerState); i++) { | ||||
|       WriteParam(aMsg, aParam.mControllerState[i]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) | ||||
|  | @ -124,26 +128,28 @@ struct ParamTraits<mozilla::gfx::VRDisplayInfo> | |||
|         !ReadParam(aMsg, aIter, &(aResult->mDisplayState))) { | ||||
|       return false; | ||||
|     } | ||||
|     for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) { | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aResult->mLastSensorState); i++) { | ||||
|       if (!ReadParam(aMsg, aIter, &(aResult->mLastSensorState[i]))) { | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aResult->mControllerState); 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]); | ||||
|  | @ -163,20 +169,11 @@ struct ParamTraits<mozilla::gfx::VRHMDSensorState> | |||
|     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])) || | ||||
|  | @ -197,12 +194,43 @@ struct ParamTraits<mozilla::gfx::VRHMDSensorState> | |||
|         !ReadParam(aMsg, aIter, &(aResult->linearAcceleration[2]))) { | ||||
|       return false; | ||||
|     } | ||||
|     for (int i=0; i < 16; i++) { | ||||
|     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 (size_t i = 0; i < mozilla::ArrayLength(aParam.leftViewMatrix); i++) { | ||||
|       WriteParam(aMsg, aParam.leftViewMatrix[i]); | ||||
|     } | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aParam.rightViewMatrix); 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 (size_t i = 0; i < mozilla::ArrayLength(aResult->leftViewMatrix); i++) { | ||||
|       if (!ReadParam(aMsg, aIter, &(aResult->leftViewMatrix[i]))) { | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
|     for (int i=0; i < 16; i++) { | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aResult->rightViewMatrix); i++) { | ||||
|       if (!ReadParam(aMsg, aIter, &(aResult->rightViewMatrix[i]))) { | ||||
|         return false; | ||||
|       } | ||||
|  | @ -246,19 +274,23 @@ struct ParamTraits<mozilla::gfx::VRControllerState> | |||
|   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); | ||||
|     for (int i=0; i < mozilla::gfx::kVRControllerMaxAxis; i++) { | ||||
|       WriteParam(aMsg, aParam.mAxisValue[i]); | ||||
|     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 (size_t i = 0; i < mozilla::ArrayLength(aParam.axisValue); i++) { | ||||
|       WriteParam(aMsg, aParam.axisValue[i]); | ||||
|     } | ||||
|     for (int i=0; i < mozilla::gfx::kVRControllerMaxTriggers; i++) { | ||||
|       WriteParam(aMsg, aParam.mTriggerValue[i]); | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aParam.triggerValue); i++) { | ||||
|       WriteParam(aMsg, aParam.triggerValue[i]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -266,25 +298,29 @@ struct ParamTraits<mozilla::gfx::VRControllerState> | |||
|   { | ||||
|     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]))) { | ||||
|     for (size_t i = 0; i < mozilla::ArrayLength(aResult->axisValue); 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 (size_t i = 0; i < mozilla::ArrayLength(aResult->triggerValue); 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; | ||||
|   } | ||||
|  |  | |||
|  | @ -1,14 +1,13 @@ | |||
| #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 | ||||
|  | @ -17,17 +16,91 @@ | |||
| #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) | ||||
| { | ||||
| } | ||||
| 
 | ||||
|  | @ -43,8 +116,10 @@ OpenVRSession::Initialize(mozilla::gfx::VRSystemState& aSystemState) | |||
|     // 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; | ||||
|   } | ||||
| 
 | ||||
|  | @ -143,95 +218,97 @@ OpenVRSession::InitState(VRSystemState& aSystemState) | |||
|   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
 | ||||
|     aState.mStageSize.width = 1.0f; | ||||
|     aState.mStageSize.height = 1.0f; | ||||
| 
 | ||||
|     state.mStageSize.width = 1.0f; | ||||
|     state.mStageSize.height = 1.0f; | ||||
|     aState.mSittingToStandingTransform[0] = 1.0f; | ||||
|     aState.mSittingToStandingTransform[1] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[2] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[3] = 0.0f; | ||||
| 
 | ||||
|     state.mSittingToStandingTransform[0] = 1.0f; | ||||
|     state.mSittingToStandingTransform[1] = 0.0f; | ||||
|     state.mSittingToStandingTransform[2] = 0.0f; | ||||
|     state.mSittingToStandingTransform[3] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[4] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[5] = 1.0f; | ||||
|     aState.mSittingToStandingTransform[6] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[7] = 0.0f; | ||||
| 
 | ||||
|     state.mSittingToStandingTransform[4] = 0.0f; | ||||
|     state.mSittingToStandingTransform[5] = 1.0f; | ||||
|     state.mSittingToStandingTransform[6] = 0.0f; | ||||
|     state.mSittingToStandingTransform[7] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[8] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[9] = 0.0f; | ||||
|     aState.mSittingToStandingTransform[10] = 1.0f; | ||||
|     aState.mSittingToStandingTransform[11] = 0.0f; | ||||
| 
 | ||||
|     state.mSittingToStandingTransform[8] = 0.0f; | ||||
|     state.mSittingToStandingTransform[9] = 0.0f; | ||||
|     state.mSittingToStandingTransform[10] = 1.0f; | ||||
|     state.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
 | ||||
|  | @ -241,23 +318,21 @@ OpenVRSession::UpdateEyeParameters(VRDisplayState& state, gfx::Matrix4x4* headTo | |||
|     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"); | ||||
|  | @ -281,39 +356,411 @@ OpenVRSession::GetSensorState(VRSystemState& state) | |||
|     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]; | ||||
| 
 | ||||
|     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]; | ||||
|     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]; | ||||
|   } | ||||
| 
 | ||||
|   state.sensorState.CalcViewMatrices(headToEyeTransforms); | ||||
|   state.sensorState.inputFrameID++; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| OpenVRSession::GetControllerState(VRSystemState &state) | ||||
| OpenVRSession::EnumerateControllers(VRSystemState& aState) | ||||
| { | ||||
|   // TODO - Implement
 | ||||
|   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; | ||||
| 
 | ||||
|       // 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; | ||||
|   } | ||||
|   // 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::UpdateControllerButtons(VRSystemState& aState) | ||||
| { | ||||
|   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 | ||||
|  |  | |||
|  | @ -42,13 +42,17 @@ private: | |||
|   ::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, | ||||
|  | @ -57,6 +61,9 @@ private: | |||
| #if defined(XP_WIN) | ||||
|   bool CreateD3DObjects(); | ||||
| #endif | ||||
|   void GetControllerDeviceId(::vr::ETrackedDeviceClass aDeviceType, | ||||
|                              ::vr::TrackedDeviceIndex_t aDeviceIndex, | ||||
|                              nsCString& aId); | ||||
| }; | ||||
| 
 | ||||
| } // namespace mozilla
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Kearwood Gilbert
						Kearwood Gilbert