Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/ipc/GPUParent.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
#ifdef XP_WIN
7
#include "WMF.h"
8
#endif
9
#include "GPUParent.h"
10
#include "gfxConfig.h"
11
#include "gfxCrashReporterUtils.h"
12
#include "gfxPlatform.h"
13
#include "gfxPrefs.h"
14
#include "GLContextProvider.h"
15
#include "GPUProcessHost.h"
16
#include "GPUProcessManager.h"
17
#include "mozilla/Assertions.h"
18
#include "mozilla/Telemetry.h"
19
#include "mozilla/TimeStamp.h"
20
#include "mozilla/dom/MemoryReportRequest.h"
21
#include "mozilla/dom/VideoDecoderManagerChild.h"
22
#include "mozilla/dom/VideoDecoderManagerParent.h"
23
#include "mozilla/gfx/2D.h"
24
#include "mozilla/gfx/gfxVars.h"
25
#include "mozilla/ipc/CrashReporterClient.h"
26
#include "mozilla/ipc/ProcessChild.h"
27
#include "mozilla/layers/APZInputBridgeParent.h"
28
#include "mozilla/layers/APZThreadUtils.h"
29
#include "mozilla/layers/APZUtils.h"    // for apz::InitializeGlobalState
30
#include "mozilla/layers/CompositorBridgeParent.h"
31
#include "mozilla/layers/CompositorManagerParent.h"
32
#include "mozilla/layers/CompositorThread.h"
33
#include "mozilla/layers/ImageBridgeParent.h"
34
#include "mozilla/layers/LayerTreeOwnerTracker.h"
35
#include "mozilla/layers/UiCompositorControllerParent.h"
36
#include "mozilla/layers/MemoryReportingMLGPU.h"
37
#include "mozilla/webrender/RenderThread.h"
38
#include "mozilla/webrender/WebRenderAPI.h"
39
#include "mozilla/HangDetails.h"
40
#include "nsDebugImpl.h"
41
#include "nsIGfxInfo.h"
42
#include "nsThreadManager.h"
43
#include "prenv.h"
44
#include "ProcessUtils.h"
45
#include "VRGPUChild.h"
46
#include "VRManager.h"
47
#include "VRManagerParent.h"
48
#include "VRThread.h"
49
#include "VsyncBridgeParent.h"
50
#if defined(XP_WIN)
51
# include "mozilla/gfx/DeviceManagerDx.h"
52
# include <process.h>
53
# include <dwrite.h>
54
#endif
55
#ifdef MOZ_WIDGET_GTK
56
# include <gtk/gtk.h>
57
#endif
58
#ifdef MOZ_GECKO_PROFILER
59
#include "ChildProfilerController.h"
60
#endif
61
62
namespace mozilla {
63
namespace gfx {
64
65
using namespace ipc;
66
using namespace layers;
67
68
static GPUParent* sGPUParent;
69
70
GPUParent::GPUParent()
71
  : mLaunchTime(TimeStamp::Now())
72
0
{
73
0
  sGPUParent = this;
74
0
}
75
76
GPUParent::~GPUParent()
77
0
{
78
0
  sGPUParent = nullptr;
79
0
}
80
81
/* static */ GPUParent*
82
GPUParent::GetSingleton()
83
0
{
84
0
  return sGPUParent;
85
0
}
86
87
bool
88
GPUParent::Init(base::ProcessId aParentPid,
89
                const char* aParentBuildID,
90
                MessageLoop* aIOLoop,
91
                IPC::Channel* aChannel)
92
0
{
93
0
  // Initialize the thread manager before starting IPC. Otherwise, messages
94
0
  // may be posted to the main thread and we won't be able to process them.
95
0
  if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
96
0
    return false;
97
0
  }
98
0
99
0
  // Now it's safe to start IPC.
100
0
  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
101
0
    return false;
102
0
  }
103
0
104
0
  nsDebugImpl::SetMultiprocessMode("GPU");
105
0
106
0
  // This must be checked before any IPDL message, which may hit sentinel
107
0
  // errors due to parent and content processes having different
108
0
  // versions.
109
0
  MessageChannel* channel = GetIPCChannel();
110
0
  if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
111
0
    // We need to quit this process if the buildID doesn't match the parent's.
112
0
    // This can occur when an update occurred in the background.
113
0
    ProcessChild::QuickExit();
114
0
  }
