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 "prlink.h"
10 : #include "prenv.h"
11 : #include "gfxPrefs.h"
12 : #include "mozilla/Preferences.h"
13 :
14 : #include "mozilla/gfx/Quaternion.h"
15 :
16 : #ifdef XP_WIN
17 : #include "CompositorD3D11.h"
18 : #include "TextureD3D11.h"
19 : static const char* kShmemName = "moz.gecko.vr_ext.0.0.1";
20 : #elif defined(XP_MACOSX)
21 : #include "mozilla/gfx/MacIOSurface.h"
22 : #include <sys/mman.h>
23 : #include <sys/stat.h> /* For mode constants */
24 : #include <fcntl.h> /* For O_* constants */
25 : #include <errno.h>
26 : static const char* kShmemName = "/moz.gecko.vr_ext.0.0.1";
27 : #elif defined(MOZ_WIDGET_ANDROID)
28 : #include <string.h>
29 : #include <pthread.h>
30 : #include "GeckoVRManager.h"
31 : #endif // defined(MOZ_WIDGET_ANDROID)
32 :
33 : #include "gfxVRExternal.h"
34 : #include "VRManagerParent.h"
35 : #include "VRManager.h"
36 : #include "VRThread.h"
37 :
38 : #include "nsServiceManagerUtils.h"
39 : #include "nsIScreenManager.h"
40 :
41 : #include "mozilla/dom/GamepadEventTypes.h"
42 : #include "mozilla/dom/GamepadBinding.h"
43 : #include "mozilla/Telemetry.h"
44 :
45 : #ifndef M_PI
46 : # define M_PI 3.14159265358979323846
47 : #endif
48 :
49 : using namespace mozilla;
50 : using namespace mozilla::gfx;
51 : using namespace mozilla::gfx::impl;
52 : using namespace mozilla::layers;
53 : using namespace mozilla::dom;
54 :
55 : static const uint32_t kNumExternalHaptcs = 1;
56 :
57 0 : VRDisplayExternal::VRDisplayExternal(const VRDisplayState& aDisplayState)
58 : : VRDisplayHost(VRDeviceType::External)
59 : , mIsPresenting(false)
60 0 : , mLastSensorState{}
61 : {
62 0 : MOZ_COUNT_CTOR_INHERITED(VRDisplayExternal, VRDisplayHost);
63 0 : mDisplayInfo.mDisplayState = aDisplayState;
64 :
65 : // default to an identity quaternion
66 0 : mLastSensorState.orientation[3] = 1.0f;
67 0 : }
68 :
69 0 : VRDisplayExternal::~VRDisplayExternal()
70 : {
71 0 : Destroy();
72 0 : MOZ_COUNT_DTOR_INHERITED(VRDisplayExternal, VRDisplayHost);
73 0 : }
74 :
75 : void
76 0 : VRDisplayExternal::Destroy()
77 : {
78 0 : StopPresentation();
79 :
80 : // TODO - Implement
81 0 : }
82 :
83 : void
84 0 : VRDisplayExternal::ZeroSensor()
85 : {
86 0 : }
87 :
88 : void
89 0 : VRDisplayExternal::Refresh()
90 : {
91 0 : VRManager *vm = VRManager::Get();
92 0 : VRSystemManagerExternal* manager = vm->GetExternalManager();
93 :
94 0 : manager->PullState(&mDisplayInfo.mDisplayState);
95 0 : }
96 :
97 : VRHMDSensorState
98 0 : VRDisplayExternal::GetSensorState()
99 : {
100 0 : VRManager *vm = VRManager::Get();
101 0 : VRSystemManagerExternal* manager = vm->GetExternalManager();
102 :
103 0 : manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState);
104 :
105 : // result.CalcViewMatrices(headToEyeTransforms);
106 0 : mLastSensorState.inputFrameID = mDisplayInfo.mFrameId;
107 0 : return mLastSensorState;
108 : }
109 :
110 : void
111 0 : VRDisplayExternal::StartPresentation()
112 : {
113 0 : if (mIsPresenting) {
114 : return;
115 : }
116 0 : mIsPresenting = true;
117 0 : mTelemetry.Clear();
118 0 : mTelemetry.mPresentationStart = TimeStamp::Now();
119 :
120 : // TODO - Implement this
121 :
122 : // mTelemetry.mLastDroppedFrameCount = stats.m_nNumReprojectedFrames;
123 : }
124 :
125 : void
126 0 : VRDisplayExternal::StopPresentation()
127 : {
128 : if (!mIsPresenting) {
129 : return;
130 : }
131 :
132 : // TODO - Implement this
133 :
134 : /*
135 : mIsPresenting = false;
136 : const TimeDuration duration = TimeStamp::Now() - mTelemetry.mPresentationStart;
137 : Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 2);
138 : Telemetry::Accumulate(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OPENVR,
139 : duration.ToMilliseconds());
140 :
141 : ::vr::Compositor_CumulativeStats stats;
142 : mVRCompositor->GetCumulativeStats(&stats, sizeof(::vr::Compositor_CumulativeStats));
143 : const uint32_t droppedFramesPerSec = (stats.m_nNumReprojectedFrames -
144 : mTelemetry.mLastDroppedFrameCount) / duration.ToSeconds();
145 : Telemetry::Accumulate(Telemetry::WEBVR_DROPPED_FRAMES_IN_OPENVR, droppedFramesPerSec);
146 : */
147 : }
148 :
149 : #if defined(XP_WIN)
150 :
151 : bool
152 : VRDisplayExternal::SubmitFrame(ID3D11Texture2D* aSource,
153 : const IntSize& aSize,
154 : const gfx::Rect& aLeftEyeRect,
155 : const gfx::Rect& aRightEyeRect)
156 : {
157 : // FINDME! Implement this
158 : return false;
159 : }
160 :
161 : #elif defined(XP_MACOSX)
162 :
163 : bool
164 : VRDisplayExternal::SubmitFrame(MacIOSurface* aMacIOSurface,
165 : const IntSize& aSize,
166 : const gfx::Rect& aLeftEyeRect,
167 : const gfx::Rect& aRightEyeRect)
168 : {
169 : const void* ioSurface = aMacIOSurface->GetIOSurfacePtr();
170 : bool result = false;
171 : if (ioSurface == nullptr) {
172 : NS_WARNING("VRDisplayExternal::SubmitFrame() could not get an IOSurface");
173 : } else {
174 : // FINDME! Implement this
175 : }
176 : return result;
177 : }
178 :
179 : #elif defined(MOZ_WIDGET_ANDROID)
180 :
181 : bool
182 : VRDisplayExternal::SubmitFrame(const layers::SurfaceTextureDescriptor& aSurface,
183 : const gfx::Rect& aLeftEyeRect,
184 : const gfx::Rect& aRightEyeRect) {
185 :
186 : return false;
187 : }
188 :
189 : #endif
190 :
191 0 : VRControllerExternal::VRControllerExternal(dom::GamepadHand aHand, uint32_t aDisplayID,
192 : uint32_t aNumButtons, uint32_t aNumTriggers,
193 0 : uint32_t aNumAxes, const nsCString& aId)
194 0 : : VRControllerHost(VRDeviceType::External, aHand, aDisplayID)
195 : {
196 0 : MOZ_COUNT_CTOR_INHERITED(VRControllerExternal, VRControllerHost);
197 :
198 0 : VRControllerState& state = mControllerInfo.mControllerState;
199 0 : strncpy(state.mControllerName, aId.BeginReading(), kVRControllerNameMaxLen);
200 0 : state.mNumButtons = aNumButtons;
201 0 : state.mNumAxes = aNumAxes;
202 0 : state.mNumTriggers = aNumTriggers;
203 0 : state.mNumHaptics = kNumExternalHaptcs;
204 0 : }
205 :
206 0 : VRControllerExternal::~VRControllerExternal()
207 : {
208 0 : MOZ_COUNT_DTOR_INHERITED(VRControllerExternal, VRControllerHost);
209 0 : }
210 :
211 0 : VRSystemManagerExternal::VRSystemManagerExternal()
212 0 : : mExternalShmem(nullptr)
213 : {
214 : #if defined(XP_MACOSX)
215 : mShmemFD = 0;
216 : #elif defined(XP_WIN)
217 : mShmemFile = NULL;
218 : #elif defined(MOZ_WIDGET_ANDROID)
219 : mDoShutdown = false;
220 : mExternalStructFailed = false;
221 : #endif
222 0 : }
223 :
224 0 : VRSystemManagerExternal::~VRSystemManagerExternal()
225 : {
226 0 : CloseShmem();
227 0 : }
228 :
229 : void
230 0 : VRSystemManagerExternal::OpenShmem()
231 : {
232 0 : if (mExternalShmem) {
233 : return;
234 : #if defined(MOZ_WIDGET_ANDROID)
235 : } else if (mExternalStructFailed) {
236 : return;
237 : #endif // defined(MOZ_WIDGET_ANDROID)
238 : }
239 :
240 : #if defined(XP_MACOSX)
241 : if (mShmemFD == 0) {
242 : mShmemFD = shm_open(kShmemName, O_RDWR, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
243 : }
244 : if (mShmemFD <= 0) {
245 : mShmemFD = 0;
246 : return;
247 : }
248 :
249 : struct stat sb;
250 : fstat(mShmemFD, &sb);
251 : off_t length = sb.st_size;
252 : if (length < (off_t)sizeof(VRExternalShmem)) {
253 : // TODO - Implement logging
254 : CloseShmem();
255 : return;
256 : }
257 :
258 : mExternalShmem = (VRExternalShmem*)mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, mShmemFD, 0);
259 : if (mExternalShmem == MAP_FAILED) {
260 : // TODO - Implement logging
261 : mExternalShmem = NULL;
262 : CloseShmem();
263 : return;
264 : }
265 :
266 : #elif defined(XP_WIN)
267 : if (mShmemFile == NULL) {
268 : mShmemFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, kShmemName);
269 : if (mShmemFile == NULL) {
270 : // TODO - Implement logging
271 : CloseShmem();
272 : return;
273 : }
274 : }
275 : LARGE_INTEGER length;
276 : length.QuadPart = sizeof(VRExternalShmem);
277 : mExternalShmem = (VRExternalShmem*)MapViewOfFile(mShmemFile, // handle to map object
278 : FILE_MAP_ALL_ACCESS, // read/write permission
279 : 0,
280 : 0,
281 : length.QuadPart);
282 :
283 : if (mExternalShmem == NULL) {
284 : // TODO - Implement logging
285 : CloseShmem();
286 : return;
287 : }
288 : #elif defined(MOZ_WIDGET_ANDROID)
289 : mExternalShmem = (VRExternalShmem*)mozilla::GeckoVRManager::GetExternalContext();
290 : if (!mExternalShmem) {
291 : return;
292 : }
293 : if (mExternalShmem->version != kVRExternalVersion) {
294 : mExternalShmem = nullptr;
295 : mExternalStructFailed = true;
296 : return;
297 : }
298 : if (mExternalShmem->size != sizeof(VRExternalShmem)) {
299 : mExternalShmem = nullptr;
300 : mExternalStructFailed = true;
301 : return;
302 : }
303 : #endif
304 0 : CheckForShutdown();
305 : }
306 :
307 : void
308 0 : VRSystemManagerExternal::CheckForShutdown()
309 : {
310 : #if defined(MOZ_WIDGET_ANDROID)
311 : if (mDoShutdown) {
312 : Shutdown();
313 : }
314 : #else
315 0 : if (mExternalShmem) {
316 0 : if (mExternalShmem->generationA == -1 && mExternalShmem->generationB == -1) {
317 0 : Shutdown();
318 : }
319 : }
320 : #endif // defined(MOZ_WIDGET_ANDROID)
321 0 : }
322 :
323 : void
324 0 : VRSystemManagerExternal::CloseShmem()
325 : {
326 : #if defined(XP_MACOSX)
327 : if (mExternalShmem) {
328 : munmap((void *)mExternalShmem, sizeof(VRExternalShmem));
329 : mExternalShmem = NULL;
330 : }
331 : if (mShmemFD) {
332 : close(mShmemFD);
333 : }
334 : mShmemFD = 0;
335 : #elif defined(XP_WIN)
336 : if (mExternalShmem) {
337 : UnmapViewOfFile((void *)mExternalShmem);
338 : mExternalShmem = NULL;
339 : }
340 : if (mShmemFile) {
341 : CloseHandle(mShmemFile);
342 : mShmemFile = NULL;
343 : }
344 : #elif defined(MOZ_WIDGET_ANDROID)
345 : mExternalShmem = NULL;
346 : #endif
347 0 : }
348 :
349 : /*static*/ already_AddRefed<VRSystemManagerExternal>
350 1 : VRSystemManagerExternal::Create()
351 : {
352 1 : MOZ_ASSERT(NS_IsMainThread());
353 :
354 1 : if (!gfxPrefs::VREnabled() || !gfxPrefs::VRExternalEnabled()) {
355 : return nullptr;
356 : }
357 :
358 0 : RefPtr<VRSystemManagerExternal> manager = new VRSystemManagerExternal();
359 0 : return manager.forget();
360 : }
361 :
362 : void
363 0 : VRSystemManagerExternal::Destroy()
364 : {
365 0 : Shutdown();
366 0 : }
367 :
368 : void
369 0 : VRSystemManagerExternal::Shutdown()
370 : {
371 0 : if (mDisplay) {
372 0 : mDisplay = nullptr;
373 : }
374 0 : RemoveControllers();
375 0 : CloseShmem();
376 : #if defined(MOZ_WIDGET_ANDROID)
377 : mDoShutdown = false;
378 : #endif
379 0 : }
380 :
381 : void
382 0 : VRSystemManagerExternal::NotifyVSync()
383 : {
384 0 : VRSystemManager::NotifyVSync();
385 :
386 0 : CheckForShutdown();
387 :
388 0 : if (mDisplay) {
389 0 : mDisplay->Refresh();
390 : }
391 0 : }
392 :
393 : void
394 0 : VRSystemManagerExternal::Enumerate()
395 : {
396 0 : if (mDisplay == nullptr) {
397 0 : OpenShmem();
398 0 : if (mExternalShmem) {
399 0 : VRDisplayState displayState;
400 0 : PullState(&displayState);
401 0 : if (displayState.mIsConnected) {
402 0 : mDisplay = new VRDisplayExternal(displayState);
403 : }
404 : }
405 : }
406 0 : }
407 :
408 : bool
409 0 : VRSystemManagerExternal::ShouldInhibitEnumeration()
410 : {
411 0 : if (VRSystemManager::ShouldInhibitEnumeration()) {
412 : return true;
413 : }
414 0 : if (mDisplay) {
415 : // When we find an a VR device, don't
416 : // allow any further enumeration as it
417 : // may get picked up redundantly by other
418 : // API's.
419 : return true;
420 : }
421 0 : return false;
422 : }
423 :
424 : void
425 0 : VRSystemManagerExternal::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
426 : {
427 0 : if (mDisplay) {
428 0 : aHMDResult.AppendElement(mDisplay);
429 : }
430 0 : }
431 :
432 : bool
433 0 : VRSystemManagerExternal::GetIsPresenting()
434 : {
435 0 : if (mDisplay) {
436 0 : VRDisplayInfo displayInfo(mDisplay->GetDisplayInfo());
437 0 : return displayInfo.GetPresentingGroups() != 0;
438 : }
439 :
440 : return false;
441 : }
442 :
443 : void
444 0 : VRSystemManagerExternal::HandleInput()
445 : {
446 : // TODO - Implement This!
447 0 : }
448 :
449 : void
450 0 : VRSystemManagerExternal::VibrateHaptic(uint32_t aControllerIdx,
451 : uint32_t aHapticIndex,
452 : double aIntensity,
453 : double aDuration,
454 : const VRManagerPromise& aPromise)
455 : {
456 : // TODO - Implement this
457 0 : }
458 :
459 : void
460 0 : VRSystemManagerExternal::StopVibrateHaptic(uint32_t aControllerIdx)
461 : {
462 : // TODO - Implement this
463 0 : }
464 :
465 : void
466 : VRSystemManagerExternal::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
467 : {
468 : aControllerResult.Clear();
469 : for (uint32_t i = 0; i < mExternalController.Length(); ++i) {
470 : aControllerResult.AppendElement(mExternalController[i]);
471 : }
472 : }
473 :
474 : void
475 : VRSystemManagerExternal::ScanForControllers()
476 : {
477 : // TODO - Implement this
478 : }
479 :
480 : void
481 : VRSystemManagerExternal::RemoveControllers()
482 : {
483 : // The controller count is changed, removing the existing gamepads first.
484 : for (uint32_t i = 0; i < mExternalController.Length(); ++i) {
485 : RemoveGamepad(i);
486 : }
487 : mExternalController.Clear();
488 : mControllerCount = 0;
489 : }
490 :
491 : void
492 : VRSystemManagerExternal::PullState(VRDisplayState* aDisplayState, VRHMDSensorState* aSensorState /* = nullptr */)
493 : {
494 : MOZ_ASSERT(mExternalShmem);
495 : if (mExternalShmem) {
496 : #if defined(MOZ_WIDGET_ANDROID)
497 : if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->systemMutex)) == 0) {
498 : memcpy(aDisplayState, (void*)&(mExternalShmem->state.displayState), sizeof(VRDisplayState));
499 : if (aSensorState) {
500 : memcpy(aSensorState, (void*)&(mExternalShmem->state.sensorState), sizeof(VRHMDSensorState));
501 : }
502 : pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->systemMutex));
503 : mDoShutdown = aDisplayState->shutdown;
504 : }
505 : #else
506 : VRExternalShmem tmp;
507 : memcpy(&tmp, (void *)mExternalShmem, sizeof(VRExternalShmem));
508 : if (tmp.generationA == tmp.generationB && tmp.generationA != 0 && tmp.generationA != -1) {
509 : memcpy(aDisplayState, &tmp.state.displayState, sizeof(VRDisplayState));
510 : if (aSensorState) {
511 : memcpy(aSensorState, &tmp.state.sensorState, sizeof(VRHMDSensorState));
512 : }
513 : }
514 : #endif // defined(MOZ_WIDGET_ANDROID)
515 : }
516 : }
|