diff options
| author | 2024-02-13 23:36:06 -0500 | |
|---|---|---|
| committer | 2024-02-14 12:03:32 -0500 | |
| commit | 2e8c0e9247bfcb5cdd0f4235bda5ee6f58b16c14 (patch) | |
| tree | 7c28b4f1b8d7bbbb7b363d5569d7dd70b34d146e | |
| parent | vi: extract types (diff) | |
| download | yuzu-2e8c0e9247bfcb5cdd0f4235bda5ee6f58b16c14.tar.gz yuzu-2e8c0e9247bfcb5cdd0f4235bda5ee6f58b16c14.tar.xz yuzu-2e8c0e9247bfcb5cdd0f4235bda5ee6f58b16c14.zip | |
vi: split into implementation files
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 | |||
| 14 | namespace Service::VI { | ||
| 15 | |||
| 16 | IApplicationDisplayService::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 | |||
| 50 | IApplicationDisplayService::~IApplicationDisplayService() { | ||
| 51 | for (const auto layer_id : stray_layer_ids) { | ||
| 52 | nvnflinger.DestroyLayer(layer_id); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | void 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 | |||
| 64 | void 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 | |||
| 72 | void 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 | |||
| 80 | void 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 | |||
| 88 | void 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 | |||
| 97 | void IApplicationDisplayService::OpenDefaultDisplay(HLERequestContext& ctx) { | ||
| 98 | LOG_DEBUG(Service_VI, "called"); | ||
| 99 | |||
| 100 | OpenDisplayImpl(ctx, "Default"); | ||
| 101 | } | ||
| 102 | |||
| 103 | void 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 | |||
| 125 | void 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. | ||
| 137 | void IApplicationDisplayService::SetDisplayEnabled(HLERequestContext& ctx) { | ||
| 138 | LOG_DEBUG(Service_VI, "called."); | ||
| 139 | |||
| 140 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 141 | rb.Push(ResultSuccess); | ||
| 142 | } | ||
| 143 | |||
| 144 | void 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 | |||
| 160 | void 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 | |||
| 186 | void 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 | |||
| 196 | void 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 | |||
| 239 | void 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 | |||
| 256 | void 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 | |||
| 294 | void 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 | |||
| 305 | void 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 | |||
| 334 | void 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 | |||
| 352 | void 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 | |||
| 378 | void 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 | |||
| 395 | Result 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 | |||
| 7 | namespace Service::VI { | ||
| 8 | |||
| 9 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||
| 10 | public: | ||
| 11 | IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, | ||
| 12 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||
| 13 | ~IApplicationDisplayService() override; | ||
| 14 | |||
| 15 | private: | ||
| 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 | |||
| 37 | private: | ||
| 38 | static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, | ||
| 39 | NintendoScaleMode mode); | ||
| 40 | |||
| 41 | private: | ||
| 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 | ||
| 9 | namespace Service::VI { | 8 | namespace Service::VI { |
| 10 | 9 | ||
| 11 | VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | 10 | IApplicationRootService::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 | ||
| 22 | VI_U::~VI_U() = default; | 22 | IApplicationRootService::~IApplicationRootService() = default; |
| 23 | 23 | ||
| 24 | void VI_U::GetDisplayService(HLERequestContext& ctx) { | 24 | void 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 | ||
| 17 | namespace Service::VI { | 17 | namespace Service::VI { |
| 18 | 18 | ||
| 19 | class VI_S final : public ServiceFramework<VI_S> { | 19 | class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { |
| 20 | public: | 20 | public: |
| 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 | ||
| 25 | private: | 25 | private: |
| 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 | |||
| 9 | namespace Service::VI { | ||
| 10 | |||
| 11 | IHOSBinderDriver::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 | |||
| 23 | IHOSBinderDriver::~IHOSBinderDriver() = default; | ||
| 24 | |||
| 25 | void 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 | |||
| 40 | void 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 | |||
| 52 | void 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 | |||
| 6 | namespace Service::VI { | ||
| 7 | |||
| 8 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | ||
| 9 | public: | ||
| 10 | explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_); | ||
| 11 | ~IHOSBinderDriver() override; | ||
| 12 | |||
| 13 | private: | ||
| 14 | void TransactParcel(HLERequestContext& ctx); | ||
| 15 | void AdjustRefcount(HLERequestContext& ctx); | ||
| 16 | void GetNativeHandle(HLERequestContext& ctx); | ||
| 17 | |||
| 18 | private: | ||
| 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 | |||
| 9 | namespace Service::VI { | ||
| 10 | |||
| 11 | IManagerDisplayService::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 | |||
| 104 | IManagerDisplayService::~IManagerDisplayService() = default; | ||
| 105 | |||
| 106 | void 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 | |||
| 116 | void 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 | |||
| 140 | void 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 | |||
| 152 | void 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 | |||
| 6 | namespace Service::VI { | ||
| 7 | |||
| 8 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | ||
| 9 | public: | ||
| 10 | explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||
| 11 | ~IManagerDisplayService() override; | ||
| 12 | |||
| 13 | private: | ||
| 14 | void CloseDisplay(HLERequestContext& ctx); | ||
| 15 | void CreateManagedLayer(HLERequestContext& ctx); | ||
| 16 | void AddToLayerStack(HLERequestContext& ctx); | ||
| 17 | void SetLayerVisibility(HLERequestContext& ctx); | ||
| 18 | |||
| 19 | private: | ||
| 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 | ||
| 9 | namespace Service::VI { | 8 | namespace Service::VI { |
| 10 | 9 | ||
| 11 | VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | 10 | IManagerRootService::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 | ||
| 26 | VI_M::~VI_M() = default; | 26 | IManagerRootService::~IManagerRootService() = default; |
| 27 | 27 | ||
| 28 | void VI_M::GetDisplayService(HLERequestContext& ctx) { | 28 | void 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 | ||
| 17 | namespace Service::VI { | 17 | namespace Service::VI { |
| 18 | 18 | ||
| 19 | class VI_U final : public ServiceFramework<VI_U> { | 19 | class IManagerRootService final : public ServiceFramework<IManagerRootService> { |
| 20 | public: | 20 | public: |
| 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 | ||
| 25 | private: | 25 | private: |
| 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 | |||
| 10 | namespace Service::VI { | ||
| 11 | |||
| 12 | ISystemDisplayService::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 | |||
| 69 | ISystemDisplayService::~ISystemDisplayService() = default; | ||
| 70 | |||
| 71 | void 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 | |||
| 95 | void 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 | |||
| 105 | void 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 | |||
| 115 | void 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 | |||
| 130 | void 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 | |||
| 152 | void 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 | |||
| 175 | void 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. | ||
| 189 | void 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 | |||
| 200 | void 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 | |||
| 6 | namespace Service::VI { | ||
| 7 | |||
| 8 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||
| 9 | public: | ||
| 10 | explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||
| 11 | ~ISystemDisplayService() override; | ||
| 12 | |||
| 13 | private: | ||
| 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 | |||
| 24 | private: | ||
| 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 | ||
| 9 | namespace Service::VI { | 8 | namespace Service::VI { |
| 10 | 9 | ||
| 11 | VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | 10 | ISystemRootService::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 | ||
| 22 | VI_S::~VI_S() = default; | 21 | ISystemRootService::~ISystemRootService() = default; |
| 23 | 22 | ||
| 24 | void VI_S::GetDisplayService(HLERequestContext& ctx) { | 23 | void 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 | ||
| 17 | namespace Service::VI { | 17 | namespace Service::VI { |
| 18 | 18 | ||
| 19 | class VI_M final : public ServiceFramework<VI_M> { | 19 | class ISystemRootService final : public ServiceFramework<ISystemRootService> { |
| 20 | public: | 20 | public: |
| 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 | ||
| 25 | private: | 25 | private: |
| 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 | ||
| 34 | namespace Service::VI { | 14 | namespace Service::VI { |
| 35 | 15 | ||
| 36 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | ||
| 37 | public: | ||
| 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 | |||
| 49 | private: | ||
| 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 | |||
| 90 | private: | ||
| 91 | Nvnflinger::HosBinderDriverServer& server; | ||
| 92 | }; | ||
| 93 | |||
| 94 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||
| 95 | public: | ||
| 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 | |||
| 152 | private: | ||
| 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 | |||
| 300 | private: | ||
| 301 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 302 | }; | ||
| 303 | |||
| 304 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | ||
| 305 | public: | ||
| 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 | |||
| 398 | private: | ||
| 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 | |||
| 460 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||
| 461 | public: | ||
| 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 | |||
| 503 | private: | ||
| 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 | |||
| 889 | static bool IsValidServiceAccess(Permission permission, Policy policy) { | 16 | static 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 | |||
| 8 | namespace Core { | 6 | namespace Core { |
| 9 | class System; | 7 | class 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 | ||
| 31 | enum class ConvertedScaleMode : u64 { | ||
| 32 | Freeze = 0, | ||
| 33 | ScaleToWindow = 1, | ||
| 34 | ScaleAndCrop = 2, | ||
| 35 | None = 3, | ||
| 36 | PreserveAspectRatio = 4, | ||
| 37 | }; | ||
| 38 | |||
| 39 | enum class NintendoScaleMode : u32 { | ||
| 40 | None = 0, | ||
| 41 | Freeze = 1, | ||
| 42 | ScaleToWindow = 2, | ||
| 43 | ScaleAndCrop = 3, | ||
| 44 | PreserveAspectRatio = 4, | ||
| 45 | }; | ||
| 46 | |||
| 31 | struct DisplayInfo { | 47 | struct 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"}; |