Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "VRManagerChild.h"
9 : #include "VRManagerParent.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 "mozilla/layers/TextureClient.h"
19 : #include "nsContentUtils.h"
20 : #include "mozilla/dom/GamepadManager.h"
21 : #include "mozilla/dom/VRServiceTest.h"
22 :
23 : using layers::TextureClient;
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 3 : static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
34 3 : static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton;
35 :
36 0 : void ReleaseVRManagerParentSingleton() {
37 0 : sVRManagerParentSingleton = nullptr;
38 0 : }
39 :
40 3 : VRManagerChild::VRManagerChild()
41 : : TextureForwarder()
42 : , mDisplaysInitialized(false)
43 3 : , mMessageLoop(MessageLoop::current())
44 : , mFrameRequestCallbackCounter(0)
45 : , mBackend(layers::LayersBackend::LAYERS_NONE)
46 : , mPromiseID(0)
47 6 : , mVRMockDisplay(nullptr)
48 : {
49 3 : MOZ_ASSERT(NS_IsMainThread());
50 :
51 3 : mStartTimeStamp = TimeStamp::Now();
52 3 : }
53 :
54 0 : VRManagerChild::~VRManagerChild()
55 : {
56 0 : MOZ_ASSERT(NS_IsMainThread());
57 0 : }
58 :
59 : /*static*/ void
60 2 : VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
61 : {
62 2 : if (sVRManagerChildSingleton) {
63 2 : sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
64 2 : sVRManagerChildSingleton->mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
65 : }
66 2 : }
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 3 : VRManagerChild::IsCreated()
83 : {
84 3 : return !!sVRManagerChildSingleton;
85 : }
86 :
87 : /* static */ bool
88 2 : VRManagerChild::InitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
89 : {
90 2 : MOZ_ASSERT(NS_IsMainThread());
91 2 : MOZ_ASSERT(!sVRManagerChildSingleton);
92 :
93 4 : RefPtr<VRManagerChild> child(new VRManagerChild());
94 2 : if (!aEndpoint.Bind(child)) {
95 0 : NS_RUNTIMEABORT("Couldn't Open() Compositor channel.");
96 0 : return false;
97 : }
98 2 : sVRManagerChildSingleton = child;
99 2 : return true;
100 : }
101 :
102 : /* static */ bool
103 0 : VRManagerChild::ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint)
104 : {
105 0 : MOZ_ASSERT(NS_IsMainThread());
106 :
107 0 : ShutDown();
108 :
109 0 : return InitForContent(Move(aEndpoint));
110 : }
111 :
112 : /*static*/ void
113 1 : VRManagerChild::InitSameProcess()
114 : {
115 1 : MOZ_ASSERT(NS_IsMainThread());
116 1 : MOZ_ASSERT(!sVRManagerChildSingleton);
117 :
118 1 : sVRManagerChildSingleton = new VRManagerChild();
119 1 : sVRManagerParentSingleton = VRManagerParent::CreateSameProcess();
120 1 : sVRManagerChildSingleton->Open(sVRManagerParentSingleton->GetIPCChannel(),
121 : mozilla::layers::CompositorThreadHolder::Loop(),
122 1 : mozilla::ipc::ChildSide);
123 1 : }
124 :
125 : /* static */ void
126 0 : VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint)
127 : {
128 0 : MOZ_ASSERT(NS_IsMainThread());
129 0 : MOZ_ASSERT(!sVRManagerChildSingleton);
130 :
131 0 : sVRManagerChildSingleton = new VRManagerChild();
132 0 : if (!aEndpoint.Bind(sVRManagerChildSingleton)) {
133 0 : NS_RUNTIMEABORT("Couldn't Open() Compositor channel.");
134 0 : return;
135 : }
136 : }
137 :
138 : /*static*/ void
139 0 : VRManagerChild::ShutDown()
140 : {
141 0 : MOZ_ASSERT(NS_IsMainThread());
142 0 : if (sVRManagerChildSingleton) {
143 0 : sVRManagerChildSingleton->Destroy();
144 0 : sVRManagerChildSingleton = nullptr;
145 : }
146 0 : }
147 :
148 : /*static*/ void
149 0 : VRManagerChild::DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild)
150 : {
151 0 : aVRManagerChild->Close();
152 0 : }
153 :
154 : void
155 0 : VRManagerChild::Destroy()
156 : {
157 0 : mTexturesWaitingRecycled.Clear();
158 :
159 : // Keep ourselves alive until everything has been shut down
160 0 : RefPtr<VRManagerChild> selfRef = this;
161 :
162 : // The DeferredDestroyVRManager task takes ownership of
163 : // the VRManagerChild and will release it when it runs.
164 0 : MessageLoop::current()->PostTask(
165 0 : NewRunnableFunction(DeferredDestroy, selfRef));
166 0 : }
167 :
168 : layers::PTextureChild*
169 0 : VRManagerChild::AllocPTextureChild(const SurfaceDescriptor&,
170 : const LayersBackend&,
171 : const TextureFlags&,
172 : const uint64_t&)
173 : {
174 0 : return TextureClient::CreateIPDLActor();
175 : }
176 :
177 : bool
178 0 : VRManagerChild::DeallocPTextureChild(PTextureChild* actor)
179 : {
180 0 : return TextureClient::DestroyIPDLActor(actor);
181 : }
182 :
183 : PVRLayerChild*
184 0 : VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID,
185 : const float& aLeftEyeX,
186 : const float& aLeftEyeY,
187 : const float& aLeftEyeWidth,
188 : const float& aLeftEyeHeight,
189 : const float& aRightEyeX,
190 : const float& aRightEyeY,
191 : const float& aRightEyeWidth,
192 : const float& aRightEyeHeight,
193 : const uint32_t& aGroup)
194 : {
195 0 : RefPtr<VRLayerChild> layer = new VRLayerChild(aDisplayID, this);
196 0 : return layer.forget().take();
197 : }
198 :
199 : bool
200 0 : VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor)
201 : {
202 0 : delete actor;
203 0 : return true;
204 : }
205 :
206 : void
207 0 : VRManagerChild::UpdateDisplayInfo(nsTArray<VRDisplayInfo>& aDisplayUpdates)
208 : {
209 0 : nsTArray<uint32_t> disconnectedDisplays;
210 0 : nsTArray<uint32_t> connectedDisplays;
211 :
212 : // Check if any displays have been disconnected
213 0 : for (auto& display : mDisplays) {
214 0 : bool found = false;
215 0 : for (auto& displayUpdate : aDisplayUpdates) {
216 0 : if (display->GetDisplayInfo().GetDisplayID() == displayUpdate.GetDisplayID()) {
217 0 : found = true;
218 0 : break;
219 : }
220 : }
221 0 : if (!found) {
222 0 : display->NotifyDisconnected();
223 0 : disconnectedDisplays.AppendElement(display->GetDisplayInfo().GetDisplayID());
224 : }
225 : }
226 :
227 : // mDisplays could be a hashed container for more scalability, but not worth
228 : // it now as we expect < 10 entries.
229 0 : nsTArray<RefPtr<VRDisplayClient>> displays;
230 0 : for (VRDisplayInfo& displayUpdate : aDisplayUpdates) {
231 0 : bool isNewDisplay = true;
232 0 : for (auto& display : mDisplays) {
233 0 : const VRDisplayInfo& prevInfo = display->GetDisplayInfo();
234 0 : if (prevInfo.GetDisplayID() == displayUpdate.GetDisplayID()) {
235 0 : if (displayUpdate.GetIsConnected() && !prevInfo.GetIsConnected()) {
236 0 : connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
237 : }
238 0 : if (!displayUpdate.GetIsConnected() && prevInfo.GetIsConnected()) {
239 0 : disconnectedDisplays.AppendElement(displayUpdate.GetDisplayID());
240 : }
241 0 : display->UpdateDisplayInfo(displayUpdate);
242 0 : displays.AppendElement(display);
243 0 : isNewDisplay = false;
244 0 : break;
245 : }
246 : }
247 0 : if (isNewDisplay) {
248 0 : displays.AppendElement(new VRDisplayClient(displayUpdate));
249 0 : connectedDisplays.AppendElement(displayUpdate.GetDisplayID());
250 : }
251 : }
252 :
253 0 : mDisplays = displays;
254 :
255 : // We wish to fire the events only after mDisplays is updated
256 0 : for (uint32_t displayID : disconnectedDisplays) {
257 0 : FireDOMVRDisplayDisconnectEvent(displayID);
258 : }
259 :
260 0 : for (uint32_t displayID : connectedDisplays) {
261 0 : FireDOMVRDisplayConnectEvent(displayID);
262 : }
263 :
264 0 : mDisplaysInitialized = true;
265 0 : }
266 :
267 : mozilla::ipc::IPCResult
268 0 : VRManagerChild::RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates)
269 : {
270 0 : UpdateDisplayInfo(aDisplayUpdates);
271 0 : for (auto& windowId : mNavigatorCallbacks) {
272 : /** We must call NotifyVRDisplaysUpdated for every
273 : * window's Navigator in mNavigatorCallbacks to ensure that
274 : * the promise returned by Navigator.GetVRDevices
275 : * can resolve. This must happen even if no changes
276 : * to VRDisplays have been detected here.
277 : */
278 0 : nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(windowId);
279 0 : if (!window) {
280 0 : continue;
281 : }
282 0 : dom::Navigator* nav = window->Navigator();
283 0 : if (!nav) {
284 0 : continue;
285 : }
286 0 : nav->NotifyVRDisplaysUpdated();
287 : }
288 0 : mNavigatorCallbacks.Clear();
289 0 : return IPC_OK();
290 : }
291 :
292 : bool
293 0 : VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayClient>>& aDisplays)
294 : {
295 0 : aDisplays = mDisplays;
296 0 : return true;
297 : }
298 :
299 : bool
300 0 : VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId)
301 : {
302 0 : bool success = SendRefreshDisplays();
303 0 : if (success) {
304 0 : mNavigatorCallbacks.AppendElement(aWindowId);
305 : }
306 0 : return success;
307 : }
308 :
309 : void
310 0 : VRManagerChild::CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise)
311 : {
312 0 : SendCreateVRServiceTestDisplay(aID, mPromiseID);
313 0 : mPromiseList.Put(mPromiseID, aPromise);
314 0 : ++mPromiseID;
315 0 : }
316 :
317 : void
318 0 : VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
319 : {
320 0 : SendCreateVRServiceTestController(aID, mPromiseID);
321 0 : mPromiseList.Put(mPromiseID, aPromise);
322 0 : ++mPromiseID;
323 0 : }
324 :
325 : mozilla::ipc::IPCResult
326 0 : VRManagerChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
327 : {
328 0 : for (InfallibleTArray<AsyncParentMessageData>::index_type i = 0; i < aMessages.Length(); ++i) {
329 0 : const AsyncParentMessageData& message = aMessages[i];
330 :
331 0 : switch (message.type()) {
332 : case AsyncParentMessageData::TOpNotifyNotUsed: {
333 0 : const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
334 0 : NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
335 0 : break;
336 : }
337 : default:
338 0 : NS_ERROR("unknown AsyncParentMessageData type");
339 0 : return IPC_FAIL_NO_REASON(this);
340 : }
341 : }
342 0 : return IPC_OK();
343 : }
344 :
345 : PTextureChild*
346 0 : VRManagerChild::CreateTexture(const SurfaceDescriptor& aSharedData,
347 : LayersBackend aLayersBackend,
348 : TextureFlags aFlags,
349 : uint64_t aSerial,
350 : wr::MaybeExternalImageId& aExternalImageId,
351 : nsIEventTarget* aTarget)
352 : {
353 0 : return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
354 : }
355 :
356 : void
357 0 : VRManagerChild::CancelWaitForRecycle(uint64_t aTextureId)
358 : {
359 0 : RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
360 0 : if (!client) {
361 0 : return;
362 : }
363 0 : mTexturesWaitingRecycled.Remove(aTextureId);
364 : }
365 :
366 : void
367 0 : VRManagerChild::NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId)
368 : {
369 0 : RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
370 0 : if (!client) {
371 0 : return;
372 : }
373 0 : mTexturesWaitingRecycled.Remove(aTextureId);
374 : }
375 :
376 : bool
377 0 : VRManagerChild::AllocShmem(size_t aSize,
378 : ipc::SharedMemory::SharedMemoryType aType,
379 : ipc::Shmem* aShmem)
380 : {
381 0 : return PVRManagerChild::AllocShmem(aSize, aType, aShmem);
382 : }
383 :
384 : bool
385 0 : VRManagerChild::AllocUnsafeShmem(size_t aSize,
386 : ipc::SharedMemory::SharedMemoryType aType,
387 : ipc::Shmem* aShmem)
388 : {
389 0 : return PVRManagerChild::AllocUnsafeShmem(aSize, aType, aShmem);
390 : }
391 :
392 : bool
393 0 : VRManagerChild::DeallocShmem(ipc::Shmem& aShmem)
394 : {
395 0 : return PVRManagerChild::DeallocShmem(aShmem);
396 : }
397 :
398 : PVRLayerChild*
399 0 : VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
400 : const Rect& aLeftEyeRect,
401 : const Rect& aRightEyeRect,
402 : nsIEventTarget* aTarget,
403 : uint32_t aGroup)
404 : {
405 0 : PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aLeftEyeRect.x,
406 : aLeftEyeRect.y, aLeftEyeRect.width,
407 : aLeftEyeRect.height, aRightEyeRect.x,
408 : aRightEyeRect.y, aRightEyeRect.width,
409 : aRightEyeRect.height,
410 0 : aGroup);
411 : // Do the DOM labeling.
412 0 : if (aTarget) {
413 0 : SetEventTargetForActor(vrLayerChild, aTarget);
414 0 : MOZ_ASSERT(vrLayerChild->GetActorEventTarget());
415 : }
416 0 : return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aLeftEyeRect.x,
417 : aLeftEyeRect.y, aLeftEyeRect.width,
418 : aLeftEyeRect.height, aRightEyeRect.x,
419 : aRightEyeRect.y, aRightEyeRect.width,
420 : aRightEyeRect.height,
421 0 : aGroup);
422 : }
423 :
424 :
425 : // XXX TODO - VRManagerChild::FrameRequest is the same as nsIDocument::FrameRequest, should we consolodate these?
426 0 : struct VRManagerChild::FrameRequest
427 : {
428 0 : FrameRequest(mozilla::dom::FrameRequestCallback& aCallback,
429 0 : int32_t aHandle) :
430 : mCallback(&aCallback),
431 0 : mHandle(aHandle)
432 0 : {}
433 :
434 : // Conversion operator so that we can append these to a
435 : // FrameRequestCallbackList
436 : operator const RefPtr<mozilla::dom::FrameRequestCallback>& () const {
437 : return mCallback;
438 : }
439 :
440 : // Comparator operators to allow RemoveElementSorted with an
441 : // integer argument on arrays of FrameRequest
442 0 : bool operator==(int32_t aHandle) const {
443 0 : return mHandle == aHandle;
444 : }
445 0 : bool operator<(int32_t aHandle) const {
446 0 : return mHandle < aHandle;
447 : }
448 :
449 : RefPtr<mozilla::dom::FrameRequestCallback> mCallback;
450 : int32_t mHandle;
451 : };
452 :
453 : nsresult
454 0 : VRManagerChild::ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
455 : int32_t *aHandle)
456 : {
457 0 : if (mFrameRequestCallbackCounter == INT32_MAX) {
458 : // Can't increment without overflowing; bail out
459 0 : return NS_ERROR_NOT_AVAILABLE;
460 : }
461 0 : int32_t newHandle = ++mFrameRequestCallbackCounter;
462 :
463 : DebugOnly<FrameRequest*> request =
464 0 : mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
465 0 : NS_ASSERTION(request, "This is supposed to be infallible!");
466 :
467 0 : *aHandle = newHandle;
468 0 : return NS_OK;
469 : }
470 :
471 : void
472 0 : VRManagerChild::CancelFrameRequestCallback(int32_t aHandle)
473 : {
474 : // mFrameRequestCallbacks is stored sorted by handle
475 0 : mFrameRequestCallbacks.RemoveElementSorted(aHandle);
476 0 : }
477 :
478 : mozilla::ipc::IPCResult
479 0 : VRManagerChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
480 : {
481 : // VRManagerChild could be at other processes, but GamepadManager
482 : // only exists at the content process or the same process
483 : // in non-e10s mode.
484 0 : MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
485 :
486 0 : RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
487 0 : if (gamepadManager) {
488 0 : gamepadManager->Update(aGamepadEvent);
489 : }
490 :
491 0 : return IPC_OK();
492 : }
493 :
494 : mozilla::ipc::IPCResult
495 0 : VRManagerChild::RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
496 : const uint32_t& aPromiseID,
497 : const uint32_t& aDeviceID)
498 : {
499 0 : RefPtr<dom::Promise> p;
500 0 : if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
501 0 : MOZ_CRASH("We should always have a promise.");
502 : }
503 :
504 : // We only allow one VRMockDisplay in VR tests.
505 0 : if (!mVRMockDisplay) {
506 0 : mVRMockDisplay = new VRMockDisplay(aID, aDeviceID);
507 : }
508 0 : p->MaybeResolve(mVRMockDisplay);
509 0 : mPromiseList.Remove(aPromiseID);
510 0 : return IPC_OK();
511 : }
512 :
513 : mozilla::ipc::IPCResult
514 0 : VRManagerChild::RecvReplyCreateVRServiceTestController(const nsCString& aID,
515 : const uint32_t& aPromiseID,
516 : const uint32_t& aDeviceID)
517 : {
518 0 : RefPtr<dom::Promise> p;
519 0 : if (!mPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
520 0 : MOZ_CRASH("We should always have a promise.");
521 : }
522 :
523 0 : p->MaybeResolve(new VRMockController(aID, aDeviceID));
524 0 : mPromiseList.Remove(aPromiseID);
525 0 : return IPC_OK();
526 : }
527 :
528 : void
529 0 : VRManagerChild::RunFrameRequestCallbacks()
530 : {
531 0 : TimeStamp nowTime = TimeStamp::Now();
532 0 : mozilla::TimeDuration duration = nowTime - mStartTimeStamp;
533 0 : DOMHighResTimeStamp timeStamp = duration.ToMilliseconds();
534 :
535 :
536 0 : nsTArray<FrameRequest> callbacks;
537 0 : callbacks.AppendElements(mFrameRequestCallbacks);
538 0 : mFrameRequestCallbacks.Clear();
539 0 : for (auto& callback : callbacks) {
540 0 : callback.mCallback->Call(timeStamp);
541 : }
542 0 : }
543 :
544 : void
545 0 : VRManagerChild::FireDOMVRDisplayMountedEvent(uint32_t aDisplayID)
546 : {
547 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
548 : "gfx::VRManagerChild::FireDOMVRDisplayMountedEventInternal",
549 : this,
550 : &VRManagerChild::FireDOMVRDisplayMountedEventInternal,
551 0 : aDisplayID));
552 0 : }
553 :
554 : void
555 0 : VRManagerChild::FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID)
556 : {
557 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
558 : "gfx::VRManagerChild::FireDOMVRDisplayUnmountedEventInternal",
559 : this,
560 : &VRManagerChild::FireDOMVRDisplayUnmountedEventInternal,
561 0 : aDisplayID));
562 0 : }
563 :
564 : void
565 0 : VRManagerChild::FireDOMVRDisplayConnectEvent(uint32_t aDisplayID)
566 : {
567 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
568 : "gfx::VRManagerChild::FireDOMVRDisplayConnectEventInternal",
569 : this,
570 : &VRManagerChild::FireDOMVRDisplayConnectEventInternal,
571 0 : aDisplayID));
572 0 : }
573 :
574 : void
575 0 : VRManagerChild::FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID)
576 : {
577 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
578 : "gfx::VRManagerChild::FireDOMVRDisplayDisconnectEventInternal",
579 : this,
580 : &VRManagerChild::FireDOMVRDisplayDisconnectEventInternal,
581 0 : aDisplayID));
582 0 : }
583 :
584 : void
585 0 : VRManagerChild::FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID)
586 : {
587 0 : nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>(
588 : "gfx::VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal",
589 : this,
590 : &VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal,
591 0 : aDisplayID));
592 0 : }
593 :
594 : void
595 0 : VRManagerChild::FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID)
596 : {
597 : // Iterate over a copy of mListeners, as dispatched events may modify it.
598 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
599 0 : listeners = mListeners;
600 0 : for (auto& listener : listeners) {
601 0 : listener->NotifyVRDisplayMounted(aDisplayID);
602 : }
603 0 : }
604 :
605 : void
606 0 : VRManagerChild::FireDOMVRDisplayUnmountedEventInternal(uint32_t aDisplayID)
607 : {
608 : // Iterate over a copy of mListeners, as dispatched events may modify it.
609 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
610 0 : listeners = mListeners;
611 0 : for (auto& listener : listeners) {
612 0 : listener->NotifyVRDisplayUnmounted(aDisplayID);
613 : }
614 0 : }
615 :
616 : void
617 0 : VRManagerChild::FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID)
618 : {
619 : // Iterate over a copy of mListeners, as dispatched events may modify it.
620 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
621 0 : listeners = mListeners;
622 0 : for (auto& listener : listeners) {
623 0 : listener->NotifyVRDisplayConnect(aDisplayID);
624 : }
625 0 : }
626 :
627 : void
628 0 : VRManagerChild::FireDOMVRDisplayDisconnectEventInternal(uint32_t aDisplayID)
629 : {
630 : // Iterate over a copy of mListeners, as dispatched events may modify it.
631 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
632 0 : listeners = mListeners;
633 0 : for (auto& listener : listeners) {
634 0 : listener->NotifyVRDisplayDisconnect(aDisplayID);
635 : }
636 0 : }
637 :
638 : void
639 0 : VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal(uint32_t aDisplayID)
640 : {
641 : // Iterate over a copy of mListeners, as dispatched events may modify it.
642 0 : nsTArray<RefPtr<dom::VREventObserver>> listeners;
643 0 : listeners = mListeners;
644 0 : for (auto& listener : listeners) {
645 0 : listener->NotifyVRDisplayPresentChange(aDisplayID);
646 : }
647 0 : }
648 :
649 : void
650 0 : VRManagerChild::AddListener(dom::VREventObserver* aObserver)
651 : {
652 0 : MOZ_ASSERT(aObserver);
653 :
654 0 : if (mListeners.IndexOf(aObserver) != kNoIndex) {
655 0 : return; // already exists
656 : }
657 :
658 0 : mListeners.AppendElement(aObserver);
659 0 : if (mListeners.Length() == 1) {
660 0 : Unused << SendSetHaveEventListener(true);
661 : }
662 : }
663 :
664 : void
665 0 : VRManagerChild::RemoveListener(dom::VREventObserver* aObserver)
666 : {
667 0 : MOZ_ASSERT(aObserver);
668 :
669 0 : mListeners.RemoveElement(aObserver);
670 0 : if (mListeners.IsEmpty()) {
671 0 : Unused << SendSetHaveEventListener(false);
672 : }
673 0 : }
674 :
675 : void
676 0 : VRManagerChild::HandleFatalError(const char* aName, const char* aMsg) const
677 : {
678 0 : dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
679 0 : }
680 :
681 : void
682 0 : VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise)
683 : {
684 0 : MOZ_ASSERT(!mGamepadPromiseList.Get(aID, nullptr));
685 0 : mGamepadPromiseList.Put(aID, aPromise);
686 0 : }
687 :
688 : mozilla::ipc::IPCResult
689 0 : VRManagerChild::RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
690 : {
691 : // VRManagerChild could be at other processes, but GamepadManager
692 : // only exists at the content process or the same process
693 : // in non-e10s mode.
694 0 : MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
695 :
696 0 : RefPtr<dom::Promise> p;
697 0 : if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) {
698 0 : MOZ_CRASH("We should always have a promise.");
699 : }
700 :
701 0 : p->MaybeResolve(true);
702 0 : mGamepadPromiseList.Remove(aPromiseID);
703 0 : return IPC_OK();
704 : }
705 :
706 : mozilla::ipc::IPCResult
707 0 : VRManagerChild::RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID,
708 : const VRSubmitFrameResultInfo& aResult)
709 : {
710 0 : for (auto& display : mDisplays) {
711 0 : if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
712 0 : display->UpdateSubmitFrameResult(aResult);
713 : }
714 : }
715 :
716 0 : return IPC_OK();
717 : }
718 :
719 : } // namespace gfx
720 : } // namespace mozilla
|