diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.h | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h new file mode 100644 index 000000000..ef236303a --- /dev/null +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <list> +#include <memory> +#include <mutex> +#include <optional> +#include <thread> +#include <vector> + +#include "common/common_types.h" +#include "common/polyfill_thread.h" +#include "common/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::Nvnflinger { + +class Nvnflinger final { +public: + explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); + ~Nvnflinger(); + + void ShutdownLayers(); + + /// Sets the NVDrv module instance to use to send buffers to the GPU. + void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> 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<u64> 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<u64> 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<u32> 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<Kernel::KReadableEvent*> 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<android::BufferQueueCore> core; + std::unique_ptr<android::BufferQueueProducer> producer; + }; + +private: + [[nodiscard]] std::unique_lock<std::mutex> 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<Nvidia::Module> nvdrv; + s32 disp_fd; + + std::list<VI::Display> 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<Core::Timing::EventType> multi_composition_event; + std::shared_ptr<Core::Timing::EventType> single_composition_event; + + std::shared_ptr<std::mutex> guard; + + Core::System& system; + + Common::Event vsync_signal; + + std::jthread vsync_thread; + + KernelHelpers::ServiceContext service_context; + + HosBinderDriverServer& hos_binder_driver_server; +}; + +} // namespace Service::Nvnflinger |