summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/vi/application_display_service.cpp456
-rw-r--r--src/core/hle/service/vi/application_display_service.h77
-rw-r--r--src/core/hle/service/vi/vi_types.h4
3 files changed, 228 insertions, 309 deletions
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp
index ae0cb7a08..78229e30f 100644
--- a/src/core/hle/service/vi/application_display_service.cpp
+++ b/src/core/hle/service/vi/application_display_service.cpp
@@ -1,8 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 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/string_util.h" 4#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/ipc_helpers.h"
6#include "core/hle/service/nvnflinger/nvnflinger.h" 5#include "core/hle/service/nvnflinger/nvnflinger.h"
7#include "core/hle/service/nvnflinger/parcel.h" 6#include "core/hle/service/nvnflinger/parcel.h"
8#include "core/hle/service/vi/application_display_service.h" 7#include "core/hle/service/vi/application_display_service.h"
@@ -14,406 +13,307 @@
14namespace Service::VI { 13namespace Service::VI {
15 14
16IApplicationDisplayService::IApplicationDisplayService( 15IApplicationDisplayService::IApplicationDisplayService(
17 Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, 16 Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
18 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) 17 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server)
19 : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, 18 : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger},
20 hos_binder_driver_server{hos_binder_driver_server_} { 19 m_hos_binder_driver_server{hos_binder_driver_server} {
21 20
21 // clang-format off
22 static const FunctionInfo functions[] = { 22 static const FunctionInfo functions[] = {
23 {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, 23 {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"},
24 {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, 24 {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"},
25 {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, 25 {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"},
26 {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, 26 {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"},
27 "GetIndirectDisplayTransactionService"}, 27 {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"},
28 {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, 28 {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"},
29 {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, 29 {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"},
30 {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, 30 {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"},
31 {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, 31 {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"},
32 {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, 32 {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"},
33 {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, 33 {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"},
34 {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, 34 {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"},
35 {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, 35 {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"},
36 {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, 36 {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"},
37 {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, 37 {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"},
38 {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, 38 {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"},
39 {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, 39 {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"},
40 {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, "GetIndirectLayerImageMap"},
41 {2451, nullptr, "GetIndirectLayerImageCropMap"}, 40 {2451, nullptr, "GetIndirectLayerImageCropMap"},
42 {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, 41 {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"},
43 "GetIndirectLayerImageRequiredMemoryInfo"}, 42 {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"},
44 {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
45 {5203, nullptr, "GetDisplayVsyncEventForDebug"}, 43 {5203, nullptr, "GetDisplayVsyncEventForDebug"},
46 }; 44 };
45 // clang-format on
46
47 RegisterHandlers(functions); 47 RegisterHandlers(functions);
48} 48}
49 49
50IApplicationDisplayService::~IApplicationDisplayService() { 50IApplicationDisplayService::~IApplicationDisplayService() {
51 for (const auto layer_id : stray_layer_ids) { 51 for (const auto layer_id : m_stray_layer_ids) {
52 nvnflinger.DestroyLayer(layer_id); 52 m_nvnflinger.DestroyLayer(layer_id);
53 } 53 }
54} 54}
55 55
56void IApplicationDisplayService::GetRelayService(HLERequestContext& ctx) { 56Result IApplicationDisplayService::GetRelayService(
57 Out<SharedPointer<IHOSBinderDriver>> out_relay_service) {
57 LOG_WARNING(Service_VI, "(STUBBED) called"); 58 LOG_WARNING(Service_VI, "(STUBBED) called");
58 59 *out_relay_service = std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server);
59 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 60 R_SUCCEED();
60 rb.Push(ResultSuccess);
61 rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
62} 61}
63 62
64void IApplicationDisplayService::GetSystemDisplayService(HLERequestContext& ctx) { 63Result IApplicationDisplayService::GetSystemDisplayService(
64 Out<SharedPointer<ISystemDisplayService>> out_system_display_service) {
65 LOG_WARNING(Service_VI, "(STUBBED) called"); 65 LOG_WARNING(Service_VI, "(STUBBED) called");
66 66 *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_nvnflinger);
67 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 67 R_SUCCEED();
68 rb.Push(ResultSuccess);
69 rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger);
70} 68}
71 69
72void IApplicationDisplayService::GetManagerDisplayService(HLERequestContext& ctx) { 70Result IApplicationDisplayService::GetManagerDisplayService(
71 Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) {
73 LOG_WARNING(Service_VI, "(STUBBED) called"); 72 LOG_WARNING(Service_VI, "(STUBBED) called");
74 73 *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_nvnflinger);
75 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 74 R_SUCCEED();
76 rb.Push(ResultSuccess);
77 rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger);
78} 75}
79 76
80void IApplicationDisplayService::GetIndirectDisplayTransactionService(HLERequestContext& ctx) { 77Result IApplicationDisplayService::GetIndirectDisplayTransactionService(
78 Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service) {
81 LOG_WARNING(Service_VI, "(STUBBED) called"); 79 LOG_WARNING(Service_VI, "(STUBBED) called");
82 80 *out_indirect_display_transaction_service =
83 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 81 std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server);
84 rb.Push(ResultSuccess); 82 R_SUCCEED();
85 rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
86} 83}
87 84
88void IApplicationDisplayService::OpenDisplay(HLERequestContext& ctx) { 85Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) {
89 LOG_WARNING(Service_VI, "(STUBBED) called"); 86 LOG_WARNING(Service_VI, "(STUBBED) called");
90 87
91 IPC::RequestParser rp{ctx}; 88 display_name[display_name.size() - 1] = '\0';
92 const auto name_buf = rp.PopRaw<std::array<char, 0x40>>(); 89 ASSERT_MSG(strcmp(display_name.data(), "Default") == 0,
93 90 "Non-default displays aren't supported yet");
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 91
100 OpenDisplayImpl(ctx, "Default"); 92 const auto display_id = m_nvnflinger.OpenDisplay(display_name.data());
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) { 93 if (!display_id) {
114 LOG_ERROR(Service_VI, "Display not found! display_name={}", name); 94 LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data());
115 IPC::ResponseBuilder rb{ctx, 2}; 95 R_THROW(VI::ResultNotFound);
116 rb.Push(ResultNotFound);
117 return;
118 } 96 }
119 97
120 IPC::ResponseBuilder rb{ctx, 4}; 98 *out_display_id = *display_id;
121 rb.Push(ResultSuccess); 99 R_SUCCEED();
122 rb.Push<u64>(*display_id);
123} 100}
124 101
125void IApplicationDisplayService::CloseDisplay(HLERequestContext& ctx) { 102Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
126 IPC::RequestParser rp{ctx}; 103 LOG_DEBUG(Service_VI, "called");
127 const u64 display_id = rp.Pop<u64>(); 104 R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"}));
128
129 const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
130
131 IPC::ResponseBuilder rb{ctx, 2};
132 rb.Push(rc);
133} 105}
134 106
135// This literally does nothing internally in the actual service itself, 107Result IApplicationDisplayService::CloseDisplay(u64 display_id) {
136// and just returns a successful result code regardless of the input. 108 LOG_DEBUG(Service_VI, "called");
137void IApplicationDisplayService::SetDisplayEnabled(HLERequestContext& ctx) { 109 R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id));
138 LOG_DEBUG(Service_VI, "called."); 110 R_THROW(ResultUnknown);
139
140 IPC::ResponseBuilder rb{ctx, 2};
141 rb.Push(ResultSuccess);
142} 111}
143 112
144void IApplicationDisplayService::GetDisplayResolution(HLERequestContext& ctx) { 113Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) {
145 IPC::RequestParser rp{ctx}; 114 LOG_DEBUG(Service_VI, "called");
146 const u64 display_id = rp.Pop<u64>();
147 115
148 LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); 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}
149 120
150 IPC::ResponseBuilder rb{ctx, 6}; 121Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<s64> out_height,
151 rb.Push(ResultSuccess); 122 u64 display_id) {
123 LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
152 124
153 // This only returns the fixed values of 1280x720 and makes no distinguishing 125 // This only returns the fixed values of 1280x720 and makes no distinguishing
154 // between docked and undocked dimensions. We take the liberty of applying 126 // between docked and undocked dimensions.
155 // the resolution scaling factor here. 127 *out_width = static_cast<s64>(DisplayResolution::UndockedWidth);
156 rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth)); 128 *out_height = static_cast<s64>(DisplayResolution::UndockedHeight);
157 rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); 129 R_SUCCEED();
158} 130}
159 131
160void IApplicationDisplayService::SetLayerScalingMode(HLERequestContext& ctx) { 132Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) {
161 IPC::RequestParser rp{ctx}; 133 LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id);
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 134
168 IPC::ResponseBuilder rb{ctx, 2}; 135 if (scale_mode > NintendoScaleMode::PreserveAspectRatio) {
169
170 if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) {
171 LOG_ERROR(Service_VI, "Invalid scaling mode provided."); 136 LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
172 rb.Push(ResultOperationFailed); 137 R_THROW(VI::ResultOperationFailed);
173 return;
174 } 138 }
175 139
176 if (scaling_mode != NintendoScaleMode::ScaleToWindow && 140 if (scale_mode != NintendoScaleMode::ScaleToWindow &&
177 scaling_mode != NintendoScaleMode::PreserveAspectRatio) { 141 scale_mode != NintendoScaleMode::PreserveAspectRatio) {
178 LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); 142 LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
179 rb.Push(ResultNotSupported); 143 R_THROW(VI::ResultNotSupported);
180 return;
181 } 144 }
182 145
183 rb.Push(ResultSuccess); 146 R_SUCCEED();
184} 147}
185 148
186void IApplicationDisplayService::ListDisplays(HLERequestContext& ctx) { 149Result IApplicationDisplayService::ListDisplays(
150 Out<u64> out_count, OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays) {
187 LOG_WARNING(Service_VI, "(STUBBED) called"); 151 LOG_WARNING(Service_VI, "(STUBBED) called");
188 152
189 const DisplayInfo display_info; 153 if (out_displays.size() > 0) {
190 ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); 154 out_displays[0] = DisplayInfo{};
191 IPC::ResponseBuilder rb{ctx, 4}; 155 *out_count = 1;
192 rb.Push(ResultSuccess); 156 } else {
193 rb.Push<u64>(1); 157 *out_count = 0;
194} 158 }
195 159
196void IApplicationDisplayService::OpenLayer(HLERequestContext& ctx) { 160 R_SUCCEED();
197 IPC::RequestParser rp{ctx}; 161}
198 const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
199 const std::string display_name(Common::StringFromBuffer(name_buf));
200 162
201 const u64 layer_id = rp.Pop<u64>(); 163Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,
202 const u64 aruid = rp.Pop<u64>(); 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';
203 168
204 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); 169 LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid);
205 170
206 const auto display_id = nvnflinger.OpenDisplay(display_name); 171 const auto display_id = m_nvnflinger.OpenDisplay(display_name.data());
207 if (!display_id) { 172 if (!display_id) {
208 LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); 173 LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
209 IPC::ResponseBuilder rb{ctx, 2}; 174 R_THROW(VI::ResultNotFound);
210 rb.Push(ResultNotFound);
211 return;
212 } 175 }
213 176
214 const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); 177 const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id);
215 if (!buffer_queue_id) { 178 if (!buffer_queue_id) {
216 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); 179 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
217 IPC::ResponseBuilder rb{ctx, 2}; 180 R_THROW(VI::ResultNotFound);
218 rb.Push(ResultNotFound);
219 return;
220 } 181 }
221 182
222 if (!nvnflinger.OpenLayer(layer_id)) { 183 if (!m_nvnflinger.OpenLayer(layer_id)) {
223 LOG_WARNING(Service_VI, "Tried to open layer which was already open"); 184 LOG_WARNING(Service_VI, "Tried to open layer which was already open");
224 IPC::ResponseBuilder rb{ctx, 2}; 185 R_THROW(VI::ResultOperationFailed);
225 rb.Push(ResultOperationFailed);
226 return;
227 } 186 }
228 187
229 android::OutputParcel parcel; 188 android::OutputParcel parcel;
230 parcel.WriteInterface(NativeWindow{*buffer_queue_id}); 189 parcel.WriteInterface(NativeWindow{*buffer_queue_id});
231 190
232 const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); 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();
233 195
234 IPC::ResponseBuilder rb{ctx, 4}; 196 R_SUCCEED();
235 rb.Push(ResultSuccess);
236 rb.Push<u64>(buffer_size);
237} 197}
238 198
239void IApplicationDisplayService::CloseLayer(HLERequestContext& ctx) { 199Result IApplicationDisplayService::CloseLayer(u64 layer_id) {
240 IPC::RequestParser rp{ctx}; 200 LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
241 const auto layer_id{rp.Pop<u64>()};
242
243 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
244 201
245 if (!nvnflinger.CloseLayer(layer_id)) { 202 if (!m_nvnflinger.CloseLayer(layer_id)) {
246 LOG_WARNING(Service_VI, "Tried to close layer which was not open"); 203 LOG_WARNING(Service_VI, "Tried to close layer which was not open");
247 IPC::ResponseBuilder rb{ctx, 2}; 204 R_THROW(VI::ResultOperationFailed);
248 rb.Push(ResultOperationFailed);
249 return;
250 } 205 }
251 206
252 IPC::ResponseBuilder rb{ctx, 2}; 207 R_SUCCEED();
253 rb.Push(ResultSuccess);
254} 208}
255 209
256void IApplicationDisplayService::CreateStrayLayer(HLERequestContext& ctx) { 210Result IApplicationDisplayService::CreateStrayLayer(
257 IPC::RequestParser rp{ctx}; 211 Out<u64> out_layer_id, Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
258 const u32 flags = rp.Pop<u32>(); 212 u32 flags, u64 display_id) {
259 rp.Pop<u32>(); // padding 213 LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id);
260 const u64 display_id = rp.Pop<u64>();
261 214
262 LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); 215 const auto layer_id = m_nvnflinger.CreateLayer(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) { 216 if (!layer_id) {
268 LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); 217 LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
269 IPC::ResponseBuilder rb{ctx, 2}; 218 R_THROW(VI::ResultNotFound);
270 rb.Push(ResultNotFound);
271 return;
272 } 219 }
273 220
274 stray_layer_ids.push_back(*layer_id); 221 m_stray_layer_ids.push_back(*layer_id);
275 const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); 222 const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id);
276 if (!buffer_queue_id) { 223 if (!buffer_queue_id) {
277 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); 224 LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
278 IPC::ResponseBuilder rb{ctx, 2}; 225 R_THROW(VI::ResultNotFound);
279 rb.Push(ResultNotFound);
280 return;
281 } 226 }
282 227
283 android::OutputParcel parcel; 228 android::OutputParcel parcel;
284 parcel.WriteInterface(NativeWindow{*buffer_queue_id}); 229 parcel.WriteInterface(NativeWindow{*buffer_queue_id});
285 230
286 const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); 231 const auto buffer = parcel.Serialize();
287 232 std::memcpy(out_native_window.data(), buffer.data(),
288 IPC::ResponseBuilder rb{ctx, 6}; 233 std::min(out_native_window.size(), buffer.size()));
289 rb.Push(ResultSuccess);
290 rb.Push(*layer_id);
291 rb.Push<u64>(buffer_size);
292}
293 234
294void IApplicationDisplayService::DestroyStrayLayer(HLERequestContext& ctx) { 235 *out_layer_id = *layer_id;
295 IPC::RequestParser rp{ctx}; 236 *out_size = buffer.size();
296 const u64 layer_id = rp.Pop<u64>();
297 237
298 LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); 238 R_SUCCEED();
299 nvnflinger.DestroyLayer(layer_id);
300
301 IPC::ResponseBuilder rb{ctx, 2};
302 rb.Push(ResultSuccess);
303} 239}
304 240
305void IApplicationDisplayService::GetDisplayVsyncEvent(HLERequestContext& ctx) { 241Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) {
306 IPC::RequestParser rp{ctx}; 242 LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
307 const u64 display_id = rp.Pop<u64>(); 243 m_nvnflinger.DestroyLayer(layer_id);
244 R_SUCCEED();
245}
308 246
247Result IApplicationDisplayService::GetDisplayVsyncEvent(
248 OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) {
309 LOG_DEBUG(Service_VI, "called. display_id={}", display_id); 249 LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
310 250
311 Kernel::KReadableEvent* vsync_event{}; 251 const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id);
312 const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id);
313 if (result != ResultSuccess) { 252 if (result != ResultSuccess) {
314 if (result == ResultNotFound) { 253 if (result == ResultNotFound) {
315 LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); 254 LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
316 } 255 }
317 256
318 IPC::ResponseBuilder rb{ctx, 2}; 257 R_THROW(result);
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 } 258 }
327 vsync_event_fetched = true;
328 259
329 IPC::ResponseBuilder rb{ctx, 2, 1}; 260 R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied);
330 rb.Push(ResultSuccess); 261 m_vsync_event_fetched = true;
331 rb.PushCopyObjects(vsync_event);
332}
333 262
334void IApplicationDisplayService::ConvertScalingMode(HLERequestContext& ctx) { 263 R_SUCCEED();
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} 264}
351 265
352void IApplicationDisplayService::GetIndirectLayerImageMap(HLERequestContext& ctx) { 266Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode,
353 IPC::RequestParser rp{ctx}; 267 NintendoScaleMode mode) {
354 const auto width = rp.Pop<s64>(); 268 LOG_DEBUG(Service_VI, "called mode={}", mode);
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 269
395Result IApplicationDisplayService::ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode,
396 NintendoScaleMode mode) {
397 switch (mode) { 270 switch (mode) {
398 case NintendoScaleMode::None: 271 case NintendoScaleMode::None:
399 *out_scaling_mode = ConvertedScaleMode::None; 272 *out_scaling_mode = ConvertedScaleMode::None;
400 return ResultSuccess; 273 R_SUCCEED();
401 case NintendoScaleMode::Freeze: 274 case NintendoScaleMode::Freeze:
402 *out_scaling_mode = ConvertedScaleMode::Freeze; 275 *out_scaling_mode = ConvertedScaleMode::Freeze;
403 return ResultSuccess; 276 R_SUCCEED();
404 case NintendoScaleMode::ScaleToWindow: 277 case NintendoScaleMode::ScaleToWindow:
405 *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; 278 *out_scaling_mode = ConvertedScaleMode::ScaleToWindow;
406 return ResultSuccess; 279 R_SUCCEED();
407 case NintendoScaleMode::ScaleAndCrop: 280 case NintendoScaleMode::ScaleAndCrop:
408 *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; 281 *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop;
409 return ResultSuccess; 282 R_SUCCEED();
410 case NintendoScaleMode::PreserveAspectRatio: 283 case NintendoScaleMode::PreserveAspectRatio:
411 *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; 284 *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio;
412 return ResultSuccess; 285 R_SUCCEED();
413 default: 286 default:
414 LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); 287 LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
415 return ResultOperationFailed; 288 R_THROW(VI::ResultOperationFailed);
416 } 289 }
417} 290}
418 291
292Result 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
305Result 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
419} // namespace Service::VI 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
index 51ae2c472..5dff4bb31 100644
--- a/src/core/hle/service/vi/application_display_service.h
+++ b/src/core/hle/service/vi/application_display_service.h
@@ -1,48 +1,65 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 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 "core/hle/service/cmif_types.h"
4#include "core/hle/service/service.h" 5#include "core/hle/service/service.h"
5#include "core/hle/service/vi/vi_types.h" 6#include "core/hle/service/vi/vi_types.h"
6 7
8namespace Kernel {
9class KReadableEvent;
10}
11
7namespace Service::VI { 12namespace Service::VI {
8 13
14class IHOSBinderDriver;
15class IManagerDisplayService;
16class ISystemDisplayService;
17
9class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { 18class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
10public: 19public:
11 IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, 20 IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger,
12 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); 21 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
13 ~IApplicationDisplayService() override; 22 ~IApplicationDisplayService() override;
14 23
15private: 24private:
16 void GetRelayService(HLERequestContext& ctx); 25 Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service);
17 void GetSystemDisplayService(HLERequestContext& ctx); 26 Result GetSystemDisplayService(
18 void GetManagerDisplayService(HLERequestContext& ctx); 27 Out<SharedPointer<ISystemDisplayService>> out_system_display_service);
19 void GetIndirectDisplayTransactionService(HLERequestContext& ctx); 28 Result GetManagerDisplayService(
20 void OpenDisplay(HLERequestContext& ctx); 29 Out<SharedPointer<IManagerDisplayService>> out_manager_display_service);
21 void OpenDefaultDisplay(HLERequestContext& ctx); 30 Result GetIndirectDisplayTransactionService(
22 void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name); 31 Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service);
23 void CloseDisplay(HLERequestContext& ctx); 32 Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name);
24 void SetDisplayEnabled(HLERequestContext& ctx); 33 Result OpenDefaultDisplay(Out<u64> out_display_id);
25 void GetDisplayResolution(HLERequestContext& ctx); 34 Result CloseDisplay(u64 display_id);
26 void SetLayerScalingMode(HLERequestContext& ctx); 35 Result SetDisplayEnabled(u32 state, u64 display_id);
27 void ListDisplays(HLERequestContext& ctx); 36 Result GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, u64 display_id);
28 void OpenLayer(HLERequestContext& ctx); 37 Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id);
29 void CloseLayer(HLERequestContext& ctx); 38 Result ListDisplays(Out<u64> out_count,
30 void CreateStrayLayer(HLERequestContext& ctx); 39 OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays);
31 void DestroyStrayLayer(HLERequestContext& ctx); 40 Result OpenLayer(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
32 void GetDisplayVsyncEvent(HLERequestContext& ctx); 41 DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid);
33 void ConvertScalingMode(HLERequestContext& ctx); 42 Result CloseLayer(u64 layer_id);
34 void GetIndirectLayerImageMap(HLERequestContext& ctx); 43 Result CreateStrayLayer(Out<u64> out_layer_id, Out<u64> out_size,
35 void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx); 44 OutBuffer<BufferAttr_HipcMapAlias> out_native_window, u32 flags,
36 45 u64 display_id);
37private: 46 Result DestroyStrayLayer(u64 layer_id);
38 static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, 47 Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event,
39 NintendoScaleMode mode); 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);
40 57
41private: 58private:
42 Nvnflinger::Nvnflinger& nvnflinger; 59 Nvnflinger::Nvnflinger& m_nvnflinger;
43 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; 60 Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server;
44 std::vector<u64> stray_layer_ids; 61 std::vector<u64> m_stray_layer_ids;
45 bool vsync_event_fetched{false}; 62 bool m_vsync_event_fetched{false};
46}; 63};
47 64
48} // namespace Service::VI 65} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h
index 47fe2d11c..91e4b380c 100644
--- a/src/core/hle/service/vi/vi_types.h
+++ b/src/core/hle/service/vi/vi_types.h
@@ -44,9 +44,11 @@ enum class NintendoScaleMode : u32 {
44 PreserveAspectRatio = 4, 44 PreserveAspectRatio = 4,
45}; 45};
46 46
47using DisplayName = std::array<char, 0x40>;
48
47struct DisplayInfo { 49struct DisplayInfo {
48 /// The name of this particular display. 50 /// The name of this particular display.
49 char display_name[0x40]{"Default"}; 51 DisplayName display_name{"Default"};
50 52
51 /// Whether or not the display has a limited number of layers. 53 /// Whether or not the display has a limited number of layers.
52 u8 has_limited_layers{1}; 54 u8 has_limited_layers{1};