// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once #include #include #include #include #include #include #include "common/common_types.h" #include "common/polyfill_thread.h" #include "core/hle/result.h" #include "core/hle/service/kernel_helpers.h" namespace Common { class Event; } // namespace Common namespace Core::Timing { class CoreTiming; struct EventType; } // namespace Core::Timing namespace Kernel { class KReadableEvent; } // namespace Kernel namespace Service::Nvidia { class Module; } // namespace Service::Nvidia namespace Service::VI { class Display; class Layer; } // namespace Service::VI namespace Service::android { class BufferQueueCore; class BufferQueueProducer; } // namespace Service::android namespace Service::NVFlinger { class NVFlinger final { public: explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); ~NVFlinger(); void ShutdownLayers(); /// Sets the NVDrv module instance to use to send buffers to the GPU. void SetNVDrvInstance(std::shared_ptr instance); /// Opens the specified display and returns the ID. /// /// If an invalid display name is provided, then an empty optional is returned. [[nodiscard]] std::optional OpenDisplay(std::string_view name); /// Closes the specified display by its ID. /// /// Returns false if an invalid display ID is provided. [[nodiscard]] bool CloseDisplay(u64 display_id); /// Creates a layer on the specified display and returns the layer ID. /// /// If an invalid display ID is specified, then an empty optional is returned. [[nodiscard]] std::optional CreateLayer(u64 display_id); /// Closes a layer on all displays for the given layer ID. void CloseLayer(u64 layer_id); /// Finds the buffer queue ID of the specified layer in the specified display. /// /// If an invalid display ID or layer ID is provided, then an empty optional is returned. [[nodiscard]] std::optional FindBufferQueueId(u64 display_id, u64 layer_id); /// Gets the vsync event for the specified display. /// /// If an invalid display ID is provided, then VI::ResultNotFound is returned. /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. [[nodiscard]] ResultVal FindVsyncEvent(u64 display_id); /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when /// finished. void Compose(); [[nodiscard]] s64 GetNextTicks() const; private: struct Layer { std::unique_ptr core; std::unique_ptr producer; }; private: [[nodiscard]] std::unique_lock Lock() const { return std::unique_lock{*guard}; } /// Finds the display identified by the specified ID. [[nodiscard]] VI::Display* FindDisplay(u64 display_id); /// Finds the display identified by the specified ID. [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; /// Finds the layer identified by the specified ID in the desired display. [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); /// Finds the layer identified by the specified ID in the desired display. [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; /// Finds the layer identified by the specified ID in the desired display, /// or creates the layer if it is not found. /// To be used when the system expects the specified ID to already exist. [[nodiscard]] VI::Layer* FindOrCreateLayer(u64 display_id, u64 layer_id); /// Creates a layer with the specified layer ID in the desired display. void CreateLayerAtId(VI::Display& display, u64 layer_id); void SplitVSync(std::stop_token stop_token); std::shared_ptr nvdrv; s32 disp_fd; std::list displays; /// Id to use for the next layer that is created, this counter is shared among all displays. u64 next_layer_id = 1; /// Id to use for the next buffer queue that is created, this counter is shared among all /// layers. u32 next_buffer_queue_id = 1; s32 swap_interval = 1; /// Event that handles screen composition. std::shared_ptr multi_composition_event; std::shared_ptr single_composition_event; std::shared_ptr guard; Core::System& system; std::atomic vsync_signal; std::jthread vsync_thread; KernelHelpers::ServiceContext service_context; HosBinderDriverServer& hos_binder_driver_server; }; } // namespace Service::NVFlinger