From db871677b04aa92dac9e6a15c08eae38e1dd48df Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 13 Feb 2024 23:08:27 -0500 Subject: [PATCH 1/7] vi: extract types --- src/core/CMakeLists.txt | 1 + .../am/service/common_state_getter.cpp | 1 + src/core/hle/service/vi/vi.cpp | 44 +------------ src/core/hle/service/vi/vi.h | 21 +----- src/core/hle/service/vi/vi_m.cpp | 5 +- src/core/hle/service/vi/vi_s.cpp | 5 +- src/core/hle/service/vi/vi_types.h | 66 +++++++++++++++++++ src/core/hle/service/vi/vi_u.cpp | 5 +- 8 files changed, 79 insertions(+), 69 deletions(-) create mode 100644 src/core/hle/service/vi/vi_types.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bc7f95fea9..188ca20974 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -965,6 +965,7 @@ add_library(core STATIC hle/service/vi/vi_m.h hle/service/vi/vi_s.cpp hle/service/vi/vi_s.h + hle/service/vi/vi_types.h hle/service/vi/vi_u.cpp hle/service/vi/vi_u.h internal_network/network.cpp diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index 12d7e8cb18..548498e835 100644 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -11,6 +11,7 @@ #include "core/hle/service/pm/pm.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/vi/vi.h" +#include "core/hle/service/vi/vi_types.h" namespace Service::AM { diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index d508ed28cb..fc0880c177 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1,28 +1,20 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include -#include #include #include #include #include -#include "common/alignment.h" #include "common/assert.h" -#include "common/common_funcs.h" #include "common/logging/log.h" #include "common/math_util.h" #include "common/settings.h" #include "common/string_util.h" -#include "common/swap.h" -#include "core/core_timing.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nvdrv/devices/nvmap.h" -#include "core/hle/service/nvdrv/nvdata.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvnflinger/binder.h" #include "core/hle/service/nvnflinger/buffer_queue_producer.h" @@ -36,45 +28,11 @@ #include "core/hle/service/vi/vi_m.h" #include "core/hle/service/vi/vi_results.h" #include "core/hle/service/vi/vi_s.h" +#include "core/hle/service/vi/vi_types.h" #include "core/hle/service/vi/vi_u.h" namespace Service::VI { -struct DisplayInfo { - /// The name of this particular display. - char display_name[0x40]{"Default"}; - - /// Whether or not the display has a limited number of layers. - u8 has_limited_layers{1}; - INSERT_PADDING_BYTES(7); - - /// Indicates the total amount of layers supported by the display. - /// @note This is only valid if has_limited_layers is set. - u64 max_layers{1}; - - /// Maximum width in pixels. - u64 width{1920}; - - /// Maximum height in pixels. - u64 height{1080}; -}; -static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); - -class NativeWindow final { -public: - constexpr explicit NativeWindow(u32 id_) : id{id_} {} - constexpr explicit NativeWindow(const NativeWindow& other) = default; - -private: - const u32 magic = 2; - const u32 process_id = 1; - const u64 id; - INSERT_PADDING_WORDS(2); - std::array dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; - INSERT_PADDING_WORDS(2); -}; -static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); - class IHOSBinderDriver final : public ServiceFramework { public: explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_) diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index ee4bcbcfa4..e7a38fdbd0 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -20,26 +20,7 @@ class Nvnflinger; namespace Service::VI { -enum class DisplayResolution : u32 { - DockedWidth = 1920, - DockedHeight = 1080, - UndockedWidth = 1280, - UndockedHeight = 720, -}; - -/// Permission level for a particular VI service instance -enum class Permission { - User, - System, - Manager, -}; - -/// A policy type that may be requested via GetDisplayService and -/// GetDisplayServiceWithProxyNameExchange -enum class Policy { - User, - Compositor, -}; +enum class Permission; namespace detail { void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp index 0f06dc2f36..b1b98cf110 100644 --- a/src/core/hle/service/vi/vi_m.cpp +++ b/src/core/hle/service/vi/vi_m.cpp @@ -4,13 +4,14 @@ #include "common/logging/log.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_m.h" +#include "core/hle/service/vi/vi_types.h" namespace Service::VI { VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ - hos_binder_driver_server_} { + : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, + hos_binder_driver_server{hos_binder_driver_server_} { static const FunctionInfo functions[] = { {2, &VI_M::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp index 77f7a88ff6..2400694b01 100644 --- a/src/core/hle/service/vi/vi_s.cpp +++ b/src/core/hle/service/vi/vi_s.cpp @@ -4,13 +4,14 @@ #include "common/logging/log.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_s.h" +#include "core/hle/service/vi/vi_types.h" namespace Service::VI { VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ - hos_binder_driver_server_} { + : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, + hos_binder_driver_server{hos_binder_driver_server_} { static const FunctionInfo functions[] = { {1, &VI_S::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h new file mode 100644 index 0000000000..59976fc72d --- /dev/null +++ b/src/core/hle/service/vi/vi_types.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_funcs.h" + +namespace Service::VI { + +enum class DisplayResolution : u32 { + DockedWidth = 1920, + DockedHeight = 1080, + UndockedWidth = 1280, + UndockedHeight = 720, +}; + +/// Permission level for a particular VI service instance +enum class Permission { + User, + System, + Manager, +}; + +/// A policy type that may be requested via GetDisplayService and +/// GetDisplayServiceWithProxyNameExchange +enum class Policy { + User, + Compositor, +}; + +struct DisplayInfo { + /// The name of this particular display. + char display_name[0x40]{"Default"}; + + /// Whether or not the display has a limited number of layers. + u8 has_limited_layers{1}; + INSERT_PADDING_BYTES(7); + + /// Indicates the total amount of layers supported by the display. + /// @note This is only valid if has_limited_layers is set. + u64 max_layers{1}; + + /// Maximum width in pixels. + u64 width{1920}; + + /// Maximum height in pixels. + u64 height{1080}; +}; +static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); + +class NativeWindow final { +public: + constexpr explicit NativeWindow(u32 id_) : id{id_} {} + constexpr explicit NativeWindow(const NativeWindow& other) = default; + +private: + const u32 magic = 2; + const u32 process_id = 1; + const u64 id; + INSERT_PADDING_WORDS(2); + std::array dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; + INSERT_PADDING_WORDS(2); +}; +static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp index 59e13c86bd..9845e2c57a 100644 --- a/src/core/hle/service/vi/vi_u.cpp +++ b/src/core/hle/service/vi/vi_u.cpp @@ -3,14 +3,15 @@ #include "common/logging/log.h" #include "core/hle/service/vi/vi.h" +#include "core/hle/service/vi/vi_types.h" #include "core/hle/service/vi/vi_u.h" namespace Service::VI { VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{ - hos_binder_driver_server_} { + : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, + hos_binder_driver_server{hos_binder_driver_server_} { static const FunctionInfo functions[] = { {0, &VI_U::GetDisplayService, "GetDisplayService"}, {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, From 2e8c0e9247bfcb5cdd0f4235bda5ee6f58b16c14 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 13 Feb 2024 23:36:06 -0500 Subject: [PATCH 2/7] vi: split into implementation files --- src/core/CMakeLists.txt | 23 +- .../vi/application_display_service.cpp | 419 ++++++++ .../service/vi/application_display_service.h | 48 + ...{vi_u.cpp => application_root_service.cpp} | 14 +- .../vi/{vi_s.h => application_root_service.h} | 8 +- src/core/hle/service/vi/hos_binder_driver.cpp | 64 ++ src/core/hle/service/vi/hos_binder_driver.h | 22 + .../service/vi/manager_display_service.cpp | 164 ++++ .../hle/service/vi/manager_display_service.h | 23 + .../vi/{vi_m.cpp => manager_root_service.cpp} | 14 +- .../vi/{vi_u.h => manager_root_service.h} | 8 +- .../hle/service/vi/system_display_service.cpp | 218 +++++ .../hle/service/vi/system_display_service.h | 28 + .../vi/{vi_s.cpp => system_root_service.cpp} | 13 +- .../vi/{vi_m.h => system_root_service.h} | 8 +- src/core/hle/service/vi/vi.cpp | 891 +----------------- src/core/hle/service/vi/vi.h | 2 - src/core/hle/service/vi/vi_types.h | 16 + 18 files changed, 1059 insertions(+), 924 deletions(-) create mode 100644 src/core/hle/service/vi/application_display_service.cpp create mode 100644 src/core/hle/service/vi/application_display_service.h rename src/core/hle/service/vi/{vi_u.cpp => application_root_service.cpp} (60%) rename src/core/hle/service/vi/{vi_s.h => application_root_service.h} (62%) create mode 100644 src/core/hle/service/vi/hos_binder_driver.cpp create mode 100644 src/core/hle/service/vi/hos_binder_driver.h create mode 100644 src/core/hle/service/vi/manager_display_service.cpp create mode 100644 src/core/hle/service/vi/manager_display_service.h rename src/core/hle/service/vi/{vi_m.cpp => manager_root_service.cpp} (67%) rename src/core/hle/service/vi/{vi_u.h => manager_root_service.h} (63%) create mode 100644 src/core/hle/service/vi/system_display_service.cpp create mode 100644 src/core/hle/service/vi/system_display_service.h rename src/core/hle/service/vi/{vi_s.cpp => system_root_service.cpp} (60%) rename src/core/hle/service/vi/{vi_m.h => system_root_service.h} (64%) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 188ca20974..fa4a251565 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -959,15 +959,24 @@ add_library(core STATIC hle/service/vi/display/vi_display.h hle/service/vi/layer/vi_layer.cpp hle/service/vi/layer/vi_layer.h + hle/service/vi/application_display_service.cpp + hle/service/vi/application_display_service.h + hle/service/vi/application_root_service.cpp + hle/service/vi/application_root_service.h + hle/service/vi/hos_binder_driver.cpp + hle/service/vi/hos_binder_driver.h + hle/service/vi/manager_display_service.cpp + hle/service/vi/manager_display_service.h + hle/service/vi/manager_root_service.cpp + hle/service/vi/manager_root_service.h + hle/service/vi/system_display_service.cpp + hle/service/vi/system_display_service.h + hle/service/vi/system_root_service.cpp + hle/service/vi/system_root_service.h + hle/service/vi/vi_results.h + hle/service/vi/vi_types.h hle/service/vi/vi.cpp hle/service/vi/vi.h - hle/service/vi/vi_m.cpp - hle/service/vi/vi_m.h - hle/service/vi/vi_s.cpp - hle/service/vi/vi_s.h - hle/service/vi/vi_types.h - hle/service/vi/vi_u.cpp - hle/service/vi/vi_u.h internal_network/network.cpp internal_network/network.h 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 0000000000..ae0cb7a083 --- /dev/null +++ b/src/core/hle/service/vi/application_display_service.cpp @@ -0,0 +1,419 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/string_util.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/nvnflinger/parcel.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/hos_binder_driver.h" +#include "core/hle/service/vi/manager_display_service.h" +#include "core/hle/service/vi/system_display_service.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::VI { + +IApplicationDisplayService::IApplicationDisplayService( + Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) + : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, + hos_binder_driver_server{hos_binder_driver_server_} { + + static const FunctionInfo functions[] = { + {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, + {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, + {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, + {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, + "GetIndirectDisplayTransactionService"}, + {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, + {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, + {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, + {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, + {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, + {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, + {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, + {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, + {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, + {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, + {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, + {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, + {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, "GetIndirectLayerImageMap"}, + {2451, nullptr, "GetIndirectLayerImageCropMap"}, + {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, + "GetIndirectLayerImageRequiredMemoryInfo"}, + {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, + {5203, nullptr, "GetDisplayVsyncEventForDebug"}, + }; + RegisterHandlers(functions); +} + +IApplicationDisplayService::~IApplicationDisplayService() { + for (const auto layer_id : stray_layer_ids) { + nvnflinger.DestroyLayer(layer_id); + } +} + +void IApplicationDisplayService::GetRelayService(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system, hos_binder_driver_server); +} + +void IApplicationDisplayService::GetSystemDisplayService(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system, nvnflinger); +} + +void IApplicationDisplayService::GetManagerDisplayService(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system, nvnflinger); +} + +void IApplicationDisplayService::GetIndirectDisplayTransactionService(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system, hos_binder_driver_server); +} + +void IApplicationDisplayService::OpenDisplay(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + const auto name_buf = rp.PopRaw>(); + + OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); +} + +void IApplicationDisplayService::OpenDefaultDisplay(HLERequestContext& ctx) { + LOG_DEBUG(Service_VI, "called"); + + OpenDisplayImpl(ctx, "Default"); +} + +void IApplicationDisplayService::OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { + const auto trim_pos = name.find('\0'); + + if (trim_pos != std::string_view::npos) { + name.remove_suffix(name.size() - trim_pos); + } + + ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); + + const auto display_id = nvnflinger.OpenDisplay(name); + if (!display_id) { + LOG_ERROR(Service_VI, "Display not found! display_name={}", name); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(*display_id); +} + +void IApplicationDisplayService::CloseDisplay(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 display_id = rp.Pop(); + + const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(rc); +} + +// This literally does nothing internally in the actual service itself, +// and just returns a successful result code regardless of the input. +void IApplicationDisplayService::SetDisplayEnabled(HLERequestContext& ctx) { + LOG_DEBUG(Service_VI, "called."); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IApplicationDisplayService::GetDisplayResolution(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 display_id = rp.Pop(); + + LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + + // This only returns the fixed values of 1280x720 and makes no distinguishing + // between docked and undocked dimensions. We take the liberty of applying + // the resolution scaling factor here. + rb.Push(static_cast(DisplayResolution::UndockedWidth)); + rb.Push(static_cast(DisplayResolution::UndockedHeight)); +} + +void IApplicationDisplayService::SetLayerScalingMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto scaling_mode = rp.PopEnum(); + const u64 unknown = rp.Pop(); + + LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, + unknown); + + IPC::ResponseBuilder rb{ctx, 2}; + + if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Invalid scaling mode provided."); + rb.Push(ResultOperationFailed); + return; + } + + if (scaling_mode != NintendoScaleMode::ScaleToWindow && + scaling_mode != NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); + rb.Push(ResultNotSupported); + return; + } + + rb.Push(ResultSuccess); +} + +void IApplicationDisplayService::ListDisplays(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + const DisplayInfo display_info; + ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(1); +} + +void IApplicationDisplayService::OpenLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto name_buf = rp.PopRaw>(); + const std::string display_name(Common::StringFromBuffer(name_buf)); + + const u64 layer_id = rp.Pop(); + const u64 aruid = rp.Pop(); + + LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); + + const auto display_id = nvnflinger.OpenDisplay(display_name); + if (!display_id) { + LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultNotFound); + return; + } + + const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); + if (!buffer_queue_id) { + LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultNotFound); + return; + } + + if (!nvnflinger.OpenLayer(layer_id)) { + LOG_WARNING(Service_VI, "Tried to open layer which was already open"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultOperationFailed); + return; + } + + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + + const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(buffer_size); +} + +void IApplicationDisplayService::CloseLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto layer_id{rp.Pop()}; + + LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); + + if (!nvnflinger.CloseLayer(layer_id)) { + LOG_WARNING(Service_VI, "Tried to close layer which was not open"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultOperationFailed); + return; + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IApplicationDisplayService::CreateStrayLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 flags = rp.Pop(); + rp.Pop(); // padding + const u64 display_id = rp.Pop(); + + LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); + + // TODO(Subv): What's the difference between a Stray and a Managed layer? + + const auto layer_id = nvnflinger.CreateLayer(display_id); + if (!layer_id) { + LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultNotFound); + return; + } + + stray_layer_ids.push_back(*layer_id); + const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); + if (!buffer_queue_id) { + LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultNotFound); + return; + } + + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + + const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.Push(*layer_id); + rb.Push(buffer_size); +} + +void IApplicationDisplayService::DestroyStrayLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.Pop(); + + LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); + nvnflinger.DestroyLayer(layer_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IApplicationDisplayService::GetDisplayVsyncEvent(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 display_id = rp.Pop(); + + LOG_DEBUG(Service_VI, "called. display_id={}", display_id); + + Kernel::KReadableEvent* vsync_event{}; + const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); + if (result != ResultSuccess) { + if (result == ResultNotFound) { + LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + return; + } + if (vsync_event_fetched) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(VI::ResultPermissionDenied); + return; + } + vsync_event_fetched = true; + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(vsync_event); +} + +void IApplicationDisplayService::ConvertScalingMode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto mode = rp.PopEnum(); + LOG_DEBUG(Service_VI, "called mode={}", mode); + + ConvertedScaleMode converted_mode{}; + const auto result = ConvertScalingModeImpl(&converted_mode, mode); + + if (result == ResultSuccess) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.PushEnum(converted_mode); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); + } +} + +void IApplicationDisplayService::GetIndirectLayerImageMap(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto width = rp.Pop(); + const auto height = rp.Pop(); + const auto indirect_layer_consumer_handle = rp.Pop(); + const auto applet_resource_user_id = rp.Pop(); + + LOG_WARNING(Service_VI, + "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " + "applet_resource_user_id={}", + width, height, indirect_layer_consumer_handle, applet_resource_user_id); + + std::vector out_buffer(0x46); + ctx.WriteBuffer(out_buffer); + + // TODO: Figure out what these are + + constexpr s64 unknown_result_1 = 0; + constexpr s64 unknown_result_2 = 0; + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(unknown_result_1); + rb.Push(unknown_result_2); + rb.Push(ResultSuccess); +} + +void IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto width = rp.Pop(); + const auto height = rp.Pop(); + LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); + + constexpr u64 base_size = 0x20000; + constexpr u64 alignment = 0x1000; + const auto texture_size = width * height * 4; + const auto out_size = (texture_size + base_size - 1) / base_size * base_size; + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.Push(out_size); + rb.Push(alignment); +} + +Result IApplicationDisplayService::ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, + NintendoScaleMode mode) { + switch (mode) { + case NintendoScaleMode::None: + *out_scaling_mode = ConvertedScaleMode::None; + return ResultSuccess; + case NintendoScaleMode::Freeze: + *out_scaling_mode = ConvertedScaleMode::Freeze; + return ResultSuccess; + case NintendoScaleMode::ScaleToWindow: + *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; + return ResultSuccess; + case NintendoScaleMode::ScaleAndCrop: + *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; + return ResultSuccess; + case NintendoScaleMode::PreserveAspectRatio: + *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; + return ResultSuccess; + default: + LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); + return ResultOperationFailed; + } +} + +} // 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 0000000000..51ae2c4722 --- /dev/null +++ b/src/core/hle/service/vi/application_display_service.h @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/service.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +class IApplicationDisplayService final : public ServiceFramework { +public: + IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + ~IApplicationDisplayService() override; + +private: + void GetRelayService(HLERequestContext& ctx); + void GetSystemDisplayService(HLERequestContext& ctx); + void GetManagerDisplayService(HLERequestContext& ctx); + void GetIndirectDisplayTransactionService(HLERequestContext& ctx); + void OpenDisplay(HLERequestContext& ctx); + void OpenDefaultDisplay(HLERequestContext& ctx); + void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name); + void CloseDisplay(HLERequestContext& ctx); + void SetDisplayEnabled(HLERequestContext& ctx); + void GetDisplayResolution(HLERequestContext& ctx); + void SetLayerScalingMode(HLERequestContext& ctx); + void ListDisplays(HLERequestContext& ctx); + void OpenLayer(HLERequestContext& ctx); + void CloseLayer(HLERequestContext& ctx); + void CreateStrayLayer(HLERequestContext& ctx); + void DestroyStrayLayer(HLERequestContext& ctx); + void GetDisplayVsyncEvent(HLERequestContext& ctx); + void ConvertScalingMode(HLERequestContext& ctx); + void GetIndirectLayerImageMap(HLERequestContext& ctx); + void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx); + +private: + static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, + NintendoScaleMode mode); + +private: + Nvnflinger::Nvnflinger& nvnflinger; + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; + std::vector stray_layer_ids; + bool vsync_event_fetched{false}; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/application_root_service.cpp similarity index 60% rename from src/core/hle/service/vi/vi_u.cpp rename to src/core/hle/service/vi/application_root_service.cpp index 9845e2c57a..caba3d1d94 100644 --- a/src/core/hle/service/vi/vi_u.cpp +++ b/src/core/hle/service/vi/application_root_service.cpp @@ -1,27 +1,27 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" +#include "core/hle/service/vi/application_root_service.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_types.h" -#include "core/hle/service/vi/vi_u.h" namespace Service::VI { -VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) +IApplicationRootService::IApplicationRootService( + Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{hos_binder_driver_server_} { static const FunctionInfo functions[] = { - {0, &VI_U::GetDisplayService, "GetDisplayService"}, + {0, &IApplicationRootService::GetDisplayService, "GetDisplayService"}, {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, }; RegisterHandlers(functions); } -VI_U::~VI_U() = default; +IApplicationRootService::~IApplicationRootService() = default; -void VI_U::GetDisplayService(HLERequestContext& ctx) { +void IApplicationRootService::GetDisplayService(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); 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 similarity index 62% rename from src/core/hle/service/vi/vi_s.h rename to src/core/hle/service/vi/application_root_service.h index 157839c914..231d268916 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; namespace Service::VI { -class VI_S final : public ServiceFramework { +class IApplicationRootService final : public ServiceFramework { public: - explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); - ~VI_S() override; + explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + ~IApplicationRootService() override; private: 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 0000000000..e04acc297b --- /dev/null +++ b/src/core/hle/service/vi/hos_binder_driver.cpp @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/binder.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/vi/hos_binder_driver.h" + +namespace Service::VI { + +IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, + Nvnflinger::HosBinderDriverServer& server_) + : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { + static const FunctionInfo functions[] = { + {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, + {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, + {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, + {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, + }; + RegisterHandlers(functions); +} + +IHOSBinderDriver::~IHOSBinderDriver() = default; + +void IHOSBinderDriver::TransactParcel(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 id = rp.Pop(); + const auto transaction = static_cast(rp.Pop()); + const u32 flags = rp.Pop(); + + LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, transaction, + flags); + + server.TryGetProducer(id)->Transact(ctx, transaction, flags); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IHOSBinderDriver::AdjustRefcount(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 id = rp.Pop(); + const s32 addval = rp.PopRaw(); + const u32 type = rp.Pop(); + + LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, type); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IHOSBinderDriver::GetNativeHandle(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 id = rp.Pop(); + const u32 unknown = rp.Pop(); + + LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); +} + +} // 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 0000000000..24780c7d86 --- /dev/null +++ b/src/core/hle/service/vi/hos_binder_driver.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/service.h" + +namespace Service::VI { + +class IHOSBinderDriver final : public ServiceFramework { +public: + explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_); + ~IHOSBinderDriver() override; + +private: + void TransactParcel(HLERequestContext& ctx); + void AdjustRefcount(HLERequestContext& ctx); + void GetNativeHandle(HLERequestContext& ctx); + +private: + Nvnflinger::HosBinderDriverServer& server; +}; + +} // 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 0000000000..650b420cc0 --- /dev/null +++ b/src/core/hle/service/vi/manager_display_service.cpp @@ -0,0 +1,164 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/vi/manager_display_service.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::VI { + +IManagerDisplayService::IManagerDisplayService(Core::System& system_, + Nvnflinger::Nvnflinger& nvnflinger_) + : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { + // clang-format off + static const FunctionInfo functions[] = { + {200, nullptr, "AllocateProcessHeapBlock"}, + {201, nullptr, "FreeProcessHeapBlock"}, + {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, + {1102, nullptr, "GetDisplayResolution"}, + {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, + {2011, nullptr, "DestroyManagedLayer"}, + {2012, nullptr, "CreateStrayLayer"}, + {2050, nullptr, "CreateIndirectLayer"}, + {2051, nullptr, "DestroyIndirectLayer"}, + {2052, nullptr, "CreateIndirectProducerEndPoint"}, + {2053, nullptr, "DestroyIndirectProducerEndPoint"}, + {2054, nullptr, "CreateIndirectConsumerEndPoint"}, + {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, + {2060, nullptr, "CreateWatermarkCompositor"}, + {2062, nullptr, "SetWatermarkText"}, + {2063, nullptr, "SetWatermarkLayerStacks"}, + {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, + {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, + {2302, nullptr, "GetDisplayHotplugEvent"}, + {2303, nullptr, "GetDisplayModeChangedEvent"}, + {2402, nullptr, "GetDisplayHotplugState"}, + {2501, nullptr, "GetCompositorErrorInfo"}, + {2601, nullptr, "GetDisplayErrorEvent"}, + {2701, nullptr, "GetDisplayFatalErrorEvent"}, + {4201, nullptr, "SetDisplayAlpha"}, + {4203, nullptr, "SetDisplayLayerStack"}, + {4205, nullptr, "SetDisplayPowerState"}, + {4206, nullptr, "SetDefaultDisplay"}, + {4207, nullptr, "ResetDisplayPanel"}, + {4208, nullptr, "SetDisplayFatalErrorEnabled"}, + {4209, nullptr, "IsDisplayPanelOn"}, + {4300, nullptr, "GetInternalPanelId"}, + {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, + {6001, nullptr, "RemoveFromLayerStack"}, + {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, + {6003, nullptr, "SetLayerConfig"}, + {6004, nullptr, "AttachLayerPresentationTracer"}, + {6005, nullptr, "DetachLayerPresentationTracer"}, + {6006, nullptr, "StartLayerPresentationRecording"}, + {6007, nullptr, "StopLayerPresentationRecording"}, + {6008, nullptr, "StartLayerPresentationFenceWait"}, + {6009, nullptr, "StopLayerPresentationFenceWait"}, + {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, + {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, + {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, + {6013, nullptr, "SetLayerOpacity"}, + {6014, nullptr, "AttachLayerWatermarkCompositor"}, + {6015, nullptr, "DetachLayerWatermarkCompositor"}, + {7000, nullptr, "SetContentVisibility"}, + {8000, nullptr, "SetConductorLayer"}, + {8001, nullptr, "SetTimestampTracking"}, + {8100, nullptr, "SetIndirectProducerFlipOffset"}, + {8200, nullptr, "CreateSharedBufferStaticStorage"}, + {8201, nullptr, "CreateSharedBufferTransferMemory"}, + {8202, nullptr, "DestroySharedBuffer"}, + {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, + {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, + {8207, nullptr, "UnbindSharedLowLevelLayer"}, + {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, + {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, + {8210, nullptr, "CreateSharedLayer"}, + {8211, nullptr, "DestroySharedLayer"}, + {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, + {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, + {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, + {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, + {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, + {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, + {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, + {8223, nullptr, "RegisterSharedBufferImporterAruid"}, + {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, + {8227, nullptr, "CreateSharedBufferProcessHeap"}, + {8228, nullptr, "GetSharedLayerLayerStacks"}, + {8229, nullptr, "SetSharedLayerLayerStacks"}, + {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, + {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, + {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, + {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, + {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, + {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, + {8297, nullptr, "GetSharedFrameBufferContentParameter"}, + {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +IManagerDisplayService::~IManagerDisplayService() = default; + +void IManagerDisplayService::CloseDisplay(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 display = rp.Pop(); + + const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(rc); +} + +void IManagerDisplayService::CreateManagedLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 unknown = rp.Pop(); + rp.Skip(1, false); + const u64 display = rp.Pop(); + const u64 aruid = rp.Pop(); + + LOG_WARNING(Service_VI, + "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", unknown, + display, aruid); + + const auto layer_id = nvnflinger.CreateLayer(display); + if (!layer_id) { + LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultNotFound); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(*layer_id); +} + +void IManagerDisplayService::AddToLayerStack(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 stack = rp.Pop(); + const u64 layer_id = rp.Pop(); + + LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, + layer_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IManagerDisplayService::SetLayerVisibility(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.Pop(); + const bool visibility = rp.Pop(); + + LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, + visibility); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +} // 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 0000000000..6a5554eff1 --- /dev/null +++ b/src/core/hle/service/vi/manager_display_service.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/service.h" + +namespace Service::VI { + +class IManagerDisplayService final : public ServiceFramework { +public: + explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); + ~IManagerDisplayService() override; + +private: + void CloseDisplay(HLERequestContext& ctx); + void CreateManagedLayer(HLERequestContext& ctx); + void AddToLayerStack(HLERequestContext& ctx); + void SetLayerVisibility(HLERequestContext& ctx); + +private: + Nvnflinger::Nvnflinger& nvnflinger; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/manager_root_service.cpp similarity index 67% rename from src/core/hle/service/vi/vi_m.cpp rename to src/core/hle/service/vi/manager_root_service.cpp index b1b98cf110..3ab88111d5 100644 --- a/src/core/hle/service/vi/vi_m.cpp +++ b/src/core/hle/service/vi/manager_root_service.cpp @@ -1,19 +1,19 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" +#include "core/hle/service/vi/manager_root_service.h" #include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_m.h" #include "core/hle/service/vi/vi_types.h" namespace Service::VI { -VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) +IManagerRootService::IManagerRootService( + Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{hos_binder_driver_server_} { static const FunctionInfo functions[] = { - {2, &VI_M::GetDisplayService, "GetDisplayService"}, + {2, &IManagerRootService::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, {100, nullptr, "PrepareFatal"}, {101, nullptr, "ShowFatal"}, @@ -23,9 +23,9 @@ VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, RegisterHandlers(functions); } -VI_M::~VI_M() = default; +IManagerRootService::~IManagerRootService() = default; -void VI_M::GetDisplayService(HLERequestContext& ctx) { +void IManagerRootService::GetDisplayService(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); 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 similarity index 63% rename from src/core/hle/service/vi/vi_u.h rename to src/core/hle/service/vi/manager_root_service.h index 5d9ca54c66..3776619ad1 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; namespace Service::VI { -class VI_U final : public ServiceFramework { +class IManagerRootService final : public ServiceFramework { public: - explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); - ~VI_U() override; + explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + ~IManagerRootService() override; private: 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 0000000000..b40321d452 --- /dev/null +++ b/src/core/hle/service/vi/system_display_service.cpp @@ -0,0 +1,218 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" +#include "core/hle/service/vi/system_display_service.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +ISystemDisplayService::ISystemDisplayService(Core::System& system_, + Nvnflinger::Nvnflinger& nvnflinger_) + : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { + // clang-format off + static const FunctionInfo functions[] = { + {1200, nullptr, "GetZOrderCountMin"}, + {1202, nullptr, "GetZOrderCountMax"}, + {1203, nullptr, "GetDisplayLogicalResolution"}, + {1204, nullptr, "SetDisplayMagnification"}, + {2201, nullptr, "SetLayerPosition"}, + {2203, nullptr, "SetLayerSize"}, + {2204, nullptr, "GetLayerZ"}, + {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, + {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, + {2209, nullptr, "SetLayerAlpha"}, + {2210, nullptr, "SetLayerPositionAndSize"}, + {2312, nullptr, "CreateStrayLayer"}, + {2400, nullptr, "OpenIndirectLayer"}, + {2401, nullptr, "CloseIndirectLayer"}, + {2402, nullptr, "FlipIndirectLayer"}, + {3000, nullptr, "ListDisplayModes"}, + {3001, nullptr, "ListDisplayRgbRanges"}, + {3002, nullptr, "ListDisplayContentTypes"}, + {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, + {3201, nullptr, "SetDisplayMode"}, + {3202, nullptr, "GetDisplayUnderscan"}, + {3203, nullptr, "SetDisplayUnderscan"}, + {3204, nullptr, "GetDisplayContentType"}, + {3205, nullptr, "SetDisplayContentType"}, + {3206, nullptr, "GetDisplayRgbRange"}, + {3207, nullptr, "SetDisplayRgbRange"}, + {3208, nullptr, "GetDisplayCmuMode"}, + {3209, nullptr, "SetDisplayCmuMode"}, + {3210, nullptr, "GetDisplayContrastRatio"}, + {3211, nullptr, "SetDisplayContrastRatio"}, + {3214, nullptr, "GetDisplayGamma"}, + {3215, nullptr, "SetDisplayGamma"}, + {3216, nullptr, "GetDisplayCmuLuma"}, + {3217, nullptr, "SetDisplayCmuLuma"}, + {3218, nullptr, "SetDisplayCrcMode"}, + {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, + {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, + {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, + {8251, nullptr, "CloseSharedLayer"}, + {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, + {8253, nullptr, "DisconnectSharedLayer"}, + {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, + {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, + {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, + {8257, nullptr, "FillSharedFrameBufferColor"}, + {8258, nullptr, "CancelSharedFrameBuffer"}, + {9000, nullptr, "GetDp2hdmiController"}, + }; + // clang-format on + RegisterHandlers(functions); +} + +ISystemDisplayService::~ISystemDisplayService() = default; + +void ISystemDisplayService::GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 buffer_id = rp.PopRaw(); + const u64 aruid = ctx.GetPID(); + + LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); + + struct OutputParameters { + s32 nvmap_handle; + u64 size; + }; + + OutputParameters out{}; + Nvnflinger::SharedMemoryPoolLayout layout{}; + const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( + &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); + + ctx.WriteBuffer(&layout, sizeof(layout)); + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(result); + rb.PushRaw(out); +} + +void ISystemDisplayService::OpenSharedLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.PopRaw(); + + LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISystemDisplayService::ConnectSharedLayer(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.PopRaw(); + + LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { + LOG_DEBUG(Service_VI, "called"); + + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.PopRaw(); + + Kernel::KReadableEvent* event{}; + const auto result = + nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(&event, layer_id); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(result); + rb.PushCopyObjects(event); +} + +void ISystemDisplayService::AcquireSharedFrameBuffer(HLERequestContext& ctx) { + LOG_DEBUG(Service_VI, "called"); + + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.PopRaw(); + + struct OutputParameters { + android::Fence fence; + std::array slots; + s64 target_slot; + }; + static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); + + OutputParameters out{}; + const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( + &out.fence, out.slots, &out.target_slot, layer_id); + + IPC::ResponseBuilder rb{ctx, 18}; + rb.Push(result); + rb.PushRaw(out); +} + +void ISystemDisplayService::PresentSharedFrameBuffer(HLERequestContext& ctx) { + LOG_DEBUG(Service_VI, "called"); + + struct InputParameters { + android::Fence fence; + Common::Rectangle crop_region; + u32 window_transform; + s32 swap_interval; + u64 layer_id; + s64 surface_id; + }; + static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); + + IPC::RequestParser rp{ctx}; + auto input = rp.PopRaw(); + + const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( + input.fence, input.crop_region, input.window_transform, input.swap_interval, input.layer_id, + input.surface_id); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void ISystemDisplayService::SetLayerZ(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.Pop(); + const u64 z_value = rp.Pop(); + + LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, + z_value); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +// This function currently does nothing but return a success error code in +// the vi library itself, so do the same thing, but log out the passed in values. +void ISystemDisplayService::SetLayerVisibility(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 layer_id = rp.Pop(); + const bool visibility = rp.Pop(); + + LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISystemDisplayService::GetDisplayMode(HLERequestContext& ctx) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + + if (Settings::IsDockedMode()) { + rb.Push(static_cast(DisplayResolution::DockedWidth)); + rb.Push(static_cast(DisplayResolution::DockedHeight)); + } else { + rb.Push(static_cast(DisplayResolution::UndockedWidth)); + rb.Push(static_cast(DisplayResolution::UndockedHeight)); + } + + rb.PushRaw(60.0f); // This wouldn't seem to be correct for 30 fps games. + rb.Push(0); +} + +} // 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 0000000000..57ffbbf768 --- /dev/null +++ b/src/core/hle/service/vi/system_display_service.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/service.h" + +namespace Service::VI { + +class ISystemDisplayService final : public ServiceFramework { +public: + explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); + ~ISystemDisplayService() override; + +private: + void GetSharedBufferMemoryHandleId(HLERequestContext& ctx); + void OpenSharedLayer(HLERequestContext& ctx); + void ConnectSharedLayer(HLERequestContext& ctx); + void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx); + void AcquireSharedFrameBuffer(HLERequestContext& ctx); + void PresentSharedFrameBuffer(HLERequestContext& ctx); + void SetLayerZ(HLERequestContext& ctx); + void SetLayerVisibility(HLERequestContext& ctx); + void GetDisplayMode(HLERequestContext& ctx); + +private: + Nvnflinger::Nvnflinger& nvnflinger; +}; + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/system_root_service.cpp similarity index 60% rename from src/core/hle/service/vi/vi_s.cpp rename to src/core/hle/service/vi/system_root_service.cpp index 2400694b01..c3228d73bd 100644 --- a/src/core/hle/service/vi/vi_s.cpp +++ b/src/core/hle/service/vi/system_root_service.cpp @@ -1,27 +1,26 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/logging/log.h" +#include "core/hle/service/vi/system_root_service.h" #include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_s.h" #include "core/hle/service/vi/vi_types.h" namespace Service::VI { -VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) +ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{hos_binder_driver_server_} { static const FunctionInfo functions[] = { - {1, &VI_S::GetDisplayService, "GetDisplayService"}, + {1, &ISystemRootService::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, }; RegisterHandlers(functions); } -VI_S::~VI_S() = default; +ISystemRootService::~ISystemRootService() = default; -void VI_S::GetDisplayService(HLERequestContext& ctx) { +void ISystemRootService::GetDisplayService(HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); 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 similarity index 64% rename from src/core/hle/service/vi/vi_m.h rename to src/core/hle/service/vi/system_root_service.h index 9ca6f39051..5a8ecfd1a0 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; namespace Service::VI { -class VI_M final : public ServiceFramework { +class ISystemRootService final : public ServiceFramework { public: - explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); - ~VI_M() override; + explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + ~ISystemRootService() override; private: void GetDisplayService(HLERequestContext& ctx); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index fc0880c177..bb84d27b36 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1,891 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include -#include -#include -#include - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/math_util.h" -#include "common/settings.h" -#include "common/string_util.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_thread.h" #include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/nvdrv/nvdrv.h" -#include "core/hle/service/nvnflinger/binder.h" -#include "core/hle/service/nvnflinger/buffer_queue_producer.h" -#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" -#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" -#include "core/hle/service/nvnflinger/nvnflinger.h" -#include "core/hle/service/nvnflinger/parcel.h" #include "core/hle/service/server_manager.h" -#include "core/hle/service/service.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/application_root_service.h" +#include "core/hle/service/vi/manager_root_service.h" +#include "core/hle/service/vi/system_root_service.h" #include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_m.h" #include "core/hle/service/vi/vi_results.h" -#include "core/hle/service/vi/vi_s.h" #include "core/hle/service/vi/vi_types.h" -#include "core/hle/service/vi/vi_u.h" namespace Service::VI { -class IHOSBinderDriver final : public ServiceFramework { -public: - explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_) - : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { - static const FunctionInfo functions[] = { - {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, - {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, - {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, - {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, - }; - RegisterHandlers(functions); - } - -private: - void TransactParcel(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop(); - const auto transaction = static_cast(rp.Pop()); - const u32 flags = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, - transaction, flags); - - server.TryGetProducer(id)->Transact(ctx, transaction, flags); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void AdjustRefcount(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop(); - const s32 addval = rp.PopRaw(); - const u32 type = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, - type); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetNativeHandle(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop(); - const u32 unknown = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); - } - -private: - Nvnflinger::HosBinderDriverServer& server; -}; - -class ISystemDisplayService final : public ServiceFramework { -public: - explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { - // clang-format off - static const FunctionInfo functions[] = { - {1200, nullptr, "GetZOrderCountMin"}, - {1202, nullptr, "GetZOrderCountMax"}, - {1203, nullptr, "GetDisplayLogicalResolution"}, - {1204, nullptr, "SetDisplayMagnification"}, - {2201, nullptr, "SetLayerPosition"}, - {2203, nullptr, "SetLayerSize"}, - {2204, nullptr, "GetLayerZ"}, - {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, - {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, - {2209, nullptr, "SetLayerAlpha"}, - {2210, nullptr, "SetLayerPositionAndSize"}, - {2312, nullptr, "CreateStrayLayer"}, - {2400, nullptr, "OpenIndirectLayer"}, - {2401, nullptr, "CloseIndirectLayer"}, - {2402, nullptr, "FlipIndirectLayer"}, - {3000, nullptr, "ListDisplayModes"}, - {3001, nullptr, "ListDisplayRgbRanges"}, - {3002, nullptr, "ListDisplayContentTypes"}, - {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, - {3201, nullptr, "SetDisplayMode"}, - {3202, nullptr, "GetDisplayUnderscan"}, - {3203, nullptr, "SetDisplayUnderscan"}, - {3204, nullptr, "GetDisplayContentType"}, - {3205, nullptr, "SetDisplayContentType"}, - {3206, nullptr, "GetDisplayRgbRange"}, - {3207, nullptr, "SetDisplayRgbRange"}, - {3208, nullptr, "GetDisplayCmuMode"}, - {3209, nullptr, "SetDisplayCmuMode"}, - {3210, nullptr, "GetDisplayContrastRatio"}, - {3211, nullptr, "SetDisplayContrastRatio"}, - {3214, nullptr, "GetDisplayGamma"}, - {3215, nullptr, "SetDisplayGamma"}, - {3216, nullptr, "GetDisplayCmuLuma"}, - {3217, nullptr, "SetDisplayCmuLuma"}, - {3218, nullptr, "SetDisplayCrcMode"}, - {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, - {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, - {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, - {8251, nullptr, "CloseSharedLayer"}, - {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, - {8253, nullptr, "DisconnectSharedLayer"}, - {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, - {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, - {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, - {8257, nullptr, "FillSharedFrameBufferColor"}, - {8258, nullptr, "CancelSharedFrameBuffer"}, - {9000, nullptr, "GetDp2hdmiController"}, - }; - // clang-format on - RegisterHandlers(functions); - } - -private: - void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 buffer_id = rp.PopRaw(); - const u64 aruid = ctx.GetPID(); - - LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); - - struct OutputParameters { - s32 nvmap_handle; - u64 size; - }; - - OutputParameters out{}; - Nvnflinger::SharedMemoryPoolLayout layout{}; - const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( - &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); - - ctx.WriteBuffer(&layout, sizeof(layout)); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(result); - rb.PushRaw(out); - } - - void OpenSharedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void ConnectSharedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - Kernel::KReadableEvent* event{}; - const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( - &event, layer_id); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(result); - rb.PushCopyObjects(event); - } - - void AcquireSharedFrameBuffer(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - struct OutputParameters { - android::Fence fence; - std::array slots; - s64 target_slot; - }; - static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); - - OutputParameters out{}; - const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( - &out.fence, out.slots, &out.target_slot, layer_id); - - IPC::ResponseBuilder rb{ctx, 18}; - rb.Push(result); - rb.PushRaw(out); - } - - void PresentSharedFrameBuffer(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - struct InputParameters { - android::Fence fence; - Common::Rectangle crop_region; - u32 window_transform; - s32 swap_interval; - u64 layer_id; - s64 surface_id; - }; - static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); - - IPC::RequestParser rp{ctx}; - auto input = rp.PopRaw(); - - const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( - input.fence, input.crop_region, input.window_transform, input.swap_interval, - input.layer_id, input.surface_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - } - - void SetLayerZ(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - const u64 z_value = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, - z_value); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - // This function currently does nothing but return a success error code in - // the vi library itself, so do the same thing, but log out the passed in values. - void SetLayerVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - const bool visibility = rp.Pop(); - - LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetDisplayMode(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - - if (Settings::IsDockedMode()) { - rb.Push(static_cast(Service::VI::DisplayResolution::DockedWidth)); - rb.Push(static_cast(Service::VI::DisplayResolution::DockedHeight)); - } else { - rb.Push(static_cast(Service::VI::DisplayResolution::UndockedWidth)); - rb.Push(static_cast(Service::VI::DisplayResolution::UndockedHeight)); - } - - rb.PushRaw(60.0f); // This wouldn't seem to be correct for 30 fps games. - rb.Push(0); - } - -private: - Nvnflinger::Nvnflinger& nvnflinger; -}; - -class IManagerDisplayService final : public ServiceFramework { -public: - explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { - // clang-format off - static const FunctionInfo functions[] = { - {200, nullptr, "AllocateProcessHeapBlock"}, - {201, nullptr, "FreeProcessHeapBlock"}, - {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, - {1102, nullptr, "GetDisplayResolution"}, - {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, - {2011, nullptr, "DestroyManagedLayer"}, - {2012, nullptr, "CreateStrayLayer"}, - {2050, nullptr, "CreateIndirectLayer"}, - {2051, nullptr, "DestroyIndirectLayer"}, - {2052, nullptr, "CreateIndirectProducerEndPoint"}, - {2053, nullptr, "DestroyIndirectProducerEndPoint"}, - {2054, nullptr, "CreateIndirectConsumerEndPoint"}, - {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, - {2060, nullptr, "CreateWatermarkCompositor"}, - {2062, nullptr, "SetWatermarkText"}, - {2063, nullptr, "SetWatermarkLayerStacks"}, - {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, - {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, - {2302, nullptr, "GetDisplayHotplugEvent"}, - {2303, nullptr, "GetDisplayModeChangedEvent"}, - {2402, nullptr, "GetDisplayHotplugState"}, - {2501, nullptr, "GetCompositorErrorInfo"}, - {2601, nullptr, "GetDisplayErrorEvent"}, - {2701, nullptr, "GetDisplayFatalErrorEvent"}, - {4201, nullptr, "SetDisplayAlpha"}, - {4203, nullptr, "SetDisplayLayerStack"}, - {4205, nullptr, "SetDisplayPowerState"}, - {4206, nullptr, "SetDefaultDisplay"}, - {4207, nullptr, "ResetDisplayPanel"}, - {4208, nullptr, "SetDisplayFatalErrorEnabled"}, - {4209, nullptr, "IsDisplayPanelOn"}, - {4300, nullptr, "GetInternalPanelId"}, - {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, - {6001, nullptr, "RemoveFromLayerStack"}, - {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, - {6003, nullptr, "SetLayerConfig"}, - {6004, nullptr, "AttachLayerPresentationTracer"}, - {6005, nullptr, "DetachLayerPresentationTracer"}, - {6006, nullptr, "StartLayerPresentationRecording"}, - {6007, nullptr, "StopLayerPresentationRecording"}, - {6008, nullptr, "StartLayerPresentationFenceWait"}, - {6009, nullptr, "StopLayerPresentationFenceWait"}, - {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, - {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, - {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, - {6013, nullptr, "SetLayerOpacity"}, - {6014, nullptr, "AttachLayerWatermarkCompositor"}, - {6015, nullptr, "DetachLayerWatermarkCompositor"}, - {7000, nullptr, "SetContentVisibility"}, - {8000, nullptr, "SetConductorLayer"}, - {8001, nullptr, "SetTimestampTracking"}, - {8100, nullptr, "SetIndirectProducerFlipOffset"}, - {8200, nullptr, "CreateSharedBufferStaticStorage"}, - {8201, nullptr, "CreateSharedBufferTransferMemory"}, - {8202, nullptr, "DestroySharedBuffer"}, - {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, - {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, - {8207, nullptr, "UnbindSharedLowLevelLayer"}, - {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, - {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, - {8210, nullptr, "CreateSharedLayer"}, - {8211, nullptr, "DestroySharedLayer"}, - {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, - {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, - {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, - {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, - {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, - {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, - {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, - {8223, nullptr, "RegisterSharedBufferImporterAruid"}, - {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, - {8227, nullptr, "CreateSharedBufferProcessHeap"}, - {8228, nullptr, "GetSharedLayerLayerStacks"}, - {8229, nullptr, "SetSharedLayerLayerStacks"}, - {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, - {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, - {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, - {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, - {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, - {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, - {8297, nullptr, "GetSharedFrameBufferContentParameter"}, - {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, - }; - // clang-format on - - RegisterHandlers(functions); - } - -private: - void CloseDisplay(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display = rp.Pop(); - - const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - } - - void CreateManagedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 unknown = rp.Pop(); - rp.Skip(1, false); - const u64 display = rp.Pop(); - const u64 aruid = rp.Pop(); - - LOG_WARNING(Service_VI, - "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", - unknown, display, aruid); - - const auto layer_id = nvnflinger.CreateLayer(display); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(*layer_id); - } - - void AddToLayerStack(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 stack = rp.Pop(); - const u64 layer_id = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, - layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void SetLayerVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - const bool visibility = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, - visibility); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - Nvnflinger::Nvnflinger& nvnflinger; -}; - -class IApplicationDisplayService final : public ServiceFramework { -public: - IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, - hos_binder_driver_server{hos_binder_driver_server_} { - - static const FunctionInfo functions[] = { - {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, - {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, - {102, &IApplicationDisplayService::GetManagerDisplayService, - "GetManagerDisplayService"}, - {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, - "GetIndirectDisplayTransactionService"}, - {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, - {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, - {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, - {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, - {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, - {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, - {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, - {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, - {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, - {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, - {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, - {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, - {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, - "GetIndirectLayerImageMap"}, - {2451, nullptr, "GetIndirectLayerImageCropMap"}, - {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, - "GetIndirectLayerImageRequiredMemoryInfo"}, - {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, - {5203, nullptr, "GetDisplayVsyncEventForDebug"}, - }; - RegisterHandlers(functions); - } - - ~IApplicationDisplayService() { - for (const auto layer_id : stray_layer_ids) { - nvnflinger.DestroyLayer(layer_id); - } - } - -private: - enum class ConvertedScaleMode : u64 { - Freeze = 0, - ScaleToWindow = 1, - ScaleAndCrop = 2, - None = 3, - PreserveAspectRatio = 4, - }; - - enum class NintendoScaleMode : u32 { - None = 0, - Freeze = 1, - ScaleToWindow = 2, - ScaleAndCrop = 3, - PreserveAspectRatio = 4, - }; - - void GetRelayService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, hos_binder_driver_server); - } - - void GetSystemDisplayService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); - } - - void GetManagerDisplayService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); - } - - void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, hos_binder_driver_server); - } - - void OpenDisplay(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::RequestParser rp{ctx}; - const auto name_buf = rp.PopRaw>(); - - OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); - } - - void OpenDefaultDisplay(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - OpenDisplayImpl(ctx, "Default"); - } - - void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { - const auto trim_pos = name.find('\0'); - - if (trim_pos != std::string_view::npos) { - name.remove_suffix(name.size() - trim_pos); - } - - ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); - - const auto display_id = nvnflinger.OpenDisplay(name); - if (!display_id) { - LOG_ERROR(Service_VI, "Display not found! display_name={}", name); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(*display_id); - } - - void CloseDisplay(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop(); - - const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); - } - - // This literally does nothing internally in the actual service itself, - // and just returns a successful result code regardless of the input. - void SetDisplayEnabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetDisplayResolution(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - - // This only returns the fixed values of 1280x720 and makes no distinguishing - // between docked and undocked dimensions. We take the liberty of applying - // the resolution scaling factor here. - rb.Push(static_cast(DisplayResolution::UndockedWidth)); - rb.Push(static_cast(DisplayResolution::UndockedHeight)); - } - - void SetLayerScalingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto scaling_mode = rp.PopEnum(); - const u64 unknown = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, - unknown); - - IPC::ResponseBuilder rb{ctx, 2}; - - if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { - LOG_ERROR(Service_VI, "Invalid scaling mode provided."); - rb.Push(ResultOperationFailed); - return; - } - - if (scaling_mode != NintendoScaleMode::ScaleToWindow && - scaling_mode != NintendoScaleMode::PreserveAspectRatio) { - LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); - rb.Push(ResultNotSupported); - return; - } - - rb.Push(ResultSuccess); - } - - void ListDisplays(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - const DisplayInfo display_info; - ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(1); - } - - void OpenLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto name_buf = rp.PopRaw>(); - const std::string display_name(Common::StringFromBuffer(name_buf)); - - const u64 layer_id = rp.Pop(); - const u64 aruid = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); - - const auto display_id = nvnflinger.OpenDisplay(display_name); - if (!display_id) { - LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - if (!nvnflinger.OpenLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to open layer which was already open"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultOperationFailed); - return; - } - - android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); - - const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(buffer_size); - } - - void CloseLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto layer_id{rp.Pop()}; - - LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); - - if (!nvnflinger.CloseLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to close layer which was not open"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultOperationFailed); - return; - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void CreateStrayLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 flags = rp.Pop(); - rp.Pop(); // padding - const u64 display_id = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); - - // TODO(Subv): What's the difference between a Stray and a Managed layer? - - const auto layer_id = nvnflinger.CreateLayer(display_id); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - stray_layer_ids.push_back(*layer_id); - const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); - - const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(*layer_id); - rb.Push(buffer_size); - } - - void DestroyStrayLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); - nvnflinger.DestroyLayer(layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetDisplayVsyncEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. display_id={}", display_id); - - Kernel::KReadableEvent* vsync_event{}; - const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); - if (result != ResultSuccess) { - if (result == ResultNotFound) { - LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; - } - if (vsync_event_fetched) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(VI::ResultPermissionDenied); - return; - } - vsync_event_fetched = true; - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(vsync_event); - } - - void ConvertScalingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto mode = rp.PopEnum(); - LOG_DEBUG(Service_VI, "called mode={}", mode); - - ConvertedScaleMode converted_mode{}; - const auto result = ConvertScalingModeImpl(&converted_mode, mode); - - if (result == ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(converted_mode); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - } - } - - void GetIndirectLayerImageMap(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto width = rp.Pop(); - const auto height = rp.Pop(); - const auto indirect_layer_consumer_handle = rp.Pop(); - const auto applet_resource_user_id = rp.Pop(); - - LOG_WARNING(Service_VI, - "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " - "applet_resource_user_id={}", - width, height, indirect_layer_consumer_handle, applet_resource_user_id); - - std::vector out_buffer(0x46); - ctx.WriteBuffer(out_buffer); - - // TODO: Figure out what these are - - constexpr s64 unknown_result_1 = 0; - constexpr s64 unknown_result_2 = 0; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(unknown_result_1); - rb.Push(unknown_result_2); - rb.Push(ResultSuccess); - } - - void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto width = rp.Pop(); - const auto height = rp.Pop(); - LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); - - constexpr u64 base_size = 0x20000; - constexpr u64 alignment = 0x1000; - const auto texture_size = width * height * 4; - const auto out_size = (texture_size + base_size - 1) / base_size * base_size; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(out_size); - rb.Push(alignment); - } - - static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, - NintendoScaleMode mode) { - switch (mode) { - case NintendoScaleMode::None: - *out_scaling_mode = ConvertedScaleMode::None; - return ResultSuccess; - case NintendoScaleMode::Freeze: - *out_scaling_mode = ConvertedScaleMode::Freeze; - return ResultSuccess; - case NintendoScaleMode::ScaleToWindow: - *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; - return ResultSuccess; - case NintendoScaleMode::ScaleAndCrop: - *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; - return ResultSuccess; - case NintendoScaleMode::PreserveAspectRatio: - *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; - return ResultSuccess; - default: - LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); - return ResultOperationFailed; - } - } - - Nvnflinger::Nvnflinger& nvnflinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; - std::vector stray_layer_ids; - bool vsync_event_fetched{false}; -}; - static bool IsValidServiceAccess(Permission permission, Policy policy) { if (permission == Permission::User) { return policy == Policy::User; @@ -921,12 +48,12 @@ void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { auto server_manager = std::make_unique(system); + server_manager->RegisterNamedService("vi:m", std::make_shared( + system, nvnflinger, hos_binder_driver_server)); server_manager->RegisterNamedService( - "vi:m", std::make_shared(system, nvnflinger, hos_binder_driver_server)); - server_manager->RegisterNamedService( - "vi:s", std::make_shared(system, nvnflinger, hos_binder_driver_server)); - server_manager->RegisterNamedService( - "vi:u", std::make_shared(system, nvnflinger, hos_binder_driver_server)); + "vi:s", std::make_shared(system, nvnflinger, hos_binder_driver_server)); + server_manager->RegisterNamedService("vi:u", std::make_shared( + system, nvnflinger, hos_binder_driver_server)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index e7a38fdbd0..799def36d3 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -3,8 +3,6 @@ #pragma once -#include "common/common_types.h" - namespace Core { class System; } diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h index 59976fc72d..0297676afe 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 { Compositor, }; +enum class ConvertedScaleMode : u64 { + Freeze = 0, + ScaleToWindow = 1, + ScaleAndCrop = 2, + None = 3, + PreserveAspectRatio = 4, +}; + +enum class NintendoScaleMode : u32 { + None = 0, + Freeze = 1, + ScaleToWindow = 2, + ScaleAndCrop = 3, + PreserveAspectRatio = 4, +}; + struct DisplayInfo { /// The name of this particular display. char display_name[0x40]{"Default"}; From c448001d4766a4959b4c1468b5a9de6dfe3d9bc4 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 13 Feb 2024 23:53:56 -0500 Subject: [PATCH 3/7] vi: rewrite IApplicationRootService, IManagerRootService, ISystemRootService --- src/core/CMakeLists.txt | 2 + .../service/vi/application_root_service.cpp | 21 +++++----- .../hle/service/vi/application_root_service.h | 17 +++++--- .../hle/service/vi/manager_root_service.cpp | 21 +++++----- .../hle/service/vi/manager_root_service.h | 16 +++++--- src/core/hle/service/vi/service_creator.cpp | 39 +++++++++++++++++++ src/core/hle/service/vi/service_creator.h | 33 ++++++++++++++++ .../hle/service/vi/system_root_service.cpp | 21 +++++----- src/core/hle/service/vi/system_root_service.h | 16 +++++--- src/core/hle/service/vi/vi.cpp | 34 ---------------- src/core/hle/service/vi/vi.h | 13 ------- src/core/hle/service/vi/vi_types.h | 2 +- 12 files changed, 145 insertions(+), 90 deletions(-) create mode 100644 src/core/hle/service/vi/service_creator.cpp create mode 100644 src/core/hle/service/vi/service_creator.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fa4a251565..7770dbeaeb 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -969,6 +969,8 @@ add_library(core STATIC hle/service/vi/manager_display_service.h hle/service/vi/manager_root_service.cpp hle/service/vi/manager_root_service.h + hle/service/vi/service_creator.cpp + hle/service/vi/service_creator.h hle/service/vi/system_display_service.cpp hle/service/vi/system_display_service.h hle/service/vi/system_root_service.cpp diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp index caba3d1d94..7af7f062c4 100644 --- a/src/core/hle/service/vi/application_root_service.cpp +++ b/src/core/hle/service/vi/application_root_service.cpp @@ -1,19 +1,22 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/application_display_service.h" #include "core/hle/service/vi/application_root_service.h" +#include "core/hle/service/vi/service_creator.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_types.h" namespace Service::VI { IApplicationRootService::IApplicationRootService( - Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, - hos_binder_driver_server{hos_binder_driver_server_} { + Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) + : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ + hos_binder_driver_server} { static const FunctionInfo functions[] = { - {0, &IApplicationRootService::GetDisplayService, "GetDisplayService"}, + {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, }; RegisterHandlers(functions); @@ -21,11 +24,11 @@ IApplicationRootService::IApplicationRootService( IApplicationRootService::~IApplicationRootService() = default; -void IApplicationRootService::GetDisplayService(HLERequestContext& ctx) { +Result IApplicationRootService::GetDisplayService( + Out> out_application_display_service, Policy policy) { LOG_DEBUG(Service_VI, "called"); - - detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, - Permission::User); + R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, + m_hos_binder_driver_server, Permission::User, policy)); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h index 231d268916..9dbf28cb4c 100644 --- a/src/core/hle/service/vi/application_root_service.h +++ b/src/core/hle/service/vi/application_root_service.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" namespace Core { @@ -16,17 +17,23 @@ class Nvnflinger; namespace Service::VI { +class IApplicationDisplayService; +enum class Policy : u32; + class IApplicationRootService final : public ServiceFramework { public: - explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); ~IApplicationRootService() override; private: - void GetDisplayService(HLERequestContext& ctx); + Result GetDisplayService( + Out> out_application_display_service, + Policy policy); - Nvnflinger::Nvnflinger& nv_flinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; +private: + Nvnflinger::Nvnflinger& m_nvnflinger; + Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp index 3ab88111d5..a7eee4f04f 100644 --- a/src/core/hle/service/vi/manager_root_service.cpp +++ b/src/core/hle/service/vi/manager_root_service.cpp @@ -1,19 +1,22 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/application_display_service.h" #include "core/hle/service/vi/manager_root_service.h" +#include "core/hle/service/vi/service_creator.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_types.h" namespace Service::VI { IManagerRootService::IManagerRootService( - Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, - hos_binder_driver_server{hos_binder_driver_server_} { + Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) + : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ + hos_binder_driver_server} { static const FunctionInfo functions[] = { - {2, &IManagerRootService::GetDisplayService, "GetDisplayService"}, + {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, {100, nullptr, "PrepareFatal"}, {101, nullptr, "ShowFatal"}, @@ -25,11 +28,11 @@ IManagerRootService::IManagerRootService( IManagerRootService::~IManagerRootService() = default; -void IManagerRootService::GetDisplayService(HLERequestContext& ctx) { +Result IManagerRootService::GetDisplayService( + Out> out_application_display_service, Policy policy) { LOG_DEBUG(Service_VI, "called"); - - detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, - Permission::Manager); + R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, + m_hos_binder_driver_server, Permission::Manager, policy)); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h index 3776619ad1..e6cb77aeb4 100644 --- a/src/core/hle/service/vi/manager_root_service.h +++ b/src/core/hle/service/vi/manager_root_service.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" namespace Core { @@ -16,17 +17,22 @@ class Nvnflinger; namespace Service::VI { +class IApplicationDisplayService; +enum class Policy : u32; + class IManagerRootService final : public ServiceFramework { public: - explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); ~IManagerRootService() override; private: - void GetDisplayService(HLERequestContext& ctx); + Result GetDisplayService( + Out> out_application_display_service, + Policy policy); - Nvnflinger::Nvnflinger& nv_flinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::Nvnflinger& m_nvnflinger; + Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp new file mode 100644 index 0000000000..1de9d61a4c --- /dev/null +++ b/src/core/hle/service/vi/service_creator.cpp @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/service_creator.h" +#include "core/hle/service/vi/vi_results.h" +#include "core/hle/service/vi/vi_types.h" + +namespace Service::VI { + +static bool IsValidServiceAccess(Permission permission, Policy policy) { + if (permission == Permission::User) { + return policy == Policy::User; + } + + if (permission == Permission::System || permission == Permission::Manager) { + return policy == Policy::User || policy == Policy::Compositor; + } + + return false; +} + +Result GetApplicationDisplayService( + std::shared_ptr* out_application_display_service, + Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, + Policy policy) { + + if (!IsValidServiceAccess(permission, policy)) { + LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); + R_THROW(ResultPermissionDenied); + } + + *out_application_display_service = + std::make_shared(system, nvnflinger, hos_binder_driver_server); + R_SUCCEED(); +} + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h new file mode 100644 index 0000000000..8963bcd269 --- /dev/null +++ b/src/core/hle/service/vi/service_creator.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/common_types.h" + +namespace Core { +class System; +} + +namespace Service::Nvnflinger { +class HosBinderDriverServer; +class Nvnflinger; +} // namespace Service::Nvnflinger + +union Result; + +namespace Service::VI { + +class IApplicationDisplayService; +enum class Permission; +enum class Policy : u32; + +Result GetApplicationDisplayService( + std::shared_ptr* out_application_display_service, + Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, + Policy policy); + +} // namespace Service::VI diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp index c3228d73bd..8789b4cfb1 100644 --- a/src/core/hle/service/vi/system_root_service.cpp +++ b/src/core/hle/service/vi/system_root_service.cpp @@ -1,18 +1,21 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/vi/application_display_service.h" +#include "core/hle/service/vi/service_creator.h" #include "core/hle/service/vi/system_root_service.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/vi/vi_types.h" namespace Service::VI { -ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, - hos_binder_driver_server{hos_binder_driver_server_} { +ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) + : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ + hos_binder_driver_server} { static const FunctionInfo functions[] = { - {1, &ISystemRootService::GetDisplayService, "GetDisplayService"}, + {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, }; RegisterHandlers(functions); @@ -20,11 +23,11 @@ ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnfli ISystemRootService::~ISystemRootService() = default; -void ISystemRootService::GetDisplayService(HLERequestContext& ctx) { +Result ISystemRootService::GetDisplayService( + Out> out_application_display_service, Policy policy) { LOG_DEBUG(Service_VI, "called"); - - detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, - Permission::System); + R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, + m_hos_binder_driver_server, Permission::System, policy)); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h index 5a8ecfd1a0..2c547faa50 100644 --- a/src/core/hle/service/vi/system_root_service.h +++ b/src/core/hle/service/vi/system_root_service.h @@ -3,6 +3,7 @@ #pragma once +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" namespace Core { @@ -16,17 +17,22 @@ class Nvnflinger; namespace Service::VI { +class IApplicationDisplayService; +enum class Policy : u32; + class ISystemRootService final : public ServiceFramework { public: - explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); ~ISystemRootService() override; private: - void GetDisplayService(HLERequestContext& ctx); + Result GetDisplayService( + Out> out_application_display_service, + Policy policy); - Nvnflinger::Nvnflinger& nv_flinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; + Nvnflinger::Nvnflinger& m_nvnflinger; + Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index bb84d27b36..304e589b7f 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1,49 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/server_manager.h" #include "core/hle/service/vi/application_display_service.h" #include "core/hle/service/vi/application_root_service.h" #include "core/hle/service/vi/manager_root_service.h" #include "core/hle/service/vi/system_root_service.h" #include "core/hle/service/vi/vi.h" -#include "core/hle/service/vi/vi_results.h" -#include "core/hle/service/vi/vi_types.h" namespace Service::VI { -static bool IsValidServiceAccess(Permission permission, Policy policy) { - if (permission == Permission::User) { - return policy == Policy::User; - } - - if (permission == Permission::System || permission == Permission::Manager) { - return policy == Policy::User || policy == Policy::Compositor; - } - - return false; -} - -void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, - Nvnflinger::Nvnflinger& nvnflinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, - Permission permission) { - IPC::RequestParser rp{ctx}; - const auto policy = rp.PopEnum(); - - if (!IsValidServiceAccess(permission, policy)) { - LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultPermissionDenied); - return; - } - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger, hos_binder_driver_server); -} - void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { auto server_manager = std::make_unique(system); diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 799def36d3..8e681370d2 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -7,10 +7,6 @@ namespace Core { class System; } -namespace Service { -class HLERequestContext; -} - namespace Service::Nvnflinger { class HosBinderDriverServer; class Nvnflinger; @@ -18,15 +14,6 @@ class Nvnflinger; namespace Service::VI { -enum class Permission; - -namespace detail { -void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, - Nvnflinger::Nvnflinger& nv_flinger, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, - Permission permission); -} // namespace detail - void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h index 0297676afe..47fe2d11c3 100644 --- a/src/core/hle/service/vi/vi_types.h +++ b/src/core/hle/service/vi/vi_types.h @@ -23,7 +23,7 @@ enum class Permission { /// A policy type that may be requested via GetDisplayService and /// GetDisplayServiceWithProxyNameExchange -enum class Policy { +enum class Policy : u32 { User, Compositor, }; From 59011a04a10d20804eb1eb4c8164b64d0f0ca824 Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 14 Feb 2024 00:09:29 -0500 Subject: [PATCH 4/7] vi: rewrite IHOSBinderDriver --- src/core/hle/service/nvnflinger/binder.h | 5 +- .../nvnflinger/buffer_queue_producer.cpp | 9 ++- .../nvnflinger/buffer_queue_producer.h | 3 +- src/core/hle/service/vi/hos_binder_driver.cpp | 67 ++++++++----------- src/core/hle/service/vi/hos_binder_driver.h | 18 +++-- 5 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h index aef1477e38..179938192e 100644 --- a/src/core/hle/service/nvnflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h @@ -6,6 +6,8 @@ #pragma once +#include + #include "common/common_types.h" namespace Kernel { @@ -38,7 +40,8 @@ enum class TransactionId { class IBinder { public: virtual ~IBinder() = default; - virtual void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 0; + virtual void Transact(android::TransactionId code, u32 flags, std::span parcel_data, + std::span parcel_reply) = 0; virtual Kernel::KReadableEvent& GetNativeHandle() = 0; }; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 5d8762d253..ec83beb9bb 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -807,9 +807,10 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, return Status::NoError; } -void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) { +void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span parcel_data, + std::span parcel_reply) { Status status{Status::NoError}; - InputParcel parcel_in{ctx.ReadBuffer()}; + InputParcel parcel_in{parcel_data}; OutputParcel parcel_out{}; switch (code) { @@ -917,7 +918,9 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u parcel_out.Write(status); - ctx.WriteBuffer(parcel_out.Serialize()); + const auto serialized = parcel_out.Serialize(); + std::memcpy(parcel_reply.data(), serialized.data(), + std::min(parcel_reply.size(), serialized.size())); } Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 64c17d56c9..4682b0f846 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -47,7 +47,8 @@ public: Service::Nvidia::NvCore::NvMap& nvmap_); ~BufferQueueProducer(); - void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) override; + void Transact(android::TransactionId code, u32 flags, std::span parcel_data, + std::span parcel_reply) override; Kernel::KReadableEvent& GetNativeHandle() override; diff --git a/src/core/hle/service/vi/hos_binder_driver.cpp b/src/core/hle/service/vi/hos_binder_driver.cpp index e04acc297b..ba03172456 100644 --- a/src/core/hle/service/vi/hos_binder_driver.cpp +++ b/src/core/hle/service/vi/hos_binder_driver.cpp @@ -1,64 +1,53 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/nvnflinger/binder.h" #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" #include "core/hle/service/vi/hos_binder_driver.h" namespace Service::VI { -IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, - Nvnflinger::HosBinderDriverServer& server_) - : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { +IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server) + : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server) { static const FunctionInfo functions[] = { - {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, - {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, - {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, - {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, + {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"}, + {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, + {2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"}, + {3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"}, }; RegisterHandlers(functions); } IHOSBinderDriver::~IHOSBinderDriver() = default; -void IHOSBinderDriver::TransactParcel(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop(); - const auto transaction = static_cast(rp.Pop()); - const u32 flags = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, transaction, +Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id, + InBuffer parcel_data, + OutBuffer parcel_reply, + u32 flags) { + LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id, flags); - - server.TryGetProducer(id)->Transact(ctx, transaction, flags); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + m_server.TryGetProducer(binder_id)->Transact(transaction_id, flags, parcel_data, parcel_reply); + R_SUCCEED(); } -void IHOSBinderDriver::AdjustRefcount(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop(); - const s32 addval = rp.PopRaw(); - const u32 type = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, type); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); +Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) { + LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type); + R_SUCCEED(); } -void IHOSBinderDriver::GetNativeHandle(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 id = rp.Pop(); - const u32 unknown = rp.Pop(); +Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, + OutCopyHandle out_handle) { + LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); + *out_handle = &m_server.TryGetProducer(binder_id)->GetNativeHandle(); + R_SUCCEED(); +} - LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); +Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, + InBuffer parcel_data, + OutBuffer parcel_reply, + u32 flags) { + R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags)); } } // 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 index 24780c7d86..ed6e8cdbee 100644 --- a/src/core/hle/service/vi/hos_binder_driver.h +++ b/src/core/hle/service/vi/hos_binder_driver.h @@ -1,22 +1,30 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/nvnflinger/binder.h" #include "core/hle/service/service.h" namespace Service::VI { class IHOSBinderDriver final : public ServiceFramework { public: - explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_); + explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server); ~IHOSBinderDriver() override; private: - void TransactParcel(HLERequestContext& ctx); - void AdjustRefcount(HLERequestContext& ctx); - void GetNativeHandle(HLERequestContext& ctx); + Result TransactParcel(s32 binder_id, android::TransactionId transaction_id, + InBuffer parcel_data, + OutBuffer parcel_reply, u32 flags); + Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); + Result GetNativeHandle(s32 binder_id, u32 type_id, + OutCopyHandle out_handle); + Result TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, + InBuffer parcel_data, + OutBuffer parcel_reply, u32 flags); private: - Nvnflinger::HosBinderDriverServer& server; + Nvnflinger::HosBinderDriverServer& m_server; }; } // namespace Service::VI From b1c71f976c1311caa6cb7dec1fdbbc1d611e0e7a Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 14 Feb 2024 00:17:48 -0500 Subject: [PATCH 5/7] vi: rewrite IManagerDisplayService --- .../service/vi/manager_display_service.cpp | 76 +++++-------------- .../hle/service/vi/manager_display_service.h | 13 ++-- 2 files changed, 28 insertions(+), 61 deletions(-) diff --git a/src/core/hle/service/vi/manager_display_service.cpp b/src/core/hle/service/vi/manager_display_service.cpp index 650b420cc0..17f2f3b8fe 100644 --- a/src/core/hle/service/vi/manager_display_service.cpp +++ b/src/core/hle/service/vi/manager_display_service.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/nvnflinger/nvnflinger.h" #include "core/hle/service/vi/manager_display_service.h" #include "core/hle/service/vi/vi_results.h" @@ -9,15 +9,14 @@ namespace Service::VI { IManagerDisplayService::IManagerDisplayService(Core::System& system_, - Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { + Nvnflinger::Nvnflinger& nvnflinger) + : ServiceFramework{system_, "IManagerDisplayService"}, m_nvnflinger{nvnflinger} { // clang-format off static const FunctionInfo functions[] = { {200, nullptr, "AllocateProcessHeapBlock"}, {201, nullptr, "FreeProcessHeapBlock"}, - {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, {1102, nullptr, "GetDisplayResolution"}, - {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, + {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, {2011, nullptr, "DestroyManagedLayer"}, {2012, nullptr, "CreateStrayLayer"}, {2050, nullptr, "CreateIndirectLayer"}, @@ -45,9 +44,9 @@ IManagerDisplayService::IManagerDisplayService(Core::System& system_, {4208, nullptr, "SetDisplayFatalErrorEnabled"}, {4209, nullptr, "IsDisplayPanelOn"}, {4300, nullptr, "GetInternalPanelId"}, - {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, + {6000, C<&IManagerDisplayService::AddToLayerStack>, "AddToLayerStack"}, {6001, nullptr, "RemoveFromLayerStack"}, - {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, + {6002, C<&IManagerDisplayService::SetLayerVisibility>, "SetLayerVisibility"}, {6003, nullptr, "SetLayerConfig"}, {6004, nullptr, "AttachLayerPresentationTracer"}, {6005, nullptr, "DetachLayerPresentationTracer"}, @@ -103,62 +102,29 @@ IManagerDisplayService::IManagerDisplayService(Core::System& system_, IManagerDisplayService::~IManagerDisplayService() = default; -void IManagerDisplayService::CloseDisplay(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display = rp.Pop(); +Result IManagerDisplayService::CreateManagedLayer(Out out_layer_id, u32 unknown, + u64 display_id, AppletResourceUserId aruid) { + LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, + display_id, aruid.pid); - const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); -} - -void IManagerDisplayService::CreateManagedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 unknown = rp.Pop(); - rp.Skip(1, false); - const u64 display = rp.Pop(); - const u64 aruid = rp.Pop(); - - LOG_WARNING(Service_VI, - "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", unknown, - display, aruid); - - const auto layer_id = nvnflinger.CreateLayer(display); + const auto layer_id = m_nvnflinger.CreateLayer(display_id); if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; + LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); + R_THROW(VI::ResultNotFound); } - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(*layer_id); + *out_layer_id = *layer_id; + R_SUCCEED(); } -void IManagerDisplayService::AddToLayerStack(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 stack = rp.Pop(); - const u64 layer_id = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, - layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); +Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called. stack_id={}, layer_id={}", stack_id, layer_id); + R_SUCCEED(); } -void IManagerDisplayService::SetLayerVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - const bool visibility = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, - visibility); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); +Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); + R_SUCCEED(); } } // 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 index 6a5554eff1..60e646ee04 100644 --- a/src/core/hle/service/vi/manager_display_service.h +++ b/src/core/hle/service/vi/manager_display_service.h @@ -1,23 +1,24 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" namespace Service::VI { class IManagerDisplayService final : public ServiceFramework { public: - explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); + explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); ~IManagerDisplayService() override; private: - void CloseDisplay(HLERequestContext& ctx); - void CreateManagedLayer(HLERequestContext& ctx); - void AddToLayerStack(HLERequestContext& ctx); - void SetLayerVisibility(HLERequestContext& ctx); + Result CreateManagedLayer(Out out_layer_id, u32 unknown, u64 display_id, + AppletResourceUserId aruid); + Result AddToLayerStack(u32 stack_id, u64 layer_id); + Result SetLayerVisibility(bool visible, u64 layer_id); private: - Nvnflinger::Nvnflinger& nvnflinger; + Nvnflinger::Nvnflinger& m_nvnflinger; }; } // namespace Service::VI From 8863940bf5c57bf0a286c1eea4798d8160f9cee2 Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 14 Feb 2024 00:40:06 -0500 Subject: [PATCH 6/7] vi: rewrite ISystemDisplayService --- .../hle/service/vi/system_display_service.cpp | 217 ++++++------------ .../hle/service/vi/system_display_service.h | 39 +++- 2 files changed, 100 insertions(+), 156 deletions(-) diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp index b40321d452..1e1cfc8179 100644 --- a/src/core/hle/service/vi/system_display_service.cpp +++ b/src/core/hle/service/vi/system_display_service.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/settings.h" -#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" #include "core/hle/service/vi/system_display_service.h" #include "core/hle/service/vi/vi_types.h" @@ -10,8 +10,8 @@ namespace Service::VI { ISystemDisplayService::ISystemDisplayService(Core::System& system_, - Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { + Nvnflinger::Nvnflinger& nvnflinger) + : ServiceFramework{system_, "ISystemDisplayService"}, m_nvnflinger{nvnflinger} { // clang-format off static const FunctionInfo functions[] = { {1200, nullptr, "GetZOrderCountMin"}, @@ -21,8 +21,8 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, {2201, nullptr, "SetLayerPosition"}, {2203, nullptr, "SetLayerSize"}, {2204, nullptr, "GetLayerZ"}, - {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, - {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, + {2205, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"}, + {2207, C<&ISystemDisplayService::SetLayerVisibility>, "SetLayerVisibility"}, {2209, nullptr, "SetLayerAlpha"}, {2210, nullptr, "SetLayerPositionAndSize"}, {2312, nullptr, "CreateStrayLayer"}, @@ -32,7 +32,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, {3000, nullptr, "ListDisplayModes"}, {3001, nullptr, "ListDisplayRgbRanges"}, {3002, nullptr, "ListDisplayContentTypes"}, - {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, + {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, {3201, nullptr, "SetDisplayMode"}, {3202, nullptr, "GetDisplayUnderscan"}, {3203, nullptr, "SetDisplayUnderscan"}, @@ -50,14 +50,14 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, {3217, nullptr, "SetDisplayCmuLuma"}, {3218, nullptr, "SetDisplayCrcMode"}, {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, - {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, - {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, + {8225, C<&ISystemDisplayService::GetSharedBufferMemoryHandleId>, "GetSharedBufferMemoryHandleId"}, + {8250, C<&ISystemDisplayService::OpenSharedLayer>, "OpenSharedLayer"}, {8251, nullptr, "CloseSharedLayer"}, - {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, + {8252, C<&ISystemDisplayService::ConnectSharedLayer>, "ConnectSharedLayer"}, {8253, nullptr, "DisconnectSharedLayer"}, - {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, - {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, - {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, + {8254, C<&ISystemDisplayService::AcquireSharedFrameBuffer>, "AcquireSharedFrameBuffer"}, + {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, + {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, {8257, nullptr, "FillSharedFrameBufferColor"}, {8258, nullptr, "CancelSharedFrameBuffer"}, {9000, nullptr, "GetDp2hdmiController"}, @@ -68,151 +68,78 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, ISystemDisplayService::~ISystemDisplayService() = default; -void ISystemDisplayService::GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 buffer_id = rp.PopRaw(); - const u64 aruid = ctx.GetPID(); - - LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); - - struct OutputParameters { - s32 nvmap_handle; - u64 size; - }; - - OutputParameters out{}; - Nvnflinger::SharedMemoryPoolLayout layout{}; - const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( - &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); - - ctx.WriteBuffer(&layout, sizeof(layout)); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(result); - rb.PushRaw(out); -} - -void ISystemDisplayService::OpenSharedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISystemDisplayService::ConnectSharedLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - Kernel::KReadableEvent* event{}; - const auto result = - nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(&event, layer_id); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(result); - rb.PushCopyObjects(event); -} - -void ISystemDisplayService::AcquireSharedFrameBuffer(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.PopRaw(); - - struct OutputParameters { - android::Fence fence; - std::array slots; - s64 target_slot; - }; - static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); - - OutputParameters out{}; - const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( - &out.fence, out.slots, &out.target_slot, layer_id); - - IPC::ResponseBuilder rb{ctx, 18}; - rb.Push(result); - rb.PushRaw(out); -} - -void ISystemDisplayService::PresentSharedFrameBuffer(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called"); - - struct InputParameters { - android::Fence fence; - Common::Rectangle crop_region; - u32 window_transform; - s32 swap_interval; - u64 layer_id; - s64 surface_id; - }; - static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); - - IPC::RequestParser rp{ctx}; - auto input = rp.PopRaw(); - - const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( - input.fence, input.crop_region, input.window_transform, input.swap_interval, input.layer_id, - input.surface_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); -} - -void ISystemDisplayService::SetLayerZ(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - const u64 z_value = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, - z_value); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); +Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value); + R_SUCCEED(); } // This function currently does nothing but return a success error code in // the vi library itself, so do the same thing, but log out the passed in values. -void ISystemDisplayService::SetLayerVisibility(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - const bool visibility = rp.Pop(); - - LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); +Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { + LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); + R_SUCCEED(); } -void ISystemDisplayService::GetDisplayMode(HLERequestContext& ctx) { +Result ISystemDisplayService::GetDisplayMode(Out out_width, Out out_height, + Out out_refresh_rate, Out out_unknown) { LOG_WARNING(Service_VI, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - if (Settings::IsDockedMode()) { - rb.Push(static_cast(DisplayResolution::DockedWidth)); - rb.Push(static_cast(DisplayResolution::DockedHeight)); + *out_width = static_cast(DisplayResolution::DockedWidth); + *out_height = static_cast(DisplayResolution::DockedHeight); } else { - rb.Push(static_cast(DisplayResolution::UndockedWidth)); - rb.Push(static_cast(DisplayResolution::UndockedHeight)); + *out_width = static_cast(DisplayResolution::UndockedWidth); + *out_height = static_cast(DisplayResolution::UndockedHeight); } - rb.PushRaw(60.0f); // This wouldn't seem to be correct for 30 fps games. - rb.Push(0); + *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. + *out_unknown = 0; + + R_SUCCEED(); +} + +Result ISystemDisplayService::GetSharedBufferMemoryHandleId( + Out out_nvmap_handle, Out out_size, + OutLargeData out_pool_layout, + u64 buffer_id, ClientAppletResourceUserId aruid) { + LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); + + R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( + out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); +} + +Result ISystemDisplayService::OpenSharedLayer(u64 layer_id) { + LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); + R_SUCCEED(); +} + +Result ISystemDisplayService::ConnectSharedLayer(u64 layer_id) { + LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); + R_SUCCEED(); +} + +Result ISystemDisplayService::AcquireSharedFrameBuffer(Out out_fence, + Out> out_slots, + Out out_target_slot, u64 layer_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( + out_fence, *out_slots, out_target_slot, layer_id)); +} + +Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, + Common::Rectangle crop_region, + u32 window_transform, s32 swap_interval, + u64 layer_id, s64 surface_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( + fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); +} + +Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( + OutCopyHandle out_event, u64 layer_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event, + layer_id)); } } // 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 index 57ffbbf768..cfcb196fd7 100644 --- a/src/core/hle/service/vi/system_display_service.h +++ b/src/core/hle/service/vi/system_display_service.h @@ -1,28 +1,45 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/math_util.h" +#include "core/hle/service/cmif_types.h" +#include "core/hle/service/nvnflinger/ui/fence.h" #include "core/hle/service/service.h" +namespace Service::Nvnflinger { +struct SharedMemoryPoolLayout; +} + namespace Service::VI { class ISystemDisplayService final : public ServiceFramework { public: - explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); + explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); ~ISystemDisplayService() override; private: - void GetSharedBufferMemoryHandleId(HLERequestContext& ctx); - void OpenSharedLayer(HLERequestContext& ctx); - void ConnectSharedLayer(HLERequestContext& ctx); - void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx); - void AcquireSharedFrameBuffer(HLERequestContext& ctx); - void PresentSharedFrameBuffer(HLERequestContext& ctx); - void SetLayerZ(HLERequestContext& ctx); - void SetLayerVisibility(HLERequestContext& ctx); - void GetDisplayMode(HLERequestContext& ctx); + Result SetLayerZ(u32 z_value, u64 layer_id); + Result SetLayerVisibility(bool visible, u64 layer_id); + Result GetDisplayMode(Out out_width, Out out_height, Out out_refresh_rate, + Out out_unknown); + + Result GetSharedBufferMemoryHandleId( + Out out_nvmap_handle, Out out_size, + OutLargeData out_pool_layout, + u64 buffer_id, ClientAppletResourceUserId aruid); + Result OpenSharedLayer(u64 layer_id); + Result ConnectSharedLayer(u64 layer_id); + Result GetSharedFrameBufferAcquirableEvent(OutCopyHandle out_event, + u64 layer_id); + Result AcquireSharedFrameBuffer(Out out_fence, + Out> out_slots, Out out_target_slot, + u64 layer_id); + Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle crop_region, + u32 window_transform, s32 swap_interval, u64 layer_id, + s64 surface_id); private: - Nvnflinger::Nvnflinger& nvnflinger; + Nvnflinger::Nvnflinger& m_nvnflinger; }; } // namespace Service::VI From 1842df1da5fc52f6aca52d7916e64e43351c6bee Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 14 Feb 2024 01:18:07 -0500 Subject: [PATCH 7/7] vi: rewrite IApplicationDisplayService --- .../vi/application_display_service.cpp | 584 ++++++++---------- .../service/vi/application_display_service.h | 77 ++- src/core/hle/service/vi/vi_types.h | 4 +- 3 files changed, 292 insertions(+), 373 deletions(-) diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp index ae0cb7a083..78229e30f1 100644 --- a/src/core/hle/service/vi/application_display_service.cpp +++ b/src/core/hle/service/vi/application_display_service.cpp @@ -1,8 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/string_util.h" -#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/nvnflinger/nvnflinger.h" #include "core/hle/service/nvnflinger/parcel.h" #include "core/hle/service/vi/application_display_service.h" @@ -14,406 +13,307 @@ namespace Service::VI { IApplicationDisplayService::IApplicationDisplayService( - Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) - : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, - hos_binder_driver_server{hos_binder_driver_server_} { + Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) + : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger}, + m_hos_binder_driver_server{hos_binder_driver_server} { + // clang-format off static const FunctionInfo functions[] = { - {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, - {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, - {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, - {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, - "GetIndirectDisplayTransactionService"}, - {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, - {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, - {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, - {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, - {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, - {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, - {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, - {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, - {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, - {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, - {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, - {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, - {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, "GetIndirectLayerImageMap"}, + {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, + {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"}, + {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"}, + {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"}, + {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"}, + {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"}, + {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"}, + {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"}, + {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"}, + {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"}, + {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"}, + {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"}, + {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"}, + {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"}, + {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"}, + {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"}, + {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"}, {2451, nullptr, "GetIndirectLayerImageCropMap"}, - {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, - "GetIndirectLayerImageRequiredMemoryInfo"}, - {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, + {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"}, + {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"}, {5203, nullptr, "GetDisplayVsyncEventForDebug"}, }; + // clang-format on + RegisterHandlers(functions); } IApplicationDisplayService::~IApplicationDisplayService() { - for (const auto layer_id : stray_layer_ids) { - nvnflinger.DestroyLayer(layer_id); + for (const auto layer_id : m_stray_layer_ids) { + m_nvnflinger.DestroyLayer(layer_id); } } -void IApplicationDisplayService::GetRelayService(HLERequestContext& ctx) { +Result IApplicationDisplayService::GetRelayService( + Out> out_relay_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, hos_binder_driver_server); + *out_relay_service = std::make_shared(system, m_hos_binder_driver_server); + R_SUCCEED(); } -void IApplicationDisplayService::GetSystemDisplayService(HLERequestContext& ctx) { +Result IApplicationDisplayService::GetSystemDisplayService( + Out> out_system_display_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); + *out_system_display_service = std::make_shared(system, m_nvnflinger); + R_SUCCEED(); } -void IApplicationDisplayService::GetManagerDisplayService(HLERequestContext& ctx) { +Result IApplicationDisplayService::GetManagerDisplayService( + Out> out_manager_display_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, nvnflinger); + *out_manager_display_service = std::make_shared(system, m_nvnflinger); + R_SUCCEED(); } -void IApplicationDisplayService::GetIndirectDisplayTransactionService(HLERequestContext& ctx) { +Result IApplicationDisplayService::GetIndirectDisplayTransactionService( + Out> out_indirect_display_transaction_service) { LOG_WARNING(Service_VI, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface(system, hos_binder_driver_server); + *out_indirect_display_transaction_service = + std::make_shared(system, m_hos_binder_driver_server); + R_SUCCEED(); } -void IApplicationDisplayService::OpenDisplay(HLERequestContext& ctx) { +Result IApplicationDisplayService::OpenDisplay(Out out_display_id, DisplayName display_name) { LOG_WARNING(Service_VI, "(STUBBED) called"); - IPC::RequestParser rp{ctx}; - const auto name_buf = rp.PopRaw>(); + display_name[display_name.size() - 1] = '\0'; + ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, + "Non-default displays aren't supported yet"); - OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); + const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); + if (!display_id) { + LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); + R_THROW(VI::ResultNotFound); + } + + *out_display_id = *display_id; + R_SUCCEED(); } -void IApplicationDisplayService::OpenDefaultDisplay(HLERequestContext& ctx) { +Result IApplicationDisplayService::OpenDefaultDisplay(Out out_display_id) { + LOG_DEBUG(Service_VI, "called"); + R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"})); +} + +Result IApplicationDisplayService::CloseDisplay(u64 display_id) { + LOG_DEBUG(Service_VI, "called"); + R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id)); + R_THROW(ResultUnknown); +} + +Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { LOG_DEBUG(Service_VI, "called"); - OpenDisplayImpl(ctx, "Default"); + // This literally does nothing internally in the actual service itself, + // and just returns a successful result code regardless of the input. + R_SUCCEED(); } -void IApplicationDisplayService::OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { - const auto trim_pos = name.find('\0'); - - if (trim_pos != std::string_view::npos) { - name.remove_suffix(name.size() - trim_pos); - } - - ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); - - const auto display_id = nvnflinger.OpenDisplay(name); - if (!display_id) { - LOG_ERROR(Service_VI, "Display not found! display_name={}", name); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(*display_id); -} - -void IApplicationDisplayService::CloseDisplay(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop(); - - const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(rc); -} - -// This literally does nothing internally in the actual service itself, -// and just returns a successful result code regardless of the input. -void IApplicationDisplayService::SetDisplayEnabled(HLERequestContext& ctx) { - LOG_DEBUG(Service_VI, "called."); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationDisplayService::GetDisplayResolution(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - - // This only returns the fixed values of 1280x720 and makes no distinguishing - // between docked and undocked dimensions. We take the liberty of applying - // the resolution scaling factor here. - rb.Push(static_cast(DisplayResolution::UndockedWidth)); - rb.Push(static_cast(DisplayResolution::UndockedHeight)); -} - -void IApplicationDisplayService::SetLayerScalingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto scaling_mode = rp.PopEnum(); - const u64 unknown = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, - unknown); - - IPC::ResponseBuilder rb{ctx, 2}; - - if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { - LOG_ERROR(Service_VI, "Invalid scaling mode provided."); - rb.Push(ResultOperationFailed); - return; - } - - if (scaling_mode != NintendoScaleMode::ScaleToWindow && - scaling_mode != NintendoScaleMode::PreserveAspectRatio) { - LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); - rb.Push(ResultNotSupported); - return; - } - - rb.Push(ResultSuccess); -} - -void IApplicationDisplayService::ListDisplays(HLERequestContext& ctx) { - LOG_WARNING(Service_VI, "(STUBBED) called"); - - const DisplayInfo display_info; - ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(1); -} - -void IApplicationDisplayService::OpenLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto name_buf = rp.PopRaw>(); - const std::string display_name(Common::StringFromBuffer(name_buf)); - - const u64 layer_id = rp.Pop(); - const u64 aruid = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); - - const auto display_id = nvnflinger.OpenDisplay(display_name); - if (!display_id) { - LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - if (!nvnflinger.OpenLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to open layer which was already open"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultOperationFailed); - return; - } - - android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); - - const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push(buffer_size); -} - -void IApplicationDisplayService::CloseLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto layer_id{rp.Pop()}; - - LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); - - if (!nvnflinger.CloseLayer(layer_id)) { - LOG_WARNING(Service_VI, "Tried to close layer which was not open"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultOperationFailed); - return; - } - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationDisplayService::CreateStrayLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u32 flags = rp.Pop(); - rp.Pop(); // padding - const u64 display_id = rp.Pop(); - - LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); - - // TODO(Subv): What's the difference between a Stray and a Managed layer? - - const auto layer_id = nvnflinger.CreateLayer(display_id); - if (!layer_id) { - LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - stray_layer_ids.push_back(*layer_id); - const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); - if (!buffer_queue_id) { - LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNotFound); - return; - } - - android::OutputParcel parcel; - parcel.WriteInterface(NativeWindow{*buffer_queue_id}); - - const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(*layer_id); - rb.Push(buffer_size); -} - -void IApplicationDisplayService::DestroyStrayLayer(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 layer_id = rp.Pop(); - - LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); - nvnflinger.DestroyLayer(layer_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void IApplicationDisplayService::GetDisplayVsyncEvent(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 display_id = rp.Pop(); - +Result IApplicationDisplayService::GetDisplayResolution(Out out_width, Out out_height, + u64 display_id) { LOG_DEBUG(Service_VI, "called. display_id={}", display_id); - Kernel::KReadableEvent* vsync_event{}; - const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); + // This only returns the fixed values of 1280x720 and makes no distinguishing + // between docked and undocked dimensions. + *out_width = static_cast(DisplayResolution::UndockedWidth); + *out_height = static_cast(DisplayResolution::UndockedHeight); + R_SUCCEED(); +} + +Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) { + LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id); + + if (scale_mode > NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Invalid scaling mode provided."); + R_THROW(VI::ResultOperationFailed); + } + + if (scale_mode != NintendoScaleMode::ScaleToWindow && + scale_mode != NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); + R_THROW(VI::ResultNotSupported); + } + + R_SUCCEED(); +} + +Result IApplicationDisplayService::ListDisplays( + Out out_count, OutArray out_displays) { + LOG_WARNING(Service_VI, "(STUBBED) called"); + + if (out_displays.size() > 0) { + out_displays[0] = DisplayInfo{}; + *out_count = 1; + } else { + *out_count = 0; + } + + R_SUCCEED(); +} + +Result IApplicationDisplayService::OpenLayer(Out out_size, + OutBuffer out_native_window, + DisplayName display_name, u64 layer_id, + ClientAppletResourceUserId aruid) { + display_name[display_name.size() - 1] = '\0'; + + LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); + + const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); + if (!display_id) { + LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); + R_THROW(VI::ResultNotFound); + } + + const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id); + if (!buffer_queue_id) { + LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); + R_THROW(VI::ResultNotFound); + } + + if (!m_nvnflinger.OpenLayer(layer_id)) { + LOG_WARNING(Service_VI, "Tried to open layer which was already open"); + R_THROW(VI::ResultOperationFailed); + } + + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + + const auto buffer = parcel.Serialize(); + std::memcpy(out_native_window.data(), buffer.data(), + std::min(out_native_window.size(), buffer.size())); + *out_size = buffer.size(); + + R_SUCCEED(); +} + +Result IApplicationDisplayService::CloseLayer(u64 layer_id) { + LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); + + if (!m_nvnflinger.CloseLayer(layer_id)) { + LOG_WARNING(Service_VI, "Tried to close layer which was not open"); + R_THROW(VI::ResultOperationFailed); + } + + R_SUCCEED(); +} + +Result IApplicationDisplayService::CreateStrayLayer( + Out out_layer_id, Out out_size, OutBuffer out_native_window, + u32 flags, u64 display_id) { + LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); + + const auto layer_id = m_nvnflinger.CreateLayer(display_id); + if (!layer_id) { + LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); + R_THROW(VI::ResultNotFound); + } + + m_stray_layer_ids.push_back(*layer_id); + const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id); + if (!buffer_queue_id) { + LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); + R_THROW(VI::ResultNotFound); + } + + android::OutputParcel parcel; + parcel.WriteInterface(NativeWindow{*buffer_queue_id}); + + const auto buffer = parcel.Serialize(); + std::memcpy(out_native_window.data(), buffer.data(), + std::min(out_native_window.size(), buffer.size())); + + *out_layer_id = *layer_id; + *out_size = buffer.size(); + + R_SUCCEED(); +} + +Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { + LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); + m_nvnflinger.DestroyLayer(layer_id); + R_SUCCEED(); +} + +Result IApplicationDisplayService::GetDisplayVsyncEvent( + OutCopyHandle out_vsync_event, u64 display_id) { + LOG_DEBUG(Service_VI, "called. display_id={}", display_id); + + const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id); if (result != ResultSuccess) { if (result == ResultNotFound) { LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); } - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - return; + R_THROW(result); } - if (vsync_event_fetched) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(VI::ResultPermissionDenied); - return; - } - vsync_event_fetched = true; - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(vsync_event); + R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); + m_vsync_event_fetched = true; + + R_SUCCEED(); } -void IApplicationDisplayService::ConvertScalingMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto mode = rp.PopEnum(); +Result IApplicationDisplayService::ConvertScalingMode(Out out_scaling_mode, + NintendoScaleMode mode) { LOG_DEBUG(Service_VI, "called mode={}", mode); - ConvertedScaleMode converted_mode{}; - const auto result = ConvertScalingModeImpl(&converted_mode, mode); - - if (result == ResultSuccess) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.PushEnum(converted_mode); - } else { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); - } -} - -void IApplicationDisplayService::GetIndirectLayerImageMap(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto width = rp.Pop(); - const auto height = rp.Pop(); - const auto indirect_layer_consumer_handle = rp.Pop(); - const auto applet_resource_user_id = rp.Pop(); - - LOG_WARNING(Service_VI, - "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " - "applet_resource_user_id={}", - width, height, indirect_layer_consumer_handle, applet_resource_user_id); - - std::vector out_buffer(0x46); - ctx.WriteBuffer(out_buffer); - - // TODO: Figure out what these are - - constexpr s64 unknown_result_1 = 0; - constexpr s64 unknown_result_2 = 0; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(unknown_result_1); - rb.Push(unknown_result_2); - rb.Push(ResultSuccess); -} - -void IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto width = rp.Pop(); - const auto height = rp.Pop(); - LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); - - constexpr u64 base_size = 0x20000; - constexpr u64 alignment = 0x1000; - const auto texture_size = width * height * 4; - const auto out_size = (texture_size + base_size - 1) / base_size * base_size; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.Push(out_size); - rb.Push(alignment); -} - -Result IApplicationDisplayService::ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, - NintendoScaleMode mode) { switch (mode) { case NintendoScaleMode::None: *out_scaling_mode = ConvertedScaleMode::None; - return ResultSuccess; + R_SUCCEED(); case NintendoScaleMode::Freeze: *out_scaling_mode = ConvertedScaleMode::Freeze; - return ResultSuccess; + R_SUCCEED(); case NintendoScaleMode::ScaleToWindow: *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; - return ResultSuccess; + R_SUCCEED(); case NintendoScaleMode::ScaleAndCrop: *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; - return ResultSuccess; + R_SUCCEED(); case NintendoScaleMode::PreserveAspectRatio: *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; - return ResultSuccess; + R_SUCCEED(); default: LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); - return ResultOperationFailed; + R_THROW(VI::ResultOperationFailed); } } +Result IApplicationDisplayService::GetIndirectLayerImageMap( + Out out_size, Out out_stride, + OutBuffer out_buffer, + s64 width, s64 height, u64 indirect_layer_consumer_handle, ClientAppletResourceUserId aruid) { + LOG_WARNING( + Service_VI, + "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, aruid={:#x}", + width, height, indirect_layer_consumer_handle, aruid.pid); + *out_size = 0; + *out_stride = 0; + R_SUCCEED(); +} + +Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(Out out_size, + Out out_alignment, + s64 width, s64 height) { + LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); + + constexpr u64 base_size = 0x20000; + const auto texture_size = width * height * 4; + + *out_alignment = 0x1000; + *out_size = (texture_size + base_size - 1) / base_size * base_size; + + R_SUCCEED(); +} + } // namespace Service::VI diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h index 51ae2c4722..5dff4bb31c 100644 --- a/src/core/hle/service/vi/application_display_service.h +++ b/src/core/hle/service/vi/application_display_service.h @@ -1,48 +1,65 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" #include "core/hle/service/vi/vi_types.h" +namespace Kernel { +class KReadableEvent; +} + namespace Service::VI { +class IHOSBinderDriver; +class IManagerDisplayService; +class ISystemDisplayService; + class IApplicationDisplayService final : public ServiceFramework { public: - IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); + IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, + Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); ~IApplicationDisplayService() override; private: - void GetRelayService(HLERequestContext& ctx); - void GetSystemDisplayService(HLERequestContext& ctx); - void GetManagerDisplayService(HLERequestContext& ctx); - void GetIndirectDisplayTransactionService(HLERequestContext& ctx); - void OpenDisplay(HLERequestContext& ctx); - void OpenDefaultDisplay(HLERequestContext& ctx); - void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name); - void CloseDisplay(HLERequestContext& ctx); - void SetDisplayEnabled(HLERequestContext& ctx); - void GetDisplayResolution(HLERequestContext& ctx); - void SetLayerScalingMode(HLERequestContext& ctx); - void ListDisplays(HLERequestContext& ctx); - void OpenLayer(HLERequestContext& ctx); - void CloseLayer(HLERequestContext& ctx); - void CreateStrayLayer(HLERequestContext& ctx); - void DestroyStrayLayer(HLERequestContext& ctx); - void GetDisplayVsyncEvent(HLERequestContext& ctx); - void ConvertScalingMode(HLERequestContext& ctx); - void GetIndirectLayerImageMap(HLERequestContext& ctx); - void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx); + Result GetRelayService(Out> out_relay_service); + Result GetSystemDisplayService( + Out> out_system_display_service); + Result GetManagerDisplayService( + Out> out_manager_display_service); + Result GetIndirectDisplayTransactionService( + Out> out_indirect_display_transaction_service); + Result OpenDisplay(Out out_display_id, DisplayName display_name); + Result OpenDefaultDisplay(Out out_display_id); + Result CloseDisplay(u64 display_id); + Result SetDisplayEnabled(u32 state, u64 display_id); + Result GetDisplayResolution(Out out_width, Out out_height, u64 display_id); + Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id); + Result ListDisplays(Out out_count, + OutArray out_displays); + Result OpenLayer(Out out_size, OutBuffer out_native_window, + DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid); + Result CloseLayer(u64 layer_id); + Result CreateStrayLayer(Out out_layer_id, Out out_size, + OutBuffer out_native_window, u32 flags, + u64 display_id); + Result DestroyStrayLayer(u64 layer_id); + Result GetDisplayVsyncEvent(OutCopyHandle out_vsync_event, + u64 display_id); + Result ConvertScalingMode(Out out_scaling_mode, NintendoScaleMode mode); + Result GetIndirectLayerImageMap( + Out out_size, Out out_stride, + OutBuffer out_buffer, + s64 width, s64 height, u64 indirect_layer_consumer_handle, + ClientAppletResourceUserId aruid); + Result GetIndirectLayerImageRequiredMemoryInfo(Out out_size, Out out_alignment, + s64 width, s64 height); private: - static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, - NintendoScaleMode mode); - -private: - Nvnflinger::Nvnflinger& nvnflinger; - Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; - std::vector stray_layer_ids; - bool vsync_event_fetched{false}; + Nvnflinger::Nvnflinger& m_nvnflinger; + Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; + std::vector m_stray_layer_ids; + bool m_vsync_event_fetched{false}; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h index 47fe2d11c3..91e4b380ce 100644 --- a/src/core/hle/service/vi/vi_types.h +++ b/src/core/hle/service/vi/vi_types.h @@ -44,9 +44,11 @@ enum class NintendoScaleMode : u32 { PreserveAspectRatio = 4, }; +using DisplayName = std::array; + struct DisplayInfo { /// The name of this particular display. - char display_name[0x40]{"Default"}; + DisplayName display_name{"Default"}; /// Whether or not the display has a limited number of layers. u8 has_limited_layers{1};