2017-10-28 02:10:06 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2016-06-11 05:27:24 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "GPUChild.h"
|
2016-08-21 06:59:10 +03:00
|
|
|
#include "gfxConfig.h"
|
2016-06-27 09:33:20 +03:00
|
|
|
#include "gfxPrefs.h"
|
2016-06-11 05:37:03 +03:00
|
|
|
#include "GPUProcessHost.h"
|
2016-11-06 22:01:52 +03:00
|
|
|
#include "GPUProcessManager.h"
|
2016-10-20 18:33:40 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2017-02-15 18:25:40 +03:00
|
|
|
#include "mozilla/TelemetryIPC.h"
|
2016-09-22 08:38:44 +03:00
|
|
|
#include "mozilla/dom/CheckerboardReportService.h"
|
2017-01-27 03:35:54 +03:00
|
|
|
#include "mozilla/dom/MemoryReportRequest.h"
|
2016-08-04 21:33:42 +03:00
|
|
|
#include "mozilla/gfx/gfxVars.h"
|
2016-08-21 06:59:11 +03:00
|
|
|
#if defined(XP_WIN)
|
2016-08-24 01:18:55 +03:00
|
|
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
2016-08-21 06:59:11 +03:00
|
|
|
#endif
|
2016-10-12 00:25:41 +03:00
|
|
|
#include "mozilla/ipc/CrashReporterHost.h"
|
2018-03-16 23:28:19 +03:00
|
|
|
#include "mozilla/layers/APZInputBridgeChild.h"
|
2017-04-04 01:13:38 +03:00
|
|
|
#include "mozilla/layers/LayerTreeOwnerTracker.h"
|
2017-03-22 02:39:13 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2018-01-11 01:27:18 +03:00
|
|
|
#include "mozilla/HangDetails.h"
|
2017-07-20 19:49:28 +03:00
|
|
|
#include "nsIObserverService.h"
|
2017-06-02 23:03:39 +03:00
|
|
|
|
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
2017-05-30 22:06:14 +03:00
|
|
|
#include "ProfilerParent.h"
|
2017-06-02 23:03:39 +03:00
|
|
|
#endif
|
2016-06-11 05:27:24 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gfx {
|
|
|
|
|
2017-04-04 01:13:38 +03:00
|
|
|
using namespace layers;
|
|
|
|
|
2016-06-11 05:37:03 +03:00
|
|
|
GPUChild::GPUChild(GPUProcessHost* aHost)
|
2016-08-21 06:59:11 +03:00
|
|
|
: mHost(aHost),
|
|
|
|
mGPUReady(false)
|
2016-06-11 05:27:24 +03:00
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(GPUChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
GPUChild::~GPUChild()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(GPUChild);
|
|
|
|
}
|
|
|
|
|
2016-06-27 09:33:20 +03:00
|
|
|
void
|
|
|
|
GPUChild::Init()
|
|
|
|
{
|
|
|
|
// Build a list of prefs the GPU process will need. Note that because we
|
|
|
|
// limit the GPU process to prefs contained in gfxPrefs, we can simplify
|
|
|
|
// the message in two ways: one, we only need to send its index in gfxPrefs
|
|
|
|
// rather than its name, and two, we only need to send prefs that don't
|
|
|
|
// have their default value.
|
|
|
|
nsTArray<GfxPrefSetting> prefs;
|
|
|
|
for (auto pref : gfxPrefs::all()) {
|
|
|
|
if (pref->HasDefaultValue()) {
|
2016-07-26 09:18:01 +03:00
|
|
|
continue;
|
2016-06-27 09:33:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
GfxPrefValue value;
|
|
|
|
pref->GetCachedValue(&value);
|
|
|
|
prefs.AppendElement(GfxPrefSetting(pref->Index(), value));
|
|
|
|
}
|
|
|
|
|
2016-08-04 21:33:42 +03:00
|
|
|
nsTArray<GfxVarUpdate> updates = gfxVars::FetchNonDefaultVars();
|
2016-08-21 06:59:10 +03:00
|
|
|
|
|
|
|
DevicePrefs devicePrefs;
|
|
|
|
devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
|
|
|
|
devicePrefs.d3d11Compositing() = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
|
|
|
|
devicePrefs.oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
|
2017-06-24 00:23:12 +03:00
|
|
|
devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
|
2016-08-21 06:59:10 +03:00
|
|
|
devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
|
|
|
|
|
2017-04-04 01:13:38 +03:00
|
|
|
nsTArray<LayerTreeIdMapping> mappings;
|
2018-03-25 02:06:01 +03:00
|
|
|
LayerTreeOwnerTracker::Get()->Iterate([&](LayersId aLayersId, base::ProcessId aProcessId) {
|
2017-04-04 01:13:38 +03:00
|
|
|
mappings.AppendElement(LayerTreeIdMapping(aLayersId, aProcessId));
|
|
|
|
});
|
|
|
|
|
|
|
|
SendInit(prefs, updates, devicePrefs, mappings);
|
2016-08-04 21:33:42 +03:00
|
|
|
|
|
|
|
gfxVars::AddReceiver(this);
|
2017-05-23 05:45:35 +03:00
|
|
|
|
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
2017-05-30 22:06:14 +03:00
|
|
|
Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
|
2017-05-23 05:45:35 +03:00
|
|
|
#endif
|
2016-08-04 21:33:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUChild::OnVarChanged(const GfxVarUpdate& aVar)
|
|
|
|
{
|
|
|
|
SendUpdateVar(aVar);
|
2016-06-27 09:33:20 +03:00
|
|
|
}
|
|
|
|
|
2017-03-30 04:23:24 +03:00
|
|
|
bool
|
2016-08-21 06:59:11 +03:00
|
|
|
GPUChild::EnsureGPUReady()
|
|
|
|
{
|
|
|
|
if (mGPUReady) {
|
2017-03-30 04:23:24 +03:00
|
|
|
return true;
|
2016-08-21 06:59:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUDeviceData data;
|
2017-03-30 04:23:24 +03:00
|
|
|
if (!SendGetDeviceStatus(&data)) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-08-21 06:59:11 +03:00
|
|
|
|
|
|
|
gfxPlatform::GetPlatform()->ImportGPUDeviceData(data);
|
2016-12-02 22:59:03 +03:00
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2, mHost->GetLaunchTime());
|
2016-08-21 06:59:11 +03:00
|
|
|
mGPUReady = true;
|
2017-03-30 04:23:24 +03:00
|
|
|
return true;
|
2016-08-21 06:59:11 +03:00
|
|
|
}
|
|
|
|
|
2018-03-16 23:28:19 +03:00
|
|
|
PAPZInputBridgeChild*
|
2018-03-25 02:06:01 +03:00
|
|
|
GPUChild::AllocPAPZInputBridgeChild(const LayersId& aLayersId)
|
2018-03-16 23:28:19 +03:00
|
|
|
{
|
|
|
|
APZInputBridgeChild* child = new APZInputBridgeChild();
|
|
|
|
child->AddRef();
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
GPUChild::DeallocPAPZInputBridgeChild(PAPZInputBridgeChild* aActor)
|
|
|
|
{
|
|
|
|
APZInputBridgeChild* child = static_cast<APZInputBridgeChild*>(aActor);
|
|
|
|
child->Release();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2016-08-21 06:59:11 +03:00
|
|
|
GPUChild::RecvInitComplete(const GPUDeviceData& aData)
|
|
|
|
{
|
|
|
|
// We synchronously requested GPU parameters before this arrived.
|
|
|
|
if (mGPUReady) {
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-08-21 06:59:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
|
2016-12-02 22:59:03 +03:00
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2, mHost->GetLaunchTime());
|
2016-08-21 06:59:11 +03:00
|
|
|
mGPUReady = true;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-08-21 06:59:11 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2016-09-22 08:38:44 +03:00
|
|
|
GPUChild::RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog)
|
|
|
|
{
|
|
|
|
layers::CheckerboardEventStorage::Report(aSeverity, std::string(aLog.get()));
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-09-22 08:38:44 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2016-10-01 00:31:06 +03:00
|
|
|
GPUChild::RecvGraphicsError(const nsCString& aError)
|
|
|
|
{
|
|
|
|
gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
|
|
|
|
if (lf) {
|
|
|
|
std::stringstream message;
|
|
|
|
message << "GP+" << aError.get();
|
|
|
|
lf->UpdateStringsVector(message.str());
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-10-01 00:31:06 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2017-02-16 01:44:29 +03:00
|
|
|
GPUChild::RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId)
|
2016-10-12 00:25:41 +03:00
|
|
|
{
|
2017-02-16 01:44:29 +03:00
|
|
|
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
|
|
|
|
GeckoProcessType_GPU,
|
|
|
|
aShmem,
|
|
|
|
aThreadId);
|
2017-10-10 16:11:07 +03:00
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-10-12 00:25:41 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2016-10-15 15:45:02 +03:00
|
|
|
GPUChild::RecvNotifyUiObservers(const nsCString& aTopic)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
|
|
|
|
MOZ_ASSERT(obsSvc);
|
|
|
|
if (obsSvc) {
|
|
|
|
obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-10-15 15:45:02 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2017-09-13 12:20:36 +03:00
|
|
|
GPUChild::RecvAccumulateChildHistograms(InfallibleTArray<HistogramAccumulation>&& aAccumulations)
|
2016-10-31 08:35:57 +03:00
|
|
|
{
|
2017-05-23 09:47:58 +03:00
|
|
|
TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Gpu, aAccumulations);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-10-31 08:35:57 +03:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2017-09-13 12:20:36 +03:00
|
|
|
GPUChild::RecvAccumulateChildKeyedHistograms(InfallibleTArray<KeyedHistogramAccumulation>&& aAccumulations)
|
2016-10-31 08:35:57 +03:00
|
|
|
{
|
2017-05-23 09:47:58 +03:00
|
|
|
TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Gpu, aAccumulations);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-10-31 08:35:57 +03:00
|
|
|
}
|
|
|
|
|
2017-01-16 07:12:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions)
|
|
|
|
{
|
2017-05-23 09:47:58 +03:00
|
|
|
TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Gpu, aScalarActions);
|
2017-01-16 07:12:00 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions)
|
|
|
|
{
|
2017-05-23 09:47:58 +03:00
|
|
|
TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Gpu, aScalarActions);
|
2017-01-16 07:12:00 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2017-02-14 16:43:51 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents)
|
|
|
|
{
|
2017-05-23 09:47:58 +03:00
|
|
|
TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
|
2017-02-14 16:43:51 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2017-06-09 16:53:42 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvRecordDiscardedData(const mozilla::Telemetry::DiscardedData& aDiscardedData)
|
|
|
|
{
|
|
|
|
TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Gpu, aDiscardedData);
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2016-11-15 06:26:00 +03:00
|
|
|
mozilla::ipc::IPCResult
|
2017-04-05 10:17:36 +03:00
|
|
|
GPUChild::RecvNotifyDeviceReset(const GPUDeviceData& aData)
|
2016-11-06 22:01:52 +03:00
|
|
|
{
|
2017-04-05 10:17:36 +03:00
|
|
|
gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
|
2017-06-15 21:34:00 +03:00
|
|
|
mHost->mListener->OnRemoteProcessDeviceReset(mHost);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-11-06 22:01:52 +03:00
|
|
|
}
|
|
|
|
|
2017-01-27 03:35:54 +03:00
|
|
|
bool
|
|
|
|
GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
|
|
|
|
const bool& aAnonymize,
|
|
|
|
const bool& aMinimizeMemoryUsage,
|
|
|
|
const MaybeFileDesc& aDMDFile)
|
|
|
|
{
|
|
|
|
mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
|
|
|
|
Unused << PGPUChild::SendRequestMemoryReport(
|
|
|
|
aGeneration,
|
|
|
|
aAnonymize,
|
|
|
|
aMinimizeMemoryUsage,
|
|
|
|
aDMDFile);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvAddMemoryReport(const MemoryReport& aReport)
|
|
|
|
{
|
|
|
|
if (mMemoryReportRequest) {
|
|
|
|
mMemoryReportRequest->RecvReport(aReport);
|
|
|
|
}
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvFinishMemoryReport(const uint32_t& aGeneration)
|
|
|
|
{
|
|
|
|
if (mMemoryReportRequest) {
|
|
|
|
mMemoryReportRequest->Finish(aGeneration);
|
|
|
|
mMemoryReportRequest = nullptr;
|
|
|
|
}
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2016-06-11 05:37:03 +03:00
|
|
|
void
|
|
|
|
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
|
|
{
|
2016-10-12 00:25:41 +03:00
|
|
|
if (aWhy == AbnormalShutdown) {
|
|
|
|
if (mCrashReporter) {
|
|
|
|
mCrashReporter->GenerateCrashReport(OtherPid());
|
|
|
|
mCrashReporter = nullptr;
|
|
|
|
}
|
2017-01-27 03:35:55 +03:00
|
|
|
|
2016-10-20 18:33:40 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
|
2017-01-27 03:35:55 +03:00
|
|
|
nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU)), 1);
|
2016-10-27 18:04:50 +03:00
|
|
|
|
|
|
|
// Notify the Telemetry environment so that we can refresh and do a subsession split
|
|
|
|
if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
|
|
|
|
obsvc->NotifyObservers(nullptr, "compositor:process-aborted", nullptr);
|
|
|
|
}
|
|
|
|
|
2016-10-12 00:25:41 +03:00
|
|
|
}
|
|
|
|
|
2016-08-04 21:33:42 +03:00
|
|
|
gfxVars::RemoveReceiver(this);
|
2016-06-11 05:37:03 +03:00
|
|
|
mHost->OnChannelClosed();
|
|
|
|
}
|
|
|
|
|
2017-06-24 00:23:12 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvUpdateFeature(const Feature& aFeature, const FeatureFailure& aChange)
|
|
|
|
{
|
|
|
|
gfxConfig::SetFailed(aFeature, aChange.status(), aChange.message().get(), aChange.failureId());
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2017-07-11 10:13:26 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvUsedFallback(const Fallback& aFallback, const nsCString& aMessage)
|
|
|
|
{
|
|
|
|
gfxConfig::EnableFallback(aFallback, aMessage.get());
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2017-07-20 19:49:28 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
GPUChild::RecvBHRThreadHang(const HangDetails& aDetails)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
// Copy the HangDetails recieved over the network into a nsIHangDetails, and
|
|
|
|
// then fire our own observer notification.
|
|
|
|
// XXX: We should be able to avoid this potentially expensive copy here by
|
|
|
|
// moving our deserialized argument.
|
|
|
|
nsCOMPtr<nsIHangDetails> hangDetails =
|
|
|
|
new nsHangDetails(HangDetails(aDetails));
|
|
|
|
obs->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
|
|
|
|
}
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2016-06-11 05:37:03 +03:00
|
|
|
class DeferredDeleteGPUChild : public Runnable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
|
2017-06-12 22:34:10 +03:00
|
|
|
: Runnable("gfx::DeferredDeleteGPUChild")
|
|
|
|
, mChild(Move(aChild))
|
2016-06-11 05:37:03 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP Run() override {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
UniquePtr<GPUChild> mChild;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
GPUChild::Destroy(UniquePtr<GPUChild>&& aChild)
|
|
|
|
{
|
|
|
|
NS_DispatchToMainThread(new DeferredDeleteGPUChild(Move(aChild)));
|
|
|
|
}
|
|
|
|
|
2016-06-11 05:27:24 +03:00
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|