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