Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/ipc/GPUChild.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
#include "GPUChild.h"
7
#include "gfxConfig.h"
8
#include "gfxPrefs.h"
9
#include "GPUProcessHost.h"
10
#include "GPUProcessManager.h"
11
#include "VRProcessManager.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/APZInputBridgeChild.h"
22
#include "mozilla/layers/LayerTreeOwnerTracker.h"
23
#include "mozilla/Unused.h"
24
#include "mozilla/HangDetails.h"
25
#include "nsIObserverService.h"
26
27
#ifdef MOZ_GECKO_PROFILER
28
#include "ProfilerParent.h"
29
#endif
30
31
namespace mozilla {
32
namespace gfx {
33
34
using namespace layers;
35
36
GPUChild::GPUChild(GPUProcessHost* aHost)
37
 : mHost(aHost),
38
   mGPUReady(false)
39
0
{
40
0
  MOZ_COUNT_CTOR(GPUChild);
41
0
}
42
43
GPUChild::~GPUChild()
44
0
{
45
0
  MOZ_COUNT_DTOR(GPUChild);
46
0
}
47
48
void
49
GPUChild::Init()
50
0
{
51
0
  // Build a list of prefs the GPU process will need. Note that because we
52
0
  // limit the GPU process to prefs contained in gfxPrefs, we can simplify
53
0
  // the message in two ways: one, we only need to send its index in gfxPrefs
54
0
  // rather than its name, and two, we only need to send prefs that don't
55
0
  // have their default value.
56
0
  nsTArray<GfxPrefSetting> prefs;
57
0
  for (auto pref : gfxPrefs::all()) {
58
0
    if (pref->HasDefaultValue()) {
59
0
      continue;
60
0
    }
61
0
62
0
    GfxPrefValue value;
63
0
    pref->GetCachedValue(&value);
64
0
    prefs.AppendElement(GfxPrefSetting(pref->Index(), value));
65
0
  }
66
0
67
0
  nsTArray<GfxVarUpdate> updates = gfxVars::FetchNonDefaultVars();
68
0
69
0
  DevicePrefs devicePrefs;
70
0
  devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
71
0
  devicePrefs.d3d11Compositing() = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
72
0
  devicePrefs.oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
73
0
  devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
74
0
  devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
75
0
76
0
  nsTArray<LayerTreeIdMapping> mappings;
77
0
  LayerTreeOwnerTracker::Get()->Iterate([&](LayersId aLayersId, base::ProcessId aProcessId) {
78
0
    mappings.AppendElement(LayerTreeIdMapping(aLayersId, aProcessId));
79
0
  });
80
0
81
0
  SendInit(prefs, updates, devicePrefs, mappings);
82
0
83
0
  gfxVars::AddReceiver(this);
84
0
85
0
#ifdef MOZ_GECKO_PROFILER
86
0
  Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
87
0
#endif
88
0
}
89
90
void
91
GPUChild::OnVarChanged(const GfxVarUpdate& aVar)
92
0
{
93
0
  SendUpdateVar(aVar);
94
0
}
95
96
bool
97
GPUChild::EnsureGPUReady()
98
0
{
99
0
  if (mGPUReady) {
100
0
    return true;
101
0
  }
102
0
103
0
  GPUDeviceData data;
104
0
  if (!SendGetDeviceStatus(&data)) {
105
0
    return false;
106
0
  }
107
0
108
0
  gfxPlatform::GetPlatform()->ImportGPUDeviceData(data);
109
0
  Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2, mHost->GetLaunchTime());
110
0
  mGPUReady = true;
111
0
  return true;
112
0
}
113
114
base::ProcessHandle
115
GPUChild::GetChildProcessHandle()
116
0
{
117
0
  return mHost->GetChildProcessHandle();
118
0
}
119
120
PAPZInputBridgeChild*
121
GPUChild::AllocPAPZInputBridgeChild(const LayersId& aLayersId)
122
0
{
123
0
  APZInputBridgeChild* child = new APZInputBridgeChild();
124
0
  child->AddRef();
125
0
  return child;
126
0
}
127
128
bool
129
GPUChild::DeallocPAPZInputBridgeChild(PAPZInputBridgeChild* aActor)
130
0
{
131
0
  APZInputBridgeChild* child = static_cast<APZInputBridgeChild*>(aActor);
132
0
  child->Release();
133
0
  return true;
134
0
}
135
136
mozilla::ipc::IPCResult
137
GPUChild::RecvInitComplete(const GPUDeviceData& aData)
138
0
{
139
0
  // We synchronously requested GPU parameters before this arrived.
140
0
  if (mGPUReady) {
141
0
    return IPC_OK();
142
0
  }
143
0
144
0
  gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
145
0
  Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2, mHost->GetLaunchTime());
146
0
  mGPUReady = true;
147
0
  return IPC_OK();
148
0
}
149
150
mozilla::ipc::IPCResult
151
GPUChild::RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog)
152
0
{
153
0
  layers::CheckerboardEventStorage::Report(aSeverity, std::string(aLog.get()));
154
0
  return IPC_OK();
155
0
}
156
157
mozilla::ipc::IPCResult
158
GPUChild::RecvGraphicsError(const nsCString& aError)
159
0
{
160
0
  gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
161
0
  if (lf) {
162
0
    std::stringstream message;
163
0
    message << "GP+" << aError.get();
164
0
    lf->UpdateStringsVector(message.str());
165
0
  }
166
0
  return IPC_OK();
167
0
}
168
169
mozilla::ipc::IPCResult
170
GPUChild::RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId)
171
0
{
172
0
  mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
173
0
    GeckoProcessType_GPU,
174
0
    aShmem,
175
0
    aThreadId);