115
0
116
0
  // Init crash reporter support.
117
0
  CrashReporterClient::InitSingleton(this);
118
0
119
0
  // Ensure gfxPrefs are initialized.
120
0
  gfxPrefs::GetSingleton();
121
0
  gfxConfig::Init();
122
0
  gfxVars::Initialize();
123
0
  gfxPlatform::InitNullMetadata();
124
0
  // Ensure our Factory is initialised, mainly for gfx logging to work.
125
0
  gfxPlatform::InitMoz2DLogging();
126
0
  mlg::InitializeMemoryReporters();
127
#if defined(XP_WIN)
128
  DeviceManagerDx::Init();
129
#endif
130
131
0
  if (NS_FAILED(NS_InitMinimalXPCOM())) {
132
0
    return false;
133
0
  }
134
0
135
0
  CompositorThreadHolder::Start();
136
0
  // TODO: Bug 1406327, Start VRListenerThreadHolder when loading VR content.
137
0
  VRListenerThreadHolder::Start();
138
0
  APZThreadUtils::SetControllerThread(MessageLoop::current());
139
0
  apz::InitializeGlobalState();
140
0
  LayerTreeOwnerTracker::Initialize();
141
0
  mozilla::ipc::SetThisProcessName("GPU Process");
142
#ifdef XP_WIN
143
  wmf::MFStartup();
144
#endif
145
  return true;
146
0
}
147
148
void
149
GPUParent::NotifyDeviceReset()
150
0
{
151
0
  if (!NS_IsMainThread()) {
152
0
    NS_DispatchToMainThread(
153
0
      NS_NewRunnableFunction("gfx::GPUParent::NotifyDeviceReset", []() -> void {
154
0
        GPUParent::GetSingleton()->NotifyDeviceReset();
155
0
      }));
156
0
    return;
157
0
  }
158
0
159
0
  // Reset and reinitialize the compositor devices
160
#ifdef XP_WIN
161
  if (!DeviceManagerDx::Get()->MaybeResetAndReacquireDevices()) {
162
    // If the device doesn't need to be reset then the device
163
    // has already been reset by a previous NotifyDeviceReset message.
164
    return;
165
  }
166
#endif
167
168
0
  // Notify the main process that there's been a device reset
169
0
  // and that they should reset their compositors and repaint
170
0
  GPUDeviceData data;
171
0
  RecvGetDeviceStatus(&data);
172
0
  Unused << SendNotifyDeviceReset(data);
173
0
}
174
175
PAPZInputBridgeParent*
176
GPUParent::AllocPAPZInputBridgeParent(const LayersId& aLayersId)
177
0
{
178
0
  APZInputBridgeParent* parent = new APZInputBridgeParent(aLayersId);
179
0
  parent->AddRef();
180
0
  return parent;
181
0
}
182
183
bool
184
GPUParent::DeallocPAPZInputBridgeParent(PAPZInputBridgeParent* aActor)
185
0
{
186
0
  APZInputBridgeParent* parent = static_cast<APZInputBridgeParent*>(aActor);
187
0
  parent->Release();
188
0
  return true;
189
0
}
190
191
mozilla::ipc::IPCResult
192
GPUParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
193
                    nsTArray<GfxVarUpdate>&& vars,
194
                    const DevicePrefs& devicePrefs,
195
                    nsTArray<LayerTreeIdMapping>&& aMappings)
