Bug 1856663 - Add more chunks for Android mochitest-plain. r=jmaher,taskgraph-reviewe...
[gecko.git] / gfx / ipc / GPUChild.cpp
blobafc9f61ee4dfd7dd8a00a85ec698794c33a20ae5
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 #include "GPUChild.h"
8 #include "GPUProcessHost.h"
9 #include "GPUProcessManager.h"
10 #include "GfxInfoBase.h"
11 #include "VRProcessManager.h"
12 #include "gfxConfig.h"
13 #include "gfxPlatform.h"
14 #include "mozilla/Components.h"
15 #include "mozilla/FOGIPC.h"
16 #include "mozilla/StaticPrefs_dom.h"
17 #include "mozilla/Telemetry.h"
18 #include "mozilla/TelemetryIPC.h"
19 #include "mozilla/dom/CheckerboardReportService.h"
20 #include "mozilla/dom/ContentParent.h"
21 #include "mozilla/dom/MemoryReportRequest.h"
22 #include "mozilla/gfx/Logging.h"
23 #include "mozilla/gfx/gfxVars.h"
24 #if defined(XP_WIN)
25 # include "mozilla/gfx/DeviceManagerDx.h"
26 #endif
27 #include "mozilla/HangDetails.h"
28 #include "mozilla/RemoteDecoderManagerChild.h" // For RemoteDecodeIn
29 #include "mozilla/Unused.h"
30 #include "mozilla/ipc/Endpoint.h"
31 #include "mozilla/layers/APZInputBridgeChild.h"
32 #include "mozilla/layers/LayerTreeOwnerTracker.h"
33 #include "nsHashPropertyBag.h"
34 #include "nsIGfxInfo.h"
35 #include "nsIObserverService.h"
36 #include "nsIPropertyBag2.h"
37 #include "ProfilerParent.h"
39 namespace mozilla {
40 namespace gfx {
42 using namespace layers;
44 GPUChild::GPUChild(GPUProcessHost* aHost) : mHost(aHost), mGPUReady(false) {}
46 GPUChild::~GPUChild() = default;
48 void GPUChild::Init() {
49 nsTArray<GfxVarUpdate> updates = gfxVars::FetchNonDefaultVars();
51 DevicePrefs devicePrefs;
52 devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
53 devicePrefs.d3d11Compositing() =
54 gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
55 devicePrefs.oglCompositing() =
56 gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
57 devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
58 devicePrefs.d3d11HwAngle() = gfxConfig::GetValue(Feature::D3D11_HW_ANGLE);
60 nsTArray<LayerTreeIdMapping> mappings;
61 LayerTreeOwnerTracker::Get()->Iterate(
62 [&](LayersId aLayersId, base::ProcessId aProcessId) {
63 mappings.AppendElement(LayerTreeIdMapping(aLayersId, aProcessId));
64 });
66 nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
67 nsTArray<GfxInfoFeatureStatus> features;
68 if (gfxInfo) {
69 auto* gfxInfoRaw = static_cast<widget::GfxInfoBase*>(gfxInfo.get());
70 features = gfxInfoRaw->GetAllFeatures();
73 SendInit(updates, devicePrefs, mappings, features,
74 GPUProcessManager::Get()->AllocateNamespace());
76 gfxVars::AddReceiver(this);
78 Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
81 void GPUChild::OnVarChanged(const GfxVarUpdate& aVar) { SendUpdateVar(aVar); }
83 bool GPUChild::EnsureGPUReady() {
84 // On our initial process launch, we want to block on the GetDeviceStatus
85 // message. Additionally, we may have updated our compositor configuration
86 // through the gfxVars after fallback, in which case we want to ensure the
87 // GPU process has handled any updates before creating compositor sessions.
88 if (mGPUReady && !mWaitForVarUpdate) {
89 return true;
92 GPUDeviceData data;
93 if (!SendGetDeviceStatus(&data)) {
94 return false;
97 // Only import and collect telemetry for the initial GPU process launch.
98 if (!mGPUReady) {
99 gfxPlatform::GetPlatform()->ImportGPUDeviceData(data);
100 Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2,
101 mHost->GetLaunchTime());
102 mGPUReady = true;
105 mWaitForVarUpdate = false;
106 return true;
109 void GPUChild::OnUnexpectedShutdown() { mUnexpectedShutdown = true; }
111 mozilla::ipc::IPCResult GPUChild::RecvInitComplete(const GPUDeviceData& aData) {
112 // We synchronously requested GPU parameters before this arrived.
113 if (mGPUReady) {
114 return IPC_OK();
117 gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
118 Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2,
119 mHost->GetLaunchTime());
120 mGPUReady = true;
121 return IPC_OK();
124 mozilla::ipc::IPCResult GPUChild::RecvDeclareStable() {
125 mHost->mListener->OnProcessDeclaredStable();
126 return IPC_OK();
129 mozilla::ipc::IPCResult GPUChild::RecvReportCheckerboard(
130 const uint32_t& aSeverity, const nsCString& aLog) {
131 layers::CheckerboardEventStorage::Report(aSeverity, std::string(aLog.get()));
132 return IPC_OK();
135 mozilla::ipc::IPCResult GPUChild::RecvGraphicsError(const nsCString& aError) {
136 gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
137 if (lf) {
138 std::stringstream message;
139 message << "GP+" << aError.get();
140 lf->UpdateStringsVector(message.str());
142 return IPC_OK();
145 mozilla::ipc::IPCResult GPUChild::RecvCreateVRProcess() {
146 // Make sure create VR process at the main process
147 MOZ_ASSERT(XRE_IsParentProcess());
148 if (StaticPrefs::dom_vr_process_enabled_AtStartup()) {
149 VRProcessManager::Initialize();
150 VRProcessManager* vr = VRProcessManager::Get();
151 MOZ_ASSERT(vr, "VRProcessManager must be initialized first.");
153 if (vr) {
154 vr->LaunchVRProcess();
158 return IPC_OK();
161 mozilla::ipc::IPCResult GPUChild::RecvShutdownVRProcess() {
162 // Make sure stopping VR process at the main process
163 MOZ_ASSERT(XRE_IsParentProcess());
164 if (StaticPrefs::dom_vr_process_enabled_AtStartup()) {
165 VRProcessManager::Shutdown();
168 return IPC_OK();
171 mozilla::ipc::IPCResult GPUChild::RecvNotifyUiObservers(
172 const nsCString& aTopic) {
173 nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
174 MOZ_ASSERT(obsSvc);
175 if (obsSvc) {
176 obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
178 return IPC_OK();
181 mozilla::ipc::IPCResult GPUChild::RecvAccumulateChildHistograms(
182 nsTArray<HistogramAccumulation>&& aAccumulations) {
183 TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Gpu,
184 aAccumulations);
185 return IPC_OK();
188 mozilla::ipc::IPCResult GPUChild::RecvAccumulateChildKeyedHistograms(
189 nsTArray<KeyedHistogramAccumulation>&& aAccumulations) {
190 TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Gpu,
191 aAccumulations);
192 return IPC_OK();
195 mozilla::ipc::IPCResult GPUChild::RecvUpdateChildScalars(
196 nsTArray<ScalarAction>&& aScalarActions) {
197 TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Gpu, aScalarActions);
198 return IPC_OK();
201 mozilla::ipc::IPCResult GPUChild::RecvUpdateChildKeyedScalars(
202 nsTArray<KeyedScalarAction>&& aScalarActions) {
203 TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Gpu,
204 aScalarActions);
205 return IPC_OK();
208 mozilla::ipc::IPCResult GPUChild::RecvRecordChildEvents(
209 nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents) {
210 TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
211 return IPC_OK();
214 mozilla::ipc::IPCResult GPUChild::RecvRecordDiscardedData(
215 const mozilla::Telemetry::DiscardedData& aDiscardedData) {
216 TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Gpu, aDiscardedData);
217 return IPC_OK();
220 mozilla::ipc::IPCResult GPUChild::RecvNotifyDeviceReset(
221 const GPUDeviceData& aData) {
222 gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
223 mHost->mListener->OnRemoteProcessDeviceReset(mHost);
224 return IPC_OK();
227 mozilla::ipc::IPCResult GPUChild::RecvNotifyOverlayInfo(
228 const OverlayInfo aInfo) {
229 gfxPlatform::GetPlatform()->SetOverlayInfo(aInfo);
230 return IPC_OK();
233 mozilla::ipc::IPCResult GPUChild::RecvNotifySwapChainInfo(
234 const SwapChainInfo aInfo) {
235 gfxPlatform::GetPlatform()->SetSwapChainInfo(aInfo);
236 return IPC_OK();
239 mozilla::ipc::IPCResult GPUChild::RecvNotifyDisableRemoteCanvas() {
240 gfxPlatform::DisableRemoteCanvas();
241 return IPC_OK();
244 mozilla::ipc::IPCResult GPUChild::RecvFlushMemory(const nsString& aReason) {
245 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
246 if (os) {
247 os->NotifyObservers(nullptr, "memory-pressure", aReason.get());
249 return IPC_OK();
252 bool GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
253 const bool& aAnonymize,
254 const bool& aMinimizeMemoryUsage,
255 const Maybe<FileDescriptor>& aDMDFile) {
256 mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
258 PGPUChild::SendRequestMemoryReport(
259 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile,
260 [&](const uint32_t& aGeneration2) {
261 if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
262 if (GPUChild* child = gpm->GetGPUChild()) {
263 if (child->mMemoryReportRequest) {
264 child->mMemoryReportRequest->Finish(aGeneration2);
265 child->mMemoryReportRequest = nullptr;
270 [&](mozilla::ipc::ResponseRejectReason) {
271 if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
272 if (GPUChild* child = gpm->GetGPUChild()) {
273 child->mMemoryReportRequest = nullptr;
278 return true;
281 mozilla::ipc::IPCResult GPUChild::RecvAddMemoryReport(
282 const MemoryReport& aReport) {
283 if (mMemoryReportRequest) {
284 mMemoryReportRequest->RecvReport(aReport);
286 return IPC_OK();
289 void GPUChild::ActorDestroy(ActorDestroyReason aWhy) {
290 if (aWhy == AbnormalShutdown || mUnexpectedShutdown) {
291 nsAutoString dumpId;
292 GenerateCrashReport(OtherPid(), &dumpId);
294 Telemetry::Accumulate(
295 Telemetry::SUBPROCESS_ABNORMAL_ABORT,
296 nsDependentCString(XRE_GeckoProcessTypeToString(GeckoProcessType_GPU)),
299 // Notify the Telemetry environment so that we can refresh and do a
300 // subsession split. This also notifies the crash reporter on geckoview.
301 if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
302 RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
303 props->SetPropertyAsBool(u"abnormal"_ns, true);
304 props->SetPropertyAsAString(u"dumpID"_ns, dumpId);
305 obsvc->NotifyObservers((nsIPropertyBag2*)props,
306 "compositor:process-aborted", nullptr);
310 gfxVars::RemoveReceiver(this);
311 mHost->OnChannelClosed();
314 mozilla::ipc::IPCResult GPUChild::RecvUpdateFeature(
315 const Feature& aFeature, const FeatureFailure& aChange) {
316 gfxConfig::SetFailed(aFeature, aChange.status(), aChange.message().get(),
317 aChange.failureId());
318 return IPC_OK();
321 mozilla::ipc::IPCResult GPUChild::RecvUsedFallback(const Fallback& aFallback,
322 const nsCString& aMessage) {
323 gfxConfig::EnableFallback(aFallback, aMessage.get());
324 return IPC_OK();
327 mozilla::ipc::IPCResult GPUChild::RecvBHRThreadHang(
328 const HangDetails& aDetails) {
329 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
330 if (obs) {
331 // Copy the HangDetails recieved over the network into a nsIHangDetails, and
332 // then fire our own observer notification.
333 // XXX: We should be able to avoid this potentially expensive copy here by
334 // moving our deserialized argument.
335 nsCOMPtr<nsIHangDetails> hangDetails =
336 new nsHangDetails(HangDetails(aDetails), PersistedToDisk::No);
337 obs->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
339 return IPC_OK();
342 mozilla::ipc::IPCResult GPUChild::RecvUpdateMediaCodecsSupported(
343 const media::MediaCodecsSupported& aSupported) {
344 dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(
345 RemoteDecodeIn::GpuProcess, aSupported);
346 return IPC_OK();
349 mozilla::ipc::IPCResult GPUChild::RecvFOGData(ByteBuf&& aBuf) {
350 glean::FOGData(std::move(aBuf));
351 return IPC_OK();
354 class DeferredDeleteGPUChild : public Runnable {
355 public:
356 explicit DeferredDeleteGPUChild(RefPtr<GPUChild>&& aChild)
357 : Runnable("gfx::DeferredDeleteGPUChild"), mChild(std::move(aChild)) {}
359 NS_IMETHODIMP Run() override { return NS_OK; }
361 private:
362 RefPtr<GPUChild> mChild;
365 /* static */
366 void GPUChild::Destroy(RefPtr<GPUChild>&& aChild) {
367 NS_DispatchToMainThread(new DeferredDeleteGPUChild(std::move(aChild)));
370 } // namespace gfx
371 } // namespace mozilla