summaryrefslogtreecommitdiffstats
path: root/gfx/ipc/GPUChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/ipc/GPUChild.cpp')
-rw-r--r--gfx/ipc/GPUChild.cpp329
1 files changed, 329 insertions, 0 deletions
diff --git a/gfx/ipc/GPUChild.cpp b/gfx/ipc/GPUChild.cpp
new file mode 100644
index 0000000000..909d0aad81
--- /dev/null
+++ b/gfx/ipc/GPUChild.cpp
@@ -0,0 +1,329 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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"
+
+#include "GPUProcessHost.h"
+#include "GPUProcessManager.h"
+#include "GfxInfoBase.h"
+#include "VRProcessManager.h"
+#include "gfxConfig.h"
+#include "gfxPlatform.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPrefs_dom.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/TelemetryIPC.h"
+#include "mozilla/dom/CheckerboardReportService.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/MemoryReportRequest.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/gfx/gfxVars.h"
+#if defined(XP_WIN)
+# include "mozilla/gfx/DeviceManagerDx.h"
+#endif
+#include "mozilla/HangDetails.h"
+#include "mozilla/RemoteDecoderManagerChild.h" // For RemoteDecodeIn
+#include "mozilla/Unused.h"
+#include "mozilla/ipc/Endpoint.h"
+#include "mozilla/layers/APZInputBridgeChild.h"
+#include "mozilla/layers/LayerTreeOwnerTracker.h"
+#include "nsIGfxInfo.h"
+#include "nsIObserverService.h"
+
+#ifdef MOZ_GECKO_PROFILER
+# include "ProfilerParent.h"
+#endif
+
+namespace mozilla {
+namespace gfx {
+
+using namespace layers;
+
+GPUChild::GPUChild(GPUProcessHost* aHost) : mHost(aHost), mGPUReady(false) {
+ MOZ_COUNT_CTOR(GPUChild);
+}
+
+GPUChild::~GPUChild() { MOZ_COUNT_DTOR(GPUChild); }
+
+void GPUChild::Init() {
+ nsTArray<GfxVarUpdate> updates = gfxVars::FetchNonDefaultVars();
+
+ DevicePrefs devicePrefs;
+ devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
+ devicePrefs.d3d11Compositing() =
+ gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
+ devicePrefs.oglCompositing() =
+ gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
+ devicePrefs.advancedLayers() = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
+ devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
+ devicePrefs.webGPU() = gfxConfig::GetValue(Feature::WEBGPU);
+ devicePrefs.d3d11HwAngle() = gfxConfig::GetValue(Feature::D3D11_HW_ANGLE);
+
+ nsTArray<LayerTreeIdMapping> mappings;
+ LayerTreeOwnerTracker::Get()->Iterate(
+ [&](LayersId aLayersId, base::ProcessId aProcessId) {
+ mappings.AppendElement(LayerTreeIdMapping(aLayersId, aProcessId));
+ });
+
+ nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+ nsTArray<GfxInfoFeatureStatus> features;
+ if (gfxInfo) {
+ auto* gfxInfoRaw = static_cast<widget::GfxInfoBase*>(gfxInfo.get());
+ features = gfxInfoRaw->GetAllFeatures();
+ }
+
+ SendInit(updates, devicePrefs, mappings, features);
+
+ gfxVars::AddReceiver(this);
+
+#ifdef MOZ_GECKO_PROFILER
+ Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
+#endif
+}
+
+void GPUChild::OnVarChanged(const GfxVarUpdate& aVar) { SendUpdateVar(aVar); }
+
+bool GPUChild::EnsureGPUReady() {
+ if (mGPUReady) {
+ return true;
+ }
+
+ GPUDeviceData data;
+ if (!SendGetDeviceStatus(&data)) {
+ return false;
+ }
+
+ gfxPlatform::GetPlatform()->ImportGPUDeviceData(data);
+ Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2,
+ mHost->GetLaunchTime());
+ mGPUReady = true;
+ return true;
+}
+
+base::ProcessHandle GPUChild::GetChildProcessHandle() {
+ return mHost->GetChildProcessHandle();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvInitComplete(const GPUDeviceData& aData) {
+ // We synchronously requested GPU parameters before this arrived.
+ if (mGPUReady) {
+ return IPC_OK();
+ }
+
+ gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
+ Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_LAUNCH_TIME_MS_2,
+ mHost->GetLaunchTime());
+ mGPUReady = true;
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvReportCheckerboard(
+ const uint32_t& aSeverity, const nsCString& aLog) {
+ layers::CheckerboardEventStorage::Report(aSeverity, std::string(aLog.get()));
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvGraphicsError(const nsCString& aError) {
+ gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
+ if (lf) {
+ std::stringstream message;
+ message << "GP+" << aError.get();
+ lf->UpdateStringsVector(message.str());
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvCreateVRProcess() {
+ // Make sure create VR process at the main process
+ MOZ_ASSERT(XRE_IsParentProcess());
+ if (StaticPrefs::dom_vr_process_enabled_AtStartup()) {
+ VRProcessManager::Initialize();
+ VRProcessManager* vr = VRProcessManager::Get();
+ MOZ_ASSERT(vr, "VRProcessManager must be initialized first.");
+
+ if (vr) {
+ vr->LaunchVRProcess();
+ }
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvShutdownVRProcess() {
+ // Make sure stopping VR process at the main process
+ MOZ_ASSERT(XRE_IsParentProcess());
+ if (StaticPrefs::dom_vr_process_enabled_AtStartup()) {
+ VRProcessManager::Shutdown();
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvNotifyUiObservers(
+ const nsCString& aTopic) {
+ nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
+ MOZ_ASSERT(obsSvc);
+ if (obsSvc) {
+ obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvAccumulateChildHistograms(
+ nsTArray<HistogramAccumulation>&& aAccumulations) {
+ TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Gpu,
+ aAccumulations);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvAccumulateChildKeyedHistograms(
+ nsTArray<KeyedHistogramAccumulation>&& aAccumulations) {
+ TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Gpu,
+ aAccumulations);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvUpdateChildScalars(
+ nsTArray<ScalarAction>&& aScalarActions) {
+ TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Gpu, aScalarActions);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvUpdateChildKeyedScalars(
+ nsTArray<KeyedScalarAction>&& aScalarActions) {
+ TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Gpu,
+ aScalarActions);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvRecordChildEvents(
+ nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents) {
+ TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Gpu, aEvents);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvRecordDiscardedData(
+ const mozilla::Telemetry::DiscardedData& aDiscardedData) {
+ TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Gpu, aDiscardedData);
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvNotifyDeviceReset(
+ const GPUDeviceData& aData) {
+ gfxPlatform::GetPlatform()->ImportGPUDeviceData(aData);
+ mHost->mListener->OnRemoteProcessDeviceReset(mHost);
+ return IPC_OK();
+}
+
+bool GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
+ const bool& aAnonymize,
+ const bool& aMinimizeMemoryUsage,
+ const Maybe<FileDescriptor>& aDMDFile) {
+ mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
+
+ PGPUChild::SendRequestMemoryReport(
+ aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile,
+ [&](const uint32_t& aGeneration2) {
+ if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+ if (GPUChild* child = gpm->GetGPUChild()) {
+ if (child->mMemoryReportRequest) {
+ child->mMemoryReportRequest->Finish(aGeneration2);
+ child->mMemoryReportRequest = nullptr;
+ }
+ }
+ }
+ },
+ [&](mozilla::ipc::ResponseRejectReason) {
+ if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+ if (GPUChild* child = gpm->GetGPUChild()) {
+ child->mMemoryReportRequest = nullptr;
+ }
+ }
+ });
+
+ return true;
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvAddMemoryReport(
+ const MemoryReport& aReport) {
+ if (mMemoryReportRequest) {
+ mMemoryReportRequest->RecvReport(aReport);
+ }
+ return IPC_OK();
+}
+
+void GPUChild::ActorDestroy(ActorDestroyReason aWhy) {
+ if (aWhy == AbnormalShutdown) {
+ GenerateCrashReport(OtherPid());
+
+ Telemetry::Accumulate(
+ Telemetry::SUBPROCESS_ABNORMAL_ABORT,
+ nsDependentCString(XRE_GeckoProcessTypeToString(GeckoProcessType_GPU)),
+ 1);
+
+ // 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);
+ }
+ }
+
+ gfxVars::RemoveReceiver(this);
+ mHost->OnChannelClosed();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvUpdateFeature(
+ const Feature& aFeature, const FeatureFailure& aChange) {
+ gfxConfig::SetFailed(aFeature, aChange.status(), aChange.message().get(),
+ aChange.failureId());
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvUsedFallback(const Fallback& aFallback,
+ const nsCString& aMessage) {
+ gfxConfig::EnableFallback(aFallback, aMessage.get());
+ return IPC_OK();
+}
+
+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), PersistedToDisk::No);
+ obs->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult GPUChild::RecvUpdateMediaCodecsSupported(
+ const PDMFactory::MediaCodecsSupported& aSupported) {
+ dom::ContentParent::BroadcastMediaCodecsSupportedUpdate(
+ RemoteDecodeIn::GpuProcess, aSupported);
+ return IPC_OK();
+}
+
+class DeferredDeleteGPUChild : public Runnable {
+ public:
+ explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
+ : Runnable("gfx::DeferredDeleteGPUChild"), mChild(std::move(aChild)) {}
+
+ NS_IMETHODIMP Run() override { return NS_OK; }
+
+ private:
+ UniquePtr<GPUChild> mChild;
+};
+
+/* static */
+void GPUChild::Destroy(UniquePtr<GPUChild>&& aChild) {
+ NS_DispatchToMainThread(new DeferredDeleteGPUChild(std::move(aChild)));
+}
+
+} // namespace gfx
+} // namespace mozilla