196
0
{
197
0
  const nsTArray<gfxPrefs::Pref*>& globalPrefs = gfxPrefs::all();
198
0
  for (auto& setting : prefs) {
199
0
    gfxPrefs::Pref* pref = globalPrefs[setting.index()];
200
0
    pref->SetCachedValue(setting.value());
201
0
  }
202
0
  for (const auto& var : vars) {
203
0
    gfxVars::ApplyUpdate(var);
204
0
  }
205
0
206
0
  // Inherit device preferences.
207
0
  gfxConfig::Inherit(Feature::HW_COMPOSITING, devicePrefs.hwCompositing());
208
0
  gfxConfig::Inherit(Feature::D3D11_COMPOSITING, devicePrefs.d3d11Compositing());
209
0
  gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, devicePrefs.oglCompositing());
210
0
  gfxConfig::Inherit(Feature::ADVANCED_LAYERS, devicePrefs.advancedLayers());
211
0
  gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1());
212
0
213
0
  { // Let the crash reporter know if we've got WR enabled or not. For other
214
0
    // processes this happens in gfxPlatform::InitWebRenderConfig.
215
0
    ScopedGfxFeatureReporter reporter("WR", gfxPlatform::WebRenderPrefEnabled());
216
0
    if (gfxVars::UseWebRender()) {
217
0
      reporter.SetSuccessful();
218
0
    }
219
0
  }
220
0
221
0
  for (const LayerTreeIdMapping& map : aMappings) {
222
0
    LayerTreeOwnerTracker::Get()->Map(map.layersId(), map.ownerId());
223
0
  }
224
0
225
#if defined(XP_WIN)
226
  if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
227
    DeviceManagerDx::Get()->CreateCompositorDevices();
228
  }
229
  if (gfxVars::UseWebRender()) {
230
    DeviceManagerDx::Get()->CreateDirectCompositionDevice();
231
    // Ensure to initialize GfxInfo
232
    nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
233
    Unused << gfxInfo;
234
235
    Factory::EnsureDWriteFactory();
236
  }
237
#endif
238
239
0
#if defined(MOZ_WIDGET_GTK)
240
0
  char* display_name = PR_GetEnv("DISPLAY");
241
0
  if (display_name) {
242
0
    int argc = 3;
243
0
    char option_name[] = "--display";
244
0
    char* argv[] = {
245
0
      // argv0 is unused because g_set_prgname() was called in
246
0
      // XRE_InitChildProcess().
247
0
      nullptr,
248
0
      option_name,
249
0
      display_name,
250
0
      nullptr
251
0
    };
252
0
    char** argvp = argv;
253
0
    gtk_init(&argc, &argvp);
254
0
  } else {
255
0
    gtk_init(nullptr, nullptr);
256
0
  }
257
0
258
0
  // Ensure we have an FT library for font instantiation.
259
0
  // This would normally be set by gfxPlatform::Init().
260
0
  // Since we bypass that, we must do it here instead.
261
0
  if (gfxVars::UseWebRender()) {
262
0
    FT_Library library = Factory::NewFTLibrary();
263
0
    MOZ_ASSERT(library);
264
0
    Factory::SetFTLibrary(library);
265
0
  }
266
0
#endif
267
0
268
0
  // Make sure to do this *after* we update gfxVars above.
269
0
  if (gfxVars::UseWebRender()) {
270
0
    wr::RenderThread::Start();
271
0
  }
272
0
273
0
  VRManager::ManagerInit();
274
0
  // Send a message to the UI process that we're done.
275
0
  GPUDeviceData data;
276
0
  RecvGetDeviceStatus(&data);
277
0
  Unused << SendInitComplete(data);
278
0
279
0
  Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS, mLaunchTime);
280
0
  return IPC_OK();
