File: | var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp |
Warning: | line 178, column 9 Value stored to 'found' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
9 | #include "VRLayerChild.h" |
10 | #include "VRManagerParent.h" |
11 | #include "VRThread.h" |
12 | #include "VRDisplayClient.h" |
13 | #include "nsGlobalWindowInner.h" |
14 | #include "mozilla/ProfilerMarkers.h" |
15 | #include "mozilla/StaticPtr.h" |
16 | #include "mozilla/layers/CompositorThread.h" // for CompositorThread |
17 | #include "mozilla/dom/Navigator.h" |
18 | #include "mozilla/dom/VREventObserver.h" |
19 | #include "mozilla/dom/WebXRBinding.h" |
20 | #include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback |
21 | #include "mozilla/dom/XRSystem.h" |
22 | #include "mozilla/dom/XRFrame.h" |
23 | #include "mozilla/dom/ContentChild.h" |
24 | #include "nsContentUtils.h" |
25 | #include "mozilla/dom/GamepadManager.h" |
26 | #include "mozilla/ipc/Endpoint.h" |
27 | #include "mozilla/layers/SyncObject.h" |
28 | #include "mozilla/layers/TextureForwarder.h" |
29 | |
30 | using namespace mozilla::dom; |
31 | |
32 | namespace { |
33 | const nsTArray<RefPtr<mozilla::gfx::VRManagerEventObserver>>::index_type |
34 | kNoIndex = nsTArray<RefPtr<mozilla::gfx::VRManagerEventObserver>>::NoIndex; |
35 | } // namespace |
36 | |
37 | namespace mozilla { |
38 | namespace gfx { |
39 | |
40 | static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton; |
41 | static StaticRefPtr<VRManagerParent> sVRManagerParentSingleton; |
42 | |
43 | static TimeStamp sMostRecentFrameEnd; |
44 | static TimeDuration sAverageFrameInterval; |
45 | |
46 | void ReleaseVRManagerParentSingleton() { sVRManagerParentSingleton = nullptr; } |
47 | |
48 | VRManagerChild::VRManagerChild() |
49 | : mRuntimeCapabilities(VRDisplayCapabilityFlags::Cap_None), |
50 | mFrameRequestCallbackCounter(0), |
51 | mWaitingForEnumeration(false), |
52 | mBackend(layers::LayersBackend::LAYERS_NONE) { |
53 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 53); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 53; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
54 | |
55 | mStartTimeStamp = TimeStamp::Now(); |
56 | } |
57 | |
58 | VRManagerChild::~VRManagerChild() { MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 58); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 58; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } |
59 | |
60 | /*static*/ |
61 | void VRManagerChild::IdentifyTextureHost( |
62 | const TextureFactoryIdentifier& aIdentifier) { |
63 | if (sVRManagerChildSingleton) { |
64 | sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend; |
65 | } |
66 | } |
67 | |
68 | layers::LayersBackend VRManagerChild::GetBackendType() const { |
69 | return mBackend; |
70 | } |
71 | |
72 | /*static*/ |
73 | VRManagerChild* VRManagerChild::Get() { |
74 | MOZ_ASSERT(sVRManagerChildSingleton)do { static_assert( mozilla::detail::AssertionConditionType< decltype(sVRManagerChildSingleton)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(sVRManagerChildSingleton))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("sVRManagerChildSingleton" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 74); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sVRManagerChildSingleton" ")"); do { *((volatile int*)__null) = 74; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
75 | return sVRManagerChildSingleton; |
76 | } |
77 | |
78 | /* static */ |
79 | bool VRManagerChild::IsCreated() { return !!sVRManagerChildSingleton; } |
80 | |
81 | /* static */ |
82 | bool VRManagerChild::IsPresenting() { |
83 | if (!VRManagerChild::IsCreated()) { |
84 | return false; |
85 | } |
86 | |
87 | nsTArray<RefPtr<VRDisplayClient>> displays; |
88 | sVRManagerChildSingleton->GetVRDisplays(displays); |
89 | |
90 | bool result = false; |
91 | for (auto& display : displays) { |
92 | result |= display->IsPresenting(); |
93 | } |
94 | return result; |
95 | } |
96 | |
97 | TimeStamp VRManagerChild::GetIdleDeadlineHint(TimeStamp aDefault) { |
98 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 98); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 98; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
99 | if (!VRManagerChild::IsCreated() || sMostRecentFrameEnd.IsNull()) { |
100 | return aDefault; |
101 | } |
102 | |
103 | TimeStamp idleEnd = sMostRecentFrameEnd + sAverageFrameInterval; |
104 | return idleEnd < aDefault ? idleEnd : aDefault; |
105 | } |
106 | |
107 | /* static */ |
108 | bool VRManagerChild::InitForContent(Endpoint<PVRManagerChild>&& aEndpoint) { |
109 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 109; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
110 | |
111 | RefPtr<VRManagerChild> child(new VRManagerChild()); |
112 | if (!aEndpoint.Bind(child)) { |
113 | return false; |
114 | } |
115 | sVRManagerChildSingleton = child; |
116 | return true; |
117 | } |
118 | |
119 | /*static*/ |
120 | void VRManagerChild::InitSameProcess() { |
121 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 121; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
122 | MOZ_ASSERT(!sVRManagerChildSingleton)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sVRManagerChildSingleton)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sVRManagerChildSingleton))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sVRManagerChildSingleton" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sVRManagerChildSingleton" ")"); do { *((volatile int*)__null) = 122; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
123 | |
124 | sVRManagerChildSingleton = new VRManagerChild(); |
125 | sVRManagerParentSingleton = VRManagerParent::CreateSameProcess(); |
126 | sVRManagerChildSingleton->Open(sVRManagerParentSingleton, CompositorThread(), |
127 | mozilla::ipc::ChildSide); |
128 | } |
129 | |
130 | /* static */ |
131 | void VRManagerChild::InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint) { |
132 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 132; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
133 | MOZ_ASSERT(!sVRManagerChildSingleton)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!sVRManagerChildSingleton)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!sVRManagerChildSingleton))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sVRManagerChildSingleton" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sVRManagerChildSingleton" ")"); do { *((volatile int*)__null) = 133; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
134 | |
135 | sVRManagerChildSingleton = new VRManagerChild(); |
136 | if (!aEndpoint.Bind(sVRManagerChildSingleton)) { |
137 | MOZ_CRASH("Couldn't Open() Compositor channel.")do { do { } while (false); MOZ_ReportCrash("" "Couldn't Open() Compositor channel." , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 137); AnnotateMozCrashReason("MOZ_CRASH(" "Couldn't Open() Compositor channel." ")"); do { *((volatile int*)__null) = 137; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
138 | } |
139 | } |
140 | |
141 | /*static*/ |
142 | void VRManagerChild::ShutDown() { |
143 | MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType< decltype(NS_IsMainThread())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { *((volatile int*)__null) = 143; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
144 | if (!sVRManagerChildSingleton) { |
145 | return; |
146 | } |
147 | sVRManagerChildSingleton->Close(); |
148 | sVRManagerChildSingleton = nullptr; |
149 | } |
150 | |
151 | void VRManagerChild::ActorDestroy(ActorDestroyReason aReason) { |
152 | if (sVRManagerChildSingleton == this) { |
153 | sVRManagerChildSingleton = nullptr; |
154 | } |
155 | } |
156 | |
157 | PVRLayerChild* VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID, |
158 | const uint32_t& aGroup) { |
159 | return VRLayerChild::CreateIPDLActor(); |
160 | } |
161 | |
162 | bool VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor) { |
163 | return VRLayerChild::DestroyIPDLActor(actor); |
164 | } |
165 | |
166 | void VRManagerChild::UpdateDisplayInfo(const VRDisplayInfo& aDisplayInfo) { |
167 | nsTArray<uint32_t> disconnectedDisplays; |
168 | nsTArray<uint32_t> connectedDisplays; |
169 | |
170 | const nsTArray<RefPtr<VRDisplayClient>> prevDisplays(mDisplays.Clone()); |
171 | |
172 | // Check if any displays have been disconnected |
173 | for (auto& display : prevDisplays) { |
174 | bool found = false; |
175 | if (aDisplayInfo.GetDisplayID() != 0) { |
176 | if (display->GetDisplayInfo().GetDisplayID() == |
177 | aDisplayInfo.GetDisplayID()) { |
178 | found = true; |
Value stored to 'found' is never read | |
179 | break; |
180 | } |
181 | } |
182 | if (!found) { |
183 | // In order to make the current VRDisplay can continue to apply for the |
184 | // newest VRDisplayInfo, we need to exit presentionation before |
185 | // disconnecting. |
186 | if (display->IsPresentationGenerationCurrent()) { |
187 | NotifyPresentationGenerationChangedInternal( |
188 | display->GetDisplayInfo().GetDisplayID()); |
189 | |
190 | RefPtr<VRManagerChild> vm = VRManagerChild::Get(); |
191 | vm->FireDOMVRDisplayPresentChangeEvent( |
192 | display->GetDisplayInfo().GetDisplayID()); |
193 | } |
194 | display->NotifyDisconnected(); |
195 | disconnectedDisplays.AppendElement( |
196 | display->GetDisplayInfo().GetDisplayID()); |
197 | } |
198 | } |
199 | |
200 | // mDisplays could be a hashed container for more scalability, but not worth |
201 | // it now as we expect < 10 entries. |
202 | nsTArray<RefPtr<VRDisplayClient>> displays; |
203 | if (aDisplayInfo.GetDisplayID() != 0) { |
204 | bool isNewDisplay = true; |
205 | for (auto& display : prevDisplays) { |
206 | const VRDisplayInfo& prevInfo = display->GetDisplayInfo(); |
207 | if (prevInfo.GetDisplayID() == aDisplayInfo.GetDisplayID()) { |
208 | if (aDisplayInfo.GetIsConnected() && !prevInfo.GetIsConnected()) { |
209 | connectedDisplays.AppendElement(aDisplayInfo.GetDisplayID()); |
210 | } |
211 | if (!aDisplayInfo.GetIsConnected() && prevInfo.GetIsConnected()) { |
212 | disconnectedDisplays.AppendElement(aDisplayInfo.GetDisplayID()); |
213 | } |
214 | // MOZ_KnownLive because 'prevDisplays' is guaranteed to keep it alive. |
215 | // |
216 | // This can go away once |
217 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed. |
218 | MOZ_KnownLive(display)(display)->UpdateDisplayInfo(aDisplayInfo); |
219 | displays.AppendElement(display); |
220 | isNewDisplay = false; |
221 | break; |
222 | } |
223 | } |
224 | if (isNewDisplay) { |
225 | displays.AppendElement(new VRDisplayClient(aDisplayInfo)); |
226 | connectedDisplays.AppendElement(aDisplayInfo.GetDisplayID()); |
227 | } |
228 | } |
229 | |
230 | mDisplays = std::move(displays); |
231 | |
232 | // We wish to fire the events only after mDisplays is updated |
233 | for (uint32_t displayID : disconnectedDisplays) { |
234 | FireDOMVRDisplayDisconnectEvent(displayID); |
235 | } |
236 | |
237 | for (uint32_t displayID : connectedDisplays) { |
238 | FireDOMVRDisplayConnectEvent(displayID); |
239 | } |
240 | } |
241 | |
242 | bool VRManagerChild::RuntimeSupportsVR() const { |
243 | return bool(mRuntimeCapabilities & VRDisplayCapabilityFlags::Cap_ImmersiveVR); |
244 | } |
245 | bool VRManagerChild::RuntimeSupportsAR() const { |
246 | return bool(mRuntimeCapabilities & VRDisplayCapabilityFlags::Cap_ImmersiveAR); |
247 | } |
248 | bool VRManagerChild::RuntimeSupportsInline() const { |
249 | return bool(mRuntimeCapabilities & VRDisplayCapabilityFlags::Cap_Inline); |
250 | } |
251 | |
252 | mozilla::ipc::IPCResult VRManagerChild::RecvUpdateRuntimeCapabilities( |
253 | const VRDisplayCapabilityFlags& aCapabilities) { |
254 | mRuntimeCapabilities = aCapabilities; |
255 | nsContentUtils::AddScriptRunner(NewRunnableMethod<>( |
256 | "gfx::VRManagerChild::NotifyRuntimeCapabilitiesUpdatedInternal", this, |
257 | &VRManagerChild::NotifyRuntimeCapabilitiesUpdatedInternal)); |
258 | return IPC_OK()mozilla::ipc::IPCResult::Ok(); |
259 | } |
260 | |
261 | void VRManagerChild::NotifyRuntimeCapabilitiesUpdatedInternal() { |
262 | const nsTArray<RefPtr<VRManagerEventObserver>> listeners = mListeners.Clone(); |
263 | for (auto& listener : listeners) { |
264 | listener->NotifyDetectRuntimesCompleted(); |
265 | } |
266 | } |
267 | |
268 | mozilla::ipc::IPCResult VRManagerChild::RecvUpdateDisplayInfo( |
269 | const VRDisplayInfo& aDisplayInfo) { |
270 | UpdateDisplayInfo(aDisplayInfo); |
271 | 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 | nsGlobalWindowInner* window = |
279 | nsGlobalWindowInner::GetInnerWindowWithId(windowId); |
280 | if (!window) { |
281 | continue; |
282 | } |
283 | dom::Navigator* nav = window->Navigator(); |
284 | if (!nav) { |
285 | continue; |
286 | } |
287 | nav->NotifyVRDisplaysUpdated(); |
288 | } |
289 | mNavigatorCallbacks.Clear(); |
290 | if (mWaitingForEnumeration) { |
291 | nsContentUtils::AddScriptRunner(NewRunnableMethod<>( |
292 | "gfx::VRManagerChild::NotifyEnumerationCompletedInternal", this, |
293 | &VRManagerChild::NotifyEnumerationCompletedInternal)); |
294 | mWaitingForEnumeration = false; |
295 | } |
296 | return IPC_OK()mozilla::ipc::IPCResult::Ok(); |
297 | } |
298 | |
299 | mozilla::ipc::IPCResult VRManagerChild::RecvNotifyPuppetCommandBufferCompleted( |
300 | bool aSuccess) { |
301 | RefPtr<dom::Promise> promise = mRunPuppetPromise; |
302 | mRunPuppetPromise = nullptr; |
303 | if (aSuccess) { |
304 | promise->MaybeResolve(JS::UndefinedHandleValue); |
305 | } else { |
306 | promise->MaybeRejectWithUndefined(); |
307 | } |
308 | return IPC_OK()mozilla::ipc::IPCResult::Ok(); |
309 | } |
310 | |
311 | mozilla::ipc::IPCResult VRManagerChild::RecvNotifyPuppetResetComplete() { |
312 | nsTArray<RefPtr<dom::Promise>> promises; |
313 | promises.AppendElements(mResetPuppetPromises); |
314 | mResetPuppetPromises.Clear(); |
315 | for (const auto& promise : promises) { |
316 | promise->MaybeResolve(JS::UndefinedHandleValue); |
317 | } |
318 | return IPC_OK()mozilla::ipc::IPCResult::Ok(); |
319 | } |
320 | |
321 | void VRManagerChild::RunPuppet(const nsTArray<uint64_t>& aBuffer, |
322 | dom::Promise* aPromise, ErrorResult& aRv) { |
323 | if (mRunPuppetPromise) { |
324 | // We only allow one puppet script to run simultaneously. |
325 | // The prior promise must be resolved before running a new |
326 | // script. |
327 | aRv.Throw(NS_ERROR_INVALID_ARG); |
328 | return; |
329 | } |
330 | if (!SendRunPuppet(aBuffer)) { |
331 | aRv.Throw(NS_ERROR_FAILURE); |
332 | return; |
333 | } |
334 | mRunPuppetPromise = aPromise; |
335 | } |
336 | |
337 | void VRManagerChild::ResetPuppet(dom::Promise* aPromise, ErrorResult& aRv) { |
338 | if (!SendResetPuppet()) { |
339 | aRv.Throw(NS_ERROR_FAILURE); |
340 | return; |
341 | } |
342 | mResetPuppetPromises.AppendElement(aPromise); |
343 | } |
344 | |
345 | void VRManagerChild::GetVRDisplays( |
346 | nsTArray<RefPtr<VRDisplayClient>>& aDisplays) { |
347 | aDisplays = mDisplays.Clone(); |
348 | } |
349 | |
350 | bool VRManagerChild::RefreshVRDisplaysWithCallback(uint64_t aWindowId) { |
351 | bool success = SendRefreshDisplays(); |
352 | if (success) { |
353 | mNavigatorCallbacks.AppendElement(aWindowId); |
354 | } |
355 | return success; |
356 | } |
357 | |
358 | bool VRManagerChild::EnumerateVRDisplays() { |
359 | bool success = SendRefreshDisplays(); |
360 | if (success) { |
361 | mWaitingForEnumeration = true; |
362 | } |
363 | return success; |
364 | } |
365 | |
366 | void VRManagerChild::DetectRuntimes() { Unused << SendDetectRuntimes(); } |
367 | |
368 | PVRLayerChild* VRManagerChild::CreateVRLayer(uint32_t aDisplayID, |
369 | uint32_t aGroup) { |
370 | PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aGroup); |
371 | return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aGroup); |
372 | } |
373 | |
374 | void VRManagerChild::XRFrameRequest::Call( |
375 | const DOMHighResTimeStamp& aTimeStamp) { |
376 | if (mCallback) { |
377 | RefPtr<mozilla::dom::FrameRequestCallback> callback = mCallback; |
378 | callback->Call(aTimeStamp); |
379 | } else { |
380 | RefPtr<mozilla::dom::XRFrameRequestCallback> callback = mXRCallback; |
381 | RefPtr<mozilla::dom::XRFrame> frame = mXRFrame; |
382 | callback->Call(aTimeStamp, *frame); |
383 | } |
384 | } |
385 | |
386 | nsresult VRManagerChild::ScheduleFrameRequestCallback( |
387 | mozilla::dom::FrameRequestCallback& aCallback, int32_t* aHandle) { |
388 | if (mFrameRequestCallbackCounter == INT32_MAX(2147483647)) { |
389 | // Can't increment without overflowing; bail out |
390 | return NS_ERROR_NOT_AVAILABLE; |
391 | } |
392 | int32_t newHandle = ++mFrameRequestCallbackCounter; |
393 | |
394 | mFrameRequestCallbacks.AppendElement(XRFrameRequest(aCallback, newHandle)); |
395 | |
396 | *aHandle = newHandle; |
397 | return NS_OK; |
398 | } |
399 | |
400 | void VRManagerChild::CancelFrameRequestCallback(int32_t aHandle) { |
401 | // mFrameRequestCallbacks is stored sorted by handle |
402 | mFrameRequestCallbacks.RemoveElementSorted(aHandle); |
403 | } |
404 | |
405 | void VRManagerChild::RunFrameRequestCallbacks() { |
406 | AUTO_PROFILER_TRACING_MARKER("VR", "RunFrameRequestCallbacks", GRAPHICS)AutoProfilerTracing raiiObject406("VR", "RunFrameRequestCallbacks" , geckoprofiler::category::GRAPHICS, mozilla::Nothing()); |
407 | |
408 | TimeStamp nowTime = TimeStamp::Now(); |
409 | mozilla::TimeDuration duration = nowTime - mStartTimeStamp; |
410 | DOMHighResTimeStamp timeStamp = duration.ToMilliseconds(); |
411 | |
412 | if (!sMostRecentFrameEnd.IsNull()) { |
413 | TimeDuration frameInterval = nowTime - sMostRecentFrameEnd; |
414 | if (sAverageFrameInterval.IsZero()) { |
415 | sAverageFrameInterval = frameInterval; |
416 | } else { |
417 | // Calculate the average interval between frame end and next frame start. |
418 | // Apply some smoothing to make it more stable. |
419 | const double smooth = 0.9; |
420 | sAverageFrameInterval = sAverageFrameInterval.MultDouble(smooth) + |
421 | frameInterval.MultDouble(1.0 - smooth); |
422 | } |
423 | } |
424 | |
425 | nsTArray<XRFrameRequest> callbacks; |
426 | callbacks.AppendElements(mFrameRequestCallbacks); |
427 | mFrameRequestCallbacks.Clear(); |
428 | for (auto& callback : callbacks) { |
429 | // The FrameRequest copied into the on-stack array holds a strong ref to its |
430 | // mCallback and there's nothing that can drop that ref until we return. |
431 | MOZ_KnownLive(callback.mCallback)(callback.mCallback)->Call(timeStamp); |
432 | } |
433 | |
434 | if (IsPresenting()) { |
435 | sMostRecentFrameEnd = TimeStamp::Now(); |
436 | } |
437 | } |
438 | |
439 | void VRManagerChild::NotifyPresentationGenerationChanged(uint32_t aDisplayID) { |
440 | nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>( |
441 | "gfx::VRManagerChild::NotifyPresentationGenerationChangedInternal", this, |
442 | &VRManagerChild::NotifyPresentationGenerationChangedInternal, |
443 | aDisplayID)); |
444 | } |
445 | |
446 | void VRManagerChild::FireDOMVRDisplayMountedEvent(uint32_t aDisplayID) { |
447 | nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>( |
448 | "gfx::VRManagerChild::FireDOMVRDisplayMountedEventInternal", this, |
449 | &VRManagerChild::FireDOMVRDisplayMountedEventInternal, aDisplayID)); |
450 | } |
451 | |
452 | void VRManagerChild::FireDOMVRDisplayUnmountedEvent(uint32_t aDisplayID) { |
453 | nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>( |
454 | "gfx::VRManagerChild::FireDOMVRDisplayUnmountedEventInternal", this, |
455 | &VRManagerChild::FireDOMVRDisplayUnmountedEventInternal, aDisplayID)); |
456 | } |
457 | |
458 | void VRManagerChild::FireDOMVRDisplayConnectEvent(uint32_t aDisplayID) { |
459 | nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>( |
460 | "gfx::VRManagerChild::FireDOMVRDisplayConnectEventInternal", this, |
461 | &VRManagerChild::FireDOMVRDisplayConnectEventInternal, aDisplayID)); |
462 | } |
463 | |
464 | void VRManagerChild::FireDOMVRDisplayDisconnectEvent(uint32_t aDisplayID) { |
465 | nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>( |
466 | "gfx::VRManagerChild::FireDOMVRDisplayDisconnectEventInternal", this, |
467 | &VRManagerChild::FireDOMVRDisplayDisconnectEventInternal, aDisplayID)); |
468 | } |
469 | |
470 | void VRManagerChild::FireDOMVRDisplayPresentChangeEvent(uint32_t aDisplayID) { |
471 | nsContentUtils::AddScriptRunner(NewRunnableMethod<uint32_t>( |
472 | "gfx::VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal", this, |
473 | &VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal, aDisplayID)); |
474 | |
475 | if (!IsPresenting()) { |
476 | sMostRecentFrameEnd = TimeStamp(); |
477 | sAverageFrameInterval = 0; |
478 | } |
479 | } |
480 | |
481 | void VRManagerChild::FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID) { |
482 | // Iterate over a copy of mListeners, as dispatched events may modify it. |
483 | for (auto& listener : mListeners.Clone()) { |
484 | listener->NotifyVRDisplayMounted(aDisplayID); |
485 | } |
486 | } |
487 | |
488 | void VRManagerChild::FireDOMVRDisplayUnmountedEventInternal( |
489 | uint32_t aDisplayID) { |
490 | // Iterate over a copy of mListeners, as dispatched events may modify it. |
491 | for (auto& listener : mListeners.Clone()) { |
492 | listener->NotifyVRDisplayUnmounted(aDisplayID); |
493 | } |
494 | } |
495 | |
496 | void VRManagerChild::FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID) { |
497 | // Iterate over a copy of mListeners, as dispatched events may modify it. |
498 | for (auto& listener : mListeners.Clone()) { |
499 | listener->NotifyVRDisplayConnect(aDisplayID); |
500 | } |
501 | } |
502 | |
503 | void VRManagerChild::FireDOMVRDisplayDisconnectEventInternal( |
504 | uint32_t aDisplayID) { |
505 | // Iterate over a copy of mListeners, as dispatched events may modify it. |
506 | for (auto& listener : mListeners.Clone()) { |
507 | listener->NotifyVRDisplayDisconnect(aDisplayID); |
508 | } |
509 | } |
510 | |
511 | void VRManagerChild::FireDOMVRDisplayPresentChangeEventInternal( |
512 | uint32_t aDisplayID) { |
513 | // Iterate over a copy of mListeners, as dispatched events may modify it. |
514 | for (auto& listener : mListeners.Clone()) { |
515 | // MOZ_KnownLive because 'listeners' is guaranteed to keep it alive. |
516 | // |
517 | // This can go away once |
518 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1620312 is fixed. |
519 | MOZ_KnownLive(listener)(listener)->NotifyVRDisplayPresentChange(aDisplayID); |
520 | } |
521 | } |
522 | |
523 | void VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal( |
524 | uint32_t aDisplayID, VRManagerEventObserver* aObserver) { |
525 | aObserver->NotifyVRDisplayConnect(aDisplayID); |
526 | } |
527 | |
528 | void VRManagerChild::NotifyPresentationGenerationChangedInternal( |
529 | uint32_t aDisplayID) { |
530 | for (auto& listener : mListeners.Clone()) { |
531 | listener->NotifyPresentationGenerationChanged(aDisplayID); |
532 | } |
533 | } |
534 | |
535 | void VRManagerChild::NotifyEnumerationCompletedInternal() { |
536 | for (auto& listener : mListeners.Clone()) { |
537 | listener->NotifyEnumerationCompleted(); |
538 | } |
539 | } |
540 | |
541 | void VRManagerChild::FireDOMVRDisplayConnectEventsForLoad( |
542 | VRManagerEventObserver* aObserver) { |
543 | // We need to fire the VRDisplayConnect event when a page is loaded |
544 | // for each VR Display that has already been enumerated |
545 | for (const auto& display : mDisplays.Clone()) { |
546 | const VRDisplayInfo& info = display->GetDisplayInfo(); |
547 | if (info.GetIsConnected()) { |
548 | nsContentUtils::AddScriptRunner(NewRunnableMethod< |
549 | uint32_t, RefPtr<VRManagerEventObserver>>( |
550 | "gfx::VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal", |
551 | this, &VRManagerChild::FireDOMVRDisplayConnectEventsForLoadInternal, |
552 | info.GetDisplayID(), aObserver)); |
553 | } |
554 | } |
555 | } |
556 | |
557 | void VRManagerChild::AddListener(VRManagerEventObserver* aObserver) { |
558 | MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aObserver)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")" ); do { *((volatile int*)__null) = 558; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
559 | |
560 | if (mListeners.IndexOf(aObserver) != kNoIndex) { |
561 | return; // already exists |
562 | } |
563 | |
564 | mListeners.AppendElement(aObserver); |
565 | if (mListeners.Length() == 1) { |
566 | Unused << SendSetHaveEventListener(true); |
567 | } |
568 | } |
569 | |
570 | void VRManagerChild::RemoveListener(VRManagerEventObserver* aObserver) { |
571 | MOZ_ASSERT(aObserver)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aObserver)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aObserver))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aObserver", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aObserver" ")" ); do { *((volatile int*)__null) = 571; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
572 | |
573 | mListeners.RemoveElement(aObserver); |
574 | if (mListeners.IsEmpty()) { |
575 | Unused << SendSetHaveEventListener(false); |
576 | } |
577 | } |
578 | |
579 | void VRManagerChild::StartActivity() { Unused << SendStartActivity(); } |
580 | |
581 | void VRManagerChild::StopActivity() { |
582 | for (auto& listener : mListeners) { |
583 | if (!listener->GetStopActivityStatus()) { |
584 | // We are still showing VR in the active window. |
585 | return; |
586 | } |
587 | } |
588 | |
589 | Unused << SendStopActivity(); |
590 | } |
591 | |
592 | void VRManagerChild::HandleFatalError(const char* aMsg) { |
593 | dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherChildID()); |
594 | } |
595 | |
596 | void VRManagerChild::AddPromise(const uint32_t& aID, dom::Promise* aPromise) { |
597 | MOZ_ASSERT(!mGamepadPromiseList.Contains(aID))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mGamepadPromiseList.Contains(aID))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mGamepadPromiseList.Contains (aID)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!mGamepadPromiseList.Contains(aID)", "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mGamepadPromiseList.Contains(aID)" ")"); do { *((volatile int*)__null) = 597; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
598 | mGamepadPromiseList.InsertOrUpdate(aID, RefPtr{aPromise}); |
599 | } |
600 | |
601 | gfx::VRAPIMode VRManagerChild::GetVRAPIMode(uint32_t aDisplayID) const { |
602 | for (auto& display : mDisplays) { |
603 | if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) { |
604 | return display->GetXRAPIMode(); |
605 | } |
606 | } |
607 | return VRAPIMode::WebXR; |
608 | } |
609 | |
610 | mozilla::ipc::IPCResult VRManagerChild::RecvReplyGamepadVibrateHaptic( |
611 | const uint32_t& aPromiseID) { |
612 | // VRManagerChild could be at other processes, but GamepadManager |
613 | // only exists at the content process or the same process |
614 | // in non-e10s mode. |
615 | MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess())do { static_assert( mozilla::detail::AssertionConditionType< decltype(XRE_IsContentProcess() || IsSameProcess())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(XRE_IsContentProcess() || IsSameProcess()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess() || IsSameProcess()" , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsContentProcess() || IsSameProcess()" ")"); do { *((volatile int*)__null) = 615; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
616 | |
617 | RefPtr<dom::Promise> p; |
618 | if (!mGamepadPromiseList.Get(aPromiseID, getter_AddRefs(p))) { |
619 | MOZ_CRASH("We should always have a promise.")do { do { } while (false); MOZ_ReportCrash("" "We should always have a promise." , "/var/lib/jenkins/workspace/firefox-scan-build/gfx/vr/ipc/VRManagerChild.cpp" , 619); AnnotateMozCrashReason("MOZ_CRASH(" "We should always have a promise." ")"); do { *((volatile int*)__null) = 619; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
620 | } |
621 | |
622 | p->MaybeResolve(true); |
623 | mGamepadPromiseList.Remove(aPromiseID); |
624 | return IPC_OK()mozilla::ipc::IPCResult::Ok(); |
625 | } |
626 | |
627 | } // namespace gfx |
628 | } // namespace mozilla |