176
0
177
0
  return IPC_OK();
178
0
}
179
180
mozilla::ipc::IPCResult
181
GPUChild::RecvCreateVRProcess()
182
0
{
183
0
  // Make sure create VR process at the main process
184
0
  MOZ_ASSERT(XRE_IsParentProcess());
185
0
  if (gfxPrefs::VRProcessEnabled()) {
186
0
    VRProcessManager::Initialize();
187
0
    VRProcessManager* vr = VRProcessManager::Get();
188
0
    MOZ_ASSERT(vr, "VRProcessManager must be initialized first.");
189
0
190
0
    if (vr) {
191
0
      vr->LaunchVRProcess();
192
0
    }
193
0
  }
194
0
195
0
  return IPC_OK();
196
0
}
197
198
mozilla::ipc::IPCResult
199
GPUChild::RecvNotifyUiObservers(const nsCString& aTopic)
200
0
{
201
0
  nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
202
0
  MOZ_ASSERT(obsSvc);
203
0
  if (obsSvc) {
204
0
    obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
205
0
  }
206
0
  return IPC_OK();
207
0
}
208
209
mozilla::ipc::IPCResult
210
GPUChild::RecvAccumulateChildHistograms(InfallibleTArray<HistogramAccumulation>&& aAccumulations)
211
0
{
212
0
  TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Gpu, aAccumulations);
213
0
  return IPC_OK();
214
0
}
215
216
mozilla::ipc::IPCResult
217
GPUChild::RecvAccumulateChildKeyedHistograms(InfallibleTArray<KeyedHistogramAccumulation>&& aAccumulations)
218
0
{
219
0
  TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Gpu, aAccumulations);
220
0
  return IPC_OK();
221
0
}
222
223
mozilla::ipc::IPCResult
224
GPUChild::RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions)
225
0
{
226
0
  TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Gpu, aScalarActions);
227
0
  return IPC_OK();
228
0
}
229
230
mozilla::ipc::IPCResult
231
GPUChild::RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions)
232
0
{
233
0
  TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Gpu, aScalarActions);
234
0
  return IPC_OK();
235
0
}
236
237
mozilla::ipc::IPCResult
238
GPUChild::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
239
0
{
240
0
  TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
241
0
  return IPC_OK();
242
0
}
243
244
mozilla::ipc::IPCResult
245
GPUChild::RecvRecordDiscardedData(const mozilla::Telemetry::DiscardedData& aDiscardedData)
246
0
{
247
0
  TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Gpu, aDiscardedData);
248
0
  return IPC_OK();
249
0
}
250
251
mozilla::ipc::IPCResult
252
GPUChild::RecvNotifyDeviceReset(const GPUDeviceData& aData)
253
0
{
254
0
  gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
255
0
  mHost->mListener->OnRemoteProcessDeviceReset(mHost);
256
0
  return IPC_OK();
257
0
}
258
259
bool
260
GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
261
                                  const bool& aAnonymize,
262
                                  const bool& aMinimizeMemoryUsage,
263
                                  const MaybeFileDesc& aDMDFile)
264
0
{
265
0
  mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
266
0
  Unused << PGPUChild::SendRequestMemoryReport(
267
0
    aGeneration,
268
0
    aAnonymize,
269
0
    aMinimizeMemoryUsage,
270
0
    aDMDFile);
271
0
  return true;
272
0
}
273
274
mozilla::ipc::IPCResult
275
GPUChild::RecvAddMemoryReport(const MemoryReport& aReport)
276
0
{
277
0
  if (mMemoryReportRequest) {
278
0
    mMemoryReportRequest->RecvReport(aReport);
279
0
  }
280
0
  return IPC_OK();
281
0
}
282
283
mozilla::ipc::IPCResult
284
GPUChild::RecvFinishMemoryReport(const uint32_t& aGeneration)
285
0
{
286
0
  if (mMemoryReportRequest) {
287
0
    mMemoryReportRequest->Finish(aGeneration);
288
0
    mMemoryReportRequest = nullptr;
289
0
  }
290
0
  return IPC_OK();
291
0
}
292
293
void
294
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
295
0
{
296
0
  if (aWhy == AbnormalShutdown) {
297
0
    if (mCrashReporter) {
298
0
      mCrashReporter->GenerateCrashReport(OtherPid());
299
0
      mCrashReporter = nullptr;
300
0
    }
301
0
302
0
    Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
303
0
        nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU)), 1);
304
0
305
0
    // Notify the Telemetry environment so that we can refresh and do a subsession split
306
0
    if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
307
0
      obsvc->NotifyObservers(nullptr, "compositor:process-aborted", nullptr);
308
0
    }
309
0
310
0
  }
311
0
312
0
  gfxVars::RemoveReceiver(this);
313
0
  mHost->OnChannelClosed();
314
0
}
315
316
mozilla::ipc::IPCResult
317
GPUChild::RecvUpdateFeature(const Feature& aFeature, const FeatureFailure& aChange)
318
0
{
319
0
  gfxConfig::SetFailed(aFeature, aChange.status(), aChange.message().get(), aChange.failureId());
320
0
  return IPC_OK();
321
0
}
322
323
mozilla::ipc::IPCResult
324
GPUChild::RecvUsedFallback(const Fallback& aFallback, const nsCString& aMessage)
325
0
{
326
0
  gfxConfig::EnableFallback(aFallback, aMessage.get());
327
0
  return IPC_OK();
328
0
}
329
330
mozilla::ipc::IPCResult
331
GPUChild::RecvBHRThreadHang(const HangDetails& aDetails)
332
0
{
333
0
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
334
0
  if (obs) {
335
0
    // Copy the HangDetails recieved over the network into a nsIHangDetails, and
336
0
    // then fire our own observer notification.
337
0
    // XXX: We should be able to avoid this potentially expensive copy here by
338
0
    // moving our deserialized argument.
339
0
    nsCOMPtr<nsIHangDetails> hangDetails =
340
0
      new nsHangDetails(HangDetails(aDetails));
341
0
    obs->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
342
0
  }
343
0
  return IPC_OK();
344
0
}
345
346
class DeferredDeleteGPUChild : public Runnable
347
{
348
public:
349
  explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
350
    : Runnable("gfx::DeferredDeleteGPUChild")
351
    , mChild(std::move(aChild))
352
0
  {
353
0
  }
354
355
0
  NS_IMETHODIMP Run() override {
356
0
    return NS_OK;
357
0
  }
358
359
private:
360
  UniquePtr<GPUChild> mChild;
361
};
362
363
/* static */ void
364
GPUChild::Destroy(UniquePtr<GPUChild>&& aChild)
365
0
{
366
0
  NS_DispatchToMainThread(new DeferredDeleteGPUChild(std::move(aChild)));
367
0
}
368
369
} // namespace gfx
370
} // namespace mozilla