summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nvnflinger/nvnflinger.h
blob: f5d73acdbbdb0ee494800b436ae3590246dffa19 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// 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 FbShareBufferManager;
class HosBinderDriverServer;

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]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, 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;

    FbShareBufferManager& GetSystemBufferManager();

private:
    struct Layer {
        std::unique_ptr<android::BufferQueueCore> core;
        std::unique_ptr<android::BufferQueueProducer> producer;
    };

    friend class FbShareBufferManager;

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,
    /// 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;

    bool is_abandoned = false;

    /// Event that handles screen composition.
    std::shared_ptr<Core::Timing::EventType> multi_composition_event;
    std::shared_ptr<Core::Timing::EventType> single_composition_event;

    std::unique_ptr<FbShareBufferManager> system_buffer_manager;

    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