Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include <math.h>
8 :
9 : #include "prenv.h"
10 : #include "gfxPrefs.h"
11 : #include "nsString.h"
12 : #include "mozilla/Preferences.h"
13 : #include "mozilla/SharedLibrary.h"
14 :
15 : #include "mozilla/gfx/Quaternion.h"
16 :
17 : #ifdef XP_WIN
18 : #include "../layers/d3d11/CompositorD3D11.h"
19 : #include "../layers/d3d11/TextureD3D11.h"
20 : #endif
21 :
22 : #include "gfxVROSVR.h"
23 :
24 : #include "mozilla/dom/GamepadEventTypes.h"
25 : #include "mozilla/dom/GamepadBinding.h"
26 :
27 : #ifndef M_PI
28 : #define M_PI 3.14159265358979323846
29 : #endif
30 :
31 : using namespace mozilla::layers;
32 : using namespace mozilla::gfx;
33 : using namespace mozilla::gfx::impl;
34 : using namespace mozilla::dom;
35 :
36 : namespace {
37 : // need to typedef functions that will be used in the code below
38 : extern "C" {
39 : typedef OSVR_ClientContext (*pfn_osvrClientInit)(
40 : const char applicationIdentifier[], uint32_t flags);
41 : typedef OSVR_ReturnCode (*pfn_osvrClientShutdown)(OSVR_ClientContext ctx);
42 : typedef OSVR_ReturnCode (*pfn_osvrClientUpdate)(OSVR_ClientContext ctx);
43 : typedef OSVR_ReturnCode (*pfn_osvrClientCheckStatus)(OSVR_ClientContext ctx);
44 : typedef OSVR_ReturnCode (*pfn_osvrClientGetInterface)(
45 : OSVR_ClientContext ctx, const char path[], OSVR_ClientInterface* iface);
46 : typedef OSVR_ReturnCode (*pfn_osvrClientFreeInterface)(
47 : OSVR_ClientContext ctx, OSVR_ClientInterface iface);
48 : typedef OSVR_ReturnCode (*pfn_osvrGetOrientationState)(
49 : OSVR_ClientInterface iface, OSVR_TimeValue* timestamp,
50 : OSVR_OrientationState* state);
51 : typedef OSVR_ReturnCode (*pfn_osvrGetPositionState)(OSVR_ClientInterface iface,
52 : OSVR_TimeValue* timestamp,
53 : OSVR_PositionState* state);
54 : typedef OSVR_ReturnCode (*pfn_osvrClientGetDisplay)(OSVR_ClientContext ctx,
55 : OSVR_DisplayConfig* disp);
56 : typedef OSVR_ReturnCode (*pfn_osvrClientFreeDisplay)(OSVR_DisplayConfig disp);
57 : typedef OSVR_ReturnCode (*pfn_osvrClientGetNumEyesForViewer)(
58 : OSVR_DisplayConfig disp, OSVR_ViewerCount viewer, OSVR_EyeCount* eyes);
59 : typedef OSVR_ReturnCode (*pfn_osvrClientGetViewerEyePose)(
60 : OSVR_DisplayConfig disp, OSVR_ViewerCount viewer, OSVR_EyeCount eye,
61 : OSVR_Pose3* pose);
62 : typedef OSVR_ReturnCode (*pfn_osvrClientGetDisplayDimensions)(
63 : OSVR_DisplayConfig disp, OSVR_DisplayInputCount displayInputIndex,
64 : OSVR_DisplayDimension* width, OSVR_DisplayDimension* height);
65 : typedef OSVR_ReturnCode (
66 : *pfn_osvrClientGetViewerEyeSurfaceProjectionClippingPlanes)(
67 : OSVR_DisplayConfig disp, OSVR_ViewerCount viewer, OSVR_EyeCount eye,
68 : OSVR_SurfaceCount surface, double* left, double* right, double* bottom,
69 : double* top);
70 : typedef OSVR_ReturnCode (*pfn_osvrClientGetRelativeViewportForViewerEyeSurface)(
71 : OSVR_DisplayConfig disp, OSVR_ViewerCount viewer, OSVR_EyeCount eye,
72 : OSVR_SurfaceCount surface, OSVR_ViewportDimension* left,
73 : OSVR_ViewportDimension* bottom, OSVR_ViewportDimension* width,
74 : OSVR_ViewportDimension* height);
75 : typedef OSVR_ReturnCode (*pfn_osvrClientGetViewerEyeSurfaceProjectionMatrixf)(
76 : OSVR_DisplayConfig disp, OSVR_ViewerCount viewer, OSVR_EyeCount eye,
77 : OSVR_SurfaceCount surface, float near, float far,
78 : OSVR_MatrixConventions flags, float* matrix);
79 : typedef OSVR_ReturnCode (*pfn_osvrClientCheckDisplayStartup)(
80 : OSVR_DisplayConfig disp);
81 : typedef OSVR_ReturnCode (*pfn_osvrClientSetRoomRotationUsingHead)(
82 : OSVR_ClientContext ctx);
83 : }
84 :
85 : static pfn_osvrClientInit osvr_ClientInit = nullptr;
86 : static pfn_osvrClientShutdown osvr_ClientShutdown = nullptr;
87 : static pfn_osvrClientUpdate osvr_ClientUpdate = nullptr;
88 : static pfn_osvrClientCheckStatus osvr_ClientCheckStatus = nullptr;
89 : static pfn_osvrClientGetInterface osvr_ClientGetInterface = nullptr;
90 : static pfn_osvrClientFreeInterface osvr_ClientFreeInterface = nullptr;
91 : static pfn_osvrGetOrientationState osvr_GetOrientationState = nullptr;
92 : static pfn_osvrGetPositionState osvr_GetPositionState = nullptr;
93 : static pfn_osvrClientGetDisplay osvr_ClientGetDisplay = nullptr;
94 : static pfn_osvrClientFreeDisplay osvr_ClientFreeDisplay = nullptr;
95 : static pfn_osvrClientGetNumEyesForViewer osvr_ClientGetNumEyesForViewer =
96 : nullptr;
97 : static pfn_osvrClientGetViewerEyePose osvr_ClientGetViewerEyePose = nullptr;
98 : static pfn_osvrClientGetDisplayDimensions osvr_ClientGetDisplayDimensions =
99 : nullptr;
100 : static pfn_osvrClientGetViewerEyeSurfaceProjectionClippingPlanes
101 : osvr_ClientGetViewerEyeSurfaceProjectionClippingPlanes = nullptr;
102 : static pfn_osvrClientGetRelativeViewportForViewerEyeSurface
103 : osvr_ClientGetRelativeViewportForViewerEyeSurface = nullptr;
104 : static pfn_osvrClientGetViewerEyeSurfaceProjectionMatrixf
105 : osvr_ClientGetViewerEyeSurfaceProjectionMatrixf = nullptr;
106 : static pfn_osvrClientCheckDisplayStartup osvr_ClientCheckDisplayStartup =
107 : nullptr;
108 : static pfn_osvrClientSetRoomRotationUsingHead
109 : osvr_ClientSetRoomRotationUsingHead = nullptr;
110 :
111 : bool
112 0 : LoadOSVRRuntime()
113 : {
114 : static PRLibrary* osvrUtilLib = nullptr;
115 : static PRLibrary* osvrCommonLib = nullptr;
116 : static PRLibrary* osvrClientLib = nullptr;
117 : static PRLibrary* osvrClientKitLib = nullptr;
118 : //this looks up the path in the about:config setting, from greprefs.js or modules\libpref\init\all.js
119 : //we need all the libs to be valid
120 : #ifdef XP_WIN
121 : constexpr static auto* pfnGetPathStringPref = mozilla::Preferences::GetString;
122 : nsAutoString osvrUtilPath, osvrCommonPath, osvrClientPath, osvrClientKitPath;
123 : #else
124 : constexpr static auto* pfnGetPathStringPref = mozilla::Preferences::GetCString;
125 0 : nsAutoCString osvrUtilPath, osvrCommonPath, osvrClientPath, osvrClientKitPath;
126 : #endif
127 0 : if (NS_FAILED(pfnGetPathStringPref("gfx.vr.osvr.utilLibPath",
128 0 : osvrUtilPath, PrefValueKind::User)) ||
129 0 : NS_FAILED(pfnGetPathStringPref("gfx.vr.osvr.commonLibPath",
130 0 : osvrCommonPath, PrefValueKind::User)) ||
131 0 : NS_FAILED(pfnGetPathStringPref("gfx.vr.osvr.clientLibPath",
132 0 : osvrClientPath, PrefValueKind::User)) ||
133 0 : NS_FAILED(pfnGetPathStringPref("gfx.vr.osvr.clientKitLibPath",
134 : osvrClientKitPath, PrefValueKind::User))) {
135 : return false;
136 : }
137 :
138 0 : osvrUtilLib = LoadLibraryWithFlags(osvrUtilPath.get());
139 0 : osvrCommonLib = LoadLibraryWithFlags(osvrCommonPath.get());
140 0 : osvrClientLib = LoadLibraryWithFlags(osvrClientPath.get());
141 0 : osvrClientKitLib = LoadLibraryWithFlags(osvrClientKitPath.get());
142 :
143 0 : if (!osvrUtilLib) {
144 0 : printf_stderr("[OSVR] Failed to load OSVR Util library!\n");
145 0 : return false;
146 : }
147 0 : if (!osvrCommonLib) {
148 0 : printf_stderr("[OSVR] Failed to load OSVR Common library!\n");
149 0 : return false;
150 : }
151 0 : if (!osvrClientLib) {
152 0 : printf_stderr("[OSVR] Failed to load OSVR Client library!\n");
153 0 : return false;
154 : }
155 0 : if (!osvrClientKitLib) {
156 0 : printf_stderr("[OSVR] Failed to load OSVR ClientKit library!\n");
157 0 : return false;
158 : }
159 :
160 : // make sure all functions that we'll be using are available
161 : #define REQUIRE_FUNCTION(_x) \
162 : do { \
163 : *(void**) & osvr_##_x = \
164 : (void*)PR_FindSymbol(osvrClientKitLib, "osvr" #_x); \
165 : if (!osvr_##_x) { \
166 : printf_stderr("osvr" #_x " symbol missing\n"); \
167 : goto fail; \
168 : } \
169 : } while (0)
170 :
171 0 : REQUIRE_FUNCTION(ClientInit);
172 0 : REQUIRE_FUNCTION(ClientShutdown);
173 0 : REQUIRE_FUNCTION(ClientUpdate);
174 0 : REQUIRE_FUNCTION(ClientCheckStatus);
175 0 : REQUIRE_FUNCTION(ClientGetInterface);
176 0 : REQUIRE_FUNCTION(ClientFreeInterface);
177 0 : REQUIRE_FUNCTION(GetOrientationState);
178 0 : REQUIRE_FUNCTION(GetPositionState);
179 0 : REQUIRE_FUNCTION(ClientGetDisplay);
180 0 : REQUIRE_FUNCTION(ClientFreeDisplay);
181 0 : REQUIRE_FUNCTION(ClientGetNumEyesForViewer);
182 0 : REQUIRE_FUNCTION(ClientGetViewerEyePose);
183 0 : REQUIRE_FUNCTION(ClientGetDisplayDimensions);
184 0 : REQUIRE_FUNCTION(ClientGetViewerEyeSurfaceProjectionClippingPlanes);
185 0 : REQUIRE_FUNCTION(ClientGetRelativeViewportForViewerEyeSurface);
186 0 : REQUIRE_FUNCTION(ClientGetViewerEyeSurfaceProjectionMatrixf);
187 0 : REQUIRE_FUNCTION(ClientCheckDisplayStartup);
188 0 : REQUIRE_FUNCTION(ClientSetRoomRotationUsingHead);
189 :
190 : #undef REQUIRE_FUNCTION
191 :
192 : return true;
193 :
194 : fail:
195 : return false;
196 : }
197 :
198 : } // namespace
199 :
200 : mozilla::gfx::VRFieldOfView
201 0 : SetFromTanRadians(double left, double right, double bottom, double top)
202 : {
203 : mozilla::gfx::VRFieldOfView fovInfo;
204 0 : fovInfo.leftDegrees = atan(left) * 180.0 / M_PI;
205 0 : fovInfo.rightDegrees = atan(right) * 180.0 / M_PI;
206 0 : fovInfo.upDegrees = atan(top) * 180.0 / M_PI;
207 0 : fovInfo.downDegrees = atan(bottom) * 180.0 / M_PI;
208 0 : return fovInfo;
209 : }
210 :
211 0 : VRDisplayOSVR::VRDisplayOSVR(OSVR_ClientContext* context,
212 : OSVR_ClientInterface* iface,
213 0 : OSVR_DisplayConfig* display)
214 : : VRDisplayHost(VRDeviceType::OSVR)
215 : , m_ctx(context)
216 : , m_iface(iface)
217 0 : , m_display(display)
218 : {
219 :
220 0 : MOZ_COUNT_CTOR_INHERITED(VRDisplayOSVR, VRDisplayHost);
221 :
222 0 : VRDisplayState& state = mDisplayInfo.mDisplayState;
223 0 : state.mIsConnected = true;
224 0 : strncpy(state.mDisplayName, "OSVR HMD", kVRDisplayNameMaxLen);
225 : state.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None;
226 : state.mCapabilityFlags =
227 0 : VRDisplayCapabilityFlags::Cap_Orientation | VRDisplayCapabilityFlags::Cap_Position;
228 :
229 0 : state.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
230 0 : state.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Present;
231 :
232 : // XXX OSVR display topology allows for more than one viewer
233 : // will assume only one viewer for now (most likely stay that way)
234 :
235 : OSVR_EyeCount numEyes;
236 0 : osvr_ClientGetNumEyesForViewer(*m_display, 0, &numEyes);
237 :
238 0 : for (uint8_t eye = 0; eye < numEyes; eye++) {
239 : double left, right, bottom, top;
240 : // XXX for now there is only one surface per eye
241 0 : osvr_ClientGetViewerEyeSurfaceProjectionClippingPlanes(
242 0 : *m_display, 0, eye, 0, &left, &right, &bottom, &top);
243 : state.mEyeFOV[eye] =
244 0 : SetFromTanRadians(-left, right, -bottom, top);
245 : }
246 :
247 : // XXX Assuming there is only one display input for now
248 : // however, it's possible to have more than one (dSight with 2 HDMI inputs)
249 : OSVR_DisplayDimension width, height;
250 0 : osvr_ClientGetDisplayDimensions(*m_display, 0, &width, &height);
251 :
252 :
253 0 : for (uint8_t eye = 0; eye < numEyes; eye++) {
254 :
255 : OSVR_ViewportDimension l, b, w, h;
256 0 : osvr_ClientGetRelativeViewportForViewerEyeSurface(*m_display, 0, eye, 0, &l,
257 0 : &b, &w, &h);
258 0 : state.mEyeResolution.width = w;
259 0 : state.mEyeResolution.height = h;
260 : OSVR_Pose3 eyePose;
261 : // Viewer eye pose may not be immediately available, update client context until we get it
262 : OSVR_ReturnCode ret =
263 0 : osvr_ClientGetViewerEyePose(*m_display, 0, eye, &eyePose);
264 0 : while (ret != OSVR_RETURN_SUCCESS) {
265 0 : osvr_ClientUpdate(*m_ctx);
266 0 : ret = osvr_ClientGetViewerEyePose(*m_display, 0, eye, &eyePose);
267 : }
268 0 : state.mEyeTranslation[eye].x = eyePose.translation.data[0];
269 0 : state.mEyeTranslation[eye].y = eyePose.translation.data[1];
270 0 : state.mEyeTranslation[eye].z = eyePose.translation.data[2];
271 :
272 0 : Matrix4x4 pose;
273 0 : pose.SetRotationFromQuaternion(gfx::Quaternion(osvrQuatGetX(&eyePose.rotation),
274 0 : osvrQuatGetY(&eyePose.rotation),
275 0 : osvrQuatGetZ(&eyePose.rotation),
276 0 : osvrQuatGetW(&eyePose.rotation)));
277 0 : pose.PreTranslate(eyePose.translation.data[0], eyePose.translation.data[1], eyePose.translation.data[2]);
278 0 : pose.Invert();
279 0 : mHeadToEye[eye] = pose;
280 : }
281 0 : }
282 :
283 : void
284 0 : VRDisplayOSVR::Destroy()
285 : {
286 : // destroy non-owning pointers
287 0 : m_ctx = nullptr;
288 0 : m_iface = nullptr;
289 0 : m_display = nullptr;
290 0 : }
291 :
292 : void
293 0 : VRDisplayOSVR::ZeroSensor()
294 : {
295 : // recenter pose aka reset yaw
296 0 : osvr_ClientSetRoomRotationUsingHead(*m_ctx);
297 0 : }
298 :
299 : VRHMDSensorState
300 0 : VRDisplayOSVR::GetSensorState()
301 : {
302 :
303 : //update client context before anything
304 : //this usually goes into app's mainloop
305 0 : osvr_ClientUpdate(*m_ctx);
306 :
307 0 : VRHMDSensorState result{};
308 : OSVR_TimeValue timestamp;
309 :
310 : OSVR_OrientationState orientation;
311 :
312 : OSVR_ReturnCode ret =
313 0 : osvr_GetOrientationState(*m_iface, ×tamp, &orientation);
314 :
315 0 : result.timestamp = timestamp.seconds;
316 0 : result.inputFrameID = mDisplayInfo.mFrameId;
317 :
318 0 : if (ret == OSVR_RETURN_SUCCESS) {
319 0 : result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
320 0 : result.orientation[0] = orientation.data[1];
321 0 : result.orientation[1] = orientation.data[2];
322 0 : result.orientation[2] = orientation.data[3];
323 0 : result.orientation[3] = orientation.data[0];
324 : } else {
325 : // default to an identity quaternion
326 0 : result.orientation[3] = 1.0f;
327 : }
328 :
329 : OSVR_PositionState position;
330 0 : ret = osvr_GetPositionState(*m_iface, ×tamp, &position);
331 0 : if (ret == OSVR_RETURN_SUCCESS) {
332 0 : result.flags |= VRDisplayCapabilityFlags::Cap_Position;
333 0 : result.position[0] = position.data[0];
334 0 : result.position[1] = position.data[1];
335 0 : result.position[2] = position.data[2];
336 : }
337 :
338 0 : result.CalcViewMatrices(mHeadToEye);
339 :
340 0 : return result;
341 : }
342 :
343 : #if defined(XP_WIN)
344 :
345 : bool
346 : VRDisplayOSVR::SubmitFrame(ID3D11Texture2D* aSource,
347 : const IntSize& aSize,
348 : const gfx::Rect& aLeftEyeRect,
349 : const gfx::Rect& aRightEyeRect)
350 : {
351 : // XXX Add code to submit frame
352 : return false;
353 : }
354 :
355 : #elif defined(XP_MACOSX)
356 :
357 : bool
358 : VRDisplayOSVR::SubmitFrame(MacIOSurface* aMacIOSurface,
359 : const IntSize& aSize,
360 : const gfx::Rect& aLeftEyeRect,
361 : const gfx::Rect& aRightEyeRect)
362 : {
363 : // XXX Add code to submit frame
364 : MOZ_ASSERT(mSubmitThread->GetThread() == NS_GetCurrentThread());
365 : return false;
366 : }
367 :
368 : #endif
369 :
370 : void
371 0 : VRDisplayOSVR::StartPresentation()
372 : {
373 : // XXX Add code to start VR Presentation
374 0 : }
375 :
376 : void
377 0 : VRDisplayOSVR::StopPresentation()
378 : {
379 : // XXX Add code to end VR Presentation
380 0 : }
381 :
382 : already_AddRefed<VRSystemManagerOSVR>
383 1 : VRSystemManagerOSVR::Create()
384 : {
385 1 : MOZ_ASSERT(NS_IsMainThread());
386 :
387 1 : if (!gfxPrefs::VREnabled() || !gfxPrefs::VROSVREnabled()) {
388 : return nullptr;
389 : }
390 0 : if (!LoadOSVRRuntime()) {
391 : return nullptr;
392 : }
393 0 : RefPtr<VRSystemManagerOSVR> manager = new VRSystemManagerOSVR();
394 0 : return manager.forget();
395 : }
396 :
397 : void
398 0 : VRSystemManagerOSVR::CheckOSVRStatus()
399 : {
400 0 : if (mOSVRInitialized) {
401 : return;
402 : }
403 :
404 : // client context must be initialized first
405 0 : InitializeClientContext();
406 :
407 : // update client context
408 0 : osvr_ClientUpdate(m_ctx);
409 :
410 : // initialize interface and display if they are not initialized yet
411 0 : InitializeInterface();
412 0 : InitializeDisplay();
413 :
414 : // OSVR is fully initialized now
415 0 : if (mClientContextInitialized && mDisplayConfigInitialized &&
416 0 : mInterfaceInitialized) {
417 0 : mOSVRInitialized = true;
418 : }
419 : }
420 :
421 : void
422 0 : VRSystemManagerOSVR::InitializeClientContext()
423 : {
424 : // already initialized
425 0 : if (mClientContextInitialized) {
426 : return;
427 : }
428 :
429 : // first time creating
430 0 : if (!m_ctx) {
431 : // get client context
432 0 : m_ctx = osvr_ClientInit("com.osvr.webvr", 0);
433 : // update context
434 0 : osvr_ClientUpdate(m_ctx);
435 : // verify we are connected
436 0 : if (OSVR_RETURN_SUCCESS == osvr_ClientCheckStatus(m_ctx)) {
437 0 : mClientContextInitialized = true;
438 : }
439 : }
440 : // client context exists but not up and running yet
441 : else {
442 : // update context
443 0 : osvr_ClientUpdate(m_ctx);
444 0 : if (OSVR_RETURN_SUCCESS == osvr_ClientCheckStatus(m_ctx)) {
445 0 : mClientContextInitialized = true;
446 : }
447 : }
448 : }
449 :
450 : void
451 0 : VRSystemManagerOSVR::InitializeInterface()
452 : {
453 : // already initialized
454 0 : if (mInterfaceInitialized) {
455 : return;
456 : }
457 : //Client context must be initialized before getting interface
458 0 : if (mClientContextInitialized) {
459 : // m_iface will remain nullptr if no interface is returned
460 0 : if (OSVR_RETURN_SUCCESS ==
461 0 : osvr_ClientGetInterface(m_ctx, "/me/head", &m_iface)) {
462 0 : mInterfaceInitialized = true;
463 : }
464 : }
465 : }
466 :
467 : void
468 0 : VRSystemManagerOSVR::InitializeDisplay()
469 : {
470 : // display is fully configured
471 0 : if (mDisplayConfigInitialized) {
472 : return;
473 : }
474 :
475 : //Client context must be initialized before getting interface
476 0 : if (mClientContextInitialized) {
477 : // first time creating display object
478 0 : if (m_display == nullptr) {
479 :
480 0 : OSVR_ReturnCode ret = osvr_ClientGetDisplay(m_ctx, &m_display);
481 :
482 0 : if (ret == OSVR_RETURN_SUCCESS) {
483 0 : osvr_ClientUpdate(m_ctx);
484 : // display object may have been created but not fully startup
485 0 : if (OSVR_RETURN_SUCCESS == osvr_ClientCheckDisplayStartup(m_display)) {
486 0 : mDisplayConfigInitialized = true;
487 : }
488 : }
489 :
490 : // Typically once we get Display object, pose data is available after
491 : // clientUpdate but sometimes it takes ~ 200 ms to get
492 : // a succesfull connection, so we might have to run a few update cycles
493 : } else {
494 :
495 0 : if (OSVR_RETURN_SUCCESS == osvr_ClientCheckDisplayStartup(m_display)) {
496 0 : mDisplayConfigInitialized = true;
497 : }
498 : }
499 : }
500 : }
501 :
502 : bool
503 0 : VRSystemManagerOSVR::Init()
504 : {
505 :
506 : // OSVR server should be running in the background
507 : // It would load plugins and take care of detecting HMDs
508 0 : if (!mOSVRInitialized) {
509 0 : nsIThread* thread = nullptr;
510 0 : NS_GetCurrentThread(&thread);
511 0 : mOSVRThread = already_AddRefed<nsIThread>(thread);
512 :
513 : // initialize client context
514 0 : InitializeClientContext();
515 : // try to initialize interface
516 0 : InitializeInterface();
517 : // try to initialize display object
518 0 : InitializeDisplay();
519 : // verify all components are initialized
520 0 : CheckOSVRStatus();
521 : }
522 :
523 0 : return mOSVRInitialized;
524 : }
525 :
526 : void
527 0 : VRSystemManagerOSVR::Destroy()
528 : {
529 0 : Shutdown();
530 0 : }
531 :
532 : void
533 0 : VRSystemManagerOSVR::Shutdown()
534 : {
535 0 : if (mOSVRInitialized) {
536 0 : MOZ_ASSERT(NS_GetCurrentThread() == mOSVRThread);
537 0 : mOSVRThread = nullptr;
538 0 : mHMDInfo = nullptr;
539 0 : mOSVRInitialized = false;
540 : }
541 : // client context may not have been initialized
542 0 : if (m_ctx) {
543 0 : osvr_ClientFreeDisplay(m_display);
544 : }
545 : // osvr checks that m_ctx or m_iface are not null
546 0 : osvr_ClientFreeInterface(m_ctx, m_iface);
547 0 : osvr_ClientShutdown(m_ctx);
548 0 : }
549 :
550 : void
551 0 : VRSystemManagerOSVR::NotifyVSync()
552 : {
553 0 : VRSystemManager::NotifyVSync();
554 :
555 : // TODO - Check for device disconnection or other OSVR events
556 0 : }
557 :
558 : void
559 0 : VRSystemManagerOSVR::Enumerate()
560 : {
561 : // make sure context, interface and display are initialized
562 0 : CheckOSVRStatus();
563 :
564 0 : if (!Init()) {
565 : return;
566 : }
567 :
568 0 : mHMDInfo = new VRDisplayOSVR(&m_ctx, &m_iface, &m_display);
569 : }
570 :
571 : bool
572 0 : VRSystemManagerOSVR::ShouldInhibitEnumeration()
573 : {
574 0 : if (VRSystemManager::ShouldInhibitEnumeration()) {
575 : return true;
576 : }
577 0 : if (mHMDInfo) {
578 : // When we find an a VR device, don't
579 : // allow any further enumeration as it
580 : // may get picked up redundantly by other
581 : // API's.
582 : return true;
583 : }
584 0 : return false;
585 : }
586 :
587 : void
588 0 : VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
589 : {
590 0 : if (mHMDInfo) {
591 0 : aHMDResult.AppendElement(mHMDInfo);
592 : }
593 0 : }
594 :
595 : bool
596 0 : VRSystemManagerOSVR::GetIsPresenting()
597 : {
598 0 : if (mHMDInfo) {
599 0 : VRDisplayInfo displayInfo(mHMDInfo->GetDisplayInfo());
600 0 : return displayInfo.GetPresentingGroups() != kVRGroupNone;
601 : }
602 :
603 : return false;
604 : }
605 :
606 : void
607 0 : VRSystemManagerOSVR::HandleInput()
608 : {
609 0 : }
610 :
611 : void
612 0 : VRSystemManagerOSVR::VibrateHaptic(uint32_t aControllerIdx,
613 : uint32_t aHapticIndex,
614 : double aIntensity,
615 : double aDuration,
616 : const VRManagerPromise& aPromise)
617 : {
618 0 : }
619 :
620 : void
621 0 : VRSystemManagerOSVR::StopVibrateHaptic(uint32_t aControllerIdx)
622 : {
623 0 : }
624 :
625 : void
626 0 : VRSystemManagerOSVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
627 : {
628 0 : }
629 :
630 : void
631 0 : VRSystemManagerOSVR::ScanForControllers()
632 : {
633 0 : }
634 :
635 : void
636 0 : VRSystemManagerOSVR::RemoveControllers()
637 : {
638 0 : }
|