/* -*- 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 "VRParent.h" #include "VRGPUParent.h" #include "gfxConfig.h" #include "nsDebugImpl.h" #include "nsThreadManager.h" #include "ProcessUtils.h" #include "mozilla/dom/MemoryReportRequest.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/ipc/CrashReporterClient.h" #include "mozilla/ipc/ProcessChild.h" #include "mozilla/Preferences.h" #if defined(XP_WIN) # include # include "mozilla/gfx/DeviceManagerDx.h" #else # include #endif namespace mozilla { namespace gfx { using mozilla::ipc::IPCResult; VRParent::VRParent() : mVRGPUParent(nullptr) {} IPCResult VRParent::RecvNewGPUVRManager(Endpoint&& aEndpoint) { RefPtr vrGPUParent = VRGPUParent::CreateForGPU(std::move(aEndpoint)); if (!vrGPUParent) { return IPC_FAIL_NO_REASON(this); } mVRGPUParent = std::move(vrGPUParent); return IPC_OK(); } IPCResult VRParent::RecvInit(nsTArray&& vars, const DevicePrefs& devicePrefs) { Unused << SendInitComplete(); for (const auto& var : vars) { gfxVars::ApplyUpdate(var); } // Inherit device preferences. gfxConfig::Inherit(Feature::HW_COMPOSITING, devicePrefs.hwCompositing()); gfxConfig::Inherit(Feature::D3D11_COMPOSITING, devicePrefs.d3d11Compositing()); gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, devicePrefs.oglCompositing()); gfxConfig::Inherit(Feature::ADVANCED_LAYERS, devicePrefs.advancedLayers()); gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1()); #if defined(XP_WIN) if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { DeviceManagerDx::Get()->CreateCompositorDevices(); } #endif return IPC_OK(); } IPCResult VRParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) { gfxVars::ApplyUpdate(aUpdate); return IPC_OK(); } mozilla::ipc::IPCResult VRParent::RecvPreferenceUpdate(const Pref& aPref) { Preferences::SetPreference(aPref); return IPC_OK(); } mozilla::ipc::IPCResult VRParent::RecvOpenVRControllerActionPathToVR( const nsCString& aPath) { mOpenVRControllerAction = aPath; return IPC_OK(); } mozilla::ipc::IPCResult VRParent::RecvOpenVRControllerManifestPathToVR( const VRControllerType& aType, const nsCString& aPath) { mOpenVRControllerManifest.Put(static_cast(aType), aPath); return IPC_OK(); } mozilla::ipc::IPCResult VRParent::RecvRequestMemoryReport( const uint32_t& aGeneration, const bool& aAnonymize, const bool& aMinimizeMemoryUsage, const Maybe& aDMDFile, const RequestMemoryReportResolver& aResolver) { MOZ_ASSERT(XRE_IsVRProcess()); nsPrintfCString processName("VR (pid %u)", (unsigned)getpid()); mozilla::dom::MemoryReportRequestClient::Start( aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName, [&](const MemoryReport& aReport) { Unused << SendAddMemoryReport(aReport); }, aResolver); return IPC_OK(); } void VRParent::ActorDestroy(ActorDestroyReason aWhy) { if (AbnormalShutdown == aWhy) { NS_WARNING("Shutting down VR process early due to a crash!"); ipc::ProcessChild::QuickExit(); } if (mVRGPUParent && !mVRGPUParent->IsClosed()) { mVRGPUParent->Close(); } mVRGPUParent = nullptr; #ifndef NS_FREE_PERMANENT_DATA // No point in going through XPCOM shutdown because we don't keep persistent // state. ProcessChild::QuickExit(); #endif #if defined(XP_WIN) DeviceManagerDx::Shutdown(); #endif gfxVars::Shutdown(); gfxConfig::Shutdown(); ipc::CrashReporterClient::DestroySingleton(); // Only calling XRE_ShutdownChildProcess() at the child process // instead of the main process. Otherwise, it will close all child processes // that are spawned from the main process. XRE_ShutdownChildProcess(); } bool VRParent::Init(base::ProcessId aParentPid, const char* aParentBuildID, MessageLoop* aIOLoop, UniquePtr aChannel) { // Initialize the thread manager before starting IPC. Otherwise, messages // may be posted to the main thread and we won't be able to process them. if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) { return false; } // Now it's safe to start IPC. if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) { return false; } nsDebugImpl::SetMultiprocessMode("VR"); // This must be checked before any IPDL message, which may hit sentinel // errors due to parent and content processes having different // versions. MessageChannel* channel = GetIPCChannel(); if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) { // We need to quit this process if the buildID doesn't match the parent's. // This can occur when an update occurred in the background. ipc::ProcessChild::QuickExit(); } // Init crash reporter support. ipc::CrashReporterClient::InitSingleton(this); gfxConfig::Init(); gfxVars::Initialize(); #if defined(XP_WIN) DeviceManagerDx::Init(); #endif if (NS_FAILED(NS_InitMinimalXPCOM())) { return false; } mozilla::ipc::SetThisProcessName("VR Process"); return true; } bool VRParent::GetOpenVRControllerActionPath(nsCString* aPath) { if (!mOpenVRControllerAction.IsEmpty()) { *aPath = mOpenVRControllerAction; return true; } return false; } bool VRParent::GetOpenVRControllerManifestPath(VRControllerType aType, nsCString* aPath) { return mOpenVRControllerManifest.Get(static_cast(aType), aPath); } } // namespace gfx } // namespace mozilla