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