281
0
}
282
283
mozilla::ipc::IPCResult
284
GPUParent::RecvInitCompositorManager(Endpoint<PCompositorManagerParent>&& aEndpoint)
285
0
{
286
0
  CompositorManagerParent::Create(std::move(aEndpoint));
287
0
  return IPC_OK();
288
0
}
289
290
mozilla::ipc::IPCResult
291
GPUParent::RecvInitVsyncBridge(Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint)
292
0
{
293
0
  mVsyncBridge = VsyncBridgeParent::Start(std::move(aVsyncEndpoint));
294
0
  return IPC_OK();
295
0
}
296
297
mozilla::ipc::IPCResult
298
GPUParent::RecvInitImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint)
299
0
{
300
0
  ImageBridgeParent::CreateForGPUProcess(std::move(aEndpoint));
301
0
  return IPC_OK();
302
0
}
303
304
mozilla::ipc::IPCResult
305
GPUParent::RecvInitVRManager(Endpoint<PVRManagerParent>&& aEndpoint)
306
0
{
307
0
  VRManagerParent::CreateForGPUProcess(std::move(aEndpoint));
308
0
  return IPC_OK();
309
0
}
310
311
mozilla::ipc::IPCResult
312
GPUParent::RecvInitVR(Endpoint<PVRGPUChild>&& aEndpoint)
313
0
{
314
0
  gfx::VRGPUChild::InitForGPUProcess(std::move(aEndpoint));
315
0
  return IPC_OK();
316
0
}
317
318
mozilla::ipc::IPCResult
319
GPUParent::RecvInitUiCompositorController(const LayersId& aRootLayerTreeId, Endpoint<PUiCompositorControllerParent>&& aEndpoint)
320
0
{
321
0
  UiCompositorControllerParent::Start(aRootLayerTreeId, std::move(aEndpoint));
322
0
  return IPC_OK();
323
0
}
324
325
mozilla::ipc::IPCResult
326
GPUParent::RecvInitProfiler(Endpoint<PProfilerChild>&& aEndpoint)
327
0
{
328
0
#ifdef MOZ_GECKO_PROFILER
329
0
  mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
330
0
#endif
331
0
  return IPC_OK();
332
0
}
333
334
mozilla::ipc::IPCResult
335
GPUParent::RecvUpdatePref(const GfxPrefSetting& setting)
336
0
{
337
0
  gfxPrefs::Pref* pref = gfxPrefs::all()[setting.index()];
338
0
  pref->SetCachedValue(setting.value());
339
0
  return IPC_OK();
340
0
}
341
342
mozilla::ipc::IPCResult
343
GPUParent::RecvUpdateVar(const GfxVarUpdate& aUpdate)
344
0
{
345
0
  gfxVars::ApplyUpdate(aUpdate);
346
0
  return IPC_OK();
347
0
}
348
349
static void
350
CopyFeatureChange(Feature aFeature, FeatureChange* aOut)
351
0
{
352
0
  FeatureState& feature = gfxConfig::GetFeature(aFeature);
353
0
  if (feature.DisabledByDefault() || feature.IsEnabled()) {
354
0
    // No change:
355
0
    //   - Disabled-by-default means the parent process told us not to use this feature.
356
0
    //   - Enabled means we were told to use this feature, and we didn't discover anything
357
0
    //     that would prevent us from doing so.
358
0
    *aOut = null_t();
359
0
    return;
360
0
  }
361
0
362
0
  MOZ_ASSERT(!feature.IsEnabled());
363
0
364
0
  nsCString message;
365
0
  message.AssignASCII(feature.GetFailureMessage());
366
0
367
0
  *aOut = FeatureFailure(feature.GetValue(), message, feature.GetFailureId());
368
0
}
369
370
mozilla::ipc::IPCResult
371
GPUParent::RecvGetDeviceStatus(GPUDeviceData* aOut)
372
0
{
373
0
  CopyFeatureChange(Feature::D3D11_COMPOSITING, &aOut->d3d11Compositing());
374
0
  CopyFeatureChange(Feature::OPENGL_COMPOSITING, &aOut->oglCompositing());
375
0
  CopyFeatureChange(Feature::ADVANCED_LAYERS, &aOut->advancedLayers());
376
0
377
#if defined(XP_WIN)
378
  if (DeviceManagerDx* dm = DeviceManagerDx::Get()) {
379
    D3D11DeviceStatus deviceStatus;
380
    dm->ExportDeviceInfo(&deviceStatus);
381
    aOut->gpuDevice() = deviceStatus;
382
  }
383
#else
384
  aOut->gpuDevice() = null_t();
385
0
#endif
386
0
387
0
  return IPC_OK();
388
0
}
389
390
mozilla::ipc::IPCResult
391
GPUParent::RecvSimulateDeviceReset(GPUDeviceData* aOut)
392
0
{
393
#if defined(XP_WIN)
394
  DeviceManagerDx::Get()->ForceDeviceReset(ForcedDeviceResetReason::COMPOSITOR_UPDATED);
395
  DeviceManagerDx::Get()->MaybeResetAndReacquireDevices();
396
  if (gfxVars::UseWebRender()) {
397
    wr::RenderThread::Get()->SimulateDeviceReset();
398
  }
399
#endif
400
  RecvGetDeviceStatus(aOut);
401
0
  return IPC_OK();
402
0
}
403
404
mozilla::ipc::IPCResult
405
GPUParent::RecvNewContentCompositorManager(Endpoint<PCompositorManagerParent>&& aEndpoint)
406
0
{
407
0
  CompositorManagerParent::Create(std::move(aEndpoint));
408
0
  return IPC_OK();
409
0
}
410
411
mozilla::ipc::IPCResult
412
GPUParent::RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint)
413
0
{
414
0
  if (!ImageBridgeParent::CreateForContent(std::move(aEndpoint))) {
415
0
    return IPC_FAIL_NO_REASON(this);
416
0
  }
417
0
  return IPC_OK();
418
0
}
419
420
mozilla::ipc::IPCResult
421
GPUParent::RecvNewContentVRManager(Endpoint<PVRManagerParent>&& aEndpoint)
422
0
{
423
0
  if (!VRManagerParent::CreateForContent(std::move(aEndpoint))) {
424
0
    return IPC_FAIL_NO_REASON(this);
425
0
  }
426
0
  return IPC_OK();
427
0
}
428
429
mozilla::ipc::IPCResult
430
GPUParent::RecvNewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent>&& aEndpoint)
431
0
{
432
0
  if (!dom::VideoDecoderManagerParent::CreateForContent(std::move(aEndpoint))) {
433
0
    return IPC_FAIL_NO_REASON(this);
434
0
  }
435
0
  return IPC_OK();
436
0
}
437
438
mozilla::ipc::IPCResult
439
GPUParent::RecvAddLayerTreeIdMapping(const LayerTreeIdMapping& aMapping)
440
0
{
441
0
  LayerTreeOwnerTracker::Get()->Map(aMapping.layersId(), aMapping.ownerId());
442
0
  return IPC_OK();
443
0
}
444
445
mozilla::ipc::IPCResult
446
GPUParent::RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping)
447
0
{
448
0
  LayerTreeOwnerTracker::Get()->Unmap(aMapping.layersId(), aMapping.ownerId());
449
0
  CompositorBridgeParent::DeallocateLayerTreeId(aMapping.layersId());
450
0
  return IPC_OK();
451
0
}
452
453
mozilla::ipc::IPCResult
454
GPUParent::RecvNotifyGpuObservers(const nsCString& aTopic)
455
0
{
456
0
  nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
457
0
  MOZ_ASSERT(obsSvc);
458
0
  if (obsSvc) {
459
0
    obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
460
0
  }
461
0
  return IPC_OK();
462
0
}
463
464
/* static */ void
465
GPUParent::GetGPUProcessName(nsACString& aStr)
466
0
{
467
0
  auto processType = XRE_GetProcessType();
468
0
  unsigned pid = 0;
469
0
  if (processType == GeckoProcessType_GPU) {
470
0
    pid = getpid();
471
0
  } else {
472
0
    MOZ_DIAGNOSTIC_ASSERT(processType == GeckoProcessType_Default);
473
0
    pid = GPUProcessManager::Get()->GPUProcessPid();
474
0
  }
475
0
476
0
  nsPrintfCString processName("GPU (pid %u)", pid);
477
0
  aStr.Assign(processName);
478
0
}
479
480
mozilla::ipc::IPCResult
481
GPUParent::RecvRequestMemoryReport(const uint32_t& aGeneration,
482
                                   const bool& aAnonymize,
483
                                   const bool& aMinimizeMemoryUsage,
484
                                   const MaybeFileDesc& aDMDFile)
485
0
{
486
0
  nsAutoCString processName;
487
0
  GetGPUProcessName(processName);
488
0
489
0
  mozilla::dom::MemoryReportRequestClient::Start(
490
0
    aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName);
491
0
  return IPC_OK();
492
0
}
493
494
mozilla::ipc::IPCResult
495
GPUParent::RecvShutdownVR()
496
0
{
497
0
  if (gfxPrefs::VRProcessEnabled()) {
498
0
    VRGPUChild::ShutDown();
499
0
  }
500
0
  return IPC_OK();
501
0
}
502
503
void
504
GPUParent::ActorDestroy(ActorDestroyReason aWhy)
505
0
{
506
0
  if (AbnormalShutdown == aWhy) {
507
0
    NS_WARNING("Shutting down GPU process early due to a crash!");
508
0
    ProcessChild::QuickExit();
509
0
  }
510
0
511
#ifdef XP_WIN
512
  wmf::MFShutdown();
513
#endif
514
515
0
#ifndef NS_FREE_PERMANENT_DATA
516
0
  // No point in going through XPCOM shutdown because we don't keep persistent
517
0
  // state.
518
0
  ProcessChild::QuickExit();
519
0
#endif
520
0
521
0
#ifdef MOZ_GECKO_PROFILER
522
0
  if (mProfilerController) {
523
0
    mProfilerController->Shutdown();
524
0
    mProfilerController = nullptr;
525
0
  }
526
0
#endif
527
0
528
0
  if (mVsyncBridge) {
529
0
    mVsyncBridge->Shutdown();
530
0
    mVsyncBridge = nullptr;
531
0
  }
532
0
  dom::VideoDecoderManagerParent::ShutdownVideoBridge();
533
0
  CompositorThreadHolder::Shutdown();
534
0
  VRListenerThreadHolder::Shutdown();
535
0
  // There is a case that RenderThread exists when gfxVars::UseWebRender() is false.
536
0
  // This could happen when WebRender was fallbacked to compositor.
537
0
  if (wr::RenderThread::Get()) {
538
0
    wr::RenderThread::ShutDown();
539
0
  }
540
0
541
0
  // Shut down the default GL context provider.
542
0
  gl::GLContextProvider::Shutdown();
543
0
544
#if defined(XP_WIN)
545
  // The above shutdown calls operate on the available context providers on
546
  // most platforms.  Windows is a "special snowflake", though, and has three
547
  // context providers available, so we have to shut all of them down.
548
  // We should only support the default GL provider on Windows; then, this
549
  // could go away. Unfortunately, we currently support WGL (the default) for
550
  // WebGL on Optimus.
551
  gl::GLContextProviderEGL::Shutdown();
552
#endif
553
554
0
  Factory::ShutDown();
555
#if defined(XP_WIN)
556
  DeviceManagerDx::Shutdown();
557
#endif
558
  LayerTreeOwnerTracker::Shutdown();
559
0
  gfxVars::Shutdown();
560
0
  gfxConfig::Shutdown();
561
0
  gfxPrefs::DestroySingleton();
562
0
  CrashReporterClient::DestroySingleton();
563
0
  XRE_ShutdownChildProcess();
564
0
}
565
566
} // namespace gfx
567
} // namespace mozilla