1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
14 #include "mozilla/Preferences.h"
16 #include "ovr_capi_dynamic.h"
18 #include "nsServiceManagerUtils.h"
19 #include "nsIScreenManager.h"
22 #include "gfxWindowsPlatform.h" // for gfxWindowsPlatform::GetDPIScale
26 # define M_PI 3.14159265358979323846
31 #ifdef OVR_CAPI_LIMITED_MOZILLA
32 static pfn_ovr_Initialize ovr_Initialize
= nullptr;
33 static pfn_ovr_Shutdown ovr_Shutdown
= nullptr;
34 static pfn_ovrHmd_Detect ovrHmd_Detect
= nullptr;
35 static pfn_ovrHmd_Create ovrHmd_Create
= nullptr;
36 static pfn_ovrHmd_Destroy ovrHmd_Destroy
= nullptr;
37 static pfn_ovrHmd_CreateDebug ovrHmd_CreateDebug
= nullptr;
38 static pfn_ovrHmd_GetLastError ovrHmd_GetLastError
= nullptr;
39 static pfn_ovrHmd_AttachToWindow ovrHmd_AttachToWindow
= nullptr;
40 static pfn_ovrHmd_GetEnabledCaps ovrHmd_GetEnabledCaps
= nullptr;
41 static pfn_ovrHmd_SetEnabledCaps ovrHmd_SetEnabledCaps
= nullptr;
42 static pfn_ovrHmd_ConfigureTracking ovrHmd_ConfigureTracking
= nullptr;
43 static pfn_ovrHmd_RecenterPose ovrHmd_RecenterPose
= nullptr;
44 static pfn_ovrHmd_GetTrackingState ovrHmd_GetTrackingState
= nullptr;
45 static pfn_ovrHmd_GetFovTextureSize ovrHmd_GetFovTextureSize
= nullptr;
46 static pfn_ovrHmd_GetRenderDesc ovrHmd_GetRenderDesc
= nullptr;
47 static pfn_ovrHmd_CreateDistortionMesh ovrHmd_CreateDistortionMesh
= nullptr;
48 static pfn_ovrHmd_DestroyDistortionMesh ovrHmd_DestroyDistortionMesh
= nullptr;
49 static pfn_ovrHmd_GetRenderScaleAndOffset ovrHmd_GetRenderScaleAndOffset
= nullptr;
50 static pfn_ovrHmd_GetFrameTiming ovrHmd_GetFrameTiming
= nullptr;
51 static pfn_ovrHmd_BeginFrameTiming ovrHmd_BeginFrameTiming
= nullptr;
52 static pfn_ovrHmd_EndFrameTiming ovrHmd_EndFrameTiming
= nullptr;
53 static pfn_ovrHmd_ResetFrameTiming ovrHmd_ResetFrameTiming
= nullptr;
54 static pfn_ovrHmd_GetEyePoses ovrHmd_GetEyePoses
= nullptr;
55 static pfn_ovrHmd_GetHmdPosePerEye ovrHmd_GetHmdPosePerEye
= nullptr;
56 static pfn_ovrHmd_GetEyeTimewarpMatrices ovrHmd_GetEyeTimewarpMatrices
= nullptr;
57 static pfn_ovrMatrix4f_Projection ovrMatrix4f_Projection
= nullptr;
58 static pfn_ovrMatrix4f_OrthoSubProjection ovrMatrix4f_OrthoSubProjection
= nullptr;
59 static pfn_ovr_GetTimeInSeconds ovr_GetTimeInSeconds
= nullptr;
62 # ifdef HAVE_64BIT_BUILD
63 # define OVR_LIB_NAME "libovr64.dll"
65 # define OVR_LIB_NAME "libovr.dll"
67 #elif defined(XP_MACOSX)
68 # define OVR_LIB_NAME "libovr.dylib"
70 # define OVR_LIB_NAME 0
74 InitializeOculusCAPI()
76 static PRLibrary
*ovrlib
= nullptr;
79 const char *libName
= OVR_LIB_NAME
;
81 // If the pref is present, we override libName
82 nsAdoptingCString prefLibName
= mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
83 if (prefLibName
&& prefLibName
.get()) {
84 libName
= prefLibName
.get();
87 // If the env var is present, we override libName
88 if (PR_GetEnv("OVR_LIB_NAME")) {
89 libName
= PR_GetEnv("OVR_LIB_NAME");
93 printf_stderr("Don't know how to find Oculus VR library; missing dom.vr.ovr_lib_path or OVR_LIB_NAME\n");
97 ovrlib
= PR_LoadLibrary(libName
);
100 // Not found? Try harder. Needed mainly on OSX/etc. where
101 // the binary location is not in the search path.
102 const char *xulName
= "libxul.so";
103 #if defined(XP_MACOSX)
107 char *xulpath
= PR_GetLibraryFilePathname(xulName
, (PRFuncPtr
) &InitializeOculusCAPI
);
109 char *xuldir
= strrchr(xulpath
, '/');
114 char *ovrpath
= PR_GetLibraryName(xuldir
, libName
);
115 ovrlib
= PR_LoadLibrary(ovrpath
);
123 printf_stderr("Failed to load Oculus VR library, tried '%s'\n", libName
);
128 // was it already initialized?
132 #define REQUIRE_FUNCTION(_x) do { \
133 *(void **)&_x = (void *) PR_FindSymbol(ovrlib, #_x); \
134 if (!_x) { printf_stderr(#_x " symbol missing\n"); goto fail; } \
137 REQUIRE_FUNCTION(ovr_Initialize
);
138 REQUIRE_FUNCTION(ovr_Shutdown
);
139 REQUIRE_FUNCTION(ovrHmd_Detect
);
140 REQUIRE_FUNCTION(ovrHmd_Create
);
141 REQUIRE_FUNCTION(ovrHmd_Destroy
);
142 REQUIRE_FUNCTION(ovrHmd_CreateDebug
);
143 REQUIRE_FUNCTION(ovrHmd_GetLastError
);
144 REQUIRE_FUNCTION(ovrHmd_AttachToWindow
);
145 REQUIRE_FUNCTION(ovrHmd_GetEnabledCaps
);
146 REQUIRE_FUNCTION(ovrHmd_SetEnabledCaps
);
147 REQUIRE_FUNCTION(ovrHmd_ConfigureTracking
);
148 REQUIRE_FUNCTION(ovrHmd_RecenterPose
);
149 REQUIRE_FUNCTION(ovrHmd_GetTrackingState
);
151 REQUIRE_FUNCTION(ovrHmd_GetFovTextureSize
);
152 REQUIRE_FUNCTION(ovrHmd_GetRenderDesc
);
153 REQUIRE_FUNCTION(ovrHmd_CreateDistortionMesh
);
154 REQUIRE_FUNCTION(ovrHmd_DestroyDistortionMesh
);
155 REQUIRE_FUNCTION(ovrHmd_GetRenderScaleAndOffset
);
156 REQUIRE_FUNCTION(ovrHmd_GetFrameTiming
);
157 REQUIRE_FUNCTION(ovrHmd_BeginFrameTiming
);
158 REQUIRE_FUNCTION(ovrHmd_EndFrameTiming
);
159 REQUIRE_FUNCTION(ovrHmd_ResetFrameTiming
);
160 REQUIRE_FUNCTION(ovrHmd_GetEyePoses
);
161 REQUIRE_FUNCTION(ovrHmd_GetHmdPosePerEye
);
162 REQUIRE_FUNCTION(ovrHmd_GetEyeTimewarpMatrices
);
163 REQUIRE_FUNCTION(ovrMatrix4f_Projection
);
164 REQUIRE_FUNCTION(ovrMatrix4f_OrthoSubProjection
);
165 REQUIRE_FUNCTION(ovr_GetTimeInSeconds
);
167 #undef REQUIRE_FUNCTION
172 ovr_Initialize
= nullptr;
177 // we're statically linked; it's available
178 static bool InitializeOculusCAPI()
184 } // anonymous namespace
186 using namespace mozilla::gfx
;
188 // Dummy nsIScreen implementation, for when we just need to specify a size
189 class FakeScreen
: public nsIScreen
192 explicit FakeScreen(const IntRect
& aScreenRect
)
193 : mScreenRect(aScreenRect
)
198 NS_IMETHOD
GetRect(int32_t *l
, int32_t *t
, int32_t *w
, int32_t *h
) MOZ_OVERRIDE
{
201 *w
= mScreenRect
.width
;
202 *h
= mScreenRect
.height
;
205 NS_IMETHOD
GetAvailRect(int32_t *l
, int32_t *t
, int32_t *w
, int32_t *h
) MOZ_OVERRIDE
{
206 return GetRect(l
, t
, w
, h
);
208 NS_IMETHOD
GetRectDisplayPix(int32_t *l
, int32_t *t
, int32_t *w
, int32_t *h
) MOZ_OVERRIDE
{
209 return GetRect(l
, t
, w
, h
);
211 NS_IMETHOD
GetAvailRectDisplayPix(int32_t *l
, int32_t *t
, int32_t *w
, int32_t *h
) MOZ_OVERRIDE
{
212 return GetAvailRect(l
, t
, w
, h
);
215 NS_IMETHOD
GetId(uint32_t* aId
) MOZ_OVERRIDE
{ *aId
= (uint32_t)-1; return NS_OK
; }
216 NS_IMETHOD
GetPixelDepth(int32_t* aPixelDepth
) MOZ_OVERRIDE
{ *aPixelDepth
= 24; return NS_OK
; }
217 NS_IMETHOD
GetColorDepth(int32_t* aColorDepth
) MOZ_OVERRIDE
{ *aColorDepth
= 24; return NS_OK
; }
219 NS_IMETHOD
LockMinimumBrightness(uint32_t aBrightness
) MOZ_OVERRIDE
{ return NS_ERROR_NOT_AVAILABLE
; }
220 NS_IMETHOD
UnlockMinimumBrightness(uint32_t aBrightness
) MOZ_OVERRIDE
{ return NS_ERROR_NOT_AVAILABLE
; }
221 NS_IMETHOD
GetRotation(uint32_t* aRotation
) MOZ_OVERRIDE
{
222 *aRotation
= nsIScreen::ROTATION_0_DEG
;
225 NS_IMETHOD
SetRotation(uint32_t aRotation
) MOZ_OVERRIDE
{ return NS_ERROR_NOT_AVAILABLE
; }
226 NS_IMETHOD
GetContentsScaleFactor(double* aContentsScaleFactor
) MOZ_OVERRIDE
{
227 *aContentsScaleFactor
= 1.0;
232 virtual ~FakeScreen() {}
237 NS_IMPL_ISUPPORTS(FakeScreen
, nsIScreen
)
239 class HMDInfoOculus
: public VRHMDInfo
{
240 friend class VRHMDManagerOculusImpl
;
242 explicit HMDInfoOculus(ovrHmd aHMD
);
244 bool SetFOV(const VRFieldOfView
& aFOVLeft
, const VRFieldOfView
& aFOVRight
,
245 double zNear
, double zFar
) MOZ_OVERRIDE
;
247 bool StartSensorTracking() MOZ_OVERRIDE
;
248 VRHMDSensorState
GetSensorState(double timeOffset
) MOZ_OVERRIDE
;
249 void StopSensorTracking() MOZ_OVERRIDE
;
250 void ZeroSensor() MOZ_OVERRIDE
;
252 void FillDistortionConstants(uint32_t whichEye
,
253 const IntSize
& textureSize
, const IntRect
& eyeViewport
,
254 const Size
& destViewport
, const Rect
& destRect
,
255 VRDistortionConstants
& values
) MOZ_OVERRIDE
;
260 virtual ~HMDInfoOculus() {
262 MOZ_COUNT_DTOR_INHERITED(HMDInfoOculus
, VRHMDInfo
);
266 ovrFovPort mFOVPort
[2];
267 uint32_t mStartCount
;
271 ToFovPort(const VRFieldOfView
& aFOV
)
274 fovPort
.LeftTan
= tan(aFOV
.leftDegrees
* M_PI
/ 180.0);
275 fovPort
.RightTan
= tan(aFOV
.rightDegrees
* M_PI
/ 180.0);
276 fovPort
.UpTan
= tan(aFOV
.upDegrees
* M_PI
/ 180.0);
277 fovPort
.DownTan
= tan(aFOV
.downDegrees
* M_PI
/ 180.0);
282 FromFovPort(const ovrFovPort
& aFOV
)
284 VRFieldOfView fovInfo
;
285 fovInfo
.leftDegrees
= atan(aFOV
.LeftTan
) * 180.0 / M_PI
;
286 fovInfo
.rightDegrees
= atan(aFOV
.RightTan
) * 180.0 / M_PI
;
287 fovInfo
.upDegrees
= atan(aFOV
.UpTan
) * 180.0 / M_PI
;
288 fovInfo
.downDegrees
= atan(aFOV
.DownTan
) * 180.0 / M_PI
;
292 HMDInfoOculus::HMDInfoOculus(ovrHmd aHMD
)
293 : VRHMDInfo(VRHMDType::Oculus
)
297 MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus
, VRHMDInfo
);
299 mSupportedSensorBits
= 0;
300 if (mHMD
->TrackingCaps
& ovrTrackingCap_Orientation
)
301 mSupportedSensorBits
|= State_Orientation
;
302 if (mHMD
->TrackingCaps
& ovrTrackingCap_Position
)
303 mSupportedSensorBits
|= State_Position
;
305 mRecommendedEyeFOV
[Eye_Left
] = FromFovPort(mHMD
->DefaultEyeFov
[ovrEye_Left
]);
306 mRecommendedEyeFOV
[Eye_Right
] = FromFovPort(mHMD
->DefaultEyeFov
[ovrEye_Right
]);
308 mMaximumEyeFOV
[Eye_Left
] = FromFovPort(mHMD
->MaxEyeFov
[ovrEye_Left
]);
309 mMaximumEyeFOV
[Eye_Right
] = FromFovPort(mHMD
->MaxEyeFov
[ovrEye_Right
]);
311 SetFOV(mRecommendedEyeFOV
[Eye_Left
], mRecommendedEyeFOV
[Eye_Right
], 0.01, 10000.0);
313 nsCOMPtr
<nsIScreenManager
> screenmgr
= do_GetService("@mozilla.org/gfx/screenmanager;1");
315 screenmgr
->ScreenForRect(mHMD
->WindowsPos
.x
, mHMD
->WindowsPos
.y
,
316 mHMD
->Resolution
.w
, mHMD
->Resolution
.h
,
317 getter_AddRefs(mScreen
));
322 HMDInfoOculus::Destroy()
325 ovrHmd_Destroy(mHMD
);
331 HMDInfoOculus::SetFOV(const VRFieldOfView
& aFOVLeft
, const VRFieldOfView
& aFOVRight
,
332 double zNear
, double zFar
)
334 float pixelsPerDisplayPixel
= 1.0;
337 uint32_t caps
= ovrDistortionCap_Chromatic
| ovrDistortionCap_Vignette
; // XXX TODO add TimeWarp
339 // get eye parameters and create the mesh
340 for (uint32_t eye
= 0; eye
< NumEyes
; eye
++) {
341 mEyeFOV
[eye
] = eye
== 0 ? aFOVLeft
: aFOVRight
;
342 mFOVPort
[eye
] = ToFovPort(mEyeFOV
[eye
]);
344 ovrEyeRenderDesc renderDesc
= ovrHmd_GetRenderDesc(mHMD
, (ovrEyeType
) eye
, mFOVPort
[eye
]);
346 // these values are negated so that content can add the adjustment to its camera position,
347 // instead of subtracting
348 mEyeTranslation
[eye
] = Point3D(-renderDesc
.ViewAdjust
.x
, -renderDesc
.ViewAdjust
.y
, -renderDesc
.ViewAdjust
.z
);
350 // note that we are using a right-handed coordinate system here, to match CSS
351 ovrMatrix4f projMatrix
= ovrMatrix4f_Projection(mFOVPort
[eye
], zNear
, zFar
, true);
353 // XXX this is gross, we really need better methods on Matrix4x4
354 memcpy(&mEyeProjectionMatrix
[eye
], projMatrix
.M
, sizeof(ovrMatrix4f
));
355 mEyeProjectionMatrix
[eye
].Transpose();
357 texSize
[eye
] = ovrHmd_GetFovTextureSize(mHMD
, (ovrEyeType
) eye
, mFOVPort
[eye
], pixelsPerDisplayPixel
);
359 ovrDistortionMesh mesh
;
360 bool ok
= ovrHmd_CreateDistortionMesh(mHMD
, (ovrEyeType
) eye
, mFOVPort
[eye
], caps
, &mesh
);
364 mDistortionMesh
[eye
].mVertices
.SetLength(mesh
.VertexCount
);
365 mDistortionMesh
[eye
].mIndices
.SetLength(mesh
.IndexCount
);
367 ovrDistortionVertex
*srcv
= mesh
.pVertexData
;
368 VRDistortionVertex
*destv
= mDistortionMesh
[eye
].mVertices
.Elements();
369 memset(destv
, 0, mesh
.VertexCount
* sizeof(VRDistortionVertex
));
370 for (uint32_t i
= 0; i
< mesh
.VertexCount
; ++i
) {
371 destv
[i
].pos
[0] = srcv
[i
].ScreenPosNDC
.x
;
372 destv
[i
].pos
[1] = srcv
[i
].ScreenPosNDC
.y
;
374 destv
[i
].texR
[0] = srcv
[i
].TanEyeAnglesR
.x
;
375 destv
[i
].texR
[1] = srcv
[i
].TanEyeAnglesR
.y
;
376 destv
[i
].texG
[0] = srcv
[i
].TanEyeAnglesG
.x
;
377 destv
[i
].texG
[1] = srcv
[i
].TanEyeAnglesG
.y
;
378 destv
[i
].texB
[0] = srcv
[i
].TanEyeAnglesB
.x
;
379 destv
[i
].texB
[1] = srcv
[i
].TanEyeAnglesB
.y
;
381 destv
[i
].genericAttribs
[0] = srcv
[i
].VignetteFactor
;
382 destv
[i
].genericAttribs
[1] = srcv
[i
].TimeWarpFactor
;
385 memcpy(mDistortionMesh
[eye
].mIndices
.Elements(), mesh
.pIndexData
, mesh
.IndexCount
* sizeof(uint16_t));
386 ovrHmd_DestroyDistortionMesh(&mesh
);
389 // take the max of both for eye resolution
390 mEyeResolution
.width
= std::max(texSize
[Eye_Left
].w
, texSize
[Eye_Right
].w
);
391 mEyeResolution
.height
= std::max(texSize
[Eye_Left
].h
, texSize
[Eye_Right
].h
);
393 mConfiguration
.hmdType
= mType
;
394 mConfiguration
.value
= 0;
395 mConfiguration
.fov
[0] = aFOVLeft
;
396 mConfiguration
.fov
[1] = aFOVRight
;
399 //* need to call this during rendering each frame I think? */
400 //ovrHmd_GetRenderScaleAndOffset(fovPort, texSize, renderViewport, uvScaleOffsetOut);
404 HMDInfoOculus::FillDistortionConstants(uint32_t whichEye
,
405 const IntSize
& textureSize
,
406 const IntRect
& eyeViewport
,
407 const Size
& destViewport
,
408 const Rect
& destRect
,
409 VRDistortionConstants
& values
)
411 ovrSizei texSize
= { textureSize
.width
, textureSize
.height
};
412 ovrRecti eyePort
= { { eyeViewport
.x
, eyeViewport
.y
}, { eyeViewport
.width
, eyeViewport
.height
} };
413 ovrVector2f scaleOut
[2];
415 ovrHmd_GetRenderScaleAndOffset(mFOVPort
[whichEye
], texSize
, eyePort
, scaleOut
);
417 values
.eyeToSourceScaleAndOffset
[0] = scaleOut
[0].x
;
418 values
.eyeToSourceScaleAndOffset
[1] = scaleOut
[0].y
;
419 values
.eyeToSourceScaleAndOffset
[2] = scaleOut
[1].x
;
420 values
.eyeToSourceScaleAndOffset
[3] = scaleOut
[1].y
;
422 // These values are in clip space [-1..1] range, but we're providing
423 // scaling in the 0..2 space for sanity.
425 // this is the destRect in clip space
426 float x0
= destRect
.x
/ destViewport
.width
* 2.0 - 1.0;
427 float x1
= (destRect
.x
+ destRect
.width
) / destViewport
.width
* 2.0 - 1.0;
429 float y0
= destRect
.y
/ destViewport
.height
* 2.0 - 1.0;
430 float y1
= (destRect
.y
+ destRect
.height
) / destViewport
.height
* 2.0 - 1.0;
433 values
.destinationScaleAndOffset
[0] = (x0
+x1
) / 2.0;
434 values
.destinationScaleAndOffset
[1] = (y0
+y1
) / 2.0;
436 values
.destinationScaleAndOffset
[2] = destRect
.width
/ destViewport
.width
;
437 values
.destinationScaleAndOffset
[3] = destRect
.height
/ destViewport
.height
;
441 HMDInfoOculus::StartSensorTracking()
443 if (mStartCount
== 0) {
444 bool ok
= ovrHmd_ConfigureTracking(mHMD
, ovrTrackingCap_Orientation
| ovrTrackingCap_Position
, 0);
454 HMDInfoOculus::StopSensorTracking()
456 if (--mStartCount
== 0) {
457 ovrHmd_ConfigureTracking(mHMD
, 0, 0);
462 HMDInfoOculus::ZeroSensor()
464 ovrHmd_RecenterPose(mHMD
);
468 HMDInfoOculus::GetSensorState(double timeOffset
)
470 VRHMDSensorState result
;
473 // XXX this is the wrong time base for timeOffset; we need to figure out how to synchronize
474 // the Oculus time base and the browser one.
475 ovrTrackingState state
= ovrHmd_GetTrackingState(mHMD
, ovr_GetTimeInSeconds() + timeOffset
);
476 ovrPoseStatef
& pose(state
.HeadPose
);
478 result
.timestamp
= pose
.TimeInSeconds
;
480 if (state
.StatusFlags
& ovrStatus_OrientationTracked
) {
481 result
.flags
|= State_Orientation
;
483 result
.orientation
[0] = pose
.ThePose
.Orientation
.x
;
484 result
.orientation
[1] = pose
.ThePose
.Orientation
.y
;
485 result
.orientation
[2] = pose
.ThePose
.Orientation
.z
;
486 result
.orientation
[3] = pose
.ThePose
.Orientation
.w
;
488 result
.angularVelocity
[0] = pose
.AngularVelocity
.x
;
489 result
.angularVelocity
[1] = pose
.AngularVelocity
.y
;
490 result
.angularVelocity
[2] = pose
.AngularVelocity
.z
;
492 result
.angularAcceleration
[0] = pose
.AngularAcceleration
.x
;
493 result
.angularAcceleration
[1] = pose
.AngularAcceleration
.y
;
494 result
.angularAcceleration
[2] = pose
.AngularAcceleration
.z
;
497 if (state
.StatusFlags
& ovrStatus_PositionTracked
) {
498 result
.flags
|= State_Position
;
500 result
.position
[0] = pose
.ThePose
.Position
.x
;
501 result
.position
[1] = pose
.ThePose
.Position
.y
;
502 result
.position
[2] = pose
.ThePose
.Position
.z
;
504 result
.linearVelocity
[0] = pose
.LinearVelocity
.x
;
505 result
.linearVelocity
[1] = pose
.LinearVelocity
.y
;
506 result
.linearVelocity
[2] = pose
.LinearVelocity
.z
;
508 result
.linearAcceleration
[0] = pose
.LinearAcceleration
.x
;
509 result
.linearAcceleration
[1] = pose
.LinearAcceleration
.y
;
510 result
.linearAcceleration
[2] = pose
.LinearAcceleration
.z
;
519 class VRHMDManagerOculusImpl
{
521 VRHMDManagerOculusImpl() : mOculusInitialized(false), mOculusPlatformInitialized(false)
527 void GetOculusHMDs(nsTArray
<nsRefPtr
<VRHMDInfo
> >& aHMDResult
);
529 nsTArray
<nsRefPtr
<HMDInfoOculus
>> mOculusHMDs
;
530 bool mOculusInitialized
;
531 bool mOculusPlatformInitialized
;
535 } // namespace mozilla
537 VRHMDManagerOculusImpl
*VRHMDManagerOculus::mImpl
= nullptr;
539 // These just forward to the Impl class, to have a non-static container for various
543 VRHMDManagerOculus::PlatformInit()
546 mImpl
= new VRHMDManagerOculusImpl
;
548 return mImpl
->PlatformInit();
552 VRHMDManagerOculus::Init()
555 mImpl
= new VRHMDManagerOculusImpl
;
557 return mImpl
->Init();
561 VRHMDManagerOculus::GetOculusHMDs(nsTArray
<nsRefPtr
<VRHMDInfo
>>& aHMDResult
)
564 mImpl
= new VRHMDManagerOculusImpl
;
566 mImpl
->GetOculusHMDs(aHMDResult
);
570 VRHMDManagerOculus::Destroy()
580 VRHMDManagerOculusImpl::PlatformInit()
582 if (mOculusPlatformInitialized
)
585 if (!gfxPrefs::VREnabled())
588 if (!InitializeOculusCAPI())
591 bool ok
= ovr_Initialize();
596 mOculusPlatformInitialized
= true;
601 VRHMDManagerOculusImpl::Init()
603 if (mOculusInitialized
)
609 int count
= ovrHmd_Detect();
611 for (int i
= 0; i
< count
; ++i
) {
612 ovrHmd hmd
= ovrHmd_Create(i
);
613 nsRefPtr
<HMDInfoOculus
> oc
= new HMDInfoOculus(hmd
);
614 mOculusHMDs
.AppendElement(oc
);
617 // VRAddTestDevices == 1: add test device only if no real devices present
618 // VRAddTestDevices == 2: add test device always
619 if ((count
== 0 && gfxPrefs::VRAddTestDevices() == 1) ||
620 (gfxPrefs::VRAddTestDevices() == 2))
622 ovrHmd hmd
= ovrHmd_CreateDebug(ovrHmd_DK2
);
623 nsRefPtr
<HMDInfoOculus
> oc
= new HMDInfoOculus(hmd
);
624 mOculusHMDs
.AppendElement(oc
);
627 mOculusInitialized
= true;
632 VRHMDManagerOculusImpl::Destroy()
634 if (!mOculusInitialized
)
637 for (size_t i
= 0; i
< mOculusHMDs
.Length(); ++i
) {
638 mOculusHMDs
[i
]->Destroy();
644 mOculusInitialized
= false;
648 VRHMDManagerOculusImpl::GetOculusHMDs(nsTArray
<nsRefPtr
<VRHMDInfo
>>& aHMDResult
)
651 for (size_t i
= 0; i
< mOculusHMDs
.Length(); ++i
) {
652 aHMDResult
.AppendElement(mOculusHMDs
[i
]);