Bug 1344393 - Add StageParameters for Oculus r=daoshengmu
authorKearwood Gilbert <kgilbert@mozilla.com>
Fri, 17 Mar 2017 13:33:56 -0700
changeset 348445 56dcf92f974c3b05e3d188161a245ae63b68e900
parent 348444 d921a7db8025a3f10879bb6a3c33ac054a745ea9
child 348446 65c5873eef0451b7691b99beb2010b09d6b766f9
push id39172
push userkgilbert@mozilla.com
push dateMon, 20 Mar 2017 18:13:19 +0000
treeherderautoland@56dcf92f974c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaoshengmu
bugs1344393
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1344393 - Add StageParameters for Oculus r=daoshengmu MozReview-Commit-ID: 9OkleewwS2b
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
gfx/vr/ovr_capi_dynamic.h
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -93,16 +93,17 @@ static pfn_ovr_SetBool ovr_SetBool = nul
 static pfn_ovr_GetInt ovr_GetInt = nullptr;
 static pfn_ovr_SetInt ovr_SetInt = nullptr;
 static pfn_ovr_GetFloat ovr_GetFloat = nullptr;
 static pfn_ovr_SetFloat ovr_SetFloat = nullptr;
 static pfn_ovr_GetFloatArray ovr_GetFloatArray = nullptr;
 static pfn_ovr_SetFloatArray ovr_SetFloatArray = nullptr;
 static pfn_ovr_GetString ovr_GetString = nullptr;
 static pfn_ovr_SetString ovr_SetString = nullptr;
+static pfn_ovr_GetBoundaryDimensions ovr_GetBoundaryDimensions = nullptr;
 
 #ifdef XP_WIN
 static pfn_ovr_CreateTextureSwapChainDX ovr_CreateTextureSwapChainDX = nullptr;
 static pfn_ovr_GetTextureSwapChainBufferDX ovr_GetTextureSwapChainBufferDX = nullptr;
 static pfn_ovr_CreateMirrorTextureDX ovr_CreateMirrorTextureDX = nullptr;
 static pfn_ovr_GetMirrorTextureBufferDX ovr_GetMirrorTextureBufferDX = nullptr;
 #endif
 
@@ -281,16 +282,17 @@ InitializeOculusCAPI()
   REQUIRE_FUNCTION(ovr_GetInt);
   REQUIRE_FUNCTION(ovr_SetInt);
   REQUIRE_FUNCTION(ovr_GetFloat);
   REQUIRE_FUNCTION(ovr_SetFloat);
   REQUIRE_FUNCTION(ovr_GetFloatArray);
   REQUIRE_FUNCTION(ovr_SetFloatArray);
   REQUIRE_FUNCTION(ovr_GetString);
   REQUIRE_FUNCTION(ovr_SetString);
+  REQUIRE_FUNCTION(ovr_GetBoundaryDimensions);
 
 #ifdef XP_WIN
 
   REQUIRE_FUNCTION(ovr_CreateTextureSwapChainDX);
   REQUIRE_FUNCTION(ovr_GetTextureSwapChainBufferDX);
   REQUIRE_FUNCTION(ovr_CreateMirrorTextureDX);
   REQUIRE_FUNCTION(ovr_GetMirrorTextureBufferDX);
 
@@ -351,16 +353,17 @@ VRDisplayOculus::VRDisplayOculus(ovrSess
   , mQuadVS(nullptr)
   , mQuadPS(nullptr)
   , mLinearSamplerState(nullptr)
   , mVSConstantBuffer(nullptr)
   , mPSConstantBuffer(nullptr)
   , mVertexBuffer(nullptr)
   , mInputLayout(nullptr)
   , mIsPresenting(false)
+  , mEyeHeight(OVR_DEFAULT_EYE_HEIGHT)
 {
   MOZ_COUNT_CTOR_INHERITED(VRDisplayOculus, VRDisplayHost);
 
   mDisplayInfo.mDisplayName.AssignLiteral("Oculus VR HMD");
   mDisplayInfo.mIsConnected = true;
   mDisplayInfo.mIsMounted = false;
 
   mDesc = ovr_GetHmdDesc(aSession);
@@ -368,16 +371,17 @@ VRDisplayOculus::VRDisplayOculus(ovrSess
   mDisplayInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None;
   if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Orientation) {
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Orientation;
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration;
   }
   if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Position) {
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Position;
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
+    mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_StageParameters;
   }
   mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
   mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_MountDetection;
   mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Present;
 
   mFOVPort[VRDisplayInfo::Eye_Left] = mDesc.DefaultEyeFov[ovrEye_Left];
   mFOVPort[VRDisplayInfo::Eye_Right] = mDesc.DefaultEyeFov[ovrEye_Right];
 
@@ -396,16 +400,18 @@ VRDisplayOculus::VRDisplayOculus(ovrSess
     mDisplayInfo.mEyeTranslation[eye] = Point3D(renderDesc.HmdToEyeOffset.x, renderDesc.HmdToEyeOffset.y, renderDesc.HmdToEyeOffset.z);
 
     texSize[eye] = ovr_GetFovTextureSize(mSession, (ovrEyeType)eye, mFOVPort[eye], pixelsPerDisplayPixel);
   }
 
   // take the max of both for eye resolution
   mDisplayInfo.mEyeResolution.width = std::max(texSize[VRDisplayInfo::Eye_Left].w, texSize[VRDisplayInfo::Eye_Right].w);
   mDisplayInfo.mEyeResolution.height = std::max(texSize[VRDisplayInfo::Eye_Left].h, texSize[VRDisplayInfo::Eye_Right].h);
+
+  UpdateStageParameters();
 }
 
 VRDisplayOculus::~VRDisplayOculus() {
   StopPresentation();
   Destroy();
   MOZ_COUNT_DTOR_INHERITED(VRDisplayOculus, VRDisplayHost);
 }
 
@@ -414,19 +420,58 @@ VRDisplayOculus::Destroy()
 {
   if (mSession) {
     ovr_Destroy(mSession);
     mSession = nullptr;
   }
 }
 
 void
+VRDisplayOculus::UpdateStageParameters()
+{
+  ovrVector3f playArea;
+  ovrResult res = ovr_GetBoundaryDimensions(mSession, ovrBoundary_PlayArea, &playArea);
+  if (res == ovrSuccess) {
+    mDisplayInfo.mStageSize.width = playArea.x;
+    mDisplayInfo.mStageSize.height = playArea.z;
+  } else {
+    // If we fail, fall back to reasonable defaults.
+    // 1m x 1m space
+    mDisplayInfo.mStageSize.width = 1.0f;
+    mDisplayInfo.mStageSize.height = 1.0f;
+  }
+
+  mEyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
+
+  mDisplayInfo.mSittingToStandingTransform._11 = 1.0f;
+  mDisplayInfo.mSittingToStandingTransform._12 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._13 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._14 = 0.0f;
+
+  mDisplayInfo.mSittingToStandingTransform._21 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._22 = 1.0f;
+  mDisplayInfo.mSittingToStandingTransform._23 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._24 = 0.0f;
+
+  mDisplayInfo.mSittingToStandingTransform._31 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._32 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._33 = 1.0f;
+  mDisplayInfo.mSittingToStandingTransform._34 = 0.0f;
+
+  mDisplayInfo.mSittingToStandingTransform._41 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._42 = mEyeHeight;
+  mDisplayInfo.mSittingToStandingTransform._43 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._44 = 1.0f;
+}
+
+void
 VRDisplayOculus::ZeroSensor()
 {
   ovr_RecenterTrackingOrigin(mSession);
+  UpdateStageParameters();
 }
 
 VRHMDSensorState
 VRDisplayOculus::GetSensorState()
 {
   mInputFrameID++;
 
   VRHMDSensorState result;
@@ -435,16 +480,17 @@ VRDisplayOculus::GetSensorState()
     // XXX We might need to call ovr_GetPredictedDisplayTime even if we don't use the result.
     // If we don't call it, the Oculus driver will spew out many warnings...
     double predictedFrameTime = ovr_GetPredictedDisplayTime(mSession, mInputFrameID);
     frameDelta = predictedFrameTime - ovr_GetTimeInSeconds();
   }
   result = GetSensorState(frameDelta);
   result.inputFrameID = mInputFrameID;
   mLastSensorState[result.inputFrameID % kMaxLatencyFrames] = result;
+  result.position[1] -= mEyeHeight;
   return result;
 }
 
 VRHMDSensorState
 VRDisplayOculus::GetSensorState(double timeOffset)
 {
   VRHMDSensorState result;
   result.Clear();
@@ -983,16 +1029,21 @@ VRSystemManagerOculus::GetHMDs(nsTArray<
     mHMDInfo = nullptr;
   } else if (mHMDInfo == nullptr) {
     // HMD Detected
     ovrSession session;
     ovrGraphicsLuid luid;
     ovrResult orv = ovr_Create(&session, &luid);
     if (orv == ovrSuccess) {
       mSession = session;
+      orv = ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
+      if (orv != ovrSuccess) {
+        NS_WARNING("ovr_SetTrackingOriginType failed.\n");
+      }
+
       mHMDInfo = new VRDisplayOculus(session);
     }
   }
 
   if (mHMDInfo) {
     aHMDResult.AppendElement(mHMDInfo);
   }
 }
@@ -1094,16 +1145,19 @@ VRSystemManagerOculus::HandleInput()
       poseState.linearVelocity[0] = pose.LinearVelocity.x;
       poseState.linearVelocity[1] = pose.LinearVelocity.y;
       poseState.linearVelocity[2] = pose.LinearVelocity.z;
 
       poseState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration;
       poseState.linearAcceleration[0] = pose.LinearAcceleration.x;
       poseState.linearAcceleration[1] = pose.LinearAcceleration.y;
       poseState.linearAcceleration[2] = pose.LinearAcceleration.z;
+
+      float eyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
+      poseState.position[1] -= eyeHeight;
     }
     HandlePoseTracking(i, poseState, controller);
   }
 }
 
 void
 VRSystemManagerOculus::HandleButtonPress(uint32_t aControllerIdx,
                                          uint32_t aButton,
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -43,16 +43,17 @@ public:
 protected:
   virtual void StartPresentation() override;
   virtual void StopPresentation() override;
   virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
                            const IntSize& aSize,
                            const VRHMDSensorState& aSensorState,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
+  void UpdateStageParameters();
 
 public:
   explicit VRDisplayOculus(ovrSession aSession);
 
 protected:
   virtual ~VRDisplayOculus();
   void Destroy();
 
@@ -77,17 +78,18 @@ protected:
   layers::VertexShaderConstants mVSConstants;
   layers::PixelShaderConstants mPSConstants;
   RefPtr<ID3D11Buffer> mVSConstantBuffer;
   RefPtr<ID3D11Buffer> mPSConstantBuffer;
   RefPtr<ID3D11Buffer> mVertexBuffer;
   RefPtr<ID3D11InputLayout> mInputLayout;
 
   bool mIsPresenting;
-  
+  float mEyeHeight;
+
   bool UpdateConstantBuffers();
 
   struct Vertex
   {
     float position[2];
   };
 };
 
--- a/gfx/vr/ovr_capi_dynamic.h
+++ b/gfx/vr/ovr_capi_dynamic.h
@@ -562,32 +562,40 @@ typedef enum {
   ovrDebugHudStereo_Off = 0,
   ovrDebugHudStereo_Quad = 1,
   ovrDebugHudStereo_QuadWithCrosshair = 2,
   ovrDebugHudStereo_CrosshairAtInfinity = 3,
   ovrDebugHudStereo_Count,
   ovrDebugHudStereo_EnumSize = 0x7fffffff
 } ovrDebugHudStereoMode;
 
+typedef enum {
+  // Outer boundary - closely represents user setup walls
+  ovrBoundary_Outer = 0x0001,
+  // Play area - safe rectangular area inside outer boundary which can optionally be used to restrict user interactions and motion.
+  ovrBoundary_PlayArea = 0x0100,
+} ovrBoundaryType;
+
 typedef ovrBool(OVR_PFN* pfn_ovr_GetBool)(ovrSession session, const char* propertyName, ovrBool defaultVal);
-typedef ovrBool(OVR_PFN* pfn_ovr_SetBool)(ovrSession session, const char* propertyName, ovrBool value); 
+typedef ovrBool(OVR_PFN* pfn_ovr_SetBool)(ovrSession session, const char* propertyName, ovrBool value);
 typedef int (OVR_PFN* pfn_ovr_GetInt)(ovrSession session, const char* propertyName, int defaultVal);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetInt)(ovrSession session, const char* propertyName, int value);
 typedef float (OVR_PFN* pfn_ovr_GetFloat)(ovrSession session, const char* propertyName, float defaultVal);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetFloat)(ovrSession session, const char* propertyName, float value);
 typedef unsigned int (OVR_PFN* pfn_ovr_GetFloatArray)(ovrSession session, const char* propertyName,
   float values[], unsigned int valuesCapacity);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetFloatArray)(ovrSession session, const char* propertyName,
   const float values[], unsigned int valuesSize);
 typedef const char* (OVR_PFN* pfn_ovr_GetString)(ovrSession session, const char* propertyName,
   const char* defaultVal);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetString)(ovrSession session, const char* propertyName,
   const char* value);
-
-
+typedef ovrResult (OVR_PFN* pfn_ovr_GetBoundaryDimensions)(ovrSession session,
+                                                           ovrBoundaryType boundaryType,
+                                                           ovrVector3f* outDimensions);
 
 typedef enum {
   ovrError_MemoryAllocationFailure = -1000,
   ovrError_SocketCreationFailure = -1001,
   ovrError_InvalidSession = -1002,
   ovrError_Timeout = -1003,
   ovrError_NotInitialized = -1004,
   ovrError_InvalidParameter = -1005,
@@ -709,14 +717,17 @@ typedef ovrResult (OVR_PFN* pfn_ovr_GetT
 typedef ovrResult (OVR_PFN* pfn_ovr_CreateMirrorTextureGL)(ovrSession session,
 	const ovrMirrorTextureDesc* desc,
 	ovrMirrorTexture* out_MirrorTexture);
 
 typedef ovrResult (OVR_PFN* pfn_ovr_GetMirrorTextureBufferGL)(ovrSession session,
 	ovrMirrorTexture mirrorTexture,
 	unsigned int* out_TexId);
 
-#ifdef __cplusplus 
+#define OVR_KEY_EYE_HEIGHT "EyeHeight" // float meters
+#define OVR_DEFAULT_EYE_HEIGHT 1.675f
+
+#ifdef __cplusplus
 }
 #endif
 
 #endif /* mozilla_ovr_capi_dynamic_h_ */
 #endif /* OVR_CAPI_h */