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 "VRManagerChild.h"
8 : #include "VRManagerParent.h"
9 : #include "VRThread.h"
10 : #include "VRDisplayClient.h"
11 : #include "nsGlobalWindow.h"
12 : #include "mozilla/StaticPtr.h"
13 : #include "mozilla/layers/CompositorThread.h" // for CompositorThread
14 : #include "mozilla/dom/Navigator.h"
15 : #include "mozilla/dom/VREventObserver.h"
16 : #include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
17 : #include "mozilla/dom/ContentChild.h"
18 : #include "nsContentUtils.h"
19 : #include "mozilla/dom/GamepadManager.h"
20 : #include "mozilla/dom/VRServiceTest.h"
21 : #include "mozilla/layers/SyncObject.h"
22 :
23 : using namespace mozilla::dom;
24 :
25 : namespace {
26 : const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
27 : nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
28 : } // namespace
29 :
30 : namespace mozilla {
31 : namespace gfx {
32 :
33 1 : static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
34 0 : static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton;
35 :
36 0 : void ReleaseVRManagerParentSingleton() {
37 0 : sVRManagerParentSingleton = nullptr;
38 0 : }
39 :
40 0 : VRManagerChild::VRManagerChild()
41 : : mDisplaysInitialized(false)
42 1 : , mMessageLoop(MessageLoop::current())
43 : , mFrameRequestCallbackCounter(0)
44 : , mBackend(layers::LayersBackend::LAYERS_NONE)
45 : , mPromiseID(0)
46 0 : , mVRMockDisplay(nullptr)
47 : {
48 0 : MOZ_ASSERT(NS_IsMainThread());
49 :
50 1 : mStartTimeStamp = TimeStamp::Now();
51 0 : }
52 :
53 0 : VRManagerChild::~VRManagerChild()
54 : {
55 0 : MOZ_ASSERT(NS_IsMainThread());
56 0 : }
57 :
58 : /*static*/ void
59 0 : VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
60 : {
61 0 : if (sVRManagerChildSingleton) {
62 0 : sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
63 1 : sVRManagerChildSingleton->mSyncObject =
64 0 : layers::SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
65 : }
66 1 : }
67 :
68 : layers::LayersBackend
69 0 : VRManagerChild::GetBackendType() const
70 : {
71 0 : return mBackend;
72 : }
73 :
74 : /*static*/ VRManagerChild*
75 0 : VRManagerChild::Get()
76 : {
77 0 : MOZ_ASSERT(sVRManagerChildSingleton);
78 0 : return sVRManagerChildSingleton;
79 : }
80 :
81 : /* static */ bool
82 0 : VRManagerChild::IsCreated()
83 : {
84 2 : return !!sVRManagerChildSingleton;
85 : }
86 :
87 : /* static */ bool
88 0 : VRManagerChild::InitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
89 : {
90 0 : MOZ_ASSERT(NS_IsMainThread());
91 0 : MOZ_ASSERT(!sVRManagerChildSingleton);
92 :
93 0 : RefPtr<VRManagerChild> child(new VRManagerChild());
94 0 : if (!aEndpoint.Bind(child)) {
95 : return false;
96 : }
97 0 : sVRManagerChildSingleton = child;
98 0 : return true;
99 : }
100 :
101 : /* static */ bool
102 0 : VRManagerChild::ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
103 : {
104 0 : MOZ_ASSERT(NS_IsMainThread());
105 :
106 0 : ShutDown();
107 :
108 0 : return InitForContent(std::move(aEndpoint));
109 : }
110 :
111 : /*static*/ void
112 0 : VRManagerChild::InitSameProcess()
113 : {
114 1 : MOZ_ASSERT(NS_IsMainThread());
115 0 : MOZ_ASSERT(!sVRManagerChildSingleton);
116 :
117 0 : sVRManagerChildSingleton = new VRManagerChild();
118 2 : sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
119 0 : sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
120 : VRListenerThreadHolder::Loop(),
121 1 : mozilla::ipc::ChildSide);
122 1 : }
123 :
124 : /* static */ void
125 0 : VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint)
126 : {
127 0 : MOZ_ASSERT(NS_IsMainThread());
128 0 : MOZ_ASSERT(!sVRManagerChildSingleton);
129 :
130 0 : sVRManagerChildSingleton = new VRManagerChild();
131 0 : if (!aEndpoint.Bind(sVRManagerChildSingleton)) {
132 0 : MOZ_CRASH("Couldn't Open() Compositor channel.");
133 : }
134 0 : }
135 :
136 : /*static*/ void
137 0 : VRManagerChild::ShutDown()
138 : {
139 0 : MOZ_ASSERT(NS_IsMainThread());
140 0 : if (sVRManagerChildSingleton) {
141 0 : sVRManagerChildSingleton->Destroy();
142 : sVRManagerChildSingleton = nullptr;
143 : }
144 0 : }
145 :
146 : /*static*/ void
147 0 : VRManagerChild::DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild)
148 : {
149 0 : aVRManagerChild->Close();
150 0 : }
151 :
152 : void
153 0 : VRManagerChild::Destroy()
154 : {
155 : // Keep ourselves alive until everything has been shut down
156 0 : RefPtr<VRManagerChild> selfRef = this;
157 :
158 : // The DeferredDestroyVRManager task takes ownership of
159 : // the VRManagerChild and will release it when it runs.
160 0 : MessageLoop::current()->PostTask(
161 0 : NewRunnableFunction("VRManagerChildDestroyRunnable",
162 0 : DeferredDestroy, selfRef));
163 0 : }
164 :
165 : PVRLayerChild*
166 0 : VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID,
167 : const uint32_t& aGroup)
168 : {
169 0 : return VRLayerChild::CreateIPDLActor();
170 : }
171 :
172 : bool
173 0 : VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor)
174 : {
175 0 : return VRLayerChild::DestroyIPDLActor(actor);
176 : }
177 :
178 : void
179 0 : VRManagerChild::UpdateDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayUpdates)
180 : {
181 0 : nsTArray<uint32_t> disconnectedDisplays;
182 0 : nsTArray<uint32_t> connectedDisplays;
183 :
184 0 : nsTArray<RefPtr<VRDisplayClient>> prevDisplays;
185 0 : prevDisplays = mDisplays;
186 :
187 : // Check if any displays have been disconnected
188 0 : for (auto& display : prevDisplays) {
189 0 : bool found = false;
190 0 : for (auto& displayUpdate : aDisplayUpdates) {
191 0 : if (display->GetDisplayInfo().GetDisplayID() == displayUpdate.GetDisplayID()) {
192 : found = true;
193 : break;
194 : }
195 : }
196 0 : if (!found) {
197 0 : display->NotifyDisconnected();
198 0 : disconnectedDisplays.AppendElement(display->GetDisplayInfo().GetDisplayID());
199 : }
200 : }
201 :
202 : // mDisplays could be a hashed container for more scalability, but not worth
203 : // it now as we expect < 10 entries.
204 0 : nsTArray<RefPtr<VRDisplayClient>> displays;
205 0 : for (VRDisplayInfo& displayUpdate : aDisplayUpdates) {
206 0 : bool isNewDisplay = true;
207 0 : for (auto& display : prevDisplays) {
208 0 : const VRDisplayInfo& prevInfo = display->GetDisplayInfo();
209 0 : if (prevInfo.GetDisplayID() == displayUpdate.GetDisplayID()) {
210 0 : if (displayUpdate.GetIsConnected() && !prevInfo.GetIsConnected()) {
211 0 : connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
212 : }
213 0 : if (!displayUpdate.GetIsConnected() && prevInfo.GetIsConnected()) {
214 0 : disconnectedDisplays.AppendElement(displayUpdate.GetDisplayID());
215 : }
216 0 : display->UpdateDisplayInfo(displayUpdate);
217 0 : displays.AppendElement(display);
218 0 : isNewDisplay = false;
219 0 : break;
220 : }
221 : }
222 0 : if (isNewDisplay) {
223 0 : displays.AppendElement(new VRDisplayClient(displayUpdate));
224 0 : connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
225 : }
226 : }
227 :
228 0 : mDisplays = displays;
229 :
230 : // We wish to fire the events only after mDisplays is updated
231 0 : for (uint32_t displayID : disconnectedDisplays) {
232 0 : FireDOMVRDisplayDisconnectEvent(displayID);
233 : }
234 :
235 0 : for (uint32_t displayID : connectedDisplays) {
236 0 : FireDOMVRDisplayConnectEvent(displayID);
237 : }
238 :
239 0 : mDisplaysInitialized = true;
240 0 : }
241 :
242 : mozilla::ipc::IPCResult
243 0 : VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
244 : {
245 0 : UpdateDisplayInfo(aDisplayUpdates);
246 0 : for (auto& windowId : mNavigatorCallbacks) {
247 : /** We must call NotifyVRDisplaysUpdated for every
248 : * window's Navigator in mNavigatorCallbacks to ensure that
249 : * the promise returned by Navigator.GetVRDevices
250 : * can resolve. This must happen even if no changes
251 : * to VRDisplays have been detected here.
252 : */
253 : nsGlobalWindowInner* window =
254 0 : nsGlobalWindowInner::GetInnerWindowWithId(windowId);
255 0 : if (!window) {
256 : continue;
257 : }
258 0 : dom::Navigator* nav = window->Navigator();
259 0 : if (!nav) {
260 : continue;
261 : }
262 0 : nav->NotifyVRDisplaysUpdated();
263 : }
264 0 : mNavigatorCallbacks.Clear();
265 0 : return IPC_OK();
266 : }
267 :
268 : bool
269 0 : VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayClient>>& aDisplays)
270 : {
271 0 : aDisplays = mDisplays;
272 0 : return true;
273 : }
274 :
275 : bool
276 0 : VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId)
277 : {
278 0 : bool success = SendRefreshDisplays();
279 0 : if (success) {
280 0 : mNavigatorCallbacks.AppendElement(aWindowId);
281 : }
282 0 : return success;
283 : }
284 :
285 : void
286 0 : VRManagerChild::CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise)
287 : {
288 0 : SendCreateVRServiceTestDisplay(aID, mPromiseID);
289 0 : mPromiseList.Put(mPromiseID, aPromise);
290 0 : ++mPromiseID;
291 0 : }
292 :
293 : void
294 0 : VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
295 : {
296 0 : SendCreateVRServiceTestController(aID, mPromiseID);
297 0 : mPromiseList.Put(mPromiseID, aPromise);
298 0 : ++mPromiseID;
299 0 : }
300 :
301 : PVRLayerChild*
302 0 : VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
303 : nsIEventTarget* aTarget,
304 : uint32_t aGroup)
305 : {
306 0 : PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aGroup);
307 : // Do the DOM labeling.
308 0 : if (aTarget) {
309 0 : SetEventTargetForActor(vrLayerChild, aTarget);
310 0 : MOZ_ASSERT(vrLayerChild->GetActorEventTarget());
311 : }
312 0 : return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aGroup);
313 : }
314 :
315 :
316 : // XXX TODO - VRManagerChild::FrameRequest is the same as nsIDocument::FrameRequest, should we consolodate these?
317 0 : struct VRManagerChild::FrameRequest
318 : {
319 : FrameRequest(mozilla::dom::FrameRequestCallback& aCallback,
320 0 : int32_t aHandle) :
321 : mCallback(&aCallback),
322 0 : mHandle(aHandle)
323 : {}
324 :
325 : // Conversion operator so that we can append these to a
326 : // FrameRequestCallbackList
327 : operator const RefPtr<mozilla::dom::FrameRequestCallback>& () const {
328 : return mCallback;
329 : }
330 :
331 : // Comparator operators to allow RemoveElementSorted with an
332 : // integer argument on arrays of FrameRequest
333 : bool operator==(int32_t aHandle) const {
334 : return mHandle == aHandle;
335 : }
336 : bool operator<(int32_t aHandle) const {
337 : return mHandle < aHandle;
338 : }
339 :
340 : RefPtr<mozilla::dom::FrameRequestCallback> mCallback;
341 : int32_t mHandle;
342 : };
343 :
344 : nsresult
345 0 : VRManagerChild::ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
346 : int32_t *aHandle)
347 : {
348 0 : if (mFrameRequestCallbackCounter == INT32_MAX) {
349 : // Can't increment without overflowing; bail out
350 : return NS_ERROR_NOT_AVAILABLE;
351 : }
352 0 : int32_t newHandle = ++mFrameRequestCallbackCounter;
353 :
354 : DebugOnly<FrameRequest*> request =
355 0 : mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
356 0 : NS_ASSERTION(request, "This is supposed to be infallible!");
357 :
358 0 : *aHandle = newHandle;
359 0 : return NS_OK;
360 : }
361 :
362 : void
363 0 : VRManagerChild::CancelFrameRequestCallback(int32_t aHandle)
364 : {
365 : // mFrameRequestCallbacks is stored sorted by handle
366 0 : mFrameRequestCallbacks.RemoveElementSorted(aHandle);
367 0 : }
368 :
369 : mozilla::ipc::IPCResult
370 0 : VRManagerChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
371 : {
372 : // VRManagerChild could be at other processes, but GamepadManager
373 : // only exists at the content process or the same process
374 : // in non-e10s mode.
375 0 : MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
376 :
377 0 : RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
378 0 : if (gamepadManager) {
379 0 : gamepadManager->Update(aGamepadEvent);
380 : }
381 :
382 0 : return IPC_OK();
383 : }
384 :
385 : mozilla::ipc::IPCResult
386 0 : VRManagerChild::RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
387 : const uint32_t& aPromiseID,
388 : const uint32_t& aDeviceID)
389 : {
390 0 : RefPtr<dom::Promise> p;
391 0 : if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
392 0 : MOZ_CRASH("We should always have a promise.");
393 : }
394 :
395 : // We only allow one VRMockDisplay in VR tests.
396 0 : if (!mVRMockDisplay) {
397 0 : mVRMockDisplay = new VRMockDisplay(aID, aDeviceID);
398 : }
399 0 : p->MaybeResolve(mVRMockDisplay);
400 0 : mPromiseList.Remove(aPromiseID);
401 0 : return IPC_OK();
402 : }
403 :
404 : mozilla::ipc::IPCResult
405 0 : VRManagerChild::RecvReplyCreateVRServiceTestController(const nsCString& aID,
406 : const uint32_t& aPromiseID,
407 : const uint32_t& aDeviceID)
408 : {
409 0 : RefPtr<dom::Promise> p;
410 0 : if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
411 0 : MOZ_CRASH("We should always have a promise.");
412 : }
413 :
414 0 : if (aDeviceID == 0) {
415 : // A value of 0 indicates that the controller could not
416 : // be created. Most likely due to having no VR display
417 : // to associate it with.
418 0 : p->MaybeRejectWithUndefined();
419 : } else {
420 0 : p->MaybeResolve(new VRMockController(aID, aDeviceID));
421 : }
422 0 : mPromiseList.Remove(aPromiseID);
423 0 : return IPC_OK();
424 : }
425 :
426 : void
427 0 : VRManagerChild::RunFrameRequestCallbacks()
428 : {
429 0 : AUTO_PROFILER_TRACING("VR", "RunFrameRequestCallbacks");
430 :
431 0 : TimeStamp nowTime = TimeStamp::Now();
432 0 : mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
433 0 : DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
434 :
435 :
436 0 : nsTArray<FrameRequest> callbacks;
437 0 : callbacks.AppendElements(mFrameRequestCallbacks);
438 0 : mFrameRequestCallbacks.Clear();
439 0 : for (auto& callback : callbacks) {
440 0 : callback.mCallback->Call(timeStamp);
441 : }
442 0 : }
443 :
444 : void
445 0 : VRManagerChild::FireDOMVRDisplayMountedEvent(uint32_t aDisplayID)
446 : {
447 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
448 : "gfx::VRManagerChild::FireDOMVRDisplayMountedEventInternal",
449 : this,
450 : &VRManagerChild::FireDOMVRDisplayMountedEventInternal,
451 0 : aDisplayID));
452 0 : }
453 :
454 : void
455 0 : VRManagerChild::FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID)
456 : {
457 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
458 : "gfx::VRManagerChild::FireDOMVRDisplayUnmountedEventInternal",
459 : this,
460 : &VRManagerChild::FireDOMVRDisplayUnmountedEventInternal,
461 0 : aDisplayID));
462 0 : }
463 :
464 : void
465 0 : VRManagerChild::FireDOMVRDisplayConnectEvent(uint32_t aDisplayID)
466 : {
467 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
468 : "gfx::VRManagerChild::FireDOMVRDisplayConnectEventInternal",
469 : this,
470 : &VRManagerChild::FireDOMVRDisplayConnectEventInternal,
471 0 : aDisplayID));
472 0 : }
473 :
474 : void
475 0 : VRManagerChild::FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID)
476 : {
477 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
478 : "gfx::VRManagerChild::FireDOMVRDisplayDisconnectEventInternal",
479 : this,
480 : &VRManagerChild::FireDOMVRDisplayDisconnectEventInternal,
481 0 : aDisplayID));
482 0 : }
483 :
484 : void
485 0 : VRManagerChild::FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID)
486 : {
487 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
488 : "gfx::VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal",
489 : this,
490 : &VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal,
491 0 : aDisplayID));
492 0 : }
493 :
494 : void
495 0 : VRManagerChild::FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID)
496 : {
497 : // Iterate over a copy of mListeners, as dispatched events may modify it.
498 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
499 0 : listeners = mListeners;
500 0 : for (auto& listener : listeners) {
501 0 : listener->NotifyVRDisplayMounted(aDisplayID);
502 : }
503 0 : }
504 :
505 : void
506 0 : VRManagerChild::FireDOMVRDisplayUnmountedEventInternal(uint32_t aDisplayID)
507 : {
508 : // Iterate over a copy of mListeners, as dispatched events may modify it.
509 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
510 0 : listeners = mListeners;
511 0 : for (auto& listener : listeners) {
512 0 : listener->NotifyVRDisplayUnmounted(aDisplayID);
513 : }
514 0 : }
515 :
516 : void
517 0 : VRManagerChild::FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID)
518 : {
519 : // Iterate over a copy of mListeners, as dispatched events may modify it.
520 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
521 0 : listeners = mListeners;
522 0 : for (auto& listener : listeners) {
523 0 : listener->NotifyVRDisplayConnect(aDisplayID);
524 : }
525 0 : }
526 :
527 : void
528 0 : VRManagerChild::FireDOMVRDisplayDisconnectEventInternal(uint32_t aDisplayID)
529 : {
530 : // Iterate over a copy of mListeners, as dispatched events may modify it.
531 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
532 0 : listeners = mListeners;
533 0 : for (auto& listener : listeners) {
534 0 : listener->NotifyVRDisplayDisconnect(aDisplayID);
535 : }
536 0 : }
537 :
538 : void
539 0 : VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal(uint32_t aDisplayID)
540 : {
541 : // Iterate over a copy of mListeners, as dispatched events may modify it.
542 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
543 0 : listeners = mListeners;
544 0 : for (auto& listener : listeners) {
545 0 : listener->NotifyVRDisplayPresentChange(aDisplayID);
546 : }
547 0 : }
548 :
549 : void
550 0 : VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal(uint32_t aDisplayID,
551 : dom::VREventObserver* aObserver)
552 : {
553 0 : aObserver->NotifyVRDisplayConnect(aDisplayID);
554 0 : }
555 :
556 : void
557 0 : VRManagerChild::FireDOMVRDisplayConnectEventsForLoad(dom::VREventObserver* aObserver)
558 : {
559 : // We need to fire the VRDisplayConnect event when a page is loaded
560 : // for each VR Display that has already been enumerated
561 0 : nsTArray<RefPtr<VRDisplayClient>> displays;
562 0 : displays = mDisplays;
563 0 : for (auto& display : displays) {
564 0 : const VRDisplayInfo& info = display->GetDisplayInfo();
565 0 : if (info.GetIsConnected()) {
566 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t, RefPtr<dom::VREventObserver>>(
567 : "gfx::VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal",
568 : this,
569 : &VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal,
570 0 : info.GetDisplayID(),
571 0 : aObserver));
572 : }
573 : }
574 0 : }
575 :
576 : void
577 0 : VRManagerChild::AddListener(dom::VREventObserver* aObserver)
578 : {
579 0 : MOZ_ASSERT(aObserver);
580 :
581 0 : if (mListeners.IndexOf(aObserver) != kNoIndex) {
582 : return; // already exists
583 : }
584 :
585 0 : mListeners.AppendElement(aObserver);
586 0 : if (mListeners.Length() == 1) {
587 0 : Unused << SendSetHaveEventListener(true);
588 : }
589 : }
590 :
591 : void
592 0 : VRManagerChild::RemoveListener(dom::VREventObserver* aObserver)
593 : {
594 0 : MOZ_ASSERT(aObserver);
595 :
596 0 : mListeners.RemoveElement(aObserver);
597 0 : if (mListeners.IsEmpty()) {
598 0 : Unused << SendSetHaveEventListener(false);
599 : }
600 0 : }
601 :
602 : void
603 0 : VRManagerChild::HandleFatalError(const char* aMsg) const
604 : {
605 0 : dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
606 0 : }
607 :
608 : void
609 0 : VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise)
610 : {
611 0 : MOZ_ASSERT(!mGamepadPromiseList.Get(aID, nullptr));
612 0 : mGamepadPromiseList.Put(aID, aPromise);
613 0 : }
614 :
615 : mozilla::ipc::IPCResult
616 0 : VRManagerChild::RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
617 : {
618 : // VRManagerChild could be at other processes, but GamepadManager
619 : // only exists at the content process or the same process
620 : // in non-e10s mode.
621 0 : MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
622 :
623 0 : RefPtr<dom::Promise> p;
624 0 : if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
625 0 : MOZ_CRASH("We should always have a promise.");
626 : }
627 :
628 0 : p->MaybeResolve(true);
629 0 : mGamepadPromiseList.Remove(aPromiseID);
630 0 : return IPC_OK();
631 : }
632 :
633 : mozilla::ipc::IPCResult
634 0 : VRManagerChild::RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID,
635 : const VRSubmitFrameResultInfo& aResult)
636 : {
637 0 : nsTArray<RefPtr<VRDisplayClient>> displays;
638 0 : displays = mDisplays;
639 : for (auto& display : displays) {
640 : if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
641 : display->UpdateSubmitFrameResult(aResult);
642 : }
643 : }
644 :
645 : return IPC_OK();
646 : }
647 :
648 : } // namespace gfx
649 : } // namespace mozilla
|