Line data Source code
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=99: */
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 : #ifdef XP_WIN
7 : #include "WMF.h"
8 : #endif
9 : #include "GPUParent.h"
10 : #include "gfxConfig.h"
11 : #include "gfxPlatform.h"
12 : #include "gfxPrefs.h"
13 : #include "GPUProcessHost.h"
14 : #include "mozilla/Assertions.h"
15 : #include "mozilla/Telemetry.h"
16 : #include "mozilla/TimeStamp.h"
17 : #include "mozilla/dom/MemoryReportRequest.h"
18 : #include "mozilla/dom/VideoDecoderManagerChild.h"
19 : #include "mozilla/dom/VideoDecoderManagerParent.h"
20 : #include "mozilla/gfx/2D.h"
21 : #include "mozilla/gfx/gfxVars.h"
22 : #include "mozilla/ipc/CrashReporterClient.h"
23 : #include "mozilla/ipc/ProcessChild.h"
24 : #include "mozilla/layers/APZThreadUtils.h"
25 : #include "mozilla/layers/APZCTreeManager.h"
26 : #include "mozilla/layers/CompositorBridgeParent.h"
27 : #include "mozilla/layers/CompositorManagerParent.h"
28 : #include "mozilla/layers/CompositorThread.h"
29 : #include "mozilla/layers/ImageBridgeParent.h"
30 : #include "mozilla/layers/LayerTreeOwnerTracker.h"
31 : #include "mozilla/layers/UiCompositorControllerParent.h"
32 : #include "mozilla/layers/MemoryReportingMLGPU.h"
33 : #include "mozilla/webrender/RenderThread.h"
34 : #include "nsDebugImpl.h"
35 : #include "nsExceptionHandler.h"
36 : #include "nsThreadManager.h"
37 : #include "prenv.h"
38 : #include "ProcessUtils.h"
39 : #include "VRManager.h"
40 : #include "VRManagerParent.h"
41 : #include "VsyncBridgeParent.h"
42 : #if defined(XP_WIN)
43 : # include "mozilla/gfx/DeviceManagerDx.h"
44 : # include <process.h>
45 : #endif
46 : #ifdef MOZ_WIDGET_GTK
47 : # include <gtk/gtk.h>
48 : #endif
49 : #ifdef MOZ_GECKO_PROFILER
50 : #include "ChildProfilerController.h"
51 : #endif
52 :
53 : namespace mozilla {
54 : namespace gfx {
55 :
56 : using namespace ipc;
57 : using namespace layers;
58 :
59 : static GPUParent* sGPUParent;
60 :
61 0 : GPUParent::GPUParent()
62 0 : : mLaunchTime(TimeStamp::Now())
63 : {
64 0 : sGPUParent = this;
65 0 : }
66 :
67 0 : GPUParent::~GPUParent()
68 : {
69 0 : sGPUParent = nullptr;
70 0 : }
71 :
72 : /* static */ GPUParent*
73 0 : GPUParent::GetSingleton()
74 : {
75 0 : return sGPUParent;
76 : }
77 :
78 : bool
79 0 : GPUParent::Init(base::ProcessId aParentPid,
80 : MessageLoop* aIOLoop,
81 : IPC::Channel* aChannel)
82 : {
83 : // Initialize the thread manager before starting IPC. Otherwise, messages
84 : // may be posted to the main thread and we won't be able to process them.
85 0 : if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
86 0 : return false;
87 : }
88 :
89 : // Now it's safe to start IPC.
90 0 : if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
91 0 : return false;
92 : }
93 :
94 0 : nsDebugImpl::SetMultiprocessMode("GPU");
95 :
96 : #ifdef MOZ_CRASHREPORTER
97 : // Init crash reporter support.
98 0 : CrashReporterClient::InitSingleton(this);
99 : #endif
100 :
101 : // Ensure gfxPrefs are initialized.
102 0 : gfxPrefs::GetSingleton();
103 0 : gfxConfig::Init();
104 0 : gfxVars::Initialize();
105 0 : gfxPlatform::InitNullMetadata();
106 : // Ensure our Factory is initialised, mainly for gfx logging to work.
107 0 : gfxPlatform::InitMoz2DLogging();
108 0 : mlg::InitializeMemoryReporters();
109 : #if defined(XP_WIN)
110 : DeviceManagerDx::Init();
111 : #endif
112 :
113 0 : if (NS_FAILED(NS_InitMinimalXPCOM())) {
114 0 : return false;
115 : }
116 :
117 0 : CompositorThreadHolder::Start();
118 0 : APZThreadUtils::SetControllerThread(CompositorThreadHolder::Loop());
119 0 : APZCTreeManager::InitializeGlobalState();
120 0 : LayerTreeOwnerTracker::Initialize();
121 0 : mozilla::ipc::SetThisProcessName("GPU Process");
122 : #ifdef XP_WIN
123 : wmf::MFStartup();
124 : #endif
125 0 : return true;
126 : }
127 :
128 : void
129 0 : GPUParent::NotifyDeviceReset()
130 : {
131 0 : if (!NS_IsMainThread()) {
132 0 : NS_DispatchToMainThread(
133 0 : NS_NewRunnableFunction("gfx::GPUParent::NotifyDeviceReset", []() -> void {
134 0 : GPUParent::GetSingleton()->NotifyDeviceReset();
135 0 : }));
136 0 : return;
137 : }
138 :
139 : // Reset and reinitialize the compositor devices
140 : #ifdef XP_WIN
141 : if (!DeviceManagerDx::Get()->MaybeResetAndReacquireDevices()) {
142 : // If the device doesn't need to be reset then the device
143 : // has already been reset by a previous NotifyDeviceReset message.
144 : return;
145 : }
146 : #endif
147 :
148 : // Notify the main process that there's been a device reset
149 : // and that they should reset their compositors and repaint
150 0 : GPUDeviceData data;
151 0 : RecvGetDeviceStatus(&data);
152 0 : Unused << SendNotifyDeviceReset(data);
153 : }
154 :
155 : mozilla::ipc::IPCResult
156 0 : GPUParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
157 : nsTArray<GfxVarUpdate>&& vars,
158 : const DevicePrefs& devicePrefs,
159 : nsTArray<LayerTreeIdMapping>&& aMappings)
160 : {
161 0 : const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
162 0 : for (auto& setting : prefs) {
163 0 : gfxPrefs::Pref* pref = globalPrefs[setting.index()];
164 0 : pref->SetCachedValue(setting.value());
165 : }
166 0 : for (const auto& var : vars) {
167 0 : gfxVars::ApplyUpdate(var);
168 : }
169 :
170 : // Inherit device preferences.
171 0 : gfxConfig::Inherit(Feature::HW_COMPOSITING, devicePrefs.hwCompositing());
172 0 : gfxConfig::Inherit(Feature::D3D11_COMPOSITING, devicePrefs.d3d11Compositing());
173 0 : gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, devicePrefs.oglCompositing());
174 0 : gfxConfig::Inherit(Feature::ADVANCED_LAYERS, devicePrefs.advancedLayers());
175 0 : gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1());
176 :
177 0 : for (const LayerTreeIdMapping& map : aMappings) {
178 0 : LayerTreeOwnerTracker::Get()->Map(map.layersId(), map.ownerId());
179 : }
180 :
181 : #if defined(XP_WIN)
182 : if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
183 : DeviceManagerDx::Get()->CreateCompositorDevices();
184 : }
185 : #endif
186 :
187 : #if defined(MOZ_WIDGET_GTK)
188 0 : char* display_name = PR_GetEnv("DISPLAY");
189 0 : if (display_name) {
190 0 : int argc = 3;
191 0 : char option_name[] = "--display";
192 : char* argv[] = {
193 : // argv0 is unused because g_set_prgname() was called in
194 : // XRE_InitChildProcess().
195 : nullptr,
196 : option_name,
197 : display_name,
198 : nullptr
199 0 : };
200 0 : char** argvp = argv;
201 0 : gtk_init(&argc, &argvp);
202 : } else {
203 0 : gtk_init(nullptr, nullptr);
204 : }
205 : #endif
206 :
207 : // Make sure to do this *after* we update gfxVars above.
208 0 : if (gfxVars::UseWebRender()) {
209 0 : wr::RenderThread::Start();
210 : }
211 :
212 0 : VRManager::ManagerInit();
213 : // Send a message to the UI process that we're done.
214 0 : GPUDeviceData data;
215 0 : RecvGetDeviceStatus(&data);
216 0 : Unused << SendInitComplete(data);
217 :
218 0 : Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS, mLaunchTime);
219 0 : return IPC_OK();
220 : }
221 :
222 : mozilla::ipc::IPCResult
223 0 : GPUParent::RecvInitCompositorManager(Endpoint<PCompositorManagerParent>&& aEndpoint)
224 : {
225 0 : CompositorManagerParent::Create(Move(aEndpoint));
226 0 : return IPC_OK();
227 : }
228 :
229 : mozilla::ipc::IPCResult
230 0 : GPUParent::RecvInitVsyncBridge(Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint)
231 : {
232 0 : mVsyncBridge = VsyncBridgeParent::Start(Move(aVsyncEndpoint));
233 0 : return IPC_OK();
234 : }
235 :
236 : mozilla::ipc::IPCResult
237 0 : GPUParent::RecvInitImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint)
238 : {
239 0 : ImageBridgeParent::CreateForGPUProcess(Move(aEndpoint));
240 0 : return IPC_OK();
241 : }
242 :
243 : mozilla::ipc::IPCResult
244 0 : GPUParent::RecvInitVRManager(Endpoint<PVRManagerParent>&& aEndpoint)
245 : {
246 0 : VRManagerParent::CreateForGPUProcess(Move(aEndpoint));
247 0 : return IPC_OK();
248 : }
249 :
250 : mozilla::ipc::IPCResult
251 0 : GPUParent::RecvInitUiCompositorController(const uint64_t& aRootLayerTreeId, Endpoint<PUiCompositorControllerParent>&& aEndpoint)
252 : {
253 0 : UiCompositorControllerParent::Start(aRootLayerTreeId, Move(aEndpoint));
254 0 : return IPC_OK();
255 : }
256 :
257 : mozilla::ipc::IPCResult
258 0 : GPUParent::RecvInitProfiler(Endpoint<PProfilerChild>&& aEndpoint)
259 : {
260 : #ifdef MOZ_GECKO_PROFILER
261 0 : mProfilerController = ChildProfilerController::Create(Move(aEndpoint));
262 : #endif
263 0 : return IPC_OK();
264 : }
265 :
266 : mozilla::ipc::IPCResult
267 0 : GPUParent::RecvUpdatePref(const GfxPrefSetting& setting)
268 : {
269 0 : gfxPrefs::Pref* pref = gfxPrefs::all()[setting.index()];
270 0 : pref->SetCachedValue(setting.value());
271 0 : return IPC_OK();
272 : }
273 :
274 : mozilla::ipc::IPCResult
275 0 : GPUParent::RecvUpdateVar(const GfxVarUpdate& aUpdate)
276 : {
277 0 : gfxVars::ApplyUpdate(aUpdate);
278 0 : return IPC_OK();
279 : }
280 :
281 : static void
282 0 : CopyFeatureChange(Feature aFeature, FeatureChange* aOut)
283 : {
284 0 : FeatureState& feature = gfxConfig::GetFeature(aFeature);
285 0 : if (feature.DisabledByDefault() || feature.IsEnabled()) {
286 : // No change:
287 : // - Disabled-by-default means the parent process told us not to use this feature.
288 : // - Enabled means we were told to use this feature, and we didn't discover anything
289 : // that would prevent us from doing so.
290 0 : *aOut = null_t();
291 0 : return;
292 : }
293 :
294 0 : MOZ_ASSERT(!feature.IsEnabled());
295 :
296 0 : nsCString message;
297 0 : message.AssignASCII(feature.GetFailureMessage());
298 :
299 0 : *aOut = FeatureFailure(feature.GetValue(), message, feature.GetFailureId());
300 : }
301 :
302 : mozilla::ipc::IPCResult
303 0 : GPUParent::RecvGetDeviceStatus(GPUDeviceData* aOut)
304 : {
305 0 : CopyFeatureChange(Feature::D3D11_COMPOSITING, &aOut->d3d11Compositing());
306 0 : CopyFeatureChange(Feature::OPENGL_COMPOSITING, &aOut->oglCompositing());
307 0 : CopyFeatureChange(Feature::ADVANCED_LAYERS, &aOut->advancedLayers());
308 :
309 : #if defined(XP_WIN)
310 : if (DeviceManagerDx* dm = DeviceManagerDx::Get()) {
311 : D3D11DeviceStatus deviceStatus;
312 : dm->ExportDeviceInfo(&deviceStatus);
313 : aOut->gpuDevice() = deviceStatus;
314 : }
315 : #else
316 0 : aOut->gpuDevice() = null_t();
317 : #endif
318 :
319 0 : return IPC_OK();
320 : }
321 :
322 : mozilla::ipc::IPCResult
323 0 : GPUParent::RecvNewContentCompositorManager(Endpoint<PCompositorManagerParent>&& aEndpoint)
324 : {
325 0 : CompositorManagerParent::Create(Move(aEndpoint));
326 0 : return IPC_OK();
327 : }
328 :
329 : mozilla::ipc::IPCResult
330 0 : GPUParent::RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint)
331 : {
332 0 : if (!ImageBridgeParent::CreateForContent(Move(aEndpoint))) {
333 0 : return IPC_FAIL_NO_REASON(this);
334 : }
335 0 : return IPC_OK();
336 : }
337 :
338 : mozilla::ipc::IPCResult
339 0 : GPUParent::RecvNewContentVRManager(Endpoint<PVRManagerParent>&& aEndpoint)
340 : {
341 0 : if (!VRManagerParent::CreateForContent(Move(aEndpoint))) {
342 0 : return IPC_FAIL_NO_REASON(this);
343 : }
344 0 : return IPC_OK();
345 : }
346 :
347 : mozilla::ipc::IPCResult
348 0 : GPUParent::RecvNewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent>&& aEndpoint)
349 : {
350 0 : if (!dom::VideoDecoderManagerParent::CreateForContent(Move(aEndpoint))) {
351 0 : return IPC_FAIL_NO_REASON(this);
352 : }
353 0 : return IPC_OK();
354 : }
355 :
356 : mozilla::ipc::IPCResult
357 0 : GPUParent::RecvAddLayerTreeIdMapping(const LayerTreeIdMapping& aMapping)
358 : {
359 0 : LayerTreeOwnerTracker::Get()->Map(aMapping.layersId(), aMapping.ownerId());
360 0 : return IPC_OK();
361 : }
362 :
363 : mozilla::ipc::IPCResult
364 0 : GPUParent::RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping)
365 : {
366 0 : LayerTreeOwnerTracker::Get()->Unmap(aMapping.layersId(), aMapping.ownerId());
367 0 : CompositorBridgeParent::DeallocateLayerTreeId(aMapping.layersId());
368 0 : return IPC_OK();
369 : }
370 :
371 : mozilla::ipc::IPCResult
372 0 : GPUParent::RecvNotifyGpuObservers(const nsCString& aTopic)
373 : {
374 0 : nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
375 0 : MOZ_ASSERT(obsSvc);
376 0 : if (obsSvc) {
377 0 : obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
378 : }
379 0 : return IPC_OK();
380 : }
381 :
382 : mozilla::ipc::IPCResult
383 0 : GPUParent::RecvRequestMemoryReport(const uint32_t& aGeneration,
384 : const bool& aAnonymize,
385 : const bool& aMinimizeMemoryUsage,
386 : const MaybeFileDesc& aDMDFile)
387 : {
388 0 : nsPrintfCString processName("GPU (pid %u)", (unsigned)getpid());
389 :
390 0 : mozilla::dom::MemoryReportRequestClient::Start(
391 0 : aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName);
392 0 : return IPC_OK();
393 : }
394 :
395 : void
396 0 : GPUParent::ActorDestroy(ActorDestroyReason aWhy)
397 : {
398 0 : if (AbnormalShutdown == aWhy) {
399 0 : NS_WARNING("Shutting down GPU process early due to a crash!");
400 0 : ProcessChild::QuickExit();
401 : }
402 :
403 : #ifdef XP_WIN
404 : wmf::MFShutdown();
405 : #endif
406 :
407 : #ifndef NS_FREE_PERMANENT_DATA
408 : // No point in going through XPCOM shutdown because we don't keep persistent
409 : // state.
410 : ProcessChild::QuickExit();
411 : #endif
412 :
413 : #ifdef MOZ_GECKO_PROFILER
414 0 : if (mProfilerController) {
415 0 : mProfilerController->Shutdown();
416 0 : mProfilerController = nullptr;
417 : }
418 : #endif
419 :
420 0 : if (mVsyncBridge) {
421 0 : mVsyncBridge->Shutdown();
422 0 : mVsyncBridge = nullptr;
423 : }
424 0 : dom::VideoDecoderManagerParent::ShutdownVideoBridge();
425 0 : CompositorThreadHolder::Shutdown();
426 0 : if (gfxVars::UseWebRender()) {
427 0 : wr::RenderThread::ShutDown();
428 : }
429 0 : Factory::ShutDown();
430 : #if defined(XP_WIN)
431 : DeviceManagerDx::Shutdown();
432 : #endif
433 0 : LayerTreeOwnerTracker::Shutdown();
434 0 : gfxVars::Shutdown();
435 0 : gfxConfig::Shutdown();
436 0 : gfxPrefs::DestroySingleton();
437 : #ifdef MOZ_CRASHREPORTER
438 0 : CrashReporterClient::DestroySingleton();
439 : #endif
440 0 : XRE_ShutdownChildProcess();
441 0 : }
442 :
443 : } // namespace gfx
444 : } // namespace mozilla
|