diff options
author | pineappleEA <pineaea@gmail.com> | 2024-02-14 20:17:22 +0100 |
---|---|---|
committer | pineappleEA <pineaea@gmail.com> | 2024-02-14 20:17:22 +0100 |
commit | 9cc5d38fdf3d2e8f77a7d79f937d04cdabbc3a2e (patch) | |
tree | 7871b215bd0a013d3add9c760efcd8f51eba541a | |
parent | 603970064d5714da3c58eac0d9f95516b81d7892 (diff) |
early-access version 4139EA-4139
25 files changed, 1228 insertions, 1004 deletions
@@ -1,7 +1,7 @@ | |||
1 | yuzu emulator early access | 1 | yuzu emulator early access |
2 | ============= | 2 | ============= |
3 | 3 | ||
4 | This is the source code for early-access 4138. | 4 | This is the source code for early-access 4139. |
5 | 5 | ||
6 | ## Legal Notice | 6 | ## Legal Notice |
7 | 7 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 23fd1401c..2701b481d 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
@@ -959,14 +959,26 @@ add_library(core STATIC | |||
959 | hle/service/vi/display/vi_display.h | 959 | hle/service/vi/display/vi_display.h |
960 | hle/service/vi/layer/vi_layer.cpp | 960 | hle/service/vi/layer/vi_layer.cpp |
961 | hle/service/vi/layer/vi_layer.h | 961 | hle/service/vi/layer/vi_layer.h |
962 | hle/service/vi/application_display_service.cpp | ||
963 | hle/service/vi/application_display_service.h | ||
964 | hle/service/vi/application_root_service.cpp | ||
965 | hle/service/vi/application_root_service.h | ||
966 | hle/service/vi/hos_binder_driver.cpp | ||
967 | hle/service/vi/hos_binder_driver.h | ||
968 | hle/service/vi/manager_display_service.cpp | ||
969 | hle/service/vi/manager_display_service.h | ||
970 | hle/service/vi/manager_root_service.cpp | ||
971 | hle/service/vi/manager_root_service.h | ||
972 | hle/service/vi/service_creator.cpp | ||
973 | hle/service/vi/service_creator.h | ||
974 | hle/service/vi/system_display_service.cpp | ||
975 | hle/service/vi/system_display_service.h | ||
976 | hle/service/vi/system_root_service.cpp | ||
977 | hle/service/vi/system_root_service.h | ||
978 | hle/service/vi/vi_results.h | ||
979 | hle/service/vi/vi_types.h | ||
962 | hle/service/vi/vi.cpp | 980 | hle/service/vi/vi.cpp |
963 | hle/service/vi/vi.h | 981 | hle/service/vi/vi.h |
964 | hle/service/vi/vi_m.cpp | ||
965 | hle/service/vi/vi_m.h | ||
966 | hle/service/vi/vi_s.cpp | ||
967 | hle/service/vi/vi_s.h | ||
968 | hle/service/vi/vi_u.cpp | ||
969 | hle/service/vi/vi_u.h | ||
970 | internal_network/network.cpp | 982 | internal_network/network.cpp |
971 | internal_network/network.h | 983 | internal_network/network.h |
972 | internal_network/network_interface.cpp | 984 | internal_network/network_interface.cpp |
diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index 12d7e8cb1..548498e83 100755 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "core/hle/service/pm/pm.h" | 11 | #include "core/hle/service/pm/pm.h" |
12 | #include "core/hle/service/sm/sm.h" | 12 | #include "core/hle/service/sm/sm.h" |
13 | #include "core/hle/service/vi/vi.h" | 13 | #include "core/hle/service/vi/vi.h" |
14 | #include "core/hle/service/vi/vi_types.h" | ||
14 | 15 | ||
15 | namespace Service::AM { | 16 | namespace Service::AM { |
16 | 17 | ||
diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h index aef1477e3..179938192 100755 --- a/src/core/hle/service/nvnflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | #pragma once | 7 | #pragma once |
8 | 8 | ||
9 | #include <span> | ||
10 | |||
9 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
10 | 12 | ||
11 | namespace Kernel { | 13 | namespace Kernel { |
@@ -38,7 +40,8 @@ enum class TransactionId { | |||
38 | class IBinder { | 40 | class IBinder { |
39 | public: | 41 | public: |
40 | virtual ~IBinder() = default; | 42 | virtual ~IBinder() = default; |
41 | virtual void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 0; | 43 | virtual void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, |
44 | std::span<u8> parcel_reply) = 0; | ||
42 | virtual Kernel::KReadableEvent& GetNativeHandle() = 0; | 45 | virtual Kernel::KReadableEvent& GetNativeHandle() = 0; |
43 | }; | 46 | }; |
44 | 47 | ||
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 5d8762d25..ec83beb9b 100755 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp | |||
@@ -807,9 +807,10 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | |||
807 | return Status::NoError; | 807 | return Status::NoError; |
808 | } | 808 | } |
809 | 809 | ||
810 | void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) { | 810 | void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data, |
811 | std::span<u8> parcel_reply) { | ||
811 | Status status{Status::NoError}; | 812 | Status status{Status::NoError}; |
812 | InputParcel parcel_in{ctx.ReadBuffer()}; | 813 | InputParcel parcel_in{parcel_data}; |
813 | OutputParcel parcel_out{}; | 814 | OutputParcel parcel_out{}; |
814 | 815 | ||
815 | switch (code) { | 816 | switch (code) { |
@@ -917,7 +918,9 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u | |||
917 | 918 | ||
918 | parcel_out.Write(status); | 919 | parcel_out.Write(status); |
919 | 920 | ||
920 | ctx.WriteBuffer(parcel_out.Serialize()); | 921 | const auto serialized = parcel_out.Serialize(); |
922 | std::memcpy(parcel_reply.data(), serialized.data(), | ||
923 | std::min(parcel_reply.size(), serialized.size())); | ||
921 | } | 924 | } |
922 | 925 | ||
923 | Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { | 926 | Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { |
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 64c17d56c..4682b0f84 100755 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h | |||
@@ -47,7 +47,8 @@ public: | |||
47 | Service::Nvidia::NvCore::NvMap& nvmap_); | 47 | Service::Nvidia::NvCore::NvMap& nvmap_); |
48 | ~BufferQueueProducer(); | 48 | ~BufferQueueProducer(); |
49 | 49 | ||
50 | void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) override; | 50 | void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, |
51 | std::span<u8> parcel_reply) override; | ||
51 | 52 | ||
52 | Kernel::KReadableEvent& GetNativeHandle() override; | 53 | Kernel::KReadableEvent& GetNativeHandle() override; |
53 | 54 | ||
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp new file mode 100755 index 000000000..78229e30f --- /dev/null +++ b/src/core/hle/service/vi/application_display_service.cpp | |||
@@ -0,0 +1,319 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_serialization.h" | ||
5 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
6 | #include "core/hle/service/nvnflinger/parcel.h" | ||
7 | #include "core/hle/service/vi/application_display_service.h" | ||
8 | #include "core/hle/service/vi/hos_binder_driver.h" | ||
9 | #include "core/hle/service/vi/manager_display_service.h" | ||
10 | #include "core/hle/service/vi/system_display_service.h" | ||
11 | #include "core/hle/service/vi/vi_results.h" | ||
12 | |||
13 | namespace Service::VI { | ||
14 | |||
15 | IApplicationDisplayService::IApplicationDisplayService( | ||
16 | Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
17 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||
18 | : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger}, | ||
19 | m_hos_binder_driver_server{hos_binder_driver_server} { | ||
20 | |||
21 | // clang-format off | ||
22 | static const FunctionInfo functions[] = { | ||
23 | {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, | ||
24 | {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"}, | ||
25 | {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"}, | ||
26 | {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"}, | ||
27 | {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"}, | ||
28 | {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"}, | ||
29 | {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"}, | ||
30 | {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"}, | ||
31 | {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"}, | ||
32 | {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"}, | ||
33 | {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"}, | ||
34 | {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"}, | ||
35 | {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"}, | ||
36 | {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"}, | ||
37 | {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"}, | ||
38 | {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"}, | ||
39 | {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"}, | ||
40 | {2451, nullptr, "GetIndirectLayerImageCropMap"}, | ||
41 | {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"}, | ||
42 | {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"}, | ||
43 | {5203, nullptr, "GetDisplayVsyncEventForDebug"}, | ||
44 | }; | ||
45 | // clang-format on | ||
46 | |||
47 | RegisterHandlers(functions); | ||
48 | } | ||
49 | |||
50 | IApplicationDisplayService::~IApplicationDisplayService() { | ||
51 | for (const auto layer_id : m_stray_layer_ids) { | ||
52 | m_nvnflinger.DestroyLayer(layer_id); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | Result IApplicationDisplayService::GetRelayService( | ||
57 | Out<SharedPointer<IHOSBinderDriver>> out_relay_service) { | ||
58 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
59 | *out_relay_service = std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); | ||
60 | R_SUCCEED(); | ||
61 | } | ||
62 | |||
63 | Result IApplicationDisplayService::GetSystemDisplayService( | ||
64 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { | ||
65 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
66 | *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_nvnflinger); | ||
67 | R_SUCCEED(); | ||
68 | } | ||
69 | |||
70 | Result IApplicationDisplayService::GetManagerDisplayService( | ||
71 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { | ||
72 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
73 | *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_nvnflinger); | ||
74 | R_SUCCEED(); | ||
75 | } | ||
76 | |||
77 | Result IApplicationDisplayService::GetIndirectDisplayTransactionService( | ||
78 | Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service) { | ||
79 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
80 | *out_indirect_display_transaction_service = | ||
81 | std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); | ||
82 | R_SUCCEED(); | ||
83 | } | ||
84 | |||
85 | Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { | ||
86 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
87 | |||
88 | display_name[display_name.size() - 1] = '\0'; | ||
89 | ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, | ||
90 | "Non-default displays aren't supported yet"); | ||
91 | |||
92 | const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); | ||
93 | if (!display_id) { | ||
94 | LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); | ||
95 | R_THROW(VI::ResultNotFound); | ||
96 | } | ||
97 | |||
98 | *out_display_id = *display_id; | ||
99 | R_SUCCEED(); | ||
100 | } | ||
101 | |||
102 | Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { | ||
103 | LOG_DEBUG(Service_VI, "called"); | ||
104 | R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"})); | ||
105 | } | ||
106 | |||
107 | Result IApplicationDisplayService::CloseDisplay(u64 display_id) { | ||
108 | LOG_DEBUG(Service_VI, "called"); | ||
109 | R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id)); | ||
110 | R_THROW(ResultUnknown); | ||
111 | } | ||
112 | |||
113 | Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { | ||
114 | LOG_DEBUG(Service_VI, "called"); | ||
115 | |||
116 | // This literally does nothing internally in the actual service itself, | ||
117 | // and just returns a successful result code regardless of the input. | ||
118 | R_SUCCEED(); | ||
119 | } | ||
120 | |||
121 | Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, | ||
122 | u64 display_id) { | ||
123 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||
124 | |||
125 | // This only returns the fixed values of 1280x720 and makes no distinguishing | ||
126 | // between docked and undocked dimensions. | ||
127 | *out_width = static_cast<s64>(DisplayResolution::UndockedWidth); | ||
128 | *out_height = static_cast<s64>(DisplayResolution::UndockedHeight); | ||
129 | R_SUCCEED(); | ||
130 | } | ||
131 | |||
132 | Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) { | ||
133 | LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id); | ||
134 | |||
135 | if (scale_mode > NintendoScaleMode::PreserveAspectRatio) { | ||
136 | LOG_ERROR(Service_VI, "Invalid scaling mode provided."); | ||
137 | R_THROW(VI::ResultOperationFailed); | ||
138 | } | ||
139 | |||
140 | if (scale_mode != NintendoScaleMode::ScaleToWindow && | ||
141 | scale_mode != NintendoScaleMode::PreserveAspectRatio) { | ||
142 | LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); | ||
143 | R_THROW(VI::ResultNotSupported); | ||
144 | } | ||
145 | |||
146 | R_SUCCEED(); | ||
147 | } | ||
148 | |||
149 | Result IApplicationDisplayService::ListDisplays( | ||
150 | Out<u64> out_count, OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays) { | ||
151 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
152 | |||
153 | if (out_displays.size() > 0) { | ||
154 | out_displays[0] = DisplayInfo{}; | ||
155 | *out_count = 1; | ||
156 | } else { | ||
157 | *out_count = 0; | ||
158 | } | ||
159 | |||
160 | R_SUCCEED(); | ||
161 | } | ||
162 | |||
163 | Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, | ||
164 | OutBuffer<BufferAttr_HipcMapAlias> out_native_window, | ||
165 | DisplayName display_name, u64 layer_id, | ||
166 | ClientAppletResourceUserId aruid) { | ||
167 | display_name[display_name.size() - 1] = '\0'; | ||
168 | |||
169 | LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); | ||
170 | |||
171 | const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); | ||
172 | if (!display_id) { | ||
173 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||
174 | R_THROW(VI::ResultNotFound); | ||
175 | } | ||
176 | |||
177 | const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id); | ||
178 | if (!buffer_queue_id) { | ||
179 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||
180 | R_THROW(VI::ResultNotFound); | ||
181 | } | ||
182 | |||
183 | if (!m_nvnflinger.OpenLayer(layer_id)) { | ||
184 | LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||
185 | R_THROW(VI::ResultOperationFailed); | ||
186 | } | ||
187 | |||
188 | android::OutputParcel parcel; | ||
189 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||
190 | |||
191 | const auto buffer = parcel.Serialize(); | ||
192 | std::memcpy(out_native_window.data(), buffer.data(), | ||
193 | std::min(out_native_window.size(), buffer.size())); | ||
194 | *out_size = buffer.size(); | ||
195 | |||
196 | R_SUCCEED(); | ||
197 | } | ||
198 | |||
199 | Result IApplicationDisplayService::CloseLayer(u64 layer_id) { | ||
200 | LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); | ||
201 | |||
202 | if (!m_nvnflinger.CloseLayer(layer_id)) { | ||
203 | LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||
204 | R_THROW(VI::ResultOperationFailed); | ||
205 | } | ||
206 | |||
207 | R_SUCCEED(); | ||
208 | } | ||
209 | |||
210 | Result IApplicationDisplayService::CreateStrayLayer( | ||
211 | Out<u64> out_layer_id, Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window, | ||
212 | u32 flags, u64 display_id) { | ||
213 | LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); | ||
214 | |||
215 | const auto layer_id = m_nvnflinger.CreateLayer(display_id); | ||
216 | if (!layer_id) { | ||
217 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||
218 | R_THROW(VI::ResultNotFound); | ||
219 | } | ||
220 | |||
221 | m_stray_layer_ids.push_back(*layer_id); | ||
222 | const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id); | ||
223 | if (!buffer_queue_id) { | ||
224 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||
225 | R_THROW(VI::ResultNotFound); | ||
226 | } | ||
227 | |||
228 | android::OutputParcel parcel; | ||
229 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||
230 | |||
231 | const auto buffer = parcel.Serialize(); | ||
232 | std::memcpy(out_native_window.data(), buffer.data(), | ||
233 | std::min(out_native_window.size(), buffer.size())); | ||
234 | |||
235 | *out_layer_id = *layer_id; | ||
236 | *out_size = buffer.size(); | ||
237 | |||
238 | R_SUCCEED(); | ||
239 | } | ||
240 | |||
241 | Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { | ||
242 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | ||
243 | m_nvnflinger.DestroyLayer(layer_id); | ||
244 | R_SUCCEED(); | ||
245 | } | ||
246 | |||
247 | Result IApplicationDisplayService::GetDisplayVsyncEvent( | ||
248 | OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { | ||
249 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||
250 | |||
251 | const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id); | ||
252 | if (result != ResultSuccess) { | ||
253 | if (result == ResultNotFound) { | ||
254 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||
255 | } | ||
256 | |||
257 | R_THROW(result); | ||
258 | } | ||
259 | |||
260 | R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); | ||
261 | m_vsync_event_fetched = true; | ||
262 | |||
263 | R_SUCCEED(); | ||
264 | } | ||
265 | |||
266 | Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, | ||
267 | NintendoScaleMode mode) { | ||
268 | LOG_DEBUG(Service_VI, "called mode={}", mode); | ||
269 | |||
270 | switch (mode) { | ||
271 | case NintendoScaleMode::None: | ||
272 | *out_scaling_mode = ConvertedScaleMode::None; | ||
273 | R_SUCCEED(); | ||
274 | case NintendoScaleMode::Freeze: | ||
275 | *out_scaling_mode = ConvertedScaleMode::Freeze; | ||
276 | R_SUCCEED(); | ||
277 | case NintendoScaleMode::ScaleToWindow: | ||
278 | *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; | ||
279 | R_SUCCEED(); | ||
280 | case NintendoScaleMode::ScaleAndCrop: | ||
281 | *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; | ||
282 | R_SUCCEED(); | ||
283 | case NintendoScaleMode::PreserveAspectRatio: | ||
284 | *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; | ||
285 | R_SUCCEED(); | ||
286 | default: | ||
287 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | ||
288 | R_THROW(VI::ResultOperationFailed); | ||
289 | } | ||
290 | } | ||
291 | |||
292 | Result IApplicationDisplayService::GetIndirectLayerImageMap( | ||
293 | Out<u64> out_size, Out<u64> out_stride, | ||
294 | OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer, | ||
295 | s64 width, s64 height, u64 indirect_layer_consumer_handle, ClientAppletResourceUserId aruid) { | ||
296 | LOG_WARNING( | ||
297 | Service_VI, | ||
298 | "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, aruid={:#x}", | ||
299 | width, height, indirect_layer_consumer_handle, aruid.pid); | ||
300 | *out_size = 0; | ||
301 | *out_stride = 0; | ||
302 | R_SUCCEED(); | ||
303 | } | ||
304 | |||
305 | Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, | ||
306 | Out<s64> out_alignment, | ||
307 | s64 width, s64 height) { | ||
308 | LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); | ||
309 | |||
310 | constexpr u64 base_size = 0x20000; | ||
311 | const auto texture_size = width * height * 4; | ||
312 | |||
313 | *out_alignment = 0x1000; | ||
314 | *out_size = (texture_size + base_size - 1) / base_size * base_size; | ||
315 | |||
316 | R_SUCCEED(); | ||
317 | } | ||
318 | |||
319 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h new file mode 100755 index 000000000..5dff4bb31 --- /dev/null +++ b/src/core/hle/service/vi/application_display_service.h | |||
@@ -0,0 +1,65 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_types.h" | ||
5 | #include "core/hle/service/service.h" | ||
6 | #include "core/hle/service/vi/vi_types.h" | ||
7 | |||
8 | namespace Kernel { | ||
9 | class KReadableEvent; | ||
10 | } | ||
11 | |||
12 | namespace Service::VI { | ||
13 | |||
14 | class IHOSBinderDriver; | ||
15 | class IManagerDisplayService; | ||
16 | class ISystemDisplayService; | ||
17 | |||
18 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||
19 | public: | ||
20 | IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
21 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
22 | ~IApplicationDisplayService() override; | ||
23 | |||
24 | private: | ||
25 | Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service); | ||
26 | Result GetSystemDisplayService( | ||
27 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service); | ||
28 | Result GetManagerDisplayService( | ||
29 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service); | ||
30 | Result GetIndirectDisplayTransactionService( | ||
31 | Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service); | ||
32 | Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name); | ||
33 | Result OpenDefaultDisplay(Out<u64> out_display_id); | ||
34 | Result CloseDisplay(u64 display_id); | ||
35 | Result SetDisplayEnabled(u32 state, u64 display_id); | ||
36 | Result GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, u64 display_id); | ||
37 | Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id); | ||
38 | Result ListDisplays(Out<u64> out_count, | ||
39 | OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays); | ||
40 | Result OpenLayer(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window, | ||
41 | DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid); | ||
42 | Result CloseLayer(u64 layer_id); | ||
43 | Result CreateStrayLayer(Out<u64> out_layer_id, Out<u64> out_size, | ||
44 | OutBuffer<BufferAttr_HipcMapAlias> out_native_window, u32 flags, | ||
45 | u64 display_id); | ||
46 | Result DestroyStrayLayer(u64 layer_id); | ||
47 | Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, | ||
48 | u64 display_id); | ||
49 | Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode); | ||
50 | Result GetIndirectLayerImageMap( | ||
51 | Out<u64> out_size, Out<u64> out_stride, | ||
52 | OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer, | ||
53 | s64 width, s64 height, u64 indirect_layer_consumer_handle, | ||
54 | ClientAppletResourceUserId aruid); | ||
55 | Result GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, Out<s64> out_alignment, | ||
56 | s64 width, s64 height); | ||
57 | |||
58 | private: | ||
59 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
60 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||
61 | std::vector<u64> m_stray_layer_ids; | ||
62 | bool m_vsync_event_fetched{false}; | ||
63 | }; | ||
64 | |||
65 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp new file mode 100755 index 000000000..7af7f062c --- /dev/null +++ b/src/core/hle/service/vi/application_root_service.cpp | |||
@@ -0,0 +1,34 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_serialization.h" | ||
5 | #include "core/hle/service/vi/application_display_service.h" | ||
6 | #include "core/hle/service/vi/application_root_service.h" | ||
7 | #include "core/hle/service/vi/service_creator.h" | ||
8 | #include "core/hle/service/vi/vi.h" | ||
9 | #include "core/hle/service/vi/vi_types.h" | ||
10 | |||
11 | namespace Service::VI { | ||
12 | |||
13 | IApplicationRootService::IApplicationRootService( | ||
14 | Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
15 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||
16 | : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||
17 | hos_binder_driver_server} { | ||
18 | static const FunctionInfo functions[] = { | ||
19 | {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, | ||
20 | {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||
21 | }; | ||
22 | RegisterHandlers(functions); | ||
23 | } | ||
24 | |||
25 | IApplicationRootService::~IApplicationRootService() = default; | ||
26 | |||
27 | Result IApplicationRootService::GetDisplayService( | ||
28 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | ||
29 | LOG_DEBUG(Service_VI, "called"); | ||
30 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | ||
31 | m_hos_binder_driver_server, Permission::User, policy)); | ||
32 | } | ||
33 | |||
34 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h new file mode 100755 index 000000000..9dbf28cb4 --- /dev/null +++ b/src/core/hle/service/vi/application_root_service.h | |||
@@ -0,0 +1,39 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | #include "core/hle/service/cmif_types.h" | ||
7 | #include "core/hle/service/service.h" | ||
8 | |||
9 | namespace Core { | ||
10 | class System; | ||
11 | } | ||
12 | |||
13 | namespace Service::Nvnflinger { | ||
14 | class HosBinderDriverServer; | ||
15 | class Nvnflinger; | ||
16 | } // namespace Service::Nvnflinger | ||
17 | |||
18 | namespace Service::VI { | ||
19 | |||
20 | class IApplicationDisplayService; | ||
21 | enum class Policy : u32; | ||
22 | |||
23 | class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { | ||
24 | public: | ||
25 | explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
27 | ~IApplicationRootService() override; | ||
28 | |||
29 | private: | ||
30 | Result GetDisplayService( | ||
31 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | ||
32 | Policy policy); | ||
33 | |||
34 | private: | ||
35 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
36 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||
37 | }; | ||
38 | |||
39 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/hos_binder_driver.cpp b/src/core/hle/service/vi/hos_binder_driver.cpp new file mode 100755 index 000000000..ba0317245 --- /dev/null +++ b/src/core/hle/service/vi/hos_binder_driver.cpp | |||
@@ -0,0 +1,53 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_serialization.h" | ||
5 | #include "core/hle/service/nvnflinger/binder.h" | ||
6 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||
7 | #include "core/hle/service/vi/hos_binder_driver.h" | ||
8 | |||
9 | namespace Service::VI { | ||
10 | |||
11 | IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server) | ||
12 | : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server) { | ||
13 | static const FunctionInfo functions[] = { | ||
14 | {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"}, | ||
15 | {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, | ||
16 | {2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"}, | ||
17 | {3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"}, | ||
18 | }; | ||
19 | RegisterHandlers(functions); | ||
20 | } | ||
21 | |||
22 | IHOSBinderDriver::~IHOSBinderDriver() = default; | ||
23 | |||
24 | Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id, | ||
25 | InBuffer<BufferAttr_HipcMapAlias> parcel_data, | ||
26 | OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, | ||
27 | u32 flags) { | ||
28 | LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id, | ||
29 | flags); | ||
30 | m_server.TryGetProducer(binder_id)->Transact(transaction_id, flags, parcel_data, parcel_reply); | ||
31 | R_SUCCEED(); | ||
32 | } | ||
33 | |||
34 | Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) { | ||
35 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type); | ||
36 | R_SUCCEED(); | ||
37 | } | ||
38 | |||
39 | Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, | ||
40 | OutCopyHandle<Kernel::KReadableEvent> out_handle) { | ||
41 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); | ||
42 | *out_handle = &m_server.TryGetProducer(binder_id)->GetNativeHandle(); | ||
43 | R_SUCCEED(); | ||
44 | } | ||
45 | |||
46 | Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, | ||
47 | InBuffer<BufferAttr_HipcAutoSelect> parcel_data, | ||
48 | OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, | ||
49 | u32 flags) { | ||
50 | R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags)); | ||
51 | } | ||
52 | |||
53 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/hos_binder_driver.h b/src/core/hle/service/vi/hos_binder_driver.h new file mode 100755 index 000000000..ed6e8cdbe --- /dev/null +++ b/src/core/hle/service/vi/hos_binder_driver.h | |||
@@ -0,0 +1,30 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_types.h" | ||
5 | #include "core/hle/service/nvnflinger/binder.h" | ||
6 | #include "core/hle/service/service.h" | ||
7 | |||
8 | namespace Service::VI { | ||
9 | |||
10 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | ||
11 | public: | ||
12 | explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server); | ||
13 | ~IHOSBinderDriver() override; | ||
14 | |||
15 | private: | ||
16 | Result TransactParcel(s32 binder_id, android::TransactionId transaction_id, | ||
17 | InBuffer<BufferAttr_HipcMapAlias> parcel_data, | ||
18 | OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags); | ||
19 | Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); | ||
20 | Result GetNativeHandle(s32 binder_id, u32 type_id, | ||
21 | OutCopyHandle<Kernel::KReadableEvent> out_handle); | ||
22 | Result TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, | ||
23 | InBuffer<BufferAttr_HipcAutoSelect> parcel_data, | ||
24 | OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags); | ||
25 | |||
26 | private: | ||
27 | Nvnflinger::HosBinderDriverServer& m_server; | ||
28 | }; | ||
29 | |||
30 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/manager_display_service.cpp b/src/core/hle/service/vi/manager_display_service.cpp new file mode 100755 index 000000000..17f2f3b8f --- /dev/null +++ b/src/core/hle/service/vi/manager_display_service.cpp | |||
@@ -0,0 +1,130 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_serialization.h" | ||
5 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
6 | #include "core/hle/service/vi/manager_display_service.h" | ||
7 | #include "core/hle/service/vi/vi_results.h" | ||
8 | |||
9 | namespace Service::VI { | ||
10 | |||
11 | IManagerDisplayService::IManagerDisplayService(Core::System& system_, | ||
12 | Nvnflinger::Nvnflinger& nvnflinger) | ||
13 | : ServiceFramework{system_, "IManagerDisplayService"}, m_nvnflinger{nvnflinger} { | ||
14 | // clang-format off | ||
15 | static const FunctionInfo functions[] = { | ||
16 | {200, nullptr, "AllocateProcessHeapBlock"}, | ||
17 | {201, nullptr, "FreeProcessHeapBlock"}, | ||
18 | {1102, nullptr, "GetDisplayResolution"}, | ||
19 | {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, | ||
20 | {2011, nullptr, "DestroyManagedLayer"}, | ||
21 | {2012, nullptr, "CreateStrayLayer"}, | ||
22 | {2050, nullptr, "CreateIndirectLayer"}, | ||
23 | {2051, nullptr, "DestroyIndirectLayer"}, | ||
24 | {2052, nullptr, "CreateIndirectProducerEndPoint"}, | ||
25 | {2053, nullptr, "DestroyIndirectProducerEndPoint"}, | ||
26 | {2054, nullptr, "CreateIndirectConsumerEndPoint"}, | ||
27 | {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, | ||
28 | {2060, nullptr, "CreateWatermarkCompositor"}, | ||
29 | {2062, nullptr, "SetWatermarkText"}, | ||
30 | {2063, nullptr, "SetWatermarkLayerStacks"}, | ||
31 | {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, | ||
32 | {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, | ||
33 | {2302, nullptr, "GetDisplayHotplugEvent"}, | ||
34 | {2303, nullptr, "GetDisplayModeChangedEvent"}, | ||
35 | {2402, nullptr, "GetDisplayHotplugState"}, | ||
36 | {2501, nullptr, "GetCompositorErrorInfo"}, | ||
37 | {2601, nullptr, "GetDisplayErrorEvent"}, | ||
38 | {2701, nullptr, "GetDisplayFatalErrorEvent"}, | ||
39 | {4201, nullptr, "SetDisplayAlpha"}, | ||
40 | {4203, nullptr, "SetDisplayLayerStack"}, | ||
41 | {4205, nullptr, "SetDisplayPowerState"}, | ||
42 | {4206, nullptr, "SetDefaultDisplay"}, | ||
43 | {4207, nullptr, "ResetDisplayPanel"}, | ||
44 | {4208, nullptr, "SetDisplayFatalErrorEnabled"}, | ||
45 | {4209, nullptr, "IsDisplayPanelOn"}, | ||
46 | {4300, nullptr, "GetInternalPanelId"}, | ||
47 | {6000, C<&IManagerDisplayService::AddToLayerStack>, "AddToLayerStack"}, | ||
48 | {6001, nullptr, "RemoveFromLayerStack"}, | ||
49 | {6002, C<&IManagerDisplayService::SetLayerVisibility>, "SetLayerVisibility"}, | ||
50 | {6003, nullptr, "SetLayerConfig"}, | ||
51 | {6004, nullptr, "AttachLayerPresentationTracer"}, | ||
52 | {6005, nullptr, "DetachLayerPresentationTracer"}, | ||
53 | {6006, nullptr, "StartLayerPresentationRecording"}, | ||
54 | {6007, nullptr, "StopLayerPresentationRecording"}, | ||
55 | {6008, nullptr, "StartLayerPresentationFenceWait"}, | ||
56 | {6009, nullptr, "StopLayerPresentationFenceWait"}, | ||
57 | {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, | ||
58 | {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, | ||
59 | {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, | ||
60 | {6013, nullptr, "SetLayerOpacity"}, | ||
61 | {6014, nullptr, "AttachLayerWatermarkCompositor"}, | ||
62 | {6015, nullptr, "DetachLayerWatermarkCompositor"}, | ||
63 | {7000, nullptr, "SetContentVisibility"}, | ||
64 | {8000, nullptr, "SetConductorLayer"}, | ||
65 | {8001, nullptr, "SetTimestampTracking"}, | ||
66 | {8100, nullptr, "SetIndirectProducerFlipOffset"}, | ||
67 | {8200, nullptr, "CreateSharedBufferStaticStorage"}, | ||
68 | {8201, nullptr, "CreateSharedBufferTransferMemory"}, | ||
69 | {8202, nullptr, "DestroySharedBuffer"}, | ||
70 | {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, | ||
71 | {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, | ||
72 | {8207, nullptr, "UnbindSharedLowLevelLayer"}, | ||
73 | {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, | ||
74 | {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, | ||
75 | {8210, nullptr, "CreateSharedLayer"}, | ||
76 | {8211, nullptr, "DestroySharedLayer"}, | ||
77 | {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, | ||
78 | {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, | ||
79 | {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, | ||
80 | {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, | ||
81 | {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, | ||
82 | {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, | ||
83 | {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, | ||
84 | {8223, nullptr, "RegisterSharedBufferImporterAruid"}, | ||
85 | {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, | ||
86 | {8227, nullptr, "CreateSharedBufferProcessHeap"}, | ||
87 | {8228, nullptr, "GetSharedLayerLayerStacks"}, | ||
88 | {8229, nullptr, "SetSharedLayerLayerStacks"}, | ||
89 | {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, | ||
90 | {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, | ||
91 | {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, | ||
92 | {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, | ||
93 | {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, | ||
94 | {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, | ||
95 | {8297, nullptr, "GetSharedFrameBufferContentParameter"}, | ||
96 | {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, | ||
97 | }; | ||
98 | // clang-format on | ||
99 | |||
100 | RegisterHandlers(functions); | ||
101 | } | ||
102 | |||
103 | IManagerDisplayService::~IManagerDisplayService() = default; | ||
104 | |||
105 | Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, | ||
106 | u64 display_id, AppletResourceUserId aruid) { | ||
107 | LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, | ||
108 | display_id, aruid.pid); | ||
109 | |||
110 | const auto layer_id = m_nvnflinger.CreateLayer(display_id); | ||
111 | if (!layer_id) { | ||
112 | LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); | ||
113 | R_THROW(VI::ResultNotFound); | ||
114 | } | ||
115 | |||
116 | *out_layer_id = *layer_id; | ||
117 | R_SUCCEED(); | ||
118 | } | ||
119 | |||
120 | Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { | ||
121 | LOG_WARNING(Service_VI, "(STUBBED) called. stack_id={}, layer_id={}", stack_id, layer_id); | ||
122 | R_SUCCEED(); | ||
123 | } | ||
124 | |||
125 | Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | ||
126 | LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); | ||
127 | R_SUCCEED(); | ||
128 | } | ||
129 | |||
130 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/manager_display_service.h b/src/core/hle/service/vi/manager_display_service.h new file mode 100755 index 000000000..60e646ee0 --- /dev/null +++ b/src/core/hle/service/vi/manager_display_service.h | |||
@@ -0,0 +1,24 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_types.h" | ||
5 | #include "core/hle/service/service.h" | ||
6 | |||
7 | namespace Service::VI { | ||
8 | |||
9 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | ||
10 | public: | ||
11 | explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); | ||
12 | ~IManagerDisplayService() override; | ||
13 | |||
14 | private: | ||
15 | Result CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, u64 display_id, | ||
16 | AppletResourceUserId aruid); | ||
17 | Result AddToLayerStack(u32 stack_id, u64 layer_id); | ||
18 | Result SetLayerVisibility(bool visible, u64 layer_id); | ||
19 | |||
20 | private: | ||
21 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
22 | }; | ||
23 | |||
24 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp new file mode 100755 index 000000000..a7eee4f04 --- /dev/null +++ b/src/core/hle/service/vi/manager_root_service.cpp | |||
@@ -0,0 +1,38 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_serialization.h" | ||
5 | #include "core/hle/service/vi/application_display_service.h" | ||
6 | #include "core/hle/service/vi/manager_root_service.h" | ||
7 | #include "core/hle/service/vi/service_creator.h" | ||
8 | #include "core/hle/service/vi/vi.h" | ||
9 | #include "core/hle/service/vi/vi_types.h" | ||
10 | |||
11 | namespace Service::VI { | ||
12 | |||
13 | IManagerRootService::IManagerRootService( | ||
14 | Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
15 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||
16 | : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||
17 | hos_binder_driver_server} { | ||
18 | static const FunctionInfo functions[] = { | ||
19 | {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, | ||
20 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||
21 | {100, nullptr, "PrepareFatal"}, | ||
22 | {101, nullptr, "ShowFatal"}, | ||
23 | {102, nullptr, "DrawFatalRectangle"}, | ||
24 | {103, nullptr, "DrawFatalText32"}, | ||
25 | }; | ||
26 | RegisterHandlers(functions); | ||
27 | } | ||
28 | |||
29 | IManagerRootService::~IManagerRootService() = default; | ||
30 | |||
31 | Result IManagerRootService::GetDisplayService( | ||
32 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | ||
33 | LOG_DEBUG(Service_VI, "called"); | ||
34 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | ||
35 | m_hos_binder_driver_server, Permission::Manager, policy)); | ||
36 | } | ||
37 | |||
38 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h new file mode 100755 index 000000000..e6cb77aeb --- /dev/null +++ b/src/core/hle/service/vi/manager_root_service.h | |||
@@ -0,0 +1,38 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | #include "core/hle/service/cmif_types.h" | ||
7 | #include "core/hle/service/service.h" | ||
8 | |||
9 | namespace Core { | ||
10 | class System; | ||
11 | } | ||
12 | |||
13 | namespace Service::Nvnflinger { | ||
14 | class HosBinderDriverServer; | ||
15 | class Nvnflinger; | ||
16 | } // namespace Service::Nvnflinger | ||
17 | |||
18 | namespace Service::VI { | ||
19 | |||
20 | class IApplicationDisplayService; | ||
21 | enum class Policy : u32; | ||
22 | |||
23 | class IManagerRootService final : public ServiceFramework<IManagerRootService> { | ||
24 | public: | ||
25 | explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
27 | ~IManagerRootService() override; | ||
28 | |||
29 | private: | ||
30 | Result GetDisplayService( | ||
31 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | ||
32 | Policy policy); | ||
33 | |||
34 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
35 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||
36 | }; | ||
37 | |||
38 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp new file mode 100755 index 000000000..1de9d61a4 --- /dev/null +++ b/src/core/hle/service/vi/service_creator.cpp | |||
@@ -0,0 +1,39 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/vi/application_display_service.h" | ||
5 | #include "core/hle/service/vi/service_creator.h" | ||
6 | #include "core/hle/service/vi/vi_results.h" | ||
7 | #include "core/hle/service/vi/vi_types.h" | ||
8 | |||
9 | namespace Service::VI { | ||
10 | |||
11 | static bool IsValidServiceAccess(Permission permission, Policy policy) { | ||
12 | if (permission == Permission::User) { | ||
13 | return policy == Policy::User; | ||
14 | } | ||
15 | |||
16 | if (permission == Permission::System || permission == Permission::Manager) { | ||
17 | return policy == Policy::User || policy == Policy::Compositor; | ||
18 | } | ||
19 | |||
20 | return false; | ||
21 | } | ||
22 | |||
23 | Result GetApplicationDisplayService( | ||
24 | std::shared_ptr<IApplicationDisplayService>* out_application_display_service, | ||
25 | Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | ||
26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, | ||
27 | Policy policy) { | ||
28 | |||
29 | if (!IsValidServiceAccess(permission, policy)) { | ||
30 | LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); | ||
31 | R_THROW(ResultPermissionDenied); | ||
32 | } | ||
33 | |||
34 | *out_application_display_service = | ||
35 | std::make_shared<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); | ||
36 | R_SUCCEED(); | ||
37 | } | ||
38 | |||
39 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h new file mode 100755 index 000000000..8963bcd26 --- /dev/null +++ b/src/core/hle/service/vi/service_creator.h | |||
@@ -0,0 +1,33 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | #include <memory> | ||
7 | |||
8 | #include "common/common_types.h" | ||
9 | |||
10 | namespace Core { | ||
11 | class System; | ||
12 | } | ||
13 | |||
14 | namespace Service::Nvnflinger { | ||
15 | class HosBinderDriverServer; | ||
16 | class Nvnflinger; | ||
17 | } // namespace Service::Nvnflinger | ||
18 | |||
19 | union Result; | ||
20 | |||
21 | namespace Service::VI { | ||
22 | |||
23 | class IApplicationDisplayService; | ||
24 | enum class Permission; | ||
25 | enum class Policy : u32; | ||
26 | |||
27 | Result GetApplicationDisplayService( | ||
28 | std::shared_ptr<IApplicationDisplayService>* out_application_display_service, | ||
29 | Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | ||
30 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, | ||
31 | Policy policy); | ||
32 | |||
33 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp new file mode 100755 index 000000000..1e1cfc817 --- /dev/null +++ b/src/core/hle/service/vi/system_display_service.cpp | |||
@@ -0,0 +1,145 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "common/settings.h" | ||
5 | #include "core/hle/service/cmif_serialization.h" | ||
6 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
7 | #include "core/hle/service/vi/system_display_service.h" | ||
8 | #include "core/hle/service/vi/vi_types.h" | ||
9 | |||
10 | namespace Service::VI { | ||
11 | |||
12 | ISystemDisplayService::ISystemDisplayService(Core::System& system_, | ||
13 | Nvnflinger::Nvnflinger& nvnflinger) | ||
14 | : ServiceFramework{system_, "ISystemDisplayService"}, m_nvnflinger{nvnflinger} { | ||
15 | // clang-format off | ||
16 | static const FunctionInfo functions[] = { | ||
17 | {1200, nullptr, "GetZOrderCountMin"}, | ||
18 | {1202, nullptr, "GetZOrderCountMax"}, | ||
19 | {1203, nullptr, "GetDisplayLogicalResolution"}, | ||
20 | {1204, nullptr, "SetDisplayMagnification"}, | ||
21 | {2201, nullptr, "SetLayerPosition"}, | ||
22 | {2203, nullptr, "SetLayerSize"}, | ||
23 | {2204, nullptr, "GetLayerZ"}, | ||
24 | {2205, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"}, | ||
25 | {2207, C<&ISystemDisplayService::SetLayerVisibility>, "SetLayerVisibility"}, | ||
26 | {2209, nullptr, "SetLayerAlpha"}, | ||
27 | {2210, nullptr, "SetLayerPositionAndSize"}, | ||
28 | {2312, nullptr, "CreateStrayLayer"}, | ||
29 | {2400, nullptr, "OpenIndirectLayer"}, | ||
30 | {2401, nullptr, "CloseIndirectLayer"}, | ||
31 | {2402, nullptr, "FlipIndirectLayer"}, | ||
32 | {3000, nullptr, "ListDisplayModes"}, | ||
33 | {3001, nullptr, "ListDisplayRgbRanges"}, | ||
34 | {3002, nullptr, "ListDisplayContentTypes"}, | ||
35 | {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, | ||
36 | {3201, nullptr, "SetDisplayMode"}, | ||
37 | {3202, nullptr, "GetDisplayUnderscan"}, | ||
38 | {3203, nullptr, "SetDisplayUnderscan"}, | ||
39 | {3204, nullptr, "GetDisplayContentType"}, | ||
40 | {3205, nullptr, "SetDisplayContentType"}, | ||
41 | {3206, nullptr, "GetDisplayRgbRange"}, | ||
42 | {3207, nullptr, "SetDisplayRgbRange"}, | ||
43 | {3208, nullptr, "GetDisplayCmuMode"}, | ||
44 | {3209, nullptr, "SetDisplayCmuMode"}, | ||
45 | {3210, nullptr, "GetDisplayContrastRatio"}, | ||
46 | {3211, nullptr, "SetDisplayContrastRatio"}, | ||
47 | {3214, nullptr, "GetDisplayGamma"}, | ||
48 | {3215, nullptr, "SetDisplayGamma"}, | ||
49 | {3216, nullptr, "GetDisplayCmuLuma"}, | ||
50 | {3217, nullptr, "SetDisplayCmuLuma"}, | ||
51 | {3218, nullptr, "SetDisplayCrcMode"}, | ||
52 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | ||
53 | {8225, C<&ISystemDisplayService::GetSharedBufferMemoryHandleId>, "GetSharedBufferMemoryHandleId"}, | ||
54 | {8250, C<&ISystemDisplayService::OpenSharedLayer>, "OpenSharedLayer"}, | ||
55 | {8251, nullptr, "CloseSharedLayer"}, | ||
56 | {8252, C<&ISystemDisplayService::ConnectSharedLayer>, "ConnectSharedLayer"}, | ||
57 | {8253, nullptr, "DisconnectSharedLayer"}, | ||
58 | {8254, C<&ISystemDisplayService::AcquireSharedFrameBuffer>, "AcquireSharedFrameBuffer"}, | ||
59 | {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, | ||
60 | {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, | ||
61 | {8257, nullptr, "FillSharedFrameBufferColor"}, | ||
62 | {8258, nullptr, "CancelSharedFrameBuffer"}, | ||
63 | {9000, nullptr, "GetDp2hdmiController"}, | ||
64 | }; | ||
65 | // clang-format on | ||
66 | RegisterHandlers(functions); | ||
67 | } | ||
68 | |||
69 | ISystemDisplayService::~ISystemDisplayService() = default; | ||
70 | |||
71 | Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) { | ||
72 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value); | ||
73 | R_SUCCEED(); | ||
74 | } | ||
75 | |||
76 | // This function currently does nothing but return a success error code in | ||
77 | // the vi library itself, so do the same thing, but log out the passed in values. | ||
78 | Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | ||
79 | LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); | ||
80 | R_SUCCEED(); | ||
81 | } | ||
82 | |||
83 | Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_height, | ||
84 | Out<f32> out_refresh_rate, Out<u32> out_unknown) { | ||
85 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
86 | |||
87 | if (Settings::IsDockedMode()) { | ||
88 | *out_width = static_cast<u32>(DisplayResolution::DockedWidth); | ||
89 | *out_height = static_cast<u32>(DisplayResolution::DockedHeight); | ||
90 | } else { | ||
91 | *out_width = static_cast<u32>(DisplayResolution::UndockedWidth); | ||
92 | *out_height = static_cast<u32>(DisplayResolution::UndockedHeight); | ||
93 | } | ||
94 | |||
95 | *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. | ||
96 | *out_unknown = 0; | ||
97 | |||
98 | R_SUCCEED(); | ||
99 | } | ||
100 | |||
101 | Result ISystemDisplayService::GetSharedBufferMemoryHandleId( | ||
102 | Out<s32> out_nvmap_handle, Out<u64> out_size, | ||
103 | OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, | ||
104 | u64 buffer_id, ClientAppletResourceUserId aruid) { | ||
105 | LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); | ||
106 | |||
107 | R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||
108 | out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); | ||
109 | } | ||
110 | |||
111 | Result ISystemDisplayService::OpenSharedLayer(u64 layer_id) { | ||
112 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | ||
113 | R_SUCCEED(); | ||
114 | } | ||
115 | |||
116 | Result ISystemDisplayService::ConnectSharedLayer(u64 layer_id) { | ||
117 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | ||
118 | R_SUCCEED(); | ||
119 | } | ||
120 | |||
121 | Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_fence, | ||
122 | Out<std::array<s32, 4>> out_slots, | ||
123 | Out<s64> out_target_slot, u64 layer_id) { | ||
124 | LOG_DEBUG(Service_VI, "called"); | ||
125 | R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||
126 | out_fence, *out_slots, out_target_slot, layer_id)); | ||
127 | } | ||
128 | |||
129 | Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, | ||
130 | Common::Rectangle<s32> crop_region, | ||
131 | u32 window_transform, s32 swap_interval, | ||
132 | u64 layer_id, s64 surface_id) { | ||
133 | LOG_DEBUG(Service_VI, "called"); | ||
134 | R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||
135 | fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); | ||
136 | } | ||
137 | |||
138 | Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( | ||
139 | OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { | ||
140 | LOG_DEBUG(Service_VI, "called"); | ||
141 | R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event, | ||
142 | layer_id)); | ||
143 | } | ||
144 | |||
145 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/system_display_service.h b/src/core/hle/service/vi/system_display_service.h new file mode 100755 index 000000000..cfcb196fd --- /dev/null +++ b/src/core/hle/service/vi/system_display_service.h | |||
@@ -0,0 +1,45 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "common/math_util.h" | ||
5 | #include "core/hle/service/cmif_types.h" | ||
6 | #include "core/hle/service/nvnflinger/ui/fence.h" | ||
7 | #include "core/hle/service/service.h" | ||
8 | |||
9 | namespace Service::Nvnflinger { | ||
10 | struct SharedMemoryPoolLayout; | ||
11 | } | ||
12 | |||
13 | namespace Service::VI { | ||
14 | |||
15 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||
16 | public: | ||
17 | explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); | ||
18 | ~ISystemDisplayService() override; | ||
19 | |||
20 | private: | ||
21 | Result SetLayerZ(u32 z_value, u64 layer_id); | ||
22 | Result SetLayerVisibility(bool visible, u64 layer_id); | ||
23 | Result GetDisplayMode(Out<u32> out_width, Out<u32> out_height, Out<f32> out_refresh_rate, | ||
24 | Out<u32> out_unknown); | ||
25 | |||
26 | Result GetSharedBufferMemoryHandleId( | ||
27 | Out<s32> out_nvmap_handle, Out<u64> out_size, | ||
28 | OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, | ||
29 | u64 buffer_id, ClientAppletResourceUserId aruid); | ||
30 | Result OpenSharedLayer(u64 layer_id); | ||
31 | Result ConnectSharedLayer(u64 layer_id); | ||
32 | Result GetSharedFrameBufferAcquirableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event, | ||
33 | u64 layer_id); | ||
34 | Result AcquireSharedFrameBuffer(Out<android::Fence> out_fence, | ||
35 | Out<std::array<s32, 4>> out_slots, Out<s64> out_target_slot, | ||
36 | u64 layer_id); | ||
37 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | ||
38 | u32 window_transform, s32 swap_interval, u64 layer_id, | ||
39 | s64 surface_id); | ||
40 | |||
41 | private: | ||
42 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
43 | }; | ||
44 | |||
45 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp new file mode 100755 index 000000000..8789b4cfb --- /dev/null +++ b/src/core/hle/service/vi/system_root_service.cpp | |||
@@ -0,0 +1,33 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #include "core/hle/service/cmif_serialization.h" | ||
5 | #include "core/hle/service/vi/application_display_service.h" | ||
6 | #include "core/hle/service/vi/service_creator.h" | ||
7 | #include "core/hle/service/vi/system_root_service.h" | ||
8 | #include "core/hle/service/vi/vi.h" | ||
9 | #include "core/hle/service/vi/vi_types.h" | ||
10 | |||
11 | namespace Service::VI { | ||
12 | |||
13 | ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
14 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||
15 | : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||
16 | hos_binder_driver_server} { | ||
17 | static const FunctionInfo functions[] = { | ||
18 | {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, | ||
19 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||
20 | }; | ||
21 | RegisterHandlers(functions); | ||
22 | } | ||
23 | |||
24 | ISystemRootService::~ISystemRootService() = default; | ||
25 | |||
26 | Result ISystemRootService::GetDisplayService( | ||
27 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | ||
28 | LOG_DEBUG(Service_VI, "called"); | ||
29 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | ||
30 | m_hos_binder_driver_server, Permission::System, policy)); | ||
31 | } | ||
32 | |||
33 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h new file mode 100755 index 000000000..2c547faa5 --- /dev/null +++ b/src/core/hle/service/vi/system_root_service.h | |||
@@ -0,0 +1,38 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | #include "core/hle/service/cmif_types.h" | ||
7 | #include "core/hle/service/service.h" | ||
8 | |||
9 | namespace Core { | ||
10 | class System; | ||
11 | } | ||
12 | |||
13 | namespace Service::Nvnflinger { | ||
14 | class HosBinderDriverServer; | ||
15 | class Nvnflinger; | ||
16 | } // namespace Service::Nvnflinger | ||
17 | |||
18 | namespace Service::VI { | ||
19 | |||
20 | class IApplicationDisplayService; | ||
21 | enum class Policy : u32; | ||
22 | |||
23 | class ISystemRootService final : public ServiceFramework<ISystemRootService> { | ||
24 | public: | ||
25 | explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||
26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
27 | ~ISystemRootService() override; | ||
28 | |||
29 | private: | ||
30 | Result GetDisplayService( | ||
31 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | ||
32 | Policy policy); | ||
33 | |||
34 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
35 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||
36 | }; | ||
37 | |||
38 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 77c6a069b..18442b265 100755 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
@@ -1,974 +1,25 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
3 | 3 | ||
4 | #include <algorithm> | ||
5 | #include <array> | ||
6 | #include <cstring> | ||
7 | #include <memory> | ||
8 | #include <optional> | ||
9 | #include <type_traits> | ||
10 | #include <utility> | ||
11 | |||
12 | #include "common/alignment.h" | ||
13 | #include "common/assert.h" | ||
14 | #include "common/common_funcs.h" | ||
15 | #include "common/logging/log.h" | ||
16 | #include "common/math_util.h" | ||
17 | #include "common/settings.h" | ||
18 | #include "common/string_util.h" | ||
19 | #include "common/swap.h" | ||
20 | #include "core/core_timing.h" | ||
21 | #include "core/hle/kernel/k_readable_event.h" | ||
22 | #include "core/hle/kernel/k_thread.h" | ||
23 | #include "core/hle/service/ipc_helpers.h" | ||
24 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
25 | #include "core/hle/service/nvdrv/nvdata.h" | ||
26 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
27 | #include "core/hle/service/nvnflinger/binder.h" | ||
28 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | ||
29 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
30 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||
31 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
32 | #include "core/hle/service/nvnflinger/parcel.h" | ||
33 | #include "core/hle/service/server_manager.h" | 4 | #include "core/hle/service/server_manager.h" |
34 | #include "core/hle/service/service.h" | 5 | #include "core/hle/service/vi/application_display_service.h" |
6 | #include "core/hle/service/vi/application_root_service.h" | ||
7 | #include "core/hle/service/vi/manager_root_service.h" | ||
8 | #include "core/hle/service/vi/system_root_service.h" | ||
35 | #include "core/hle/service/vi/vi.h" | 9 | #include "core/hle/service/vi/vi.h" |
36 | #include "core/hle/service/vi/vi_m.h" | ||
37 | #include "core/hle/service/vi/vi_results.h" | ||
38 | #include "core/hle/service/vi/vi_s.h" | ||
39 | #include "core/hle/service/vi/vi_u.h" | ||
40 | 10 | ||
41 | namespace Service::VI { | 11 | namespace Service::VI { |
42 | 12 | ||
43 | struct DisplayInfo { | ||
44 | /// The name of this particular display. | ||
45 | char display_name[0x40]{"Default"}; | ||
46 | |||
47 | /// Whether or not the display has a limited number of layers. | ||
48 | u8 has_limited_layers{1}; | ||
49 | INSERT_PADDING_BYTES(7); | ||
50 | |||
51 | /// Indicates the total amount of layers supported by the display. | ||
52 | /// @note This is only valid if has_limited_layers is set. | ||
53 | u64 max_layers{1}; | ||
54 | |||
55 | /// Maximum width in pixels. | ||
56 | u64 width{1920}; | ||
57 | |||
58 | /// Maximum height in pixels. | ||
59 | u64 height{1080}; | ||
60 | }; | ||
61 | static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); | ||
62 | |||
63 | class NativeWindow final { | ||
64 | public: | ||
65 | constexpr explicit NativeWindow(u32 id_) : id{id_} {} | ||
66 | constexpr explicit NativeWindow(const NativeWindow& other) = default; | ||
67 | |||
68 | private: | ||
69 | const u32 magic = 2; | ||
70 | const u32 process_id = 1; | ||
71 | const u64 id; | ||
72 | INSERT_PADDING_WORDS(2); | ||
73 | std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; | ||
74 | INSERT_PADDING_WORDS(2); | ||
75 | }; | ||
76 | static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); | ||
77 | |||
78 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | ||
79 | public: | ||
80 | explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_) | ||
81 | : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { | ||
82 | static const FunctionInfo functions[] = { | ||
83 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | ||
84 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | ||
85 | {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, | ||
86 | {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, | ||
87 | }; | ||
88 | RegisterHandlers(functions); | ||
89 | } | ||
90 | |||
91 | private: | ||
92 | void TransactParcel(HLERequestContext& ctx) { | ||
93 | IPC::RequestParser rp{ctx}; | ||
94 | const u32 id = rp.Pop<u32>(); | ||
95 | const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>()); | ||
96 | const u32 flags = rp.Pop<u32>(); | ||
97 | |||
98 | LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, | ||
99 | transaction, flags); | ||
100 | |||
101 | server.TryGetProducer(id)->Transact(ctx, transaction, flags); | ||
102 | |||
103 | IPC::ResponseBuilder rb{ctx, 2}; | ||
104 | rb.Push(ResultSuccess); | ||
105 | } | ||
106 | |||
107 | void AdjustRefcount(HLERequestContext& ctx) { | ||
108 | IPC::RequestParser rp{ctx}; | ||
109 | const u32 id = rp.Pop<u32>(); | ||
110 | const s32 addval = rp.PopRaw<s32>(); | ||
111 | const u32 type = rp.Pop<u32>(); | ||
112 | |||
113 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, | ||
114 | type); | ||
115 | |||
116 | IPC::ResponseBuilder rb{ctx, 2}; | ||
117 | rb.Push(ResultSuccess); | ||
118 | } | ||
119 | |||
120 | void GetNativeHandle(HLERequestContext& ctx) { | ||
121 | IPC::RequestParser rp{ctx}; | ||
122 | const u32 id = rp.Pop<u32>(); | ||
123 | const u32 unknown = rp.Pop<u32>(); | ||
124 | |||
125 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); | ||
126 | |||
127 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
128 | rb.Push(ResultSuccess); | ||
129 | rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); | ||
130 | } | ||
131 | |||
132 | private: | ||
133 | Nvnflinger::HosBinderDriverServer& server; | ||
134 | }; | ||
135 | |||
136 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||
137 | public: | ||
138 | explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||
139 | : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { | ||
140 | // clang-format off | ||
141 | static const FunctionInfo functions[] = { | ||
142 | {1200, nullptr, "GetZOrderCountMin"}, | ||
143 | {1202, nullptr, "GetZOrderCountMax"}, | ||
144 | {1203, nullptr, "GetDisplayLogicalResolution"}, | ||
145 | {1204, nullptr, "SetDisplayMagnification"}, | ||
146 | {2201, nullptr, "SetLayerPosition"}, | ||
147 | {2203, nullptr, "SetLayerSize"}, | ||
148 | {2204, nullptr, "GetLayerZ"}, | ||
149 | {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, | ||
150 | {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | ||
151 | {2209, nullptr, "SetLayerAlpha"}, | ||
152 | {2210, nullptr, "SetLayerPositionAndSize"}, | ||
153 | {2312, nullptr, "CreateStrayLayer"}, | ||
154 | {2400, nullptr, "OpenIndirectLayer"}, | ||
155 | {2401, nullptr, "CloseIndirectLayer"}, | ||
156 | {2402, nullptr, "FlipIndirectLayer"}, | ||
157 | {3000, nullptr, "ListDisplayModes"}, | ||
158 | {3001, nullptr, "ListDisplayRgbRanges"}, | ||
159 | {3002, nullptr, "ListDisplayContentTypes"}, | ||
160 | {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, | ||
161 | {3201, nullptr, "SetDisplayMode"}, | ||
162 | {3202, nullptr, "GetDisplayUnderscan"}, | ||
163 | {3203, nullptr, "SetDisplayUnderscan"}, | ||
164 | {3204, nullptr, "GetDisplayContentType"}, | ||
165 | {3205, nullptr, "SetDisplayContentType"}, | ||
166 | {3206, nullptr, "GetDisplayRgbRange"}, | ||
167 | {3207, nullptr, "SetDisplayRgbRange"}, | ||
168 | {3208, nullptr, "GetDisplayCmuMode"}, | ||
169 | {3209, nullptr, "SetDisplayCmuMode"}, | ||
170 | {3210, nullptr, "GetDisplayContrastRatio"}, | ||
171 | {3211, nullptr, "SetDisplayContrastRatio"}, | ||
172 | {3214, nullptr, "GetDisplayGamma"}, | ||
173 | {3215, nullptr, "SetDisplayGamma"}, | ||
174 | {3216, nullptr, "GetDisplayCmuLuma"}, | ||
175 | {3217, nullptr, "SetDisplayCmuLuma"}, | ||
176 | {3218, nullptr, "SetDisplayCrcMode"}, | ||
177 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | ||
178 | {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, | ||
179 | {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, | ||
180 | {8251, nullptr, "CloseSharedLayer"}, | ||
181 | {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, | ||
182 | {8253, nullptr, "DisconnectSharedLayer"}, | ||
183 | {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, | ||
184 | {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, | ||
185 | {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, | ||
186 | {8257, nullptr, "FillSharedFrameBufferColor"}, | ||
187 | {8258, nullptr, "CancelSharedFrameBuffer"}, | ||
188 | {9000, nullptr, "GetDp2hdmiController"}, | ||
189 | }; | ||
190 | // clang-format on | ||
191 | RegisterHandlers(functions); | ||
192 | } | ||
193 | |||
194 | private: | ||
195 | void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { | ||
196 | IPC::RequestParser rp{ctx}; | ||
197 | const u64 buffer_id = rp.PopRaw<u64>(); | ||
198 | const u64 aruid = ctx.GetPID(); | ||
199 | |||
200 | LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); | ||
201 | |||
202 | struct OutputParameters { | ||
203 | s32 nvmap_handle; | ||
204 | u64 size; | ||
205 | }; | ||
206 | |||
207 | OutputParameters out{}; | ||
208 | Nvnflinger::SharedMemoryPoolLayout layout{}; | ||
209 | const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||
210 | &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); | ||
211 | |||
212 | ctx.WriteBuffer(&layout, sizeof(layout)); | ||
213 | |||
214 | IPC::ResponseBuilder rb{ctx, 6}; | ||
215 | rb.Push(result); | ||
216 | rb.PushRaw(out); | ||
217 | } | ||
218 | |||
219 | void OpenSharedLayer(HLERequestContext& ctx) { | ||
220 | IPC::RequestParser rp{ctx}; | ||
221 | const u64 layer_id = rp.PopRaw<u64>(); | ||
222 | |||
223 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||
224 | |||
225 | IPC::ResponseBuilder rb{ctx, 2}; | ||
226 | rb.Push(ResultSuccess); | ||
227 | } | ||
228 | |||
229 | void ConnectSharedLayer(HLERequestContext& ctx) { | ||
230 | IPC::RequestParser rp{ctx}; | ||
231 | const u64 layer_id = rp.PopRaw<u64>(); | ||
232 | |||
233 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||
234 | |||
235 | IPC::ResponseBuilder rb{ctx, 2}; | ||
236 | rb.Push(ResultSuccess); | ||
237 | } | ||
238 | |||
239 | void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { | ||
240 | LOG_DEBUG(Service_VI, "called"); | ||
241 | |||
242 | IPC::RequestParser rp{ctx}; | ||
243 | const u64 layer_id = rp.PopRaw<u64>(); | ||
244 | |||
245 | Kernel::KReadableEvent* event{}; | ||
246 | const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( | ||
247 | &event, layer_id); | ||
248 | |||
249 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
250 | rb.Push(result); | ||
251 | rb.PushCopyObjects(event); | ||
252 | } | ||
253 | |||
254 | void AcquireSharedFrameBuffer(HLERequestContext& ctx) { | ||
255 | LOG_DEBUG(Service_VI, "called"); | ||
256 | |||
257 | IPC::RequestParser rp{ctx}; | ||
258 | const u64 layer_id = rp.PopRaw<u64>(); | ||
259 | |||
260 | struct OutputParameters { | ||
261 | android::Fence fence; | ||
262 | std::array<s32, 4> slots; | ||
263 | s64 target_slot; | ||
264 | }; | ||
265 | static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); | ||
266 | |||
267 | OutputParameters out{}; | ||
268 | const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||
269 | &out.fence, out.slots, &out.target_slot, layer_id); | ||
270 | |||
271 | IPC::ResponseBuilder rb{ctx, 18}; | ||
272 | rb.Push(result); | ||
273 | rb.PushRaw(out); | ||
274 | } | ||
275 | |||
276 | void PresentSharedFrameBuffer(HLERequestContext& ctx) { | ||
277 | LOG_DEBUG(Service_VI, "called"); | ||
278 | |||
279 | struct InputParameters { | ||
280 | android::Fence fence; | ||
281 | Common::Rectangle<s32> crop_region; | ||
282 | u32 window_transform; | ||
283 | s32 swap_interval; | ||
284 | u64 layer_id; | ||
285 | s64 surface_id; | ||
286 | }; | ||
287 | static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); | ||
288 | |||
289 | IPC::RequestParser rp{ctx}; | ||
290 | auto input = rp.PopRaw<InputParameters>(); | ||
291 | |||
292 | const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||
293 | input.fence, input.crop_region, input.window_transform, input.swap_interval, | ||
294 | input.layer_id, input.surface_id); | ||
295 | IPC::ResponseBuilder rb{ctx, 2}; | ||
296 | rb.Push(result); | ||
297 | } | ||
298 | |||
299 | void SetLayerZ(HLERequestContext& ctx) { | ||
300 | IPC::RequestParser rp{ctx}; | ||
301 | const u64 layer_id = rp.Pop<u64>(); | ||
302 | const u64 z_value = rp.Pop<u64>(); | ||
303 | |||
304 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, | ||
305 | z_value); | ||
306 | |||
307 | IPC::ResponseBuilder rb{ctx, 2}; | ||
308 | rb.Push(ResultSuccess); | ||
309 | } | ||
310 | |||
311 | // This function currently does nothing but return a success error code in | ||
312 | // the vi library itself, so do the same thing, but log out the passed in values. | ||
313 | void SetLayerVisibility(HLERequestContext& ctx) { | ||
314 | IPC::RequestParser rp{ctx}; | ||
315 | const u64 layer_id = rp.Pop<u64>(); | ||
316 | const bool visibility = rp.Pop<bool>(); | ||
317 | |||
318 | LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); | ||
319 | |||
320 | IPC::ResponseBuilder rb{ctx, 2}; | ||
321 | rb.Push(ResultSuccess); | ||
322 | } | ||
323 | |||
324 | void GetDisplayMode(HLERequestContext& ctx) { | ||
325 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
326 | |||
327 | IPC::ResponseBuilder rb{ctx, 6}; | ||
328 | rb.Push(ResultSuccess); | ||
329 | |||
330 | if (Settings::IsDockedMode()) { | ||
331 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); | ||
332 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); | ||
333 | } else { | ||
334 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); | ||
335 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); | ||
336 | } | ||
337 | |||
338 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. | ||
339 | rb.Push<u32>(0); | ||
340 | } | ||
341 | |||
342 | private: | ||
343 | Nvnflinger::Nvnflinger& nvnflinger; | ||
344 | }; | ||
345 | |||
346 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | ||
347 | public: | ||
348 | explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||
349 | : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { | ||
350 | // clang-format off | ||
351 | static const FunctionInfo functions[] = { | ||
352 | {200, nullptr, "AllocateProcessHeapBlock"}, | ||
353 | {201, nullptr, "FreeProcessHeapBlock"}, | ||
354 | {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, | ||
355 | {1102, nullptr, "GetDisplayResolution"}, | ||
356 | {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, | ||
357 | {2011, nullptr, "DestroyManagedLayer"}, | ||
358 | {2012, nullptr, "CreateStrayLayer"}, | ||
359 | {2050, nullptr, "CreateIndirectLayer"}, | ||
360 | {2051, nullptr, "DestroyIndirectLayer"}, | ||
361 | {2052, nullptr, "CreateIndirectProducerEndPoint"}, | ||
362 | {2053, nullptr, "DestroyIndirectProducerEndPoint"}, | ||
363 | {2054, nullptr, "CreateIndirectConsumerEndPoint"}, | ||
364 | {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, | ||
365 | {2060, nullptr, "CreateWatermarkCompositor"}, | ||
366 | {2062, nullptr, "SetWatermarkText"}, | ||
367 | {2063, nullptr, "SetWatermarkLayerStacks"}, | ||
368 | {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, | ||
369 | {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, | ||
370 | {2302, nullptr, "GetDisplayHotplugEvent"}, | ||
371 | {2303, nullptr, "GetDisplayModeChangedEvent"}, | ||
372 | {2402, nullptr, "GetDisplayHotplugState"}, | ||
373 | {2501, nullptr, "GetCompositorErrorInfo"}, | ||
374 | {2601, nullptr, "GetDisplayErrorEvent"}, | ||
375 | {2701, nullptr, "GetDisplayFatalErrorEvent"}, | ||
376 | {4201, nullptr, "SetDisplayAlpha"}, | ||
377 | {4203, nullptr, "SetDisplayLayerStack"}, | ||
378 | {4205, nullptr, "SetDisplayPowerState"}, | ||
379 | {4206, nullptr, "SetDefaultDisplay"}, | ||
380 | {4207, nullptr, "ResetDisplayPanel"}, | ||
381 | {4208, nullptr, "SetDisplayFatalErrorEnabled"}, | ||
382 | {4209, nullptr, "IsDisplayPanelOn"}, | ||
383 | {4300, nullptr, "GetInternalPanelId"}, | ||
384 | {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, | ||
385 | {6001, nullptr, "RemoveFromLayerStack"}, | ||
386 | {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | ||
387 | {6003, nullptr, "SetLayerConfig"}, | ||
388 | {6004, nullptr, "AttachLayerPresentationTracer"}, | ||
389 | {6005, nullptr, "DetachLayerPresentationTracer"}, | ||
390 | {6006, nullptr, "StartLayerPresentationRecording"}, | ||
391 | {6007, nullptr, "StopLayerPresentationRecording"}, | ||
392 | {6008, nullptr, "StartLayerPresentationFenceWait"}, | ||
393 | {6009, nullptr, "StopLayerPresentationFenceWait"}, | ||
394 | {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, | ||
395 | {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, | ||
396 | {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, | ||
397 | {6013, nullptr, "SetLayerOpacity"}, | ||
398 | {6014, nullptr, "AttachLayerWatermarkCompositor"}, | ||
399 | {6015, nullptr, "DetachLayerWatermarkCompositor"}, | ||
400 | {7000, nullptr, "SetContentVisibility"}, | ||
401 | {8000, nullptr, "SetConductorLayer"}, | ||
402 | {8001, nullptr, "SetTimestampTracking"}, | ||
403 | {8100, nullptr, "SetIndirectProducerFlipOffset"}, | ||
404 | {8200, nullptr, "CreateSharedBufferStaticStorage"}, | ||
405 | {8201, nullptr, "CreateSharedBufferTransferMemory"}, | ||
406 | {8202, nullptr, "DestroySharedBuffer"}, | ||
407 | {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, | ||
408 | {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, | ||
409 | {8207, nullptr, "UnbindSharedLowLevelLayer"}, | ||
410 | {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, | ||
411 | {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, | ||
412 | {8210, nullptr, "CreateSharedLayer"}, | ||
413 | {8211, nullptr, "DestroySharedLayer"}, | ||
414 | {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, | ||
415 | {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, | ||
416 | {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, | ||
417 | {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, | ||
418 | {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, | ||
419 | {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, | ||
420 | {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, | ||
421 | {8223, nullptr, "RegisterSharedBufferImporterAruid"}, | ||
422 | {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, | ||
423 | {8227, nullptr, "CreateSharedBufferProcessHeap"}, | ||
424 | {8228, nullptr, "GetSharedLayerLayerStacks"}, | ||
425 | {8229, nullptr, "SetSharedLayerLayerStacks"}, | ||
426 | {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, | ||
427 | {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, | ||
428 | {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, | ||
429 | {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, | ||
430 | {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, | ||
431 | {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, | ||
432 | {8297, nullptr, "GetSharedFrameBufferContentParameter"}, | ||
433 | {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, | ||
434 | }; | ||
435 | // clang-format on | ||
436 | |||
437 | RegisterHandlers(functions); | ||
438 | } | ||
439 | |||
440 | private: | ||
441 | void CloseDisplay(HLERequestContext& ctx) { | ||
442 | IPC::RequestParser rp{ctx}; | ||
443 | const u64 display = rp.Pop<u64>(); | ||
444 | |||
445 | const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; | ||
446 | |||
447 | IPC::ResponseBuilder rb{ctx, 2}; | ||
448 | rb.Push(rc); | ||
449 | } | ||
450 | |||
451 | void CreateManagedLayer(HLERequestContext& ctx) { | ||
452 | IPC::RequestParser rp{ctx}; | ||
453 | const u32 unknown = rp.Pop<u32>(); | ||
454 | rp.Skip(1, false); | ||
455 | const u64 display = rp.Pop<u64>(); | ||
456 | const u64 aruid = rp.Pop<u64>(); | ||
457 | |||
458 | LOG_WARNING(Service_VI, | ||
459 | "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", | ||
460 | unknown, display, aruid); | ||
461 | |||
462 | const auto layer_id = nvnflinger.CreateLayer(display); | ||
463 | if (!layer_id) { | ||
464 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); | ||
465 | IPC::ResponseBuilder rb{ctx, 2}; | ||
466 | rb.Push(ResultNotFound); | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | IPC::ResponseBuilder rb{ctx, 4}; | ||
471 | rb.Push(ResultSuccess); | ||
472 | rb.Push(*layer_id); | ||
473 | } | ||
474 | |||
475 | void AddToLayerStack(HLERequestContext& ctx) { | ||
476 | IPC::RequestParser rp{ctx}; | ||
477 | const u32 stack = rp.Pop<u32>(); | ||
478 | const u64 layer_id = rp.Pop<u64>(); | ||
479 | |||
480 | LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, | ||
481 | layer_id); | ||
482 | |||
483 | IPC::ResponseBuilder rb{ctx, 2}; | ||
484 | rb.Push(ResultSuccess); | ||
485 | } | ||
486 | |||
487 | void SetLayerVisibility(HLERequestContext& ctx) { | ||
488 | IPC::RequestParser rp{ctx}; | ||
489 | const u64 layer_id = rp.Pop<u64>(); | ||
490 | const bool visibility = rp.Pop<bool>(); | ||
491 | |||
492 | LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, | ||
493 | visibility); | ||
494 | |||
495 | IPC::ResponseBuilder rb{ctx, 2}; | ||
496 | rb.Push(ResultSuccess); | ||
497 | } | ||
498 | |||
499 | Nvnflinger::Nvnflinger& nvnflinger; | ||
500 | }; | ||
501 | |||
502 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||
503 | public: | ||
504 | IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, | ||
505 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | ||
506 | : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, | ||
507 | hos_binder_driver_server{hos_binder_driver_server_} { | ||
508 | |||
509 | static const FunctionInfo functions[] = { | ||
510 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | ||
511 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | ||
512 | {102, &IApplicationDisplayService::GetManagerDisplayService, | ||
513 | "GetManagerDisplayService"}, | ||
514 | {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, | ||
515 | "GetIndirectDisplayTransactionService"}, | ||
516 | {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, | ||
517 | {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, | ||
518 | {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, | ||
519 | {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, | ||
520 | {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, | ||
521 | {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, | ||
522 | {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, | ||
523 | {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, | ||
524 | {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, | ||
525 | {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, | ||
526 | {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, | ||
527 | {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, | ||
528 | {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, | ||
529 | "GetIndirectLayerImageMap"}, | ||
530 | {2451, nullptr, "GetIndirectLayerImageCropMap"}, | ||
531 | {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, | ||
532 | "GetIndirectLayerImageRequiredMemoryInfo"}, | ||
533 | {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, | ||
534 | {5203, nullptr, "GetDisplayVsyncEventForDebug"}, | ||
535 | }; | ||
536 | RegisterHandlers(functions); | ||
537 | } | ||
538 | |||
539 | ~IApplicationDisplayService() { | ||
540 | for (const auto layer_id : stray_layer_ids) { | ||
541 | nvnflinger.DestroyLayer(layer_id); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | private: | ||
546 | enum class ConvertedScaleMode : u64 { | ||
547 | Freeze = 0, | ||
548 | ScaleToWindow = 1, | ||
549 | ScaleAndCrop = 2, | ||
550 | None = 3, | ||
551 | PreserveAspectRatio = 4, | ||
552 | }; | ||
553 | |||
554 | enum class NintendoScaleMode : u32 { | ||
555 | None = 0, | ||
556 | Freeze = 1, | ||
557 | ScaleToWindow = 2, | ||
558 | ScaleAndCrop = 3, | ||
559 | PreserveAspectRatio = 4, | ||
560 | }; | ||
561 | |||
562 | void GetRelayService(HLERequestContext& ctx) { | ||
563 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
564 | |||
565 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
566 | rb.Push(ResultSuccess); | ||
567 | rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); | ||
568 | } | ||
569 | |||
570 | void GetSystemDisplayService(HLERequestContext& ctx) { | ||
571 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
572 | |||
573 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
574 | rb.Push(ResultSuccess); | ||
575 | rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger); | ||
576 | } | ||
577 | |||
578 | void GetManagerDisplayService(HLERequestContext& ctx) { | ||
579 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
580 | |||
581 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
582 | rb.Push(ResultSuccess); | ||
583 | rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger); | ||
584 | } | ||
585 | |||
586 | void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { | ||
587 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
588 | |||
589 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
590 | rb.Push(ResultSuccess); | ||
591 | rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); | ||
592 | } | ||
593 | |||
594 | void OpenDisplay(HLERequestContext& ctx) { | ||
595 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
596 | |||
597 | IPC::RequestParser rp{ctx}; | ||
598 | const auto name_buf = rp.PopRaw<std::array<char, 0x40>>(); | ||
599 | |||
600 | OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); | ||
601 | } | ||
602 | |||
603 | void OpenDefaultDisplay(HLERequestContext& ctx) { | ||
604 | LOG_DEBUG(Service_VI, "called"); | ||
605 | |||
606 | OpenDisplayImpl(ctx, "Default"); | ||
607 | } | ||
608 | |||
609 | void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { | ||
610 | const auto trim_pos = name.find('\0'); | ||
611 | |||
612 | if (trim_pos != std::string_view::npos) { | ||
613 | name.remove_suffix(name.size() - trim_pos); | ||
614 | } | ||
615 | |||
616 | ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); | ||
617 | |||
618 | const auto display_id = nvnflinger.OpenDisplay(name); | ||
619 | if (!display_id) { | ||
620 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); | ||
621 | IPC::ResponseBuilder rb{ctx, 2}; | ||
622 | rb.Push(ResultNotFound); | ||
623 | return; | ||
624 | } | ||
625 | |||
626 | IPC::ResponseBuilder rb{ctx, 4}; | ||
627 | rb.Push(ResultSuccess); | ||
628 | rb.Push<u64>(*display_id); | ||
629 | } | ||
630 | |||
631 | void CloseDisplay(HLERequestContext& ctx) { | ||
632 | IPC::RequestParser rp{ctx}; | ||
633 | const u64 display_id = rp.Pop<u64>(); | ||
634 | |||
635 | const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; | ||
636 | |||
637 | IPC::ResponseBuilder rb{ctx, 2}; | ||
638 | rb.Push(rc); | ||
639 | } | ||
640 | |||
641 | // This literally does nothing internally in the actual service itself, | ||
642 | // and just returns a successful result code regardless of the input. | ||
643 | void SetDisplayEnabled(HLERequestContext& ctx) { | ||
644 | LOG_DEBUG(Service_VI, "called."); | ||
645 | |||
646 | IPC::ResponseBuilder rb{ctx, 2}; | ||
647 | rb.Push(ResultSuccess); | ||
648 | } | ||
649 | |||
650 | void GetDisplayResolution(HLERequestContext& ctx) { | ||
651 | IPC::RequestParser rp{ctx}; | ||
652 | const u64 display_id = rp.Pop<u64>(); | ||
653 | |||
654 | LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); | ||
655 | |||
656 | IPC::ResponseBuilder rb{ctx, 6}; | ||
657 | rb.Push(ResultSuccess); | ||
658 | |||
659 | // This only returns the fixed values of 1280x720 and makes no distinguishing | ||
660 | // between docked and undocked dimensions. We take the liberty of applying | ||
661 | // the resolution scaling factor here. | ||
662 | rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth)); | ||
663 | rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); | ||
664 | } | ||
665 | |||
666 | void SetLayerScalingMode(HLERequestContext& ctx) { | ||
667 | IPC::RequestParser rp{ctx}; | ||
668 | const auto scaling_mode = rp.PopEnum<NintendoScaleMode>(); | ||
669 | const u64 unknown = rp.Pop<u64>(); | ||
670 | |||
671 | LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, | ||
672 | unknown); | ||
673 | |||
674 | IPC::ResponseBuilder rb{ctx, 2}; | ||
675 | |||
676 | if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { | ||
677 | LOG_ERROR(Service_VI, "Invalid scaling mode provided."); | ||
678 | rb.Push(ResultOperationFailed); | ||
679 | return; | ||
680 | } | ||
681 | |||
682 | if (scaling_mode != NintendoScaleMode::ScaleToWindow && | ||
683 | scaling_mode != NintendoScaleMode::PreserveAspectRatio) { | ||
684 | LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); | ||
685 | rb.Push(ResultNotSupported); | ||
686 | return; | ||
687 | } | ||
688 | |||
689 | rb.Push(ResultSuccess); | ||
690 | } | ||
691 | |||
692 | void ListDisplays(HLERequestContext& ctx) { | ||
693 | LOG_WARNING(Service_VI, "(STUBBED) called"); | ||
694 | |||
695 | const DisplayInfo display_info; | ||
696 | ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); | ||
697 | IPC::ResponseBuilder rb{ctx, 4}; | ||
698 | rb.Push(ResultSuccess); | ||
699 | rb.Push<u64>(1); | ||
700 | } | ||
701 | |||
702 | void OpenLayer(HLERequestContext& ctx) { | ||
703 | IPC::RequestParser rp{ctx}; | ||
704 | const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); | ||
705 | const std::string display_name(Common::StringFromBuffer(name_buf)); | ||
706 | |||
707 | const u64 layer_id = rp.Pop<u64>(); | ||
708 | const u64 aruid = rp.Pop<u64>(); | ||
709 | |||
710 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); | ||
711 | |||
712 | const auto display_id = nvnflinger.OpenDisplay(display_name); | ||
713 | if (!display_id) { | ||
714 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||
715 | IPC::ResponseBuilder rb{ctx, 2}; | ||
716 | rb.Push(ResultNotFound); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); | ||
721 | if (!buffer_queue_id) { | ||
722 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||
723 | IPC::ResponseBuilder rb{ctx, 2}; | ||
724 | rb.Push(ResultNotFound); | ||
725 | return; | ||
726 | } | ||
727 | |||
728 | if (!nvnflinger.OpenLayer(layer_id)) { | ||
729 | LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||
730 | IPC::ResponseBuilder rb{ctx, 2}; | ||
731 | rb.Push(ResultOperationFailed); | ||
732 | return; | ||
733 | } | ||
734 | |||
735 | android::OutputParcel parcel; | ||
736 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||
737 | |||
738 | const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); | ||
739 | |||
740 | IPC::ResponseBuilder rb{ctx, 4}; | ||
741 | rb.Push(ResultSuccess); | ||
742 | rb.Push<u64>(buffer_size); | ||
743 | } | ||
744 | |||
745 | void CloseLayer(HLERequestContext& ctx) { | ||
746 | IPC::RequestParser rp{ctx}; | ||
747 | const auto layer_id{rp.Pop<u64>()}; | ||
748 | |||
749 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | ||
750 | |||
751 | if (!nvnflinger.CloseLayer(layer_id)) { | ||
752 | LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||
753 | IPC::ResponseBuilder rb{ctx, 2}; | ||
754 | rb.Push(ResultOperationFailed); | ||
755 | return; | ||
756 | } | ||
757 | |||
758 | IPC::ResponseBuilder rb{ctx, 2}; | ||
759 | rb.Push(ResultSuccess); | ||
760 | } | ||
761 | |||
762 | void CreateStrayLayer(HLERequestContext& ctx) { | ||
763 | IPC::RequestParser rp{ctx}; | ||
764 | const u32 flags = rp.Pop<u32>(); | ||
765 | rp.Pop<u32>(); // padding | ||
766 | const u64 display_id = rp.Pop<u64>(); | ||
767 | |||
768 | LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); | ||
769 | |||
770 | // TODO(Subv): What's the difference between a Stray and a Managed layer? | ||
771 | |||
772 | const auto layer_id = nvnflinger.CreateLayer(display_id); | ||
773 | if (!layer_id) { | ||
774 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||
775 | IPC::ResponseBuilder rb{ctx, 2}; | ||
776 | rb.Push(ResultNotFound); | ||
777 | return; | ||
778 | } | ||
779 | |||
780 | stray_layer_ids.push_back(*layer_id); | ||
781 | const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); | ||
782 | if (!buffer_queue_id) { | ||
783 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||
784 | IPC::ResponseBuilder rb{ctx, 2}; | ||
785 | rb.Push(ResultNotFound); | ||
786 | return; | ||
787 | } | ||
788 | |||
789 | android::OutputParcel parcel; | ||
790 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||
791 | |||
792 | const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); | ||
793 | |||
794 | IPC::ResponseBuilder rb{ctx, 6}; | ||
795 | rb.Push(ResultSuccess); | ||
796 | rb.Push(*layer_id); | ||
797 | rb.Push<u64>(buffer_size); | ||
798 | } | ||
799 | |||
800 | void DestroyStrayLayer(HLERequestContext& ctx) { | ||
801 | IPC::RequestParser rp{ctx}; | ||
802 | const u64 layer_id = rp.Pop<u64>(); | ||
803 | |||
804 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); | ||
805 | nvnflinger.DestroyLayer(layer_id); | ||
806 | |||
807 | IPC::ResponseBuilder rb{ctx, 2}; | ||
808 | rb.Push(ResultSuccess); | ||
809 | } | ||
810 | |||
811 | void GetDisplayVsyncEvent(HLERequestContext& ctx) { | ||
812 | IPC::RequestParser rp{ctx}; | ||
813 | const u64 display_id = rp.Pop<u64>(); | ||
814 | |||
815 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||
816 | |||
817 | Kernel::KReadableEvent* vsync_event{}; | ||
818 | const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); | ||
819 | if (result != ResultSuccess) { | ||
820 | if (result == ResultNotFound) { | ||
821 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||
822 | } | ||
823 | |||
824 | IPC::ResponseBuilder rb{ctx, 2}; | ||
825 | rb.Push(result); | ||
826 | return; | ||
827 | } | ||
828 | if (vsync_event_fetched) { | ||
829 | IPC::ResponseBuilder rb{ctx, 2}; | ||
830 | rb.Push(VI::ResultPermissionDenied); | ||
831 | return; | ||
832 | } | ||
833 | vsync_event_fetched = true; | ||
834 | |||
835 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
836 | rb.Push(ResultSuccess); | ||
837 | rb.PushCopyObjects(vsync_event); | ||
838 | } | ||
839 | |||
840 | void ConvertScalingMode(HLERequestContext& ctx) { | ||
841 | IPC::RequestParser rp{ctx}; | ||
842 | const auto mode = rp.PopEnum<NintendoScaleMode>(); | ||
843 | LOG_DEBUG(Service_VI, "called mode={}", mode); | ||
844 | |||
845 | ConvertedScaleMode converted_mode{}; | ||
846 | const auto result = ConvertScalingModeImpl(&converted_mode, mode); | ||
847 | |||
848 | if (result == ResultSuccess) { | ||
849 | IPC::ResponseBuilder rb{ctx, 4}; | ||
850 | rb.Push(ResultSuccess); | ||
851 | rb.PushEnum(converted_mode); | ||
852 | } else { | ||
853 | IPC::ResponseBuilder rb{ctx, 2}; | ||
854 | rb.Push(result); | ||
855 | } | ||
856 | } | ||
857 | |||
858 | void GetIndirectLayerImageMap(HLERequestContext& ctx) { | ||
859 | IPC::RequestParser rp{ctx}; | ||
860 | const auto width = rp.Pop<s64>(); | ||
861 | const auto height = rp.Pop<s64>(); | ||
862 | const auto indirect_layer_consumer_handle = rp.Pop<u64>(); | ||
863 | const auto applet_resource_user_id = rp.Pop<u64>(); | ||
864 | |||
865 | LOG_WARNING(Service_VI, | ||
866 | "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " | ||
867 | "applet_resource_user_id={}", | ||
868 | width, height, indirect_layer_consumer_handle, applet_resource_user_id); | ||
869 | |||
870 | std::vector<u8> out_buffer(0x46); | ||
871 | ctx.WriteBuffer(out_buffer); | ||
872 | |||
873 | // TODO: Figure out what these are | ||
874 | |||
875 | constexpr s64 unknown_result_1 = 0; | ||
876 | constexpr s64 unknown_result_2 = 0; | ||
877 | |||
878 | IPC::ResponseBuilder rb{ctx, 6}; | ||
879 | rb.Push(unknown_result_1); | ||
880 | rb.Push(unknown_result_2); | ||
881 | rb.Push(ResultSuccess); | ||
882 | } | ||
883 | |||
884 | void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { | ||
885 | IPC::RequestParser rp{ctx}; | ||
886 | const auto width = rp.Pop<u64>(); | ||
887 | const auto height = rp.Pop<u64>(); | ||
888 | LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); | ||
889 | |||
890 | constexpr u64 base_size = 0x20000; | ||
891 | constexpr u64 alignment = 0x1000; | ||
892 | const auto texture_size = width * height * 4; | ||
893 | const auto out_size = (texture_size + base_size - 1) / base_size * base_size; | ||
894 | |||
895 | IPC::ResponseBuilder rb{ctx, 6}; | ||
896 | rb.Push(ResultSuccess); | ||
897 | rb.Push(out_size); | ||
898 | rb.Push(alignment); | ||
899 | } | ||
900 | |||
901 | static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, | ||
902 | NintendoScaleMode mode) { | ||
903 | switch (mode) { | ||
904 | case NintendoScaleMode::None: | ||
905 | *out_scaling_mode = ConvertedScaleMode::None; | ||
906 | return ResultSuccess; | ||
907 | case NintendoScaleMode::Freeze: | ||
908 | *out_scaling_mode = ConvertedScaleMode::Freeze; | ||
909 | return ResultSuccess; | ||
910 | case NintendoScaleMode::ScaleToWindow: | ||
911 | *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; | ||
912 | return ResultSuccess; | ||
913 | case NintendoScaleMode::ScaleAndCrop: | ||
914 | *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; | ||
915 | return ResultSuccess; | ||
916 | case NintendoScaleMode::PreserveAspectRatio: | ||
917 | *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; | ||
918 | return ResultSuccess; | ||
919 | default: | ||
920 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | ||
921 | return ResultOperationFailed; | ||
922 | } | ||
923 | } | ||
924 | |||
925 | Nvnflinger::Nvnflinger& nvnflinger; | ||
926 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||
927 | std::vector<u64> stray_layer_ids; | ||
928 | bool vsync_event_fetched{false}; | ||
929 | }; | ||
930 | |||
931 | static bool IsValidServiceAccess(Permission permission, Policy policy) { | ||
932 | if (permission == Permission::User) { | ||
933 | return policy == Policy::User; | ||
934 | } | ||
935 | |||
936 | if (permission == Permission::System || permission == Permission::Manager) { | ||
937 | return policy == Policy::User || policy == Policy::Compositor; | ||
938 | } | ||
939 | |||
940 | return false; | ||
941 | } | ||
942 | |||
943 | void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | ||
944 | Nvnflinger::Nvnflinger& nvnflinger, | ||
945 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, | ||
946 | Permission permission) { | ||
947 | IPC::RequestParser rp{ctx}; | ||
948 | const auto policy = rp.PopEnum<Policy>(); | ||
949 | |||
950 | if (!IsValidServiceAccess(permission, policy)) { | ||
951 | LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); | ||
952 | IPC::ResponseBuilder rb{ctx, 2}; | ||
953 | rb.Push(ResultPermissionDenied); | ||
954 | return; | ||
955 | } | ||
956 | |||
957 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
958 | rb.Push(ResultSuccess); | ||
959 | rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); | ||
960 | } | ||
961 | |||
962 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | 13 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, |
963 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { | 14 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { |
964 | auto server_manager = std::make_unique<ServerManager>(system); | 15 | auto server_manager = std::make_unique<ServerManager>(system); |
965 | 16 | ||
17 | server_manager->RegisterNamedService("vi:m", std::make_shared<IManagerRootService>( | ||
18 | system, nvnflinger, hos_binder_driver_server)); | ||
966 | server_manager->RegisterNamedService( | 19 | server_manager->RegisterNamedService( |
967 | "vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server)); | 20 | "vi:s", std::make_shared<ISystemRootService>(system, nvnflinger, hos_binder_driver_server)); |
968 | server_manager->RegisterNamedService( | 21 | server_manager->RegisterNamedService("vi:u", std::make_shared<IApplicationRootService>( |
969 | "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server)); | 22 | system, nvnflinger, hos_binder_driver_server)); |
970 | server_manager->RegisterNamedService( | ||
971 | "vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server)); | ||
972 | ServerManager::RunServer(std::move(server_manager)); | 23 | ServerManager::RunServer(std::move(server_manager)); |
973 | } | 24 | } |
974 | 25 | ||
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 25e0aed66..a81a701b0 100755 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
@@ -3,16 +3,10 @@ | |||
3 | 3 | ||
4 | #pragma once | 4 | #pragma once |
5 | 5 | ||
6 | #include "common/common_types.h" | ||
7 | |||
8 | namespace Core { | 6 | namespace Core { |
9 | class System; | 7 | class System; |
10 | } | 8 | } |
11 | 9 | ||
12 | namespace Service { | ||
13 | class HLERequestContext; | ||
14 | } | ||
15 | |||
16 | namespace Service::Nvnflinger { | 10 | namespace Service::Nvnflinger { |
17 | class HosBinderDriverServer; | 11 | class HosBinderDriverServer; |
18 | class Nvnflinger; | 12 | class Nvnflinger; |
@@ -20,34 +14,6 @@ class Nvnflinger; | |||
20 | 14 | ||
21 | namespace Service::VI { | 15 | namespace Service::VI { |
22 | 16 | ||
23 | enum class DisplayResolution : u32 { | ||
24 | DockedWidth = 1920, | ||
25 | DockedHeight = 1080, | ||
26 | UndockedWidth = 1280, | ||
27 | UndockedHeight = 720, | ||
28 | }; | ||
29 | |||
30 | /// Permission level for a particular VI service instance | ||
31 | enum class Permission { | ||
32 | User, | ||
33 | System, | ||
34 | Manager, | ||
35 | }; | ||
36 | |||
37 | /// A policy type that may be requested via GetDisplayService and | ||
38 | /// GetDisplayServiceWithProxyNameExchange | ||
39 | enum class Policy { | ||
40 | User, | ||
41 | Compositor, | ||
42 | }; | ||
43 | |||
44 | namespace detail { | ||
45 | void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | ||
46 | Nvnflinger::Nvnflinger& nv_flinger, | ||
47 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, | ||
48 | Permission permission); | ||
49 | } // namespace detail | ||
50 | |||
51 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | 17 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, |
52 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | 18 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); |
53 | 19 | ||
diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h new file mode 100755 index 000000000..91e4b380c --- /dev/null +++ b/src/core/hle/service/vi/vi_types.h | |||
@@ -0,0 +1,84 @@ | |||
1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | #include "common/common_funcs.h" | ||
7 | |||
8 | namespace Service::VI { | ||
9 | |||
10 | enum class DisplayResolution : u32 { | ||
11 | DockedWidth = 1920, | ||
12 | DockedHeight = 1080, | ||
13 | UndockedWidth = 1280, | ||
14 | UndockedHeight = 720, | ||
15 | }; | ||
16 | |||
17 | /// Permission level for a particular VI service instance | ||
18 | enum class Permission { | ||
19 | User, | ||
20 | System, | ||
21 | Manager, | ||
22 | }; | ||
23 | |||
24 | /// A policy type that may be requested via GetDisplayService and | ||
25 | /// GetDisplayServiceWithProxyNameExchange | ||
26 | enum class Policy : u32 { | ||
27 | User, | ||
28 | Compositor, | ||
29 | }; | ||
30 | |||
31 | enum class ConvertedScaleMode : u64 { | ||
32 | Freeze = 0, | ||
33 | ScaleToWindow = 1, | ||
34 | ScaleAndCrop = 2, | ||
35 | None = 3, | ||
36 | PreserveAspectRatio = 4, | ||
37 | }; | ||
38 | |||
39 | enum class NintendoScaleMode : u32 { | ||
40 | None = 0, | ||
41 | Freeze = 1, | ||
42 | ScaleToWindow = 2, | ||
43 | ScaleAndCrop = 3, | ||
44 | PreserveAspectRatio = 4, | ||
45 | }; | ||
46 | |||
47 | using DisplayName = std::array<char, 0x40>; | ||
48 | |||
49 | struct DisplayInfo { | ||
50 | /// The name of this particular display. | ||
51 | DisplayName display_name{"Default"}; | ||
52 | |||
53 | /// Whether or not the display has a limited number of layers. | ||
54 | u8 has_limited_layers{1}; | ||
55 | INSERT_PADDING_BYTES(7); | ||
56 | |||
57 | /// Indicates the total amount of layers supported by the display. | ||
58 | /// @note This is only valid if has_limited_layers is set. | ||
59 | u64 max_layers{1}; | ||
60 | |||
61 | /// Maximum width in pixels. | ||
62 | u64 width{1920}; | ||
63 | |||
64 | /// Maximum height in pixels. | ||
65 | u64 height{1080}; | ||
66 | }; | ||
67 | static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); | ||
68 | |||
69 | class NativeWindow final { | ||
70 | public: | ||
71 | constexpr explicit NativeWindow(u32 id_) : id{id_} {} | ||
72 | constexpr explicit NativeWindow(const NativeWindow& other) = default; | ||
73 | |||
74 | private: | ||
75 | const u32 magic = 2; | ||
76 | const u32 process_id = 1; | ||
77 | const u64 id; | ||
78 | INSERT_PADDING_WORDS(2); | ||
79 | std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; | ||
80 | INSERT_PADDING_WORDS(2); | ||
81 | }; | ||
82 | static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); | ||
83 | |||
84 | } // namespace Service::VI | ||