Line data Source code
1 :
2 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 : /* vim: set ts=8 sts=2 et sw=2 tw=99: */
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 : #include "GPUChild.h"
8 : #include "gfxConfig.h"
9 : #include "gfxPrefs.h"
10 : #include "GPUProcessHost.h"
11 : #include "GPUProcessManager.h"
12 : #include "mozilla/Telemetry.h"
13 : #include "mozilla/TelemetryIPC.h"
14 : #include "mozilla/dom/CheckerboardReportService.h"
15 : #include "mozilla/dom/MemoryReportRequest.h"
16 : #include "mozilla/gfx/gfxVars.h"
17 : #if defined(XP_WIN)
18 : # include "mozilla/gfx/DeviceManagerDx.h"
19 : #endif
20 : #include "mozilla/ipc/CrashReporterHost.h"
21 : #include "mozilla/layers/LayerTreeOwnerTracker.h"
22 : #include "mozilla/Unused.h"
23 :
24 : #ifdef MOZ_GECKO_PROFILER
25 : #include "ProfilerParent.h"
26 : #endif
27 :
28 : namespace mozilla {
29 : namespace gfx {
30 :
31 : using namespace layers;
32 :
33 0 : GPUChild::GPUChild(GPUProcessHost* aHost)
34 : : mHost(aHost),
35 0 : mGPUReady(false)
36 : {
37 0 : MOZ_COUNT_CTOR(GPUChild);
38 0 : }
39 :
40 0 : GPUChild::~GPUChild()
41 : {
42 0 : MOZ_COUNT_DTOR(GPUChild);
43 0 : }
44 :
45 : void
46 0 : GPUChild::Init()
47 : {
48 : // Build a list of prefs the GPU process will need. Note that because we
49 : // limit the GPU process to prefs contained in gfxPrefs, we can simplify
50 : // the message in two ways: one, we only need to send its index in gfxPrefs
51 : // rather than its name, and two, we only need to send prefs that don't
52 : // have their default value.
53 0 : nsTArray<GfxPrefSetting> prefs;
54 0 : for (auto pref : gfxPrefs::all()) {
55 0 : if (pref->HasDefaultValue()) {
56 0 : continue;
57 : }
58 :
59 0 : GfxPrefValue value;
60 0 : pref->GetCachedValue(&value);
61 0 : prefs.AppendElement(GfxPrefSetting(pref->Index(), value));
62 : }
63 :
64 0 : nsTArray<GfxVarUpdate> updates = gfxVars::FetchNonDefaultVars();
65 :
66 0 : DevicePrefs devicePrefs;
67 0 : devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
68 0 : devicePrefs.d3d11Compositing() = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
69 0 : devicePrefs.oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
70 0 : devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
71 0 : devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
72 :
73 0 : nsTArray<LayerTreeIdMapping> mappings;
74 0 : LayerTreeOwnerTracker::Get()->Iterate([&](uint64_t aLayersId, base::ProcessId aProcessId) {
75 0 : mappings.AppendElement(LayerTreeIdMapping(aLayersId, aProcessId));
76 0 : });
77 :
78 0 : SendInit(prefs, updates, devicePrefs, mappings);
79 :
80 0 : gfxVars::AddReceiver(this);
81 :
82 : #ifdef MOZ_GECKO_PROFILER
83 0 : Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
84 : #endif
85 0 : }
86 :
87 : void
88 0 : GPUChild::OnVarChanged(const GfxVarUpdate& aVar)
89 : {
90 0 : SendUpdateVar(aVar);
91 0 : }
92 :
93 : bool
94 0 : GPUChild::EnsureGPUReady()
95 : {
96 0 : if (mGPUReady) {
97 0 : return true;
98 : }
99 :
100 0 : GPUDeviceData data;
101 0 : if (!SendGetDeviceStatus(&data)) {
102 0 : return false;
103 : }
104 :
105 0 : gfxPlatform::GetPlatform()->ImportGPUDeviceData(data);
106 0 : Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2, mHost->GetLaunchTime());
107 0 : mGPUReady = true;
108 0 : return true;
109 : }
110 :
111 : mozilla::ipc::IPCResult
112 0 : GPUChild::RecvInitComplete(const GPUDeviceData& aData)
113 : {
114 : // We synchronously requested GPU parameters before this arrived.
115 0 : if (mGPUReady) {
116 0 : return IPC_OK();
117 : }
118 :
119 0 : gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
120 0 : Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2, mHost->GetLaunchTime());
121 0 : mGPUReady = true;
122 0 : return IPC_OK();
123 : }
124 :
125 : mozilla::ipc::IPCResult
126 0 : GPUChild::RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog)
127 : {
128 0 : layers::CheckerboardEventStorage::Report(aSeverity, std::string(aLog.get()));
129 0 : return IPC_OK();
130 : }
131 :
132 : mozilla::ipc::IPCResult
133 0 : GPUChild::RecvGraphicsError(const nsCString& aError)
134 : {
135 0 : gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
136 0 : if (lf) {
137 0 : std::stringstream message;
138 0 : message << "GP+" << aError.get();
139 0 : lf->UpdateStringsVector(message.str());
140 : }
141 0 : return IPC_OK();
142 : }
143 :
144 : mozilla::ipc::IPCResult
145 0 : GPUChild::RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId)
146 : {
147 : #ifdef MOZ_CRASHREPORTER
148 0 : mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
149 : GeckoProcessType_GPU,
150 : aShmem,
151 0 : aThreadId);
152 : #endif
153 0 : return IPC_OK();
154 : }
155 :
156 : mozilla::ipc::IPCResult
157 0 : GPUChild::RecvNotifyUiObservers(const nsCString& aTopic)
158 : {
159 0 : nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
160 0 : MOZ_ASSERT(obsSvc);
161 0 : if (obsSvc) {
162 0 : obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
163 : }
164 0 : return IPC_OK();
165 : }
166 :
167 : mozilla::ipc::IPCResult
168 0 : GPUChild::RecvAccumulateChildHistograms(InfallibleTArray<Accumulation>&& aAccumulations)
169 : {
170 0 : TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Gpu, aAccumulations);
171 0 : return IPC_OK();
172 : }
173 :
174 : mozilla::ipc::IPCResult
175 0 : GPUChild::RecvAccumulateChildKeyedHistograms(InfallibleTArray<KeyedAccumulation>&& aAccumulations)
176 : {
177 0 : TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Gpu, aAccumulations);
178 0 : return IPC_OK();
179 : }
180 :
181 : mozilla::ipc::IPCResult
182 0 : GPUChild::RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions)
183 : {
184 0 : TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Gpu, aScalarActions);
185 0 : return IPC_OK();
186 : }
187 :
188 : mozilla::ipc::IPCResult
189 0 : GPUChild::RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions)
190 : {
191 0 : TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Gpu, aScalarActions);
192 0 : return IPC_OK();
193 : }
194 :
195 : mozilla::ipc::IPCResult
196 0 : GPUChild::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
197 : {
198 0 : TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
199 0 : return IPC_OK();
200 : }
201 :
202 : mozilla::ipc::IPCResult
203 0 : GPUChild::RecvRecordDiscardedData(const mozilla::Telemetry::DiscardedData& aDiscardedData)
204 : {
205 0 : TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Gpu, aDiscardedData);
206 0 : return IPC_OK();
207 : }
208 :
209 : mozilla::ipc::IPCResult
210 0 : GPUChild::RecvNotifyDeviceReset(const GPUDeviceData& aData)
211 : {
212 0 : gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
213 0 : mHost->mListener->OnRemoteProcessDeviceReset(mHost);
214 0 : return IPC_OK();
215 : }
216 :
217 : bool
218 0 : GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
219 : const bool& aAnonymize,
220 : const bool& aMinimizeMemoryUsage,
221 : const MaybeFileDesc& aDMDFile)
222 : {
223 0 : mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
224 0 : Unused << PGPUChild::SendRequestMemoryReport(
225 : aGeneration,
226 : aAnonymize,
227 : aMinimizeMemoryUsage,
228 : aDMDFile);
229 0 : return true;
230 : }
231 :
232 : mozilla::ipc::IPCResult
233 0 : GPUChild::RecvAddMemoryReport(const MemoryReport& aReport)
234 : {
235 0 : if (mMemoryReportRequest) {
236 0 : mMemoryReportRequest->RecvReport(aReport);
237 : }
238 0 : return IPC_OK();
239 : }
240 :
241 : mozilla::ipc::IPCResult
242 0 : GPUChild::RecvFinishMemoryReport(const uint32_t& aGeneration)
243 : {
244 0 : if (mMemoryReportRequest) {
245 0 : mMemoryReportRequest->Finish(aGeneration);
246 0 : mMemoryReportRequest = nullptr;
247 : }
248 0 : return IPC_OK();
249 : }
250 :
251 : void
252 0 : GPUChild::ActorDestroy(ActorDestroyReason aWhy)
253 : {
254 0 : if (aWhy == AbnormalShutdown) {
255 : #ifdef MOZ_CRASHREPORTER
256 0 : if (mCrashReporter) {
257 0 : mCrashReporter->GenerateCrashReport(OtherPid());
258 0 : mCrashReporter = nullptr;
259 : }
260 : #endif
261 :
262 : Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
263 0 : nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU)), 1);
264 :
265 : // Notify the Telemetry environment so that we can refresh and do a subsession split
266 0 : if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
267 0 : obsvc->NotifyObservers(nullptr, "compositor:process-aborted", nullptr);
268 : }
269 :
270 : }
271 :
272 0 : gfxVars::RemoveReceiver(this);
273 0 : mHost->OnChannelClosed();
274 0 : }
275 :
276 : mozilla::ipc::IPCResult
277 0 : GPUChild::RecvUpdateFeature(const Feature& aFeature, const FeatureFailure& aChange)
278 : {
279 0 : gfxConfig::SetFailed(aFeature, aChange.status(), aChange.message().get(), aChange.failureId());
280 0 : return IPC_OK();
281 : }
282 :
283 : mozilla::ipc::IPCResult
284 0 : GPUChild::RecvUsedFallback(const Fallback& aFallback, const nsCString& aMessage)
285 : {
286 0 : gfxConfig::EnableFallback(aFallback, aMessage.get());
287 0 : return IPC_OK();
288 : }
289 :
290 0 : class DeferredDeleteGPUChild : public Runnable
291 : {
292 : public:
293 0 : explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
294 0 : : Runnable("gfx::DeferredDeleteGPUChild")
295 0 : , mChild(Move(aChild))
296 : {
297 0 : }
298 :
299 0 : NS_IMETHODIMP Run() override {
300 0 : return NS_OK;
301 : }
302 :
303 : private:
304 : UniquePtr<GPUChild> mChild;
305 : };
306 :
307 : /* static */ void
308 0 : GPUChild::Destroy(UniquePtr<GPUChild>&& aChild)
309 : {
310 0 : NS_DispatchToMainThread(new DeferredDeleteGPUChild(Move(aChild)));
311 0 : }
312 :
313 : } // namespace gfx
314 : } // namespace mozilla
|