diff options
| author | 2024-02-14 23:44:05 -0500 | |
|---|---|---|
| committer | 2024-02-17 18:08:38 -0500 | |
| commit | 812f23d05c77fb10407546c3e7a95447fcbea395 (patch) | |
| tree | bbfb035c35ccffb6dbe0995002c2937bd94edc2d /src/core/hle/service/vi | |
| parent | vi: move shared buffer management from nvnflinger (diff) | |
| download | yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.gz yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.xz yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.zip | |
vi: manage resources independently of nvnflinger and refactor
Diffstat (limited to 'src/core/hle/service/vi')
33 files changed, 1086 insertions, 721 deletions
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp index 9c009f902..6b0bcb536 100644 --- a/src/core/hle/service/vi/application_display_service.cpp +++ b/src/core/hle/service/vi/application_display_service.cpp | |||
| @@ -3,23 +3,20 @@ | |||
| 3 | 3 | ||
| 4 | #include "core/hle/service/cmif_serialization.h" | 4 | #include "core/hle/service/cmif_serialization.h" |
| 5 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" | 5 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" |
| 6 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 7 | #include "core/hle/service/nvnflinger/parcel.h" | 6 | #include "core/hle/service/nvnflinger/parcel.h" |
| 7 | #include "core/hle/service/os/event.h" | ||
| 8 | #include "core/hle/service/vi/application_display_service.h" | 8 | #include "core/hle/service/vi/application_display_service.h" |
| 9 | #include "core/hle/service/vi/container.h" | ||
| 9 | #include "core/hle/service/vi/manager_display_service.h" | 10 | #include "core/hle/service/vi/manager_display_service.h" |
| 10 | #include "core/hle/service/vi/system_display_service.h" | 11 | #include "core/hle/service/vi/system_display_service.h" |
| 11 | #include "core/hle/service/vi/vi_results.h" | 12 | #include "core/hle/service/vi/vi_results.h" |
| 12 | 13 | ||
| 13 | namespace Service::VI { | 14 | namespace Service::VI { |
| 14 | 15 | ||
| 15 | IApplicationDisplayService::IApplicationDisplayService( | 16 | IApplicationDisplayService::IApplicationDisplayService(Core::System& system_, |
| 16 | Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | 17 | std::shared_ptr<Container> container) |
| 17 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager) | ||
| 18 | : ServiceFramework{system_, "IApplicationDisplayService"}, | 18 | : ServiceFramework{system_, "IApplicationDisplayService"}, |
| 19 | m_binder_service{std::move(binder_service)}, | 19 | m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} { |
| 20 | m_surface_flinger{m_binder_service->GetSurfaceFlinger()}, | ||
| 21 | m_shared_buffer_manager{std::move(shared_buffer_manager)} { | ||
| 22 | |||
| 23 | // clang-format off | 20 | // clang-format off |
| 24 | static const FunctionInfo functions[] = { | 21 | static const FunctionInfo functions[] = { |
| 25 | {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, | 22 | {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, |
| @@ -50,39 +47,41 @@ IApplicationDisplayService::IApplicationDisplayService( | |||
| 50 | } | 47 | } |
| 51 | 48 | ||
| 52 | IApplicationDisplayService::~IApplicationDisplayService() { | 49 | IApplicationDisplayService::~IApplicationDisplayService() { |
| 50 | for (auto& [display_id, event] : m_display_vsync_events) { | ||
| 51 | m_container->UnlinkVsyncEvent(display_id, &event); | ||
| 52 | } | ||
| 53 | for (const auto layer_id : m_open_layer_ids) { | ||
| 54 | m_container->CloseLayer(layer_id); | ||
| 55 | } | ||
| 53 | for (const auto layer_id : m_stray_layer_ids) { | 56 | for (const auto layer_id : m_stray_layer_ids) { |
| 54 | m_surface_flinger->DestroyLayer(layer_id); | 57 | m_container->DestroyStrayLayer(layer_id); |
| 55 | } | 58 | } |
| 56 | } | 59 | } |
| 57 | 60 | ||
| 58 | Result IApplicationDisplayService::GetRelayService( | 61 | Result IApplicationDisplayService::GetRelayService( |
| 59 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) { | 62 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) { |
| 60 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 63 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 61 | *out_relay_service = m_binder_service; | 64 | R_RETURN(m_container->GetBinderDriver(out_relay_service)); |
| 62 | R_SUCCEED(); | ||
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | Result IApplicationDisplayService::GetSystemDisplayService( | 67 | Result IApplicationDisplayService::GetSystemDisplayService( |
| 66 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { | 68 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { |
| 67 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 69 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 68 | *out_system_display_service = | 70 | *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_container); |
| 69 | std::make_shared<ISystemDisplayService>(system, m_surface_flinger, m_shared_buffer_manager); | ||
| 70 | R_SUCCEED(); | 71 | R_SUCCEED(); |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | Result IApplicationDisplayService::GetManagerDisplayService( | 74 | Result IApplicationDisplayService::GetManagerDisplayService( |
| 74 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { | 75 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { |
| 75 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 76 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 76 | *out_manager_display_service = | 77 | *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_container); |
| 77 | std::make_shared<IManagerDisplayService>(system, m_surface_flinger); | ||
| 78 | R_SUCCEED(); | 78 | R_SUCCEED(); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | Result IApplicationDisplayService::GetIndirectDisplayTransactionService( | 81 | Result IApplicationDisplayService::GetIndirectDisplayTransactionService( |
| 82 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) { | 82 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) { |
| 83 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 83 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 84 | *out_indirect_display_transaction_service = m_binder_service; | 84 | R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service)); |
| 85 | R_SUCCEED(); | ||
| 86 | } | 85 | } |
| 87 | 86 | ||
| 88 | Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { | 87 | Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { |
| @@ -92,14 +91,7 @@ Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayN | |||
| 92 | ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, | 91 | ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, |
| 93 | "Non-default displays aren't supported yet"); | 92 | "Non-default displays aren't supported yet"); |
| 94 | 93 | ||
| 95 | const auto display_id = m_surface_flinger->OpenDisplay(display_name.data()); | 94 | R_RETURN(m_container->OpenDisplay(out_display_id, display_name)); |
| 96 | if (!display_id) { | ||
| 97 | LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); | ||
| 98 | R_THROW(VI::ResultNotFound); | ||
| 99 | } | ||
| 100 | |||
| 101 | *out_display_id = *display_id; | ||
| 102 | R_SUCCEED(); | ||
| 103 | } | 95 | } |
| 104 | 96 | ||
| 105 | Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { | 97 | Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { |
| @@ -109,8 +101,7 @@ Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { | |||
| 109 | 101 | ||
| 110 | Result IApplicationDisplayService::CloseDisplay(u64 display_id) { | 102 | Result IApplicationDisplayService::CloseDisplay(u64 display_id) { |
| 111 | LOG_DEBUG(Service_VI, "called"); | 103 | LOG_DEBUG(Service_VI, "called"); |
| 112 | R_SUCCEED_IF(m_surface_flinger->CloseDisplay(display_id)); | 104 | R_RETURN(m_container->CloseDisplay(display_id)); |
| 113 | R_THROW(ResultUnknown); | ||
| 114 | } | 105 | } |
| 115 | 106 | ||
| 116 | Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { | 107 | Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { |
| @@ -171,25 +162,19 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, | |||
| 171 | 162 | ||
| 172 | LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); | 163 | LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); |
| 173 | 164 | ||
| 174 | const auto display_id = m_surface_flinger->OpenDisplay(display_name.data()); | 165 | u64 display_id; |
| 175 | if (!display_id) { | 166 | R_TRY(m_container->OpenDisplay(&display_id, display_name)); |
| 176 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||
| 177 | R_THROW(VI::ResultNotFound); | ||
| 178 | } | ||
| 179 | 167 | ||
| 180 | const auto buffer_queue_id = m_surface_flinger->FindBufferQueueId(*display_id, layer_id); | 168 | s32 producer_binder_id; |
| 181 | if (!buffer_queue_id) { | 169 | R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid)); |
| 182 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||
| 183 | R_THROW(VI::ResultNotFound); | ||
| 184 | } | ||
| 185 | 170 | ||
| 186 | if (!m_surface_flinger->OpenLayer(layer_id)) { | 171 | { |
| 187 | LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | 172 | std::scoped_lock lk{m_lock}; |
| 188 | R_THROW(VI::ResultOperationFailed); | 173 | m_open_layer_ids.insert(layer_id); |
| 189 | } | 174 | } |
| 190 | 175 | ||
| 191 | android::OutputParcel parcel; | 176 | android::OutputParcel parcel; |
| 192 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 177 | parcel.WriteInterface(NativeWindow{producer_binder_id}); |
| 193 | 178 | ||
| 194 | const auto buffer = parcel.Serialize(); | 179 | const auto buffer = parcel.Serialize(); |
| 195 | std::memcpy(out_native_window.data(), buffer.data(), | 180 | std::memcpy(out_native_window.data(), buffer.data(), |
| @@ -202,12 +187,13 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, | |||
| 202 | Result IApplicationDisplayService::CloseLayer(u64 layer_id) { | 187 | Result IApplicationDisplayService::CloseLayer(u64 layer_id) { |
| 203 | LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); | 188 | LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); |
| 204 | 189 | ||
| 205 | if (!m_surface_flinger->CloseLayer(layer_id)) { | 190 | { |
| 206 | LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | 191 | std::scoped_lock lk{m_lock}; |
| 207 | R_THROW(VI::ResultOperationFailed); | 192 | R_UNLESS(m_open_layer_ids.contains(layer_id), VI::ResultNotFound); |
| 193 | m_open_layer_ids.erase(layer_id); | ||
| 208 | } | 194 | } |
| 209 | 195 | ||
| 210 | R_SUCCEED(); | 196 | R_RETURN(m_container->CloseLayer(layer_id)); |
| 211 | } | 197 | } |
| 212 | 198 | ||
| 213 | Result IApplicationDisplayService::CreateStrayLayer( | 199 | Result IApplicationDisplayService::CreateStrayLayer( |
| @@ -215,27 +201,19 @@ Result IApplicationDisplayService::CreateStrayLayer( | |||
| 215 | u32 flags, u64 display_id) { | 201 | u32 flags, u64 display_id) { |
| 216 | LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); | 202 | LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); |
| 217 | 203 | ||
| 218 | const auto layer_id = m_surface_flinger->CreateLayer(display_id); | 204 | s32 producer_binder_id; |
| 219 | if (!layer_id) { | 205 | R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id)); |
| 220 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||
| 221 | R_THROW(VI::ResultNotFound); | ||
| 222 | } | ||
| 223 | 206 | ||
| 224 | m_stray_layer_ids.push_back(*layer_id); | 207 | std::scoped_lock lk{m_lock}; |
| 225 | const auto buffer_queue_id = m_surface_flinger->FindBufferQueueId(display_id, *layer_id); | 208 | m_stray_layer_ids.insert(*out_layer_id); |
| 226 | if (!buffer_queue_id) { | ||
| 227 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||
| 228 | R_THROW(VI::ResultNotFound); | ||
| 229 | } | ||
| 230 | 209 | ||
| 231 | android::OutputParcel parcel; | 210 | android::OutputParcel parcel; |
| 232 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 211 | parcel.WriteInterface(NativeWindow{producer_binder_id}); |
| 233 | 212 | ||
| 234 | const auto buffer = parcel.Serialize(); | 213 | const auto buffer = parcel.Serialize(); |
| 235 | std::memcpy(out_native_window.data(), buffer.data(), | 214 | std::memcpy(out_native_window.data(), buffer.data(), |
| 236 | std::min(out_native_window.size(), buffer.size())); | 215 | std::min(out_native_window.size(), buffer.size())); |
| 237 | 216 | ||
| 238 | *out_layer_id = *layer_id; | ||
| 239 | *out_size = buffer.size(); | 217 | *out_size = buffer.size(); |
| 240 | 218 | ||
| 241 | R_SUCCEED(); | 219 | R_SUCCEED(); |
| @@ -243,25 +221,27 @@ Result IApplicationDisplayService::CreateStrayLayer( | |||
| 243 | 221 | ||
| 244 | Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { | 222 | Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { |
| 245 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | 223 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); |
| 246 | m_surface_flinger->DestroyLayer(layer_id); | 224 | |
| 247 | R_SUCCEED(); | 225 | { |
| 226 | std::scoped_lock lk{m_lock}; | ||
| 227 | R_UNLESS(m_stray_layer_ids.contains(layer_id), VI::ResultNotFound); | ||
| 228 | m_stray_layer_ids.erase(layer_id); | ||
| 229 | } | ||
| 230 | |||
| 231 | R_RETURN(m_container->DestroyStrayLayer(layer_id)); | ||
| 248 | } | 232 | } |
| 249 | 233 | ||
| 250 | Result IApplicationDisplayService::GetDisplayVsyncEvent( | 234 | Result IApplicationDisplayService::GetDisplayVsyncEvent( |
| 251 | OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { | 235 | OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { |
| 252 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | 236 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 253 | 237 | ||
| 254 | const auto result = m_surface_flinger->FindVsyncEvent(out_vsync_event, display_id); | 238 | std::scoped_lock lk{m_lock}; |
| 255 | if (result != ResultSuccess) { | ||
| 256 | if (result == ResultNotFound) { | ||
| 257 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||
| 258 | } | ||
| 259 | 239 | ||
| 260 | R_THROW(result); | 240 | auto [it, created] = m_display_vsync_events.emplace(display_id, m_context); |
| 261 | } | 241 | R_UNLESS(created, VI::ResultPermissionDenied); |
| 262 | 242 | ||
| 263 | R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); | 243 | m_container->LinkVsyncEvent(display_id, &it->second); |
| 264 | m_vsync_event_fetched = true; | 244 | *out_vsync_event = it->second.GetHandle(); |
| 265 | 245 | ||
| 266 | R_SUCCEED(); | 246 | R_SUCCEED(); |
| 267 | } | 247 | } |
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h index 5022b2f63..1bdeb8f84 100644 --- a/src/core/hle/service/vi/application_display_service.h +++ b/src/core/hle/service/vi/application_display_service.h | |||
| @@ -1,7 +1,12 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <map> | ||
| 5 | #include <set> | ||
| 6 | |||
| 4 | #include "core/hle/service/cmif_types.h" | 7 | #include "core/hle/service/cmif_types.h" |
| 8 | #include "core/hle/service/kernel_helpers.h" | ||
| 9 | #include "core/hle/service/os/event.h" | ||
| 5 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 6 | #include "core/hle/service/vi/vi_types.h" | 11 | #include "core/hle/service/vi/vi_types.h" |
| 7 | 12 | ||
| @@ -10,28 +15,25 @@ class KReadableEvent; | |||
| 10 | } | 15 | } |
| 11 | 16 | ||
| 12 | namespace Service::Nvnflinger { | 17 | namespace Service::Nvnflinger { |
| 13 | class Nvnflinger; | ||
| 14 | class IHOSBinderDriver; | 18 | class IHOSBinderDriver; |
| 15 | } // namespace Service::Nvnflinger | 19 | } |
| 16 | 20 | ||
| 17 | namespace Service::VI { | 21 | namespace Service::VI { |
| 18 | 22 | ||
| 19 | class FbshareBufferManager; | 23 | class Container; |
| 20 | class IManagerDisplayService; | 24 | class IManagerDisplayService; |
| 21 | class ISystemDisplayService; | 25 | class ISystemDisplayService; |
| 22 | 26 | ||
| 23 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | 27 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { |
| 24 | public: | 28 | public: |
| 25 | IApplicationDisplayService(Core::System& system_, | 29 | IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | ||
| 27 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager); | ||
| 28 | ~IApplicationDisplayService() override; | 30 | ~IApplicationDisplayService() override; |
| 29 | 31 | ||
| 30 | std::shared_ptr<FbshareBufferManager> GetSharedBufferManager() const { | 32 | std::shared_ptr<Container> GetContainer() const { |
| 31 | return m_shared_buffer_manager; | 33 | return m_container; |
| 32 | } | 34 | } |
| 33 | 35 | ||
| 34 | private: | 36 | public: |
| 35 | Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service); | 37 | Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service); |
| 36 | Result GetSystemDisplayService( | 38 | Result GetSystemDisplayService( |
| 37 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service); | 39 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service); |
| @@ -66,10 +68,13 @@ private: | |||
| 66 | s64 width, s64 height); | 68 | s64 width, s64 height); |
| 67 | 69 | ||
| 68 | private: | 70 | private: |
| 69 | const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; | 71 | const std::shared_ptr<Container> m_container; |
| 70 | const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger; | 72 | |
| 71 | const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager; | 73 | KernelHelpers::ServiceContext m_context; |
| 72 | std::vector<u64> m_stray_layer_ids; | 74 | std::mutex m_lock{}; |
| 75 | std::set<u64> m_open_layer_ids{}; | ||
| 76 | std::set<u64> m_stray_layer_ids{}; | ||
| 77 | std::map<u64, Event> m_display_vsync_events{}; | ||
| 73 | bool m_vsync_event_fetched{false}; | 78 | bool m_vsync_event_fetched{false}; |
| 74 | }; | 79 | }; |
| 75 | 80 | ||
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp index ed8c9b1b3..7f35a048d 100644 --- a/src/core/hle/service/vi/application_root_service.cpp +++ b/src/core/hle/service/vi/application_root_service.cpp | |||
| @@ -4,17 +4,16 @@ | |||
| 4 | #include "core/hle/service/cmif_serialization.h" | 4 | #include "core/hle/service/cmif_serialization.h" |
| 5 | #include "core/hle/service/vi/application_display_service.h" | 5 | #include "core/hle/service/vi/application_display_service.h" |
| 6 | #include "core/hle/service/vi/application_root_service.h" | 6 | #include "core/hle/service/vi/application_root_service.h" |
| 7 | #include "core/hle/service/vi/container.h" | ||
| 7 | #include "core/hle/service/vi/service_creator.h" | 8 | #include "core/hle/service/vi/service_creator.h" |
| 8 | #include "core/hle/service/vi/vi.h" | 9 | #include "core/hle/service/vi/vi.h" |
| 9 | #include "core/hle/service/vi/vi_types.h" | 10 | #include "core/hle/service/vi/vi_types.h" |
| 10 | 11 | ||
| 11 | namespace Service::VI { | 12 | namespace Service::VI { |
| 12 | 13 | ||
| 13 | IApplicationRootService::IApplicationRootService( | 14 | IApplicationRootService::IApplicationRootService(Core::System& system_, |
| 14 | Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | 15 | std::shared_ptr<Container> container) |
| 15 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager) | 16 | : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} { |
| 16 | : ServiceFramework{system_, "vi:u"}, m_binder_service{std::move(binder_service)}, | ||
| 17 | m_shared_buffer_manager{std::move(shared_buffer_manager)} { | ||
| 18 | static const FunctionInfo functions[] = { | 17 | static const FunctionInfo functions[] = { |
| 19 | {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, | 18 | {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, |
| 20 | {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 19 | {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
| @@ -27,8 +26,8 @@ IApplicationRootService::~IApplicationRootService() = default; | |||
| 27 | Result IApplicationRootService::GetDisplayService( | 26 | Result IApplicationRootService::GetDisplayService( |
| 28 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | 27 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { |
| 29 | LOG_DEBUG(Service_VI, "called"); | 28 | LOG_DEBUG(Service_VI, "called"); |
| 30 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service, | 29 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, |
| 31 | m_shared_buffer_manager, Permission::User, policy)); | 30 | Permission::User, policy)); |
| 32 | } | 31 | } |
| 33 | 32 | ||
| 34 | } // namespace Service::VI | 33 | } // 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 5970b6e68..15aa4483d 100644 --- a/src/core/hle/service/vi/application_root_service.h +++ b/src/core/hle/service/vi/application_root_service.h | |||
| @@ -10,21 +10,15 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::Nvnflinger { | ||
| 14 | class IHOSBinderDriver; | ||
| 15 | } // namespace Service::Nvnflinger | ||
| 16 | |||
| 17 | namespace Service::VI { | 13 | namespace Service::VI { |
| 18 | 14 | ||
| 19 | class FbshareBufferManager; | 15 | class Container; |
| 20 | class IApplicationDisplayService; | 16 | class IApplicationDisplayService; |
| 21 | enum class Policy : u32; | 17 | enum class Policy : u32; |
| 22 | 18 | ||
| 23 | class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { | 19 | class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { |
| 24 | public: | 20 | public: |
| 25 | explicit IApplicationRootService(Core::System& system_, | 21 | explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | ||
| 27 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager); | ||
| 28 | ~IApplicationRootService() override; | 22 | ~IApplicationRootService() override; |
| 29 | 23 | ||
| 30 | private: | 24 | private: |
| @@ -33,8 +27,7 @@ private: | |||
| 33 | Policy policy); | 27 | Policy policy); |
| 34 | 28 | ||
| 35 | private: | 29 | private: |
| 36 | const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; | 30 | const std::shared_ptr<Container> m_container; |
| 37 | const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager; | ||
| 38 | }; | 31 | }; |
| 39 | 32 | ||
| 40 | } // namespace Service::VI | 33 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp new file mode 100644 index 000000000..c8ce4fca0 --- /dev/null +++ b/src/core/hle/service/vi/conductor.cpp | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/core_timing.h" | ||
| 7 | #include "core/hle/service/vi/conductor.h" | ||
| 8 | #include "core/hle/service/vi/container.h" | ||
| 9 | #include "core/hle/service/vi/display_list.h" | ||
| 10 | #include "core/hle/service/vi/vsync_manager.h" | ||
| 11 | |||
| 12 | constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60}; | ||
| 13 | |||
| 14 | namespace Service::VI { | ||
| 15 | |||
| 16 | Conductor::Conductor(Core::System& system, Container& container, DisplayList& displays) | ||
| 17 | : m_system(system), m_container(container) { | ||
| 18 | displays.ForEachDisplay([&](Display& display) { | ||
| 19 | m_vsync_managers.insert({display.GetId(), VsyncManager{}}); | ||
| 20 | }); | ||
| 21 | |||
| 22 | if (system.IsMulticore()) { | ||
| 23 | m_event = Core::Timing::CreateEvent( | ||
| 24 | "ScreenComposition", | ||
| 25 | [this](s64 time, | ||
| 26 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 27 | m_signal.Set(); | ||
| 28 | return std::chrono::nanoseconds(this->GetNextTicks()); | ||
| 29 | }); | ||
| 30 | |||
| 31 | system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); | ||
| 32 | m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); }); | ||
| 33 | } else { | ||
| 34 | m_event = Core::Timing::CreateEvent( | ||
| 35 | "ScreenComposition", | ||
| 36 | [this](s64 time, | ||
| 37 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 38 | this->ProcessVsync(); | ||
| 39 | return std::chrono::nanoseconds(this->GetNextTicks()); | ||
| 40 | }); | ||
| 41 | |||
| 42 | system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | Conductor::~Conductor() { | ||
| 47 | m_system.CoreTiming().UnscheduleEvent(m_event); | ||
| 48 | |||
| 49 | if (m_system.IsMulticore()) { | ||
| 50 | m_thread.request_stop(); | ||
| 51 | m_signal.Set(); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | void Conductor::LinkVsyncEvent(u64 display_id, Event* event) { | ||
| 56 | if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) { | ||
| 57 | it->second.LinkVsyncEvent(event); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { | ||
| 62 | if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) { | ||
| 63 | it->second.UnlinkVsyncEvent(event); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | void Conductor::ProcessVsync() { | ||
| 68 | for (auto& [display_id, manager] : m_vsync_managers) { | ||
| 69 | m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); | ||
| 70 | manager.SignalVsync(); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | void Conductor::VsyncThread(std::stop_token token) { | ||
| 75 | Common::SetCurrentThreadName("VSyncThread"); | ||
| 76 | |||
| 77 | while (!token.stop_requested()) { | ||
| 78 | m_signal.Wait(); | ||
| 79 | |||
| 80 | if (m_system.IsShuttingDown()) { | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | |||
| 84 | this->ProcessVsync(); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | s64 Conductor::GetNextTicks() const { | ||
| 89 | const auto& settings = Settings::values; | ||
| 90 | auto speed_scale = 1.f; | ||
| 91 | if (settings.use_multi_core.GetValue()) { | ||
| 92 | if (settings.use_speed_limit.GetValue()) { | ||
| 93 | // Scales the speed based on speed_limit setting on MC. SC is handled by | ||
| 94 | // SpeedLimiter::DoSpeedLimiting. | ||
| 95 | speed_scale = 100.f / settings.speed_limit.GetValue(); | ||
| 96 | } else { | ||
| 97 | // Run at unlocked framerate. | ||
| 98 | speed_scale = 0.01f; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | // Adjust by speed limit determined during composition. | ||
| 103 | speed_scale /= m_compose_speed_scale; | ||
| 104 | |||
| 105 | if (m_system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { | ||
| 106 | // Run at intended presentation rate during video playback. | ||
| 107 | speed_scale = 1.f; | ||
| 108 | } | ||
| 109 | |||
| 110 | const f32 effective_fps = 60.f / static_cast<f32>(m_swap_interval); | ||
| 111 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); | ||
| 112 | } | ||
| 113 | |||
| 114 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/conductor.h b/src/core/hle/service/vi/conductor.h new file mode 100644 index 000000000..52e3595d2 --- /dev/null +++ b/src/core/hle/service/vi/conductor.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <unordered_map> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/polyfill_thread.h" | ||
| 11 | #include "common/thread.h" | ||
| 12 | |||
| 13 | namespace Core { | ||
| 14 | class System; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Core::Timing { | ||
| 18 | struct EventType; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Service { | ||
| 22 | class Event; | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace Service::VI { | ||
| 26 | |||
| 27 | class Container; | ||
| 28 | class DisplayList; | ||
| 29 | class VsyncManager; | ||
| 30 | |||
| 31 | class Conductor { | ||
| 32 | public: | ||
| 33 | explicit Conductor(Core::System& system, Container& container, DisplayList& displays); | ||
| 34 | ~Conductor(); | ||
| 35 | |||
| 36 | void LinkVsyncEvent(u64 display_id, Event* event); | ||
| 37 | void UnlinkVsyncEvent(u64 display_id, Event* event); | ||
| 38 | |||
| 39 | private: | ||
| 40 | void ProcessVsync(); | ||
| 41 | void VsyncThread(std::stop_token token); | ||
| 42 | s64 GetNextTicks() const; | ||
| 43 | |||
| 44 | private: | ||
| 45 | Core::System& m_system; | ||
| 46 | Container& m_container; | ||
| 47 | std::unordered_map<u64, VsyncManager> m_vsync_managers; | ||
| 48 | std::shared_ptr<Core::Timing::EventType> m_event; | ||
| 49 | Common::Event m_signal; | ||
| 50 | std::jthread m_thread; | ||
| 51 | |||
| 52 | private: | ||
| 53 | s32 m_swap_interval = 1; | ||
| 54 | f32 m_compose_speed_scale = 1.0f; | ||
| 55 | }; | ||
| 56 | |||
| 57 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/container.cpp b/src/core/hle/service/vi/container.cpp new file mode 100644 index 000000000..2d6b9cbfe --- /dev/null +++ b/src/core/hle/service/vi/container.cpp | |||
| @@ -0,0 +1,227 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/core.h" | ||
| 5 | #include "core/hle/service/nvdrv/nvdrv_interface.h" | ||
| 6 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | ||
| 7 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" | ||
| 8 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||
| 9 | #include "core/hle/service/nvnflinger/surface_flinger.h" | ||
| 10 | #include "core/hle/service/sm/sm.h" | ||
| 11 | #include "core/hle/service/vi/container.h" | ||
| 12 | #include "core/hle/service/vi/vi_results.h" | ||
| 13 | |||
| 14 | namespace Service::VI { | ||
| 15 | |||
| 16 | Container::Container(Core::System& system) { | ||
| 17 | m_displays.CreateDisplay(DisplayName{"Default"}); | ||
| 18 | m_displays.CreateDisplay(DisplayName{"External"}); | ||
| 19 | m_displays.CreateDisplay(DisplayName{"Edid"}); | ||
| 20 | m_displays.CreateDisplay(DisplayName{"Internal"}); | ||
| 21 | m_displays.CreateDisplay(DisplayName{"Null"}); | ||
| 22 | |||
| 23 | m_binder_driver = | ||
| 24 | system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true); | ||
| 25 | m_surface_flinger = m_binder_driver->GetSurfaceFlinger(); | ||
| 26 | |||
| 27 | const auto nvdrv = | ||
| 28 | system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); | ||
| 29 | m_shared_buffer_manager.emplace(system, *this, nvdrv); | ||
| 30 | |||
| 31 | m_displays.ForEachDisplay( | ||
| 32 | [&](auto& display) { m_surface_flinger->AddDisplay(display.GetId()); }); | ||
| 33 | |||
| 34 | m_conductor.emplace(system, *this, m_displays); | ||
| 35 | } | ||
| 36 | |||
| 37 | Container::~Container() { | ||
| 38 | this->OnTerminate(); | ||
| 39 | } | ||
| 40 | |||
| 41 | void Container::OnTerminate() { | ||
| 42 | std::scoped_lock lk{m_lock}; | ||
| 43 | |||
| 44 | m_is_shut_down = true; | ||
| 45 | |||
| 46 | m_layers.ForEachLayer([&](auto& layer) { | ||
| 47 | if (layer.IsOpen()) { | ||
| 48 | this->DestroyBufferQueueLocked(&layer); | ||
| 49 | } | ||
| 50 | }); | ||
| 51 | |||
| 52 | m_displays.ForEachDisplay( | ||
| 53 | [&](auto& display) { m_surface_flinger->RemoveDisplay(display.GetId()); }); | ||
| 54 | } | ||
| 55 | |||
| 56 | SharedBufferManager* Container::GetSharedBufferManager() { | ||
| 57 | return std::addressof(*m_shared_buffer_manager); | ||
| 58 | } | ||
| 59 | |||
| 60 | Result Container::GetBinderDriver( | ||
| 61 | std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver) { | ||
| 62 | *out_binder_driver = m_binder_driver; | ||
| 63 | R_SUCCEED(); | ||
| 64 | } | ||
| 65 | |||
| 66 | Result Container::GetLayerProducerHandle( | ||
| 67 | std::shared_ptr<android::BufferQueueProducer>* out_producer, u64 layer_id) { | ||
| 68 | std::scoped_lock lk{m_lock}; | ||
| 69 | |||
| 70 | auto* const layer = m_layers.GetLayerById(layer_id); | ||
| 71 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 72 | |||
| 73 | const auto binder = m_binder_driver->GetServer()->TryGetBinder(layer->GetProducerBinderId()); | ||
| 74 | R_UNLESS(binder != nullptr, VI::ResultNotFound); | ||
| 75 | |||
| 76 | *out_producer = std::static_pointer_cast<android::BufferQueueProducer>(binder); | ||
| 77 | R_SUCCEED(); | ||
| 78 | } | ||
| 79 | |||
| 80 | Result Container::OpenDisplay(u64* out_display_id, const DisplayName& display_name) { | ||
| 81 | auto* const display = m_displays.GetDisplayByName(display_name); | ||
| 82 | R_UNLESS(display != nullptr, VI::ResultNotFound); | ||
| 83 | |||
| 84 | *out_display_id = display->GetId(); | ||
| 85 | R_SUCCEED(); | ||
| 86 | } | ||
| 87 | |||
| 88 | Result Container::CloseDisplay(u64 display_id) { | ||
| 89 | R_SUCCEED(); | ||
| 90 | } | ||
| 91 | |||
| 92 | Result Container::CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid) { | ||
| 93 | std::scoped_lock lk{m_lock}; | ||
| 94 | R_RETURN(this->CreateLayerLocked(out_layer_id, display_id, owner_aruid)); | ||
| 95 | } | ||
| 96 | |||
| 97 | Result Container::DestroyManagedLayer(u64 layer_id) { | ||
| 98 | std::scoped_lock lk{m_lock}; | ||
| 99 | |||
| 100 | // Try to close, if open, but don't fail if not. | ||
| 101 | this->CloseLayerLocked(layer_id); | ||
| 102 | |||
| 103 | R_RETURN(this->DestroyLayerLocked(layer_id)); | ||
| 104 | } | ||
| 105 | |||
| 106 | Result Container::OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid) { | ||
| 107 | std::scoped_lock lk{m_lock}; | ||
| 108 | R_RETURN(this->OpenLayerLocked(out_producer_binder_id, layer_id, aruid)); | ||
| 109 | } | ||
| 110 | |||
| 111 | Result Container::CloseLayer(u64 layer_id) { | ||
| 112 | std::scoped_lock lk{m_lock}; | ||
| 113 | R_RETURN(this->CloseLayerLocked(layer_id)); | ||
| 114 | } | ||
| 115 | |||
| 116 | Result Container::SetLayerVisibility(u64 layer_id, bool visible) { | ||
| 117 | std::scoped_lock lk{m_lock}; | ||
| 118 | |||
| 119 | auto* const layer = m_layers.GetLayerById(layer_id); | ||
| 120 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 121 | |||
| 122 | m_surface_flinger->SetLayerVisibility(layer->GetConsumerBinderId(), visible); | ||
| 123 | R_SUCCEED(); | ||
| 124 | } | ||
| 125 | |||
| 126 | Result Container::SetLayerBlending(u64 layer_id, bool enabled) { | ||
| 127 | std::scoped_lock lk{m_lock}; | ||
| 128 | |||
| 129 | auto* const layer = m_layers.GetLayerById(layer_id); | ||
| 130 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 131 | |||
| 132 | m_surface_flinger->SetLayerBlending(layer->GetConsumerBinderId(), | ||
| 133 | enabled ? Nvnflinger::LayerBlending::Coverage | ||
| 134 | : Nvnflinger::LayerBlending::None); | ||
| 135 | R_SUCCEED(); | ||
| 136 | } | ||
| 137 | |||
| 138 | void Container::LinkVsyncEvent(u64 display_id, Event* event) { | ||
| 139 | std::scoped_lock lk{m_lock}; | ||
| 140 | m_conductor->LinkVsyncEvent(display_id, event); | ||
| 141 | } | ||
| 142 | |||
| 143 | void Container::UnlinkVsyncEvent(u64 display_id, Event* event) { | ||
| 144 | std::scoped_lock lk{m_lock}; | ||
| 145 | m_conductor->UnlinkVsyncEvent(display_id, event); | ||
| 146 | } | ||
| 147 | |||
| 148 | Result Container::CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id) { | ||
| 149 | std::scoped_lock lk{m_lock}; | ||
| 150 | R_TRY(this->CreateLayerLocked(out_layer_id, display_id, {})); | ||
| 151 | R_RETURN(this->OpenLayerLocked(out_producer_binder_id, *out_layer_id, {})); | ||
| 152 | } | ||
| 153 | |||
| 154 | Result Container::DestroyStrayLayer(u64 layer_id) { | ||
| 155 | std::scoped_lock lk{m_lock}; | ||
| 156 | R_TRY(this->CloseLayerLocked(layer_id)); | ||
| 157 | R_RETURN(this->DestroyLayerLocked(layer_id)); | ||
| 158 | } | ||
| 159 | |||
| 160 | Result Container::CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid) { | ||
| 161 | auto* const display = m_displays.GetDisplayById(display_id); | ||
| 162 | R_UNLESS(display != nullptr, VI::ResultNotFound); | ||
| 163 | |||
| 164 | auto* const layer = m_layers.CreateLayer(owner_aruid, display); | ||
| 165 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 166 | |||
| 167 | *out_layer_id = layer->GetId(); | ||
| 168 | R_SUCCEED(); | ||
| 169 | } | ||
| 170 | |||
| 171 | Result Container::DestroyLayerLocked(u64 layer_id) { | ||
| 172 | R_SUCCEED_IF(m_layers.DestroyLayer(layer_id)); | ||
| 173 | R_THROW(VI::ResultNotFound); | ||
| 174 | } | ||
| 175 | |||
| 176 | Result Container::OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid) { | ||
| 177 | R_UNLESS(!m_is_shut_down, VI::ResultOperationFailed); | ||
| 178 | |||
| 179 | auto* const layer = m_layers.GetLayerById(layer_id); | ||
| 180 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 181 | R_UNLESS(!layer->IsOpen(), VI::ResultOperationFailed); | ||
| 182 | R_UNLESS(layer->GetOwnerAruid() == aruid, VI::ResultPermissionDenied); | ||
| 183 | |||
| 184 | this->CreateBufferQueueLocked(layer); | ||
| 185 | *out_producer_binder_id = layer->GetProducerBinderId(); | ||
| 186 | |||
| 187 | R_SUCCEED(); | ||
| 188 | } | ||
| 189 | |||
| 190 | Result Container::CloseLayerLocked(u64 layer_id) { | ||
| 191 | auto* const layer = m_layers.GetLayerById(layer_id); | ||
| 192 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 193 | R_UNLESS(layer->IsOpen(), VI::ResultOperationFailed); | ||
| 194 | |||
| 195 | this->DestroyBufferQueueLocked(layer); | ||
| 196 | |||
| 197 | R_SUCCEED(); | ||
| 198 | } | ||
| 199 | |||
| 200 | void Container::CreateBufferQueueLocked(Layer* layer) { | ||
| 201 | s32 consumer_binder_id, producer_binder_id; | ||
| 202 | m_surface_flinger->CreateBufferQueue(&consumer_binder_id, &producer_binder_id); | ||
| 203 | layer->Open(consumer_binder_id, producer_binder_id); | ||
| 204 | |||
| 205 | if (auto* display = layer->GetDisplay(); display != nullptr) { | ||
| 206 | m_surface_flinger->AddLayerToDisplayStack(display->GetId(), consumer_binder_id); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | void Container::DestroyBufferQueueLocked(Layer* layer) { | ||
| 211 | if (auto* display = layer->GetDisplay(); display != nullptr) { | ||
| 212 | m_surface_flinger->RemoveLayerFromDisplayStack(display->GetId(), | ||
| 213 | layer->GetConsumerBinderId()); | ||
| 214 | } | ||
| 215 | |||
| 216 | layer->Close(); | ||
| 217 | m_surface_flinger->DestroyBufferQueue(layer->GetConsumerBinderId(), | ||
| 218 | layer->GetProducerBinderId()); | ||
| 219 | } | ||
| 220 | |||
| 221 | void Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, | ||
| 222 | u64 display_id) { | ||
| 223 | std::scoped_lock lk{m_lock}; | ||
| 224 | m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale, display_id); | ||
| 225 | } | ||
| 226 | |||
| 227 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/container.h b/src/core/hle/service/vi/container.h new file mode 100644 index 000000000..155c4c629 --- /dev/null +++ b/src/core/hle/service/vi/container.h | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <mutex> | ||
| 8 | #include <optional> | ||
| 9 | |||
| 10 | #include "core/hle/service/vi/conductor.h" | ||
| 11 | #include "core/hle/service/vi/display_list.h" | ||
| 12 | #include "core/hle/service/vi/layer_list.h" | ||
| 13 | #include "core/hle/service/vi/shared_buffer_manager.h" | ||
| 14 | |||
| 15 | union Result; | ||
| 16 | |||
| 17 | namespace Service::android { | ||
| 18 | class BufferQueueProducer; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Service::Nvnflinger { | ||
| 22 | class IHOSBinderDriver; | ||
| 23 | class SurfaceFlinger; | ||
| 24 | } // namespace Service::Nvnflinger | ||
| 25 | |||
| 26 | namespace Service { | ||
| 27 | class Event; | ||
| 28 | } | ||
| 29 | |||
| 30 | namespace Service::VI { | ||
| 31 | |||
| 32 | class SharedBufferManager; | ||
| 33 | |||
| 34 | class Container { | ||
| 35 | public: | ||
| 36 | explicit Container(Core::System& system); | ||
| 37 | ~Container(); | ||
| 38 | |||
| 39 | void OnTerminate(); | ||
| 40 | |||
| 41 | SharedBufferManager* GetSharedBufferManager(); | ||
| 42 | |||
| 43 | Result GetBinderDriver(std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver); | ||
| 44 | Result GetLayerProducerHandle(std::shared_ptr<android::BufferQueueProducer>* out_producer, | ||
| 45 | u64 layer_id); | ||
| 46 | |||
| 47 | Result OpenDisplay(u64* out_display_id, const DisplayName& display_name); | ||
| 48 | Result CloseDisplay(u64 display_id); | ||
| 49 | |||
| 50 | // Managed layers are created by the interaction between am and ommdisp | ||
| 51 | // on behalf of an applet. Their lifetime ends with the lifetime of the | ||
| 52 | // applet's ISelfController. | ||
| 53 | Result CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid); | ||
| 54 | Result DestroyManagedLayer(u64 layer_id); | ||
| 55 | Result OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid); | ||
| 56 | Result CloseLayer(u64 layer_id); | ||
| 57 | |||
| 58 | // Stray layers are created by non-applet sysmodules. Their lifetime ends | ||
| 59 | // with the lifetime of the IApplicationDisplayService which created them. | ||
| 60 | Result CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id); | ||
| 61 | Result DestroyStrayLayer(u64 layer_id); | ||
| 62 | |||
| 63 | Result SetLayerVisibility(u64 layer_id, bool visible); | ||
| 64 | Result SetLayerBlending(u64 layer_id, bool enabled); | ||
| 65 | |||
| 66 | void LinkVsyncEvent(u64 display_id, Event* event); | ||
| 67 | void UnlinkVsyncEvent(u64 display_id, Event* event); | ||
| 68 | |||
| 69 | private: | ||
| 70 | Result CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid); | ||
| 71 | Result DestroyLayerLocked(u64 layer_id); | ||
| 72 | Result OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid); | ||
| 73 | Result CloseLayerLocked(u64 layer_id); | ||
| 74 | |||
| 75 | void CreateBufferQueueLocked(Layer* layer); | ||
| 76 | void DestroyBufferQueueLocked(Layer* layer); | ||
| 77 | |||
| 78 | public: | ||
| 79 | void ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id); | ||
| 80 | |||
| 81 | private: | ||
| 82 | std::mutex m_lock{}; | ||
| 83 | DisplayList m_displays{}; | ||
| 84 | LayerList m_layers{}; | ||
| 85 | std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_driver{}; | ||
| 86 | std::shared_ptr<Nvnflinger::SurfaceFlinger> m_surface_flinger{}; | ||
| 87 | std::optional<SharedBufferManager> m_shared_buffer_manager{}; | ||
| 88 | std::optional<Conductor> m_conductor{}; | ||
| 89 | bool m_is_shut_down{}; | ||
| 90 | }; | ||
| 91 | |||
| 92 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/display.h b/src/core/hle/service/vi/display.h new file mode 100644 index 000000000..fceda75e3 --- /dev/null +++ b/src/core/hle/service/vi/display.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/vi/vi_types.h" | ||
| 7 | |||
| 8 | namespace Service::VI { | ||
| 9 | |||
| 10 | class Display { | ||
| 11 | public: | ||
| 12 | constexpr Display() = default; | ||
| 13 | |||
| 14 | void Initialize(u64 id, const DisplayName& display_name) { | ||
| 15 | m_id = id; | ||
| 16 | m_display_name = display_name; | ||
| 17 | m_is_initialized = true; | ||
| 18 | } | ||
| 19 | |||
| 20 | void Finalize() { | ||
| 21 | m_id = {}; | ||
| 22 | m_display_name = {}; | ||
| 23 | m_is_initialized = {}; | ||
| 24 | } | ||
| 25 | |||
| 26 | u64 GetId() const { | ||
| 27 | return m_id; | ||
| 28 | } | ||
| 29 | |||
| 30 | const DisplayName& GetDisplayName() const { | ||
| 31 | return m_display_name; | ||
| 32 | } | ||
| 33 | |||
| 34 | bool IsInitialized() const { | ||
| 35 | return m_is_initialized; | ||
| 36 | } | ||
| 37 | |||
| 38 | private: | ||
| 39 | u64 m_id{}; | ||
| 40 | DisplayName m_display_name{}; | ||
| 41 | bool m_is_initialized{}; | ||
| 42 | }; | ||
| 43 | |||
| 44 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp deleted file mode 100644 index 7f2af9acc..000000000 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ /dev/null | |||
| @@ -1,143 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <utility> | ||
| 6 | |||
| 7 | #include <fmt/format.h> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "core/core.h" | ||
| 11 | #include "core/hle/kernel/k_event.h" | ||
| 12 | #include "core/hle/kernel/k_readable_event.h" | ||
| 13 | #include "core/hle/service/kernel_helpers.h" | ||
| 14 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 15 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" | ||
| 16 | #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" | ||
| 17 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | ||
| 18 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | ||
| 19 | #include "core/hle/service/nvnflinger/hardware_composer.h" | ||
| 20 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||
| 21 | #include "core/hle/service/vi/display/vi_display.h" | ||
| 22 | #include "core/hle/service/vi/layer/vi_layer.h" | ||
| 23 | #include "core/hle/service/vi/vi_results.h" | ||
| 24 | |||
| 25 | namespace Service::VI { | ||
| 26 | |||
| 27 | struct BufferQueue { | ||
| 28 | std::shared_ptr<android::BufferQueueCore> core; | ||
| 29 | std::unique_ptr<android::BufferQueueProducer> producer; | ||
| 30 | std::unique_ptr<android::BufferQueueConsumer> consumer; | ||
| 31 | }; | ||
| 32 | |||
| 33 | static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context, | ||
| 34 | Service::Nvidia::NvCore::NvMap& nvmap) { | ||
| 35 | auto buffer_queue_core = std::make_shared<android::BufferQueueCore>(); | ||
| 36 | return { | ||
| 37 | buffer_queue_core, | ||
| 38 | std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), | ||
| 39 | std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)}; | ||
| 40 | } | ||
| 41 | |||
| 42 | Display::Display(u64 id, std::string name_, | ||
| 43 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, | ||
| 44 | KernelHelpers::ServiceContext& service_context_, Core::System& system_) | ||
| 45 | : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_}, | ||
| 46 | service_context{service_context_} { | ||
| 47 | hardware_composer = std::make_unique<Nvnflinger::HardwareComposer>(); | ||
| 48 | vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id)); | ||
| 49 | } | ||
| 50 | |||
| 51 | Display::~Display() { | ||
| 52 | service_context.CloseEvent(vsync_event); | ||
| 53 | } | ||
| 54 | |||
| 55 | Layer& Display::GetLayer(std::size_t index) { | ||
| 56 | size_t i = 0; | ||
| 57 | for (auto& layer : layers) { | ||
| 58 | if (!layer->IsOpen() || !layer->IsVisible()) { | ||
| 59 | continue; | ||
| 60 | } | ||
| 61 | |||
| 62 | if (i == index) { | ||
| 63 | return *layer; | ||
| 64 | } | ||
| 65 | |||
| 66 | i++; | ||
| 67 | } | ||
| 68 | |||
| 69 | UNREACHABLE(); | ||
| 70 | } | ||
| 71 | |||
| 72 | size_t Display::GetNumLayers() const { | ||
| 73 | return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); }); | ||
| 74 | } | ||
| 75 | |||
| 76 | Kernel::KReadableEvent* Display::GetVSyncEvent() { | ||
| 77 | return &vsync_event->GetReadableEvent(); | ||
| 78 | } | ||
| 79 | |||
| 80 | void Display::SignalVSyncEvent() { | ||
| 81 | vsync_event->Signal(); | ||
| 82 | } | ||
| 83 | |||
| 84 | void Display::CreateLayer(u64 layer_id, u32 binder_id, | ||
| 85 | Service::Nvidia::NvCore::Container& nv_core) { | ||
| 86 | auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile()); | ||
| 87 | |||
| 88 | auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer)); | ||
| 89 | buffer_item_consumer->Connect(false); | ||
| 90 | |||
| 91 | layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, | ||
| 92 | std::move(buffer_item_consumer))); | ||
| 93 | |||
| 94 | if (is_abandoned) { | ||
| 95 | this->FindLayer(layer_id)->GetConsumer().Abandon(); | ||
| 96 | } | ||
| 97 | |||
| 98 | hos_binder_driver_server.RegisterProducer(std::move(producer)); | ||
| 99 | } | ||
| 100 | |||
| 101 | void Display::DestroyLayer(u64 layer_id) { | ||
| 102 | if (auto* layer = this->FindLayer(layer_id); layer != nullptr) { | ||
| 103 | layer->GetConsumer().Abandon(); | ||
| 104 | } | ||
| 105 | |||
| 106 | std::erase_if(layers, | ||
| 107 | [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); | ||
| 108 | } | ||
| 109 | |||
| 110 | void Display::Abandon() { | ||
| 111 | for (auto& layer : layers) { | ||
| 112 | layer->GetConsumer().Abandon(); | ||
| 113 | } | ||
| 114 | is_abandoned = true; | ||
| 115 | } | ||
| 116 | |||
| 117 | Layer* Display::FindLayer(u64 layer_id) { | ||
| 118 | const auto itr = | ||
| 119 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { | ||
| 120 | return layer->GetLayerId() == layer_id; | ||
| 121 | }); | ||
| 122 | |||
| 123 | if (itr == layers.end()) { | ||
| 124 | return nullptr; | ||
| 125 | } | ||
| 126 | |||
| 127 | return itr->get(); | ||
| 128 | } | ||
| 129 | |||
| 130 | const Layer* Display::FindLayer(u64 layer_id) const { | ||
| 131 | const auto itr = | ||
| 132 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { | ||
| 133 | return layer->GetLayerId() == layer_id; | ||
| 134 | }); | ||
| 135 | |||
| 136 | if (itr == layers.end()) { | ||
| 137 | return nullptr; | ||
| 138 | } | ||
| 139 | |||
| 140 | return itr->get(); | ||
| 141 | } | ||
| 142 | |||
| 143 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h deleted file mode 100644 index 220292cff..000000000 --- a/src/core/hle/service/vi/display/vi_display.h +++ /dev/null | |||
| @@ -1,143 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "core/hle/result.h" | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class System; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Kernel { | ||
| 19 | class KEvent; | ||
| 20 | class KReadableEvent; | ||
| 21 | } // namespace Kernel | ||
| 22 | |||
| 23 | namespace Service::android { | ||
| 24 | class BufferQueueProducer; | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace Service::KernelHelpers { | ||
| 28 | class ServiceContext; | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace Service::Nvnflinger { | ||
| 32 | class HardwareComposer; | ||
| 33 | class HosBinderDriverServer; | ||
| 34 | } // namespace Service::Nvnflinger | ||
| 35 | |||
| 36 | namespace Service::Nvidia::NvCore { | ||
| 37 | class Container; | ||
| 38 | class NvMap; | ||
| 39 | } // namespace Service::Nvidia::NvCore | ||
| 40 | |||
| 41 | namespace Service::VI { | ||
| 42 | |||
| 43 | class Layer; | ||
| 44 | |||
| 45 | /// Represents a single display type | ||
| 46 | class Display { | ||
| 47 | public: | ||
| 48 | YUZU_NON_COPYABLE(Display); | ||
| 49 | YUZU_NON_MOVEABLE(Display); | ||
| 50 | |||
| 51 | /// Constructs a display with a given unique ID and name. | ||
| 52 | /// | ||
| 53 | /// @param id The unique ID for this display. | ||
| 54 | /// @param hos_binder_driver_server_ Nvnflinger HOSBinderDriver server instance. | ||
| 55 | /// @param service_context_ The ServiceContext for the owning service. | ||
| 56 | /// @param name_ The name for this display. | ||
| 57 | /// @param system_ The global system instance. | ||
| 58 | /// | ||
| 59 | Display(u64 id, std::string name_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_, | ||
| 60 | KernelHelpers::ServiceContext& service_context_, Core::System& system_); | ||
| 61 | ~Display(); | ||
| 62 | |||
| 63 | /// Gets the unique ID assigned to this display. | ||
| 64 | u64 GetID() const { | ||
| 65 | return display_id; | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Gets the name of this display | ||
| 69 | const std::string& GetName() const { | ||
| 70 | return name; | ||
| 71 | } | ||
| 72 | |||
| 73 | /// Whether or not this display has any layers added to it. | ||
| 74 | bool HasLayers() const { | ||
| 75 | return GetNumLayers() > 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | /// Gets a layer for this display based off an index. | ||
| 79 | Layer& GetLayer(std::size_t index); | ||
| 80 | |||
| 81 | std::size_t GetNumLayers() const; | ||
| 82 | |||
| 83 | /// Gets the internal vsync event. | ||
| 84 | Kernel::KReadableEvent* GetVSyncEvent(); | ||
| 85 | |||
| 86 | /// Signals the internal vsync event. | ||
| 87 | void SignalVSyncEvent(); | ||
| 88 | |||
| 89 | /// Creates and adds a layer to this display with the given ID. | ||
| 90 | /// | ||
| 91 | /// @param layer_id The ID to assign to the created layer. | ||
| 92 | /// @param binder_id The ID assigned to the buffer queue. | ||
| 93 | /// | ||
| 94 | void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core); | ||
| 95 | |||
| 96 | /// Removes a layer from this display with the given ID. | ||
| 97 | /// | ||
| 98 | /// @param layer_id The ID assigned to the layer to destroy. | ||
| 99 | /// | ||
| 100 | void DestroyLayer(u64 layer_id); | ||
| 101 | |||
| 102 | /// Resets the display for a new connection. | ||
| 103 | void Reset() { | ||
| 104 | layers.clear(); | ||
| 105 | } | ||
| 106 | |||
| 107 | void Abandon(); | ||
| 108 | |||
| 109 | /// Attempts to find a layer with the given ID. | ||
| 110 | /// | ||
| 111 | /// @param layer_id The layer ID. | ||
| 112 | /// | ||
| 113 | /// @returns If found, the Layer instance with the given ID. | ||
| 114 | /// If not found, then nullptr is returned. | ||
| 115 | /// | ||
| 116 | Layer* FindLayer(u64 layer_id); | ||
| 117 | |||
| 118 | /// Attempts to find a layer with the given ID. | ||
| 119 | /// | ||
| 120 | /// @param layer_id The layer ID. | ||
| 121 | /// | ||
| 122 | /// @returns If found, the Layer instance with the given ID. | ||
| 123 | /// If not found, then nullptr is returned. | ||
| 124 | /// | ||
| 125 | const Layer* FindLayer(u64 layer_id) const; | ||
| 126 | |||
| 127 | Nvnflinger::HardwareComposer& GetComposer() const { | ||
| 128 | return *hardware_composer; | ||
| 129 | } | ||
| 130 | |||
| 131 | private: | ||
| 132 | u64 display_id; | ||
| 133 | std::string name; | ||
| 134 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||
| 135 | KernelHelpers::ServiceContext& service_context; | ||
| 136 | |||
| 137 | std::vector<std::unique_ptr<Layer>> layers; | ||
| 138 | std::unique_ptr<Nvnflinger::HardwareComposer> hardware_composer; | ||
| 139 | Kernel::KEvent* vsync_event{}; | ||
| 140 | bool is_abandoned{}; | ||
| 141 | }; | ||
| 142 | |||
| 143 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/display_list.h b/src/core/hle/service/vi/display_list.h new file mode 100644 index 000000000..f710ac472 --- /dev/null +++ b/src/core/hle/service/vi/display_list.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <cstring> | ||
| 7 | |||
| 8 | #include "core/hle/service/vi/display.h" | ||
| 9 | |||
| 10 | namespace Service::VI { | ||
| 11 | |||
| 12 | class DisplayList { | ||
| 13 | public: | ||
| 14 | constexpr DisplayList() = default; | ||
| 15 | |||
| 16 | bool CreateDisplay(const DisplayName& name) { | ||
| 17 | Display* const display = this->GetFreeDisplay(); | ||
| 18 | if (!display) { | ||
| 19 | return false; | ||
| 20 | } | ||
| 21 | |||
| 22 | display->Initialize(m_next_id++, name); | ||
| 23 | return true; | ||
| 24 | } | ||
| 25 | |||
| 26 | bool DestroyDisplay(u64 display_id) { | ||
| 27 | Display* display = this->GetDisplayById(display_id); | ||
| 28 | if (!display) { | ||
| 29 | return false; | ||
| 30 | } | ||
| 31 | |||
| 32 | display->Finalize(); | ||
| 33 | return true; | ||
| 34 | } | ||
| 35 | |||
| 36 | Display* GetDisplayByName(const DisplayName& name) { | ||
| 37 | for (auto& display : m_displays) { | ||
| 38 | if (display.IsInitialized() && | ||
| 39 | std::strncmp(name.data(), display.GetDisplayName().data(), sizeof(DisplayName)) == | ||
| 40 | 0) { | ||
| 41 | return &display; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | return nullptr; | ||
| 46 | } | ||
| 47 | |||
| 48 | Display* GetDisplayById(u64 display_id) { | ||
| 49 | for (auto& display : m_displays) { | ||
| 50 | if (display.IsInitialized() && display.GetId() == display_id) { | ||
| 51 | return &display; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | return nullptr; | ||
| 56 | } | ||
| 57 | |||
| 58 | template <typename F> | ||
| 59 | void ForEachDisplay(F&& cb) { | ||
| 60 | for (auto& display : m_displays) { | ||
| 61 | if (display.IsInitialized()) { | ||
| 62 | cb(display); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | private: | ||
| 68 | Display* GetFreeDisplay() { | ||
| 69 | for (auto& display : m_displays) { | ||
| 70 | if (!display.IsInitialized()) { | ||
| 71 | return &display; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | return nullptr; | ||
| 76 | } | ||
| 77 | |||
| 78 | private: | ||
| 79 | std::array<Display, 8> m_displays{}; | ||
| 80 | u64 m_next_id{}; | ||
| 81 | }; | ||
| 82 | |||
| 83 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/layer.h b/src/core/hle/service/vi/layer.h new file mode 100644 index 000000000..b85c8df61 --- /dev/null +++ b/src/core/hle/service/vi/layer.h | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | |||
| 8 | namespace Service::VI { | ||
| 9 | |||
| 10 | class Display; | ||
| 11 | |||
| 12 | class Layer { | ||
| 13 | public: | ||
| 14 | constexpr Layer() = default; | ||
| 15 | |||
| 16 | void Initialize(u64 id, u64 owner_aruid, Display* display) { | ||
| 17 | m_id = id; | ||
| 18 | m_owner_aruid = owner_aruid; | ||
| 19 | m_display = display; | ||
| 20 | m_is_initialized = true; | ||
| 21 | } | ||
| 22 | |||
| 23 | void Finalize() { | ||
| 24 | m_id = {}; | ||
| 25 | m_display = {}; | ||
| 26 | m_is_initialized = {}; | ||
| 27 | } | ||
| 28 | |||
| 29 | void Open(s32 consumer_binder_id, s32 producer_binder_id) { | ||
| 30 | m_consumer_binder_id = consumer_binder_id; | ||
| 31 | m_producer_binder_id = producer_binder_id; | ||
| 32 | m_is_open = true; | ||
| 33 | } | ||
| 34 | |||
| 35 | void Close() { | ||
| 36 | m_producer_binder_id = {}; | ||
| 37 | m_consumer_binder_id = {}; | ||
| 38 | m_is_open = {}; | ||
| 39 | } | ||
| 40 | |||
| 41 | u64 GetId() const { | ||
| 42 | return m_id; | ||
| 43 | } | ||
| 44 | |||
| 45 | u64 GetOwnerAruid() const { | ||
| 46 | return m_owner_aruid; | ||
| 47 | } | ||
| 48 | |||
| 49 | Display* GetDisplay() const { | ||
| 50 | return m_display; | ||
| 51 | } | ||
| 52 | |||
| 53 | s32 GetConsumerBinderId() const { | ||
| 54 | return m_consumer_binder_id; | ||
| 55 | } | ||
| 56 | |||
| 57 | s32 GetProducerBinderId() const { | ||
| 58 | return m_producer_binder_id; | ||
| 59 | } | ||
| 60 | |||
| 61 | bool IsInitialized() const { | ||
| 62 | return m_is_initialized; | ||
| 63 | } | ||
| 64 | |||
| 65 | bool IsOpen() const { | ||
| 66 | return m_is_open; | ||
| 67 | } | ||
| 68 | |||
| 69 | private: | ||
| 70 | u64 m_id{}; | ||
| 71 | u64 m_owner_aruid{}; | ||
| 72 | Display* m_display{}; | ||
| 73 | s32 m_consumer_binder_id{}; | ||
| 74 | s32 m_producer_binder_id{}; | ||
| 75 | bool m_is_initialized{}; | ||
| 76 | bool m_is_open{}; | ||
| 77 | }; | ||
| 78 | |||
| 79 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp deleted file mode 100644 index eca35d82a..000000000 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ /dev/null | |||
| @@ -1,18 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/nvnflinger/hwc_layer.h" | ||
| 5 | #include "core/hle/service/vi/layer/vi_layer.h" | ||
| 6 | |||
| 7 | namespace Service::VI { | ||
| 8 | |||
| 9 | Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, | ||
| 10 | android::BufferQueueProducer& binder_, | ||
| 11 | std::shared_ptr<android::BufferItemConsumer>&& consumer_) | ||
| 12 | : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move( | ||
| 13 | consumer_)}, | ||
| 14 | blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {} | ||
| 15 | |||
| 16 | Layer::~Layer() = default; | ||
| 17 | |||
| 18 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h deleted file mode 100644 index 14e229903..000000000 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ /dev/null | |||
| @@ -1,118 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <utility> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Service::android { | ||
| 12 | class BufferItemConsumer; | ||
| 13 | class BufferQueueCore; | ||
| 14 | class BufferQueueProducer; | ||
| 15 | } // namespace Service::android | ||
| 16 | |||
| 17 | namespace Service::Nvnflinger { | ||
| 18 | enum class LayerBlending : u32; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Service::VI { | ||
| 22 | |||
| 23 | /// Represents a single display layer. | ||
| 24 | class Layer { | ||
| 25 | public: | ||
| 26 | /// Constructs a layer with a given ID and buffer queue. | ||
| 27 | /// | ||
| 28 | /// @param layer_id_ The ID to assign to this layer. | ||
| 29 | /// @param binder_id_ The binder ID to assign to this layer. | ||
| 30 | /// @param binder_ The buffer producer queue for this layer to use. | ||
| 31 | /// | ||
| 32 | Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, | ||
| 33 | android::BufferQueueProducer& binder_, | ||
| 34 | std::shared_ptr<android::BufferItemConsumer>&& consumer_); | ||
| 35 | ~Layer(); | ||
| 36 | |||
| 37 | Layer(const Layer&) = delete; | ||
| 38 | Layer& operator=(const Layer&) = delete; | ||
| 39 | |||
| 40 | Layer(Layer&&) = default; | ||
| 41 | Layer& operator=(Layer&&) = delete; | ||
| 42 | |||
| 43 | /// Gets the ID for this layer. | ||
| 44 | u64 GetLayerId() const { | ||
| 45 | return layer_id; | ||
| 46 | } | ||
| 47 | |||
| 48 | /// Gets the binder ID for this layer. | ||
| 49 | u32 GetBinderId() const { | ||
| 50 | return binder_id; | ||
| 51 | } | ||
| 52 | |||
| 53 | /// Gets a reference to the buffer queue this layer is using. | ||
| 54 | android::BufferQueueProducer& GetBufferQueue() { | ||
| 55 | return binder; | ||
| 56 | } | ||
| 57 | |||
| 58 | /// Gets a const reference to the buffer queue this layer is using. | ||
| 59 | const android::BufferQueueProducer& GetBufferQueue() const { | ||
| 60 | return binder; | ||
| 61 | } | ||
| 62 | |||
| 63 | android::BufferItemConsumer& GetConsumer() { | ||
| 64 | return *consumer; | ||
| 65 | } | ||
| 66 | |||
| 67 | const android::BufferItemConsumer& GetConsumer() const { | ||
| 68 | return *consumer; | ||
| 69 | } | ||
| 70 | |||
| 71 | android::BufferQueueCore& Core() { | ||
| 72 | return core; | ||
| 73 | } | ||
| 74 | |||
| 75 | const android::BufferQueueCore& Core() const { | ||
| 76 | return core; | ||
| 77 | } | ||
| 78 | |||
| 79 | bool IsVisible() const { | ||
| 80 | return visible; | ||
| 81 | } | ||
| 82 | |||
| 83 | void SetVisibility(bool v) { | ||
| 84 | visible = v; | ||
| 85 | } | ||
| 86 | |||
| 87 | bool IsOpen() const { | ||
| 88 | return open; | ||
| 89 | } | ||
| 90 | |||
| 91 | bool Close() { | ||
| 92 | return std::exchange(open, false); | ||
| 93 | } | ||
| 94 | |||
| 95 | bool Open() { | ||
| 96 | return !std::exchange(open, true); | ||
| 97 | } | ||
| 98 | |||
| 99 | Nvnflinger::LayerBlending GetBlending() { | ||
| 100 | return blending; | ||
| 101 | } | ||
| 102 | |||
| 103 | void SetBlending(Nvnflinger::LayerBlending b) { | ||
| 104 | blending = b; | ||
| 105 | } | ||
| 106 | |||
| 107 | private: | ||
| 108 | const u64 layer_id; | ||
| 109 | const u32 binder_id; | ||
| 110 | android::BufferQueueCore& core; | ||
| 111 | android::BufferQueueProducer& binder; | ||
| 112 | std::shared_ptr<android::BufferItemConsumer> consumer; | ||
| 113 | Service::Nvnflinger::LayerBlending blending; | ||
| 114 | bool open; | ||
| 115 | bool visible; | ||
| 116 | }; | ||
| 117 | |||
| 118 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/layer_list.h b/src/core/hle/service/vi/layer_list.h new file mode 100644 index 000000000..1738ede9a --- /dev/null +++ b/src/core/hle/service/vi/layer_list.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/vi/layer.h" | ||
| 7 | |||
| 8 | namespace Service::VI { | ||
| 9 | |||
| 10 | class LayerList { | ||
| 11 | public: | ||
| 12 | constexpr LayerList() = default; | ||
| 13 | |||
| 14 | Layer* CreateLayer(u64 owner_aruid, Display* display) { | ||
| 15 | Layer* const layer = GetFreeLayer(); | ||
| 16 | if (!layer) { | ||
| 17 | return nullptr; | ||
| 18 | } | ||
| 19 | |||
| 20 | layer->Initialize(++m_next_id, owner_aruid, display); | ||
| 21 | return layer; | ||
| 22 | } | ||
| 23 | |||
| 24 | bool DestroyLayer(u64 layer_id) { | ||
| 25 | Layer* const layer = GetLayerById(layer_id); | ||
| 26 | if (!layer) { | ||
| 27 | return false; | ||
| 28 | } | ||
| 29 | |||
| 30 | layer->Finalize(); | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | |||
| 34 | Layer* GetLayerById(u64 layer_id) { | ||
| 35 | for (auto& layer : m_layers) { | ||
| 36 | if (layer.IsInitialized() && layer.GetId() == layer_id) { | ||
| 37 | return &layer; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | return nullptr; | ||
| 42 | } | ||
| 43 | |||
| 44 | template <typename F> | ||
| 45 | void ForEachLayer(F&& cb) { | ||
| 46 | for (auto& layer : m_layers) { | ||
| 47 | if (layer.IsInitialized()) { | ||
| 48 | cb(layer); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | private: | ||
| 54 | Layer* GetFreeLayer() { | ||
| 55 | for (auto& layer : m_layers) { | ||
| 56 | if (!layer.IsInitialized()) { | ||
| 57 | return &layer; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | return nullptr; | ||
| 62 | } | ||
| 63 | |||
| 64 | private: | ||
| 65 | std::array<Layer, 8> m_layers{}; | ||
| 66 | u64 m_next_id{}; | ||
| 67 | }; | ||
| 68 | |||
| 69 | } // 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 index 22454ba61..9f856282e 100644 --- a/src/core/hle/service/vi/manager_display_service.cpp +++ b/src/core/hle/service/vi/manager_display_service.cpp | |||
| @@ -2,23 +2,21 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/cmif_serialization.h" | 4 | #include "core/hle/service/cmif_serialization.h" |
| 5 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 5 | #include "core/hle/service/vi/container.h" |
| 6 | #include "core/hle/service/vi/manager_display_service.h" | 6 | #include "core/hle/service/vi/manager_display_service.h" |
| 7 | #include "core/hle/service/vi/vi_results.h" | ||
| 8 | 7 | ||
| 9 | namespace Service::VI { | 8 | namespace Service::VI { |
| 10 | 9 | ||
| 11 | IManagerDisplayService::IManagerDisplayService( | 10 | IManagerDisplayService::IManagerDisplayService(Core::System& system_, |
| 12 | Core::System& system_, std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger) | 11 | std::shared_ptr<Container> container) |
| 13 | : ServiceFramework{system_, "IManagerDisplayService"}, | 12 | : ServiceFramework{system_, "IManagerDisplayService"}, m_container{std::move(container)} { |
| 14 | m_surface_flinger{std::move(surface_flinger)} { | ||
| 15 | // clang-format off | 13 | // clang-format off |
| 16 | static const FunctionInfo functions[] = { | 14 | static const FunctionInfo functions[] = { |
| 17 | {200, nullptr, "AllocateProcessHeapBlock"}, | 15 | {200, nullptr, "AllocateProcessHeapBlock"}, |
| 18 | {201, nullptr, "FreeProcessHeapBlock"}, | 16 | {201, nullptr, "FreeProcessHeapBlock"}, |
| 19 | {1102, nullptr, "GetDisplayResolution"}, | 17 | {1102, nullptr, "GetDisplayResolution"}, |
| 20 | {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, | 18 | {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, |
| 21 | {2011, nullptr, "DestroyManagedLayer"}, | 19 | {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"}, |
| 22 | {2012, nullptr, "CreateStrayLayer"}, | 20 | {2012, nullptr, "CreateStrayLayer"}, |
| 23 | {2050, nullptr, "CreateIndirectLayer"}, | 21 | {2050, nullptr, "CreateIndirectLayer"}, |
| 24 | {2051, nullptr, "DestroyIndirectLayer"}, | 22 | {2051, nullptr, "DestroyIndirectLayer"}, |
| @@ -103,19 +101,30 @@ IManagerDisplayService::IManagerDisplayService( | |||
| 103 | 101 | ||
| 104 | IManagerDisplayService::~IManagerDisplayService() = default; | 102 | IManagerDisplayService::~IManagerDisplayService() = default; |
| 105 | 103 | ||
| 106 | Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, | 104 | Result IManagerDisplayService::CreateSharedLayerSession(Kernel::KProcess* owner_process, |
| 107 | u64 display_id, AppletResourceUserId aruid) { | 105 | u64* out_buffer_id, u64* out_layer_handle, |
| 108 | LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, | 106 | u64 display_id, bool enable_blending) { |
| 109 | display_id, aruid.pid); | 107 | R_RETURN(m_container->GetSharedBufferManager()->CreateSession( |
| 108 | owner_process, out_buffer_id, out_layer_handle, display_id, enable_blending)); | ||
| 109 | } | ||
| 110 | 110 | ||
| 111 | const auto layer_id = m_surface_flinger->CreateLayer(display_id); | 111 | void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) { |
| 112 | if (!layer_id) { | 112 | m_container->GetSharedBufferManager()->DestroySession(owner_process); |
| 113 | LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); | 113 | } |
| 114 | R_THROW(VI::ResultNotFound); | ||
| 115 | } | ||
| 116 | 114 | ||
| 117 | *out_layer_id = *layer_id; | 115 | Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) { |
| 118 | R_SUCCEED(); | 116 | R_RETURN(m_container->SetLayerBlending(layer_id, enabled)); |
| 117 | } | ||
| 118 | |||
| 119 | Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id, | ||
| 120 | AppletResourceUserId aruid) { | ||
| 121 | LOG_DEBUG(Service_VI, "called. flags={}, display={}, aruid={}", flags, display_id, aruid.pid); | ||
| 122 | R_RETURN(m_container->CreateManagedLayer(out_layer_id, display_id, aruid.pid)); | ||
| 123 | } | ||
| 124 | |||
| 125 | Result IManagerDisplayService::DestroyManagedLayer(u64 layer_id) { | ||
| 126 | LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); | ||
| 127 | R_RETURN(m_container->DestroyManagedLayer(layer_id)); | ||
| 119 | } | 128 | } |
| 120 | 129 | ||
| 121 | Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { | 130 | Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { |
| @@ -124,8 +133,8 @@ Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { | |||
| 124 | } | 133 | } |
| 125 | 134 | ||
| 126 | Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | 135 | Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { |
| 127 | LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); | 136 | LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); |
| 128 | R_SUCCEED(); | 137 | R_RETURN(m_container->SetLayerVisibility(layer_id, visible)); |
| 129 | } | 138 | } |
| 130 | 139 | ||
| 131 | } // namespace Service::VI | 140 | } // 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 4a3d53ff8..b1bdf7f41 100644 --- a/src/core/hle/service/vi/manager_display_service.h +++ b/src/core/hle/service/vi/manager_display_service.h | |||
| @@ -4,22 +4,34 @@ | |||
| 4 | #include "core/hle/service/cmif_types.h" | 4 | #include "core/hle/service/cmif_types.h" |
| 5 | #include "core/hle/service/service.h" | 5 | #include "core/hle/service/service.h" |
| 6 | 6 | ||
| 7 | namespace Kernel { | ||
| 8 | class KProcess; | ||
| 9 | } | ||
| 10 | |||
| 7 | namespace Service::VI { | 11 | namespace Service::VI { |
| 8 | 12 | ||
| 13 | class Container; | ||
| 14 | |||
| 9 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | 15 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { |
| 10 | public: | 16 | public: |
| 11 | explicit IManagerDisplayService(Core::System& system_, | 17 | explicit IManagerDisplayService(Core::System& system_, std::shared_ptr<Container> container); |
| 12 | std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger); | ||
| 13 | ~IManagerDisplayService() override; | 18 | ~IManagerDisplayService() override; |
| 14 | 19 | ||
| 15 | private: | 20 | Result CreateSharedLayerSession(Kernel::KProcess* owner_process, u64* out_buffer_id, |
| 16 | Result CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, u64 display_id, | 21 | u64* out_layer_handle, u64 display_id, bool enable_blending); |
| 22 | void DestroySharedLayerSession(Kernel::KProcess* owner_process); | ||
| 23 | |||
| 24 | Result SetLayerBlending(bool enabled, u64 layer_id); | ||
| 25 | |||
| 26 | public: | ||
| 27 | Result CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id, | ||
| 17 | AppletResourceUserId aruid); | 28 | AppletResourceUserId aruid); |
| 29 | Result DestroyManagedLayer(u64 layer_id); | ||
| 18 | Result AddToLayerStack(u32 stack_id, u64 layer_id); | 30 | Result AddToLayerStack(u32 stack_id, u64 layer_id); |
| 19 | Result SetLayerVisibility(bool visible, u64 layer_id); | 31 | Result SetLayerVisibility(bool visible, u64 layer_id); |
| 20 | 32 | ||
| 21 | private: | 33 | private: |
| 22 | const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger; | 34 | const std::shared_ptr<Container> m_container; |
| 23 | }; | 35 | }; |
| 24 | 36 | ||
| 25 | } // namespace Service::VI | 37 | } // 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 b61f0ecb6..0f16a15b4 100644 --- a/src/core/hle/service/vi/manager_root_service.cpp +++ b/src/core/hle/service/vi/manager_root_service.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include "core/hle/service/cmif_serialization.h" | 4 | #include "core/hle/service/cmif_serialization.h" |
| 5 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" | 5 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" |
| 6 | #include "core/hle/service/vi/application_display_service.h" | 6 | #include "core/hle/service/vi/application_display_service.h" |
| 7 | #include "core/hle/service/vi/container.h" | ||
| 7 | #include "core/hle/service/vi/manager_root_service.h" | 8 | #include "core/hle/service/vi/manager_root_service.h" |
| 8 | #include "core/hle/service/vi/service_creator.h" | 9 | #include "core/hle/service/vi/service_creator.h" |
| 9 | #include "core/hle/service/vi/vi.h" | 10 | #include "core/hle/service/vi/vi.h" |
| @@ -11,11 +12,9 @@ | |||
| 11 | 12 | ||
| 12 | namespace Service::VI { | 13 | namespace Service::VI { |
| 13 | 14 | ||
| 14 | IManagerRootService::IManagerRootService( | 15 | IManagerRootService::IManagerRootService(Core::System& system_, |
| 15 | Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | 16 | std::shared_ptr<Container> container) |
| 16 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager) | 17 | : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} { |
| 17 | : ServiceFramework{system_, "vi:m"}, m_binder_service{std::move(binder_service)}, | ||
| 18 | m_shared_buffer_manager{std::move(shared_buffer_manager)} { | ||
| 19 | static const FunctionInfo functions[] = { | 18 | static const FunctionInfo functions[] = { |
| 20 | {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, | 19 | {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, |
| 21 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 20 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
| @@ -32,8 +31,8 @@ IManagerRootService::~IManagerRootService() = default; | |||
| 32 | Result IManagerRootService::GetDisplayService( | 31 | Result IManagerRootService::GetDisplayService( |
| 33 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | 32 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { |
| 34 | LOG_DEBUG(Service_VI, "called"); | 33 | LOG_DEBUG(Service_VI, "called"); |
| 35 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service, | 34 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, |
| 36 | m_shared_buffer_manager, Permission::Manager, policy)); | 35 | Permission::Manager, policy)); |
| 37 | } | 36 | } |
| 38 | 37 | ||
| 39 | } // namespace Service::VI | 38 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h index 509445b7b..77cd32869 100644 --- a/src/core/hle/service/vi/manager_root_service.h +++ b/src/core/hle/service/vi/manager_root_service.h | |||
| @@ -10,21 +10,15 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::Nvnflinger { | ||
| 14 | class IHOSBinderDriver; | ||
| 15 | } // namespace Service::Nvnflinger | ||
| 16 | |||
| 17 | namespace Service::VI { | 13 | namespace Service::VI { |
| 18 | 14 | ||
| 19 | class FbshareBufferManager; | 15 | class Container; |
| 20 | class IApplicationDisplayService; | 16 | class IApplicationDisplayService; |
| 21 | enum class Policy : u32; | 17 | enum class Policy : u32; |
| 22 | 18 | ||
| 23 | class IManagerRootService final : public ServiceFramework<IManagerRootService> { | 19 | class IManagerRootService final : public ServiceFramework<IManagerRootService> { |
| 24 | public: | 20 | public: |
| 25 | explicit IManagerRootService(Core::System& system_, | 21 | explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | ||
| 27 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager); | ||
| 28 | ~IManagerRootService() override; | 22 | ~IManagerRootService() override; |
| 29 | 23 | ||
| 30 | Result GetDisplayService( | 24 | Result GetDisplayService( |
| @@ -32,8 +26,7 @@ public: | |||
| 32 | Policy policy); | 26 | Policy policy); |
| 33 | 27 | ||
| 34 | private: | 28 | private: |
| 35 | const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; | 29 | const std::shared_ptr<Container> m_container; |
| 36 | const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager; | ||
| 37 | }; | 30 | }; |
| 38 | 31 | ||
| 39 | } // namespace Service::VI | 32 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp index 414bd6655..2b8e5f957 100644 --- a/src/core/hle/service/vi/service_creator.cpp +++ b/src/core/hle/service/vi/service_creator.cpp | |||
| @@ -22,8 +22,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) { | |||
| 22 | 22 | ||
| 23 | Result GetApplicationDisplayService( | 23 | Result GetApplicationDisplayService( |
| 24 | std::shared_ptr<IApplicationDisplayService>* out_application_display_service, | 24 | std::shared_ptr<IApplicationDisplayService>* out_application_display_service, |
| 25 | Core::System& system, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | 25 | Core::System& system, std::shared_ptr<Container> container, Permission permission, |
| 26 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager, Permission permission, | ||
| 27 | Policy policy) { | 26 | Policy policy) { |
| 28 | 27 | ||
| 29 | if (!IsValidServiceAccess(permission, policy)) { | 28 | if (!IsValidServiceAccess(permission, policy)) { |
| @@ -32,7 +31,7 @@ Result GetApplicationDisplayService( | |||
| 32 | } | 31 | } |
| 33 | 32 | ||
| 34 | *out_application_display_service = | 33 | *out_application_display_service = |
| 35 | std::make_shared<IApplicationDisplayService>(system, binder_service, shared_buffer_manager); | 34 | std::make_shared<IApplicationDisplayService>(system, std::move(container)); |
| 36 | R_SUCCEED(); | 35 | R_SUCCEED(); |
| 37 | } | 36 | } |
| 38 | 37 | ||
diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h index 6691f25c0..c6ba1797d 100644 --- a/src/core/hle/service/vi/service_creator.h +++ b/src/core/hle/service/vi/service_creator.h | |||
| @@ -11,23 +11,18 @@ namespace Core { | |||
| 11 | class System; | 11 | class System; |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | namespace Service::Nvnflinger { | ||
| 15 | class IHOSBinderDriver; | ||
| 16 | } // namespace Service::Nvnflinger | ||
| 17 | |||
| 18 | union Result; | 14 | union Result; |
| 19 | 15 | ||
| 20 | namespace Service::VI { | 16 | namespace Service::VI { |
| 21 | 17 | ||
| 22 | class FbshareBufferManager; | 18 | class Container; |
| 23 | class IApplicationDisplayService; | 19 | class IApplicationDisplayService; |
| 24 | enum class Permission; | 20 | enum class Permission; |
| 25 | enum class Policy : u32; | 21 | enum class Policy : u32; |
| 26 | 22 | ||
| 27 | Result GetApplicationDisplayService( | 23 | Result GetApplicationDisplayService( |
| 28 | std::shared_ptr<IApplicationDisplayService>* out_application_display_service, | 24 | std::shared_ptr<IApplicationDisplayService>* out_application_display_service, |
| 29 | Core::System& system, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | 25 | Core::System& system, std::shared_ptr<Container> container, Permission permission, |
| 30 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager, Permission permission, | ||
| 31 | Policy policy); | 26 | Policy policy); |
| 32 | 27 | ||
| 33 | } // namespace Service::VI | 28 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/fbshare_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index e61c02e1c..869b18961 100644 --- a/src/core/hle/service/vi/fbshare_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | 11 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" |
| 12 | #include "core/hle/service/nvnflinger/pixel_format.h" | 12 | #include "core/hle/service/nvnflinger/pixel_format.h" |
| 13 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 13 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" |
| 14 | #include "core/hle/service/vi/fbshare_buffer_manager.h" | 14 | #include "core/hle/service/vi/container.h" |
| 15 | #include "core/hle/service/vi/layer/vi_layer.h" | 15 | #include "core/hle/service/vi/shared_buffer_manager.h" |
| 16 | #include "core/hle/service/vi/vi_results.h" | 16 | #include "core/hle/service/vi/vi_results.h" |
| 17 | #include "video_core/gpu.h" | 17 | #include "video_core/gpu.h" |
| 18 | #include "video_core/host1x/host1x.h" | 18 | #include "video_core/host1x/host1x.h" |
| @@ -203,16 +203,15 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han | |||
| 203 | 203 | ||
| 204 | } // namespace | 204 | } // namespace |
| 205 | 205 | ||
| 206 | FbshareBufferManager::FbshareBufferManager(Core::System& system, | 206 | SharedBufferManager::SharedBufferManager(Core::System& system, Container& container, |
| 207 | std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger, | 207 | std::shared_ptr<Nvidia::Module> nvdrv) |
| 208 | std::shared_ptr<Nvidia::Module> nvdrv) | 208 | : m_system(system), m_container(container), m_nvdrv(std::move(nvdrv)) {} |
| 209 | : m_system(system), m_surface_flinger(std::move(surface_flinger)), m_nvdrv(std::move(nvdrv)) {} | ||
| 210 | 209 | ||
| 211 | FbshareBufferManager::~FbshareBufferManager() = default; | 210 | SharedBufferManager::~SharedBufferManager() = default; |
| 212 | 211 | ||
| 213 | Result FbshareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, | 212 | Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, |
| 214 | u64* out_layer_handle, u64 display_id, | 213 | u64* out_layer_handle, u64 display_id, |
| 215 | Nvnflinger::LayerBlending blending) { | 214 | bool enable_blending) { |
| 216 | std::scoped_lock lk{m_guard}; | 215 | std::scoped_lock lk{m_guard}; |
| 217 | 216 | ||
| 218 | // Ensure we haven't already created. | 217 | // Ensure we haven't already created. |
| @@ -237,7 +236,7 @@ Result FbshareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou | |||
| 237 | owner_process, m_system)); | 236 | owner_process, m_system)); |
| 238 | 237 | ||
| 239 | // Create new session. | 238 | // Create new session. |
| 240 | auto [it, was_emplaced] = m_sessions.emplace(aruid, FbshareSession{}); | 239 | auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{}); |
| 241 | auto& session = it->second; | 240 | auto& session = it->second; |
| 242 | 241 | ||
| 243 | auto& container = m_nvdrv->GetContainer(); | 242 | auto& container = m_nvdrv->GetContainer(); |
| @@ -249,17 +248,18 @@ Result FbshareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou | |||
| 249 | session.nvmap_fd, map_address, SharedBufferSize)); | 248 | session.nvmap_fd, map_address, SharedBufferSize)); |
| 250 | 249 | ||
| 251 | // Create and open a layer for the display. | 250 | // Create and open a layer for the display. |
| 252 | session.layer_id = m_surface_flinger->CreateLayer(m_display_id, blending).value(); | 251 | s32 producer_binder_id; |
| 253 | m_surface_flinger->OpenLayer(session.layer_id); | 252 | R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id), |
| 253 | std::addressof(session.layer_id), display_id)); | ||
| 254 | 254 | ||
| 255 | // Get the layer. | 255 | // Configure blending. |
| 256 | VI::Layer* layer = m_surface_flinger->FindLayer(m_display_id, session.layer_id); | 256 | R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending)); |
| 257 | ASSERT(layer != nullptr); | ||
| 258 | 257 | ||
| 259 | // Get the producer and set preallocated buffers. | 258 | // Get the producer and set preallocated buffers. |
| 260 | auto& producer = layer->GetBufferQueue(); | 259 | std::shared_ptr<android::BufferQueueProducer> producer; |
| 261 | MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle); | 260 | R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id)); |
| 262 | MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle); | 261 | MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle); |
| 262 | MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle); | ||
| 263 | 263 | ||
| 264 | // Assign outputs. | 264 | // Assign outputs. |
| 265 | *out_buffer_id = m_buffer_id; | 265 | *out_buffer_id = m_buffer_id; |
| @@ -269,7 +269,7 @@ Result FbshareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou | |||
| 269 | R_SUCCEED(); | 269 | R_SUCCEED(); |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | void FbshareBufferManager::Finalize(Kernel::KProcess* owner_process) { | 272 | void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) { |
| 273 | std::scoped_lock lk{m_guard}; | 273 | std::scoped_lock lk{m_guard}; |
| 274 | 274 | ||
| 275 | if (m_buffer_id == 0) { | 275 | if (m_buffer_id == 0) { |
| @@ -285,7 +285,7 @@ void FbshareBufferManager::Finalize(Kernel::KProcess* owner_process) { | |||
| 285 | auto& session = it->second; | 285 | auto& session = it->second; |
| 286 | 286 | ||
| 287 | // Destroy the layer. | 287 | // Destroy the layer. |
| 288 | m_surface_flinger->DestroyLayer(session.layer_id); | 288 | R_ASSERT(m_container.DestroyStrayLayer(session.layer_id)); |
| 289 | 289 | ||
| 290 | // Close nvmap handle. | 290 | // Close nvmap handle. |
| 291 | FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); | 291 | FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); |
| @@ -301,11 +301,11 @@ void FbshareBufferManager::Finalize(Kernel::KProcess* owner_process) { | |||
| 301 | m_sessions.erase(it); | 301 | m_sessions.erase(it); |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | Result FbshareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, | 304 | Result SharedBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, |
| 305 | s32* out_nvmap_handle, | 305 | s32* out_nvmap_handle, |
| 306 | SharedMemoryPoolLayout* out_pool_layout, | 306 | SharedMemoryPoolLayout* out_pool_layout, |
| 307 | u64 buffer_id, | 307 | u64 buffer_id, |
| 308 | u64 applet_resource_user_id) { | 308 | u64 applet_resource_user_id) { |
| 309 | std::scoped_lock lk{m_guard}; | 309 | std::scoped_lock lk{m_guard}; |
| 310 | 310 | ||
| 311 | R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); | 311 | R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); |
| @@ -319,36 +319,20 @@ Result FbshareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, | |||
| 319 | R_SUCCEED(); | 319 | R_SUCCEED(); |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | Result FbshareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { | 322 | Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, |
| 323 | // Ensure the layer id is valid. | 323 | std::array<s32, 4>& out_slot_indexes, |
| 324 | R_UNLESS(layer_id > 0, VI::ResultNotFound); | 324 | s64* out_target_slot, u64 layer_id) { |
| 325 | |||
| 326 | // Get the layer. | ||
| 327 | VI::Layer* layer = m_surface_flinger->FindLayer(m_display_id, layer_id); | ||
| 328 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 329 | |||
| 330 | // We succeeded. | ||
| 331 | *out_layer = layer; | ||
| 332 | R_SUCCEED(); | ||
| 333 | } | ||
| 334 | |||
| 335 | Result FbshareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, | ||
| 336 | std::array<s32, 4>& out_slot_indexes, | ||
| 337 | s64* out_target_slot, u64 layer_id) { | ||
| 338 | std::scoped_lock lk{m_guard}; | 325 | std::scoped_lock lk{m_guard}; |
| 339 | 326 | ||
| 340 | // Get the layer. | ||
| 341 | VI::Layer* layer; | ||
| 342 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 343 | |||
| 344 | // Get the producer. | 327 | // Get the producer. |
| 345 | auto& producer = layer->GetBufferQueue(); | 328 | std::shared_ptr<android::BufferQueueProducer> producer; |
| 329 | R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); | ||
| 346 | 330 | ||
| 347 | // Get the next buffer from the producer. | 331 | // Get the next buffer from the producer. |
| 348 | s32 slot; | 332 | s32 slot; |
| 349 | R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, | 333 | R_UNLESS(producer->DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, |
| 350 | SharedBufferWidth, SharedBufferHeight, | 334 | SharedBufferWidth, SharedBufferHeight, |
| 351 | SharedBufferBlockLinearFormat, 0) == android::Status::NoError, | 335 | SharedBufferBlockLinearFormat, 0) == android::Status::NoError, |
| 352 | VI::ResultOperationFailed); | 336 | VI::ResultOperationFailed); |
| 353 | 337 | ||
| 354 | // Assign remaining outputs. | 338 | // Assign remaining outputs. |
| @@ -359,27 +343,24 @@ Result FbshareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, | |||
| 359 | R_SUCCEED(); | 343 | R_SUCCEED(); |
| 360 | } | 344 | } |
| 361 | 345 | ||
| 362 | Result FbshareBufferManager::PresentSharedFrameBuffer(android::Fence fence, | 346 | Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, |
| 363 | Common::Rectangle<s32> crop_region, | 347 | Common::Rectangle<s32> crop_region, |
| 364 | u32 transform, s32 swap_interval, | 348 | u32 transform, s32 swap_interval, u64 layer_id, |
| 365 | u64 layer_id, s64 slot) { | 349 | s64 slot) { |
| 366 | std::scoped_lock lk{m_guard}; | 350 | std::scoped_lock lk{m_guard}; |
| 367 | 351 | ||
| 368 | // Get the layer. | ||
| 369 | VI::Layer* layer; | ||
| 370 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 371 | |||
| 372 | // Get the producer. | 352 | // Get the producer. |
| 373 | auto& producer = layer->GetBufferQueue(); | 353 | std::shared_ptr<android::BufferQueueProducer> producer; |
| 354 | R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); | ||
| 374 | 355 | ||
| 375 | // Request to queue the buffer. | 356 | // Request to queue the buffer. |
| 376 | std::shared_ptr<android::GraphicBuffer> buffer; | 357 | std::shared_ptr<android::GraphicBuffer> buffer; |
| 377 | R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == | 358 | R_UNLESS(producer->RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == |
| 378 | android::Status::NoError, | 359 | android::Status::NoError, |
| 379 | VI::ResultOperationFailed); | 360 | VI::ResultOperationFailed); |
| 380 | 361 | ||
| 381 | ON_RESULT_FAILURE { | 362 | ON_RESULT_FAILURE { |
| 382 | producer.CancelBuffer(static_cast<s32>(slot), fence); | 363 | producer->CancelBuffer(static_cast<s32>(slot), fence); |
| 383 | }; | 364 | }; |
| 384 | 365 | ||
| 385 | // Queue the buffer to the producer. | 366 | // Queue the buffer to the producer. |
| @@ -389,7 +370,7 @@ Result FbshareBufferManager::PresentSharedFrameBuffer(android::Fence fence, | |||
| 389 | input.fence = fence; | 370 | input.fence = fence; |
| 390 | input.transform = static_cast<android::NativeWindowTransform>(transform); | 371 | input.transform = static_cast<android::NativeWindowTransform>(transform); |
| 391 | input.swap_interval = swap_interval; | 372 | input.swap_interval = swap_interval; |
| 392 | R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == | 373 | R_UNLESS(producer->QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == |
| 393 | android::Status::NoError, | 374 | android::Status::NoError, |
| 394 | VI::ResultOperationFailed); | 375 | VI::ResultOperationFailed); |
| 395 | 376 | ||
| @@ -397,25 +378,36 @@ Result FbshareBufferManager::PresentSharedFrameBuffer(android::Fence fence, | |||
| 397 | R_SUCCEED(); | 378 | R_SUCCEED(); |
| 398 | } | 379 | } |
| 399 | 380 | ||
| 400 | Result FbshareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, | 381 | Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { |
| 401 | u64 layer_id) { | ||
| 402 | std::scoped_lock lk{m_guard}; | 382 | std::scoped_lock lk{m_guard}; |
| 403 | 383 | ||
| 404 | // Get the layer. | 384 | // Get the producer. |
| 405 | VI::Layer* layer; | 385 | std::shared_ptr<android::BufferQueueProducer> producer; |
| 406 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | 386 | R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); |
| 387 | |||
| 388 | // Cancel. | ||
| 389 | producer->CancelBuffer(static_cast<s32>(slot), android::Fence::NoFence()); | ||
| 390 | |||
| 391 | // We succeeded. | ||
| 392 | R_SUCCEED(); | ||
| 393 | } | ||
| 394 | |||
| 395 | Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, | ||
| 396 | u64 layer_id) { | ||
| 397 | std::scoped_lock lk{m_guard}; | ||
| 407 | 398 | ||
| 408 | // Get the producer. | 399 | // Get the producer. |
| 409 | auto& producer = layer->GetBufferQueue(); | 400 | std::shared_ptr<android::BufferQueueProducer> producer; |
| 401 | R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id)); | ||
| 410 | 402 | ||
| 411 | // Set the event. | 403 | // Set the event. |
| 412 | *out_event = std::addressof(producer.GetNativeHandle()); | 404 | *out_event = producer->GetNativeHandle({}); |
| 413 | 405 | ||
| 414 | // We succeeded. | 406 | // We succeeded. |
| 415 | R_SUCCEED(); | 407 | R_SUCCEED(); |
| 416 | } | 408 | } |
| 417 | 409 | ||
| 418 | Result FbshareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { | 410 | Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { |
| 419 | std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer()); | 411 | std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer()); |
| 420 | Common::ScratchBuffer<u32> scratch; | 412 | Common::ScratchBuffer<u32> scratch; |
| 421 | 413 | ||
diff --git a/src/core/hle/service/vi/fbshare_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h index b9e99e61f..7c9bb7199 100644 --- a/src/core/hle/service/vi/fbshare_buffer_manager.h +++ b/src/core/hle/service/vi/shared_buffer_manager.h | |||
| @@ -8,16 +8,28 @@ | |||
| 8 | #include "common/math_util.h" | 8 | #include "common/math_util.h" |
| 9 | #include "core/hle/service/nvdrv/core/container.h" | 9 | #include "core/hle/service/nvdrv/core/container.h" |
| 10 | #include "core/hle/service/nvdrv/nvdata.h" | 10 | #include "core/hle/service/nvdrv/nvdata.h" |
| 11 | #include "core/hle/service/nvnflinger/hwc_layer.h" | ||
| 12 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 11 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 13 | #include "core/hle/service/nvnflinger/ui/fence.h" | 12 | #include "core/hle/service/nvnflinger/ui/fence.h" |
| 14 | 13 | ||
| 15 | namespace Kernel { | 14 | namespace Kernel { |
| 16 | class KPageGroup; | 15 | class KPageGroup; |
| 16 | class KReadableEvent; | ||
| 17 | } // namespace Kernel | ||
| 18 | |||
| 19 | namespace Service::android { | ||
| 20 | class BufferQueueProducer; | ||
| 21 | } | ||
| 22 | |||
| 23 | namespace Service::Nvidia { | ||
| 24 | class Module; | ||
| 17 | } | 25 | } |
| 18 | 26 | ||
| 27 | union Result; | ||
| 28 | |||
| 19 | namespace Service::VI { | 29 | namespace Service::VI { |
| 20 | 30 | ||
| 31 | class Container; | ||
| 32 | |||
| 21 | struct SharedMemorySlot { | 33 | struct SharedMemorySlot { |
| 22 | u64 buffer_offset; | 34 | u64 buffer_offset; |
| 23 | u64 size; | 35 | u64 size; |
| @@ -32,18 +44,17 @@ struct SharedMemoryPoolLayout { | |||
| 32 | }; | 44 | }; |
| 33 | static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); | 45 | static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); |
| 34 | 46 | ||
| 35 | struct FbshareSession; | 47 | struct SharedBufferSession; |
| 36 | 48 | ||
| 37 | class FbshareBufferManager final { | 49 | class SharedBufferManager final { |
| 38 | public: | 50 | public: |
| 39 | explicit FbshareBufferManager(Core::System& system, | 51 | explicit SharedBufferManager(Core::System& system, Container& container, |
| 40 | std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger, | 52 | std::shared_ptr<Nvidia::Module> nvdrv); |
| 41 | std::shared_ptr<Nvidia::Module> nvdrv); | 53 | ~SharedBufferManager(); |
| 42 | ~FbshareBufferManager(); | ||
| 43 | 54 | ||
| 44 | Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, | 55 | Result CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, |
| 45 | u64 display_id, Nvnflinger::LayerBlending blending); | 56 | u64 display_id, bool enable_blending); |
| 46 | void Finalize(Kernel::KProcess* owner_process); | 57 | void DestroySession(Kernel::KProcess* owner_process); |
| 47 | 58 | ||
| 48 | Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, | 59 | Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, |
| 49 | SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, | 60 | SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, |
| @@ -52,28 +63,26 @@ public: | |||
| 52 | s64* out_target_slot, u64 layer_id); | 63 | s64* out_target_slot, u64 layer_id); |
| 53 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | 64 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, |
| 54 | u32 transform, s32 swap_interval, u64 layer_id, s64 slot); | 65 | u32 transform, s32 swap_interval, u64 layer_id, s64 slot); |
| 66 | Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); | ||
| 55 | Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); | 67 | Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); |
| 56 | 68 | ||
| 57 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); | 69 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); |
| 58 | 70 | ||
| 59 | private: | 71 | private: |
| 60 | Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); | ||
| 61 | |||
| 62 | private: | ||
| 63 | u64 m_next_buffer_id = 1; | 72 | u64 m_next_buffer_id = 1; |
| 64 | u64 m_display_id = 0; | 73 | u64 m_display_id = 0; |
| 65 | u64 m_buffer_id = 0; | 74 | u64 m_buffer_id = 0; |
| 66 | SharedMemoryPoolLayout m_pool_layout = {}; | 75 | SharedMemoryPoolLayout m_pool_layout = {}; |
| 67 | std::map<u64, FbshareSession> m_sessions; | 76 | std::map<u64, SharedBufferSession> m_sessions; |
| 68 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; | 77 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; |
| 69 | 78 | ||
| 70 | std::mutex m_guard; | 79 | std::mutex m_guard; |
| 71 | Core::System& m_system; | 80 | Core::System& m_system; |
| 72 | const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger; | 81 | Container& m_container; |
| 73 | const std::shared_ptr<Nvidia::Module> m_nvdrv; | 82 | const std::shared_ptr<Nvidia::Module> m_nvdrv; |
| 74 | }; | 83 | }; |
| 75 | 84 | ||
| 76 | struct FbshareSession { | 85 | struct SharedBufferSession { |
| 77 | Nvidia::DeviceFD nvmap_fd = {}; | 86 | Nvidia::DeviceFD nvmap_fd = {}; |
| 78 | Nvidia::NvCore::SessionId session_id = {}; | 87 | Nvidia::NvCore::SessionId session_id = {}; |
| 79 | u64 layer_id = {}; | 88 | u64 layer_id = {}; |
diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp index 4670cf4cc..9e28fdda3 100644 --- a/src/core/hle/service/vi/system_display_service.cpp +++ b/src/core/hle/service/vi/system_display_service.cpp | |||
| @@ -3,17 +3,15 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/settings.h" | 4 | #include "common/settings.h" |
| 5 | #include "core/hle/service/cmif_serialization.h" | 5 | #include "core/hle/service/cmif_serialization.h" |
| 6 | #include "core/hle/service/vi/container.h" | ||
| 6 | #include "core/hle/service/vi/system_display_service.h" | 7 | #include "core/hle/service/vi/system_display_service.h" |
| 7 | #include "core/hle/service/vi/vi_types.h" | 8 | #include "core/hle/service/vi/vi_types.h" |
| 8 | 9 | ||
| 9 | namespace Service::VI { | 10 | namespace Service::VI { |
| 10 | 11 | ||
| 11 | ISystemDisplayService::ISystemDisplayService( | 12 | ISystemDisplayService::ISystemDisplayService(Core::System& system_, |
| 12 | Core::System& system_, std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger, | 13 | std::shared_ptr<Container> container) |
| 13 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager) | 14 | : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} { |
| 14 | : ServiceFramework{system_, "ISystemDisplayService"}, | ||
| 15 | m_surface_flinger{std::move(surface_flinger)}, | ||
| 16 | m_shared_buffer_manager{std::move(shared_buffer_manager)} { | ||
| 17 | // clang-format off | 15 | // clang-format off |
| 18 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 19 | {1200, nullptr, "GetZOrderCountMin"}, | 17 | {1200, nullptr, "GetZOrderCountMin"}, |
| @@ -61,7 +59,7 @@ ISystemDisplayService::ISystemDisplayService( | |||
| 61 | {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, | 59 | {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, |
| 62 | {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, | 60 | {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, |
| 63 | {8257, nullptr, "FillSharedFrameBufferColor"}, | 61 | {8257, nullptr, "FillSharedFrameBufferColor"}, |
| 64 | {8258, nullptr, "CancelSharedFrameBuffer"}, | 62 | {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"}, |
| 65 | {9000, nullptr, "GetDp2hdmiController"}, | 63 | {9000, nullptr, "GetDp2hdmiController"}, |
| 66 | }; | 64 | }; |
| 67 | // clang-format on | 65 | // clang-format on |
| @@ -106,7 +104,7 @@ Result ISystemDisplayService::GetSharedBufferMemoryHandleId( | |||
| 106 | ClientAppletResourceUserId aruid) { | 104 | ClientAppletResourceUserId aruid) { |
| 107 | LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); | 105 | LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); |
| 108 | 106 | ||
| 109 | R_RETURN(m_shared_buffer_manager->GetSharedBufferMemoryHandleId( | 107 | R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId( |
| 110 | out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); | 108 | out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); |
| 111 | } | 109 | } |
| 112 | 110 | ||
| @@ -124,8 +122,8 @@ Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_f | |||
| 124 | Out<std::array<s32, 4>> out_slots, | 122 | Out<std::array<s32, 4>> out_slots, |
| 125 | Out<s64> out_target_slot, u64 layer_id) { | 123 | Out<s64> out_target_slot, u64 layer_id) { |
| 126 | LOG_DEBUG(Service_VI, "called"); | 124 | LOG_DEBUG(Service_VI, "called"); |
| 127 | R_RETURN(m_shared_buffer_manager->AcquireSharedFrameBuffer(out_fence, *out_slots, | 125 | R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer( |
| 128 | out_target_slot, layer_id)); | 126 | out_fence, *out_slots, out_target_slot, layer_id)); |
| 129 | } | 127 | } |
| 130 | 128 | ||
| 131 | Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, | 129 | Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, |
| @@ -133,14 +131,20 @@ Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, | |||
| 133 | u32 window_transform, s32 swap_interval, | 131 | u32 window_transform, s32 swap_interval, |
| 134 | u64 layer_id, s64 surface_id) { | 132 | u64 layer_id, s64 surface_id) { |
| 135 | LOG_DEBUG(Service_VI, "called"); | 133 | LOG_DEBUG(Service_VI, "called"); |
| 136 | R_RETURN(m_shared_buffer_manager->PresentSharedFrameBuffer( | 134 | R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer( |
| 137 | fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); | 135 | fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); |
| 138 | } | 136 | } |
| 139 | 137 | ||
| 140 | Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( | 138 | Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( |
| 141 | OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { | 139 | OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { |
| 142 | LOG_DEBUG(Service_VI, "called"); | 140 | LOG_DEBUG(Service_VI, "called"); |
| 143 | R_RETURN(m_shared_buffer_manager->GetSharedFrameBufferAcquirableEvent(out_event, layer_id)); | 141 | R_RETURN(m_container->GetSharedBufferManager()->GetSharedFrameBufferAcquirableEvent(out_event, |
| 142 | layer_id)); | ||
| 143 | } | ||
| 144 | |||
| 145 | Result ISystemDisplayService::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { | ||
| 146 | LOG_DEBUG(Service_VI, "called"); | ||
| 147 | R_RETURN(m_container->GetSharedBufferManager()->CancelSharedFrameBuffer(layer_id, slot)); | ||
| 144 | } | 148 | } |
| 145 | 149 | ||
| 146 | } // namespace Service::VI | 150 | } // 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 b84c9725f..63c1a4dc5 100644 --- a/src/core/hle/service/vi/system_display_service.h +++ b/src/core/hle/service/vi/system_display_service.h | |||
| @@ -5,21 +5,15 @@ | |||
| 5 | #include "core/hle/service/cmif_types.h" | 5 | #include "core/hle/service/cmif_types.h" |
| 6 | #include "core/hle/service/nvnflinger/ui/fence.h" | 6 | #include "core/hle/service/nvnflinger/ui/fence.h" |
| 7 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "core/hle/service/vi/fbshare_buffer_manager.h" | 8 | #include "core/hle/service/vi/shared_buffer_manager.h" |
| 9 | |||
| 10 | namespace Service::Nvnflinger { | ||
| 11 | class Nvnflinger; | ||
| 12 | } // namespace Service::Nvnflinger | ||
| 13 | 9 | ||
| 14 | namespace Service::VI { | 10 | namespace Service::VI { |
| 15 | 11 | ||
| 16 | class FbshareBufferManager; | 12 | class Container; |
| 17 | 13 | ||
| 18 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | 14 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { |
| 19 | public: | 15 | public: |
| 20 | explicit ISystemDisplayService(Core::System& system_, | 16 | explicit ISystemDisplayService(Core::System& system_, std::shared_ptr<Container> container); |
| 21 | std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger, | ||
| 22 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager); | ||
| 23 | ~ISystemDisplayService() override; | 17 | ~ISystemDisplayService() override; |
| 24 | 18 | ||
| 25 | private: | 19 | private: |
| @@ -42,10 +36,10 @@ private: | |||
| 42 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | 36 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, |
| 43 | u32 window_transform, s32 swap_interval, u64 layer_id, | 37 | u32 window_transform, s32 swap_interval, u64 layer_id, |
| 44 | s64 surface_id); | 38 | s64 surface_id); |
| 39 | Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); | ||
| 45 | 40 | ||
| 46 | private: | 41 | private: |
| 47 | const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger; | 42 | const std::shared_ptr<Container> m_container; |
| 48 | const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager; | ||
| 49 | }; | 43 | }; |
| 50 | 44 | ||
| 51 | } // namespace Service::VI | 45 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp index 2254ed111..3489727d8 100644 --- a/src/core/hle/service/vi/system_root_service.cpp +++ b/src/core/hle/service/vi/system_root_service.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include "core/hle/service/cmif_serialization.h" | 4 | #include "core/hle/service/cmif_serialization.h" |
| 5 | #include "core/hle/service/vi/application_display_service.h" | 5 | #include "core/hle/service/vi/application_display_service.h" |
| 6 | #include "core/hle/service/vi/container.h" | ||
| 6 | #include "core/hle/service/vi/service_creator.h" | 7 | #include "core/hle/service/vi/service_creator.h" |
| 7 | #include "core/hle/service/vi/system_root_service.h" | 8 | #include "core/hle/service/vi/system_root_service.h" |
| 8 | #include "core/hle/service/vi/vi.h" | 9 | #include "core/hle/service/vi/vi.h" |
| @@ -10,11 +11,8 @@ | |||
| 10 | 11 | ||
| 11 | namespace Service::VI { | 12 | namespace Service::VI { |
| 12 | 13 | ||
| 13 | ISystemRootService::ISystemRootService(Core::System& system_, | 14 | ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr<Container> container) |
| 14 | std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | 15 | : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} { |
| 15 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager) | ||
| 16 | : ServiceFramework{system_, "vi:s"}, m_binder_service{std::move(binder_service)}, | ||
| 17 | m_shared_buffer_manager{std::move(shared_buffer_manager)} { | ||
| 18 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 19 | {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, | 17 | {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, |
| 20 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 18 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
| @@ -27,8 +25,8 @@ ISystemRootService::~ISystemRootService() = default; | |||
| 27 | Result ISystemRootService::GetDisplayService( | 25 | Result ISystemRootService::GetDisplayService( |
| 28 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | 26 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { |
| 29 | LOG_DEBUG(Service_VI, "called"); | 27 | LOG_DEBUG(Service_VI, "called"); |
| 30 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service, | 28 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, |
| 31 | m_shared_buffer_manager, Permission::System, policy)); | 29 | Permission::System, policy)); |
| 32 | } | 30 | } |
| 33 | 31 | ||
| 34 | } // namespace Service::VI | 32 | } // 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 16c997422..9d5aa53d3 100644 --- a/src/core/hle/service/vi/system_root_service.h +++ b/src/core/hle/service/vi/system_root_service.h | |||
| @@ -10,21 +10,15 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::Nvnflinger { | ||
| 14 | class IHOSBinderDriver; | ||
| 15 | } // namespace Service::Nvnflinger | ||
| 16 | |||
| 17 | namespace Service::VI { | 13 | namespace Service::VI { |
| 18 | 14 | ||
| 19 | class FbshareBufferManager; | 15 | class Container; |
| 20 | class IApplicationDisplayService; | 16 | class IApplicationDisplayService; |
| 21 | enum class Policy : u32; | 17 | enum class Policy : u32; |
| 22 | 18 | ||
| 23 | class ISystemRootService final : public ServiceFramework<ISystemRootService> { | 19 | class ISystemRootService final : public ServiceFramework<ISystemRootService> { |
| 24 | public: | 20 | public: |
| 25 | explicit ISystemRootService(Core::System& system_, | 21 | explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, | ||
| 27 | std::shared_ptr<FbshareBufferManager> shared_buffer_manager); | ||
| 28 | ~ISystemRootService() override; | 22 | ~ISystemRootService() override; |
| 29 | 23 | ||
| 30 | private: | 24 | private: |
| @@ -32,8 +26,7 @@ private: | |||
| 32 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | 26 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, |
| 33 | Policy policy); | 27 | Policy policy); |
| 34 | 28 | ||
| 35 | const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; | 29 | const std::shared_ptr<Container> m_container; |
| 36 | const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager; | ||
| 37 | }; | 30 | }; |
| 38 | 31 | ||
| 39 | } // namespace Service::VI | 32 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index f361b9f4c..b388efaf6 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -2,38 +2,29 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/core.h" | 4 | #include "core/core.h" |
| 5 | #include "core/hle/service/nvdrv/nvdrv_interface.h" | ||
| 6 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" | ||
| 7 | #include "core/hle/service/server_manager.h" | 5 | #include "core/hle/service/server_manager.h" |
| 8 | #include "core/hle/service/sm/sm.h" | ||
| 9 | #include "core/hle/service/vi/application_display_service.h" | ||
| 10 | #include "core/hle/service/vi/application_root_service.h" | 6 | #include "core/hle/service/vi/application_root_service.h" |
| 11 | #include "core/hle/service/vi/fbshare_buffer_manager.h" | 7 | #include "core/hle/service/vi/container.h" |
| 12 | #include "core/hle/service/vi/manager_root_service.h" | 8 | #include "core/hle/service/vi/manager_root_service.h" |
| 13 | #include "core/hle/service/vi/system_root_service.h" | 9 | #include "core/hle/service/vi/system_root_service.h" |
| 14 | #include "core/hle/service/vi/vi.h" | 10 | #include "core/hle/service/vi/vi.h" |
| 15 | 11 | ||
| 16 | namespace Service::VI { | 12 | namespace Service::VI { |
| 17 | 13 | ||
| 18 | void LoopProcess(Core::System& system) { | 14 | void LoopProcess(Core::System& system, std::stop_token token) { |
| 19 | const auto binder_service = | 15 | const auto container = std::make_shared<Container>(system); |
| 20 | system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true); | ||
| 21 | const auto nvdrv = | ||
| 22 | system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); | ||
| 23 | const auto shared_buffer_manager = | ||
| 24 | std::make_shared<FbshareBufferManager>(system, binder_service->GetSurfaceFlinger(), nvdrv); | ||
| 25 | 16 | ||
| 26 | auto server_manager = std::make_unique<ServerManager>(system); | 17 | auto server_manager = std::make_unique<ServerManager>(system); |
| 27 | 18 | ||
| 19 | server_manager->RegisterNamedService("vi:m", | ||
| 20 | std::make_shared<IManagerRootService>(system, container)); | ||
| 21 | server_manager->RegisterNamedService("vi:s", | ||
| 22 | std::make_shared<ISystemRootService>(system, container)); | ||
| 28 | server_manager->RegisterNamedService( | 23 | server_manager->RegisterNamedService( |
| 29 | "vi:m", | 24 | "vi:u", std::make_shared<IApplicationRootService>(system, container)); |
| 30 | std::make_shared<IManagerRootService>(system, binder_service, shared_buffer_manager)); | 25 | |
| 31 | server_manager->RegisterNamedService( | 26 | std::stop_callback cb(token, [=] { container->OnTerminate(); }); |
| 32 | "vi:s", | 27 | |
| 33 | std::make_shared<ISystemRootService>(system, binder_service, shared_buffer_manager)); | ||
| 34 | server_manager->RegisterNamedService( | ||
| 35 | "vi:u", | ||
| 36 | std::make_shared<IApplicationRootService>(system, binder_service, shared_buffer_manager)); | ||
| 37 | ServerManager::RunServer(std::move(server_manager)); | 28 | ServerManager::RunServer(std::move(server_manager)); |
| 38 | } | 29 | } |
| 39 | 30 | ||
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 0c3dc175d..7c1f350d8 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -3,12 +3,14 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/polyfill_thread.h" | ||
| 7 | |||
| 6 | namespace Core { | 8 | namespace Core { |
| 7 | class System; | 9 | class System; |
| 8 | } | 10 | } |
| 9 | 11 | ||
| 10 | namespace Service::VI { | 12 | namespace Service::VI { |
| 11 | 13 | ||
| 12 | void LoopProcess(Core::System& system); | 14 | void LoopProcess(Core::System& system, std::stop_token token); |
| 13 | 15 | ||
| 14 | } // namespace Service::VI | 16 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h index 91e4b380c..7f2c70aef 100644 --- a/src/core/hle/service/vi/vi_types.h +++ b/src/core/hle/service/vi/vi_types.h | |||
| @@ -68,7 +68,7 @@ static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); | |||
| 68 | 68 | ||
| 69 | class NativeWindow final { | 69 | class NativeWindow final { |
| 70 | public: | 70 | public: |
| 71 | constexpr explicit NativeWindow(u32 id_) : id{id_} {} | 71 | constexpr explicit NativeWindow(s32 id_) : id{static_cast<u64>(id_)} {} |
| 72 | constexpr explicit NativeWindow(const NativeWindow& other) = default; | 72 | constexpr explicit NativeWindow(const NativeWindow& other) = default; |
| 73 | 73 | ||
| 74 | private: | 74 | private: |
diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp new file mode 100644 index 000000000..bdc4dfa96 --- /dev/null +++ b/src/core/hle/service/vi/vsync_manager.cpp | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/os/event.h" | ||
| 5 | #include "core/hle/service/vi/vsync_manager.h" | ||
| 6 | |||
| 7 | namespace Service::VI { | ||
| 8 | |||
| 9 | VsyncManager::VsyncManager() = default; | ||
| 10 | VsyncManager::~VsyncManager() = default; | ||
| 11 | |||
| 12 | void VsyncManager::SignalVsync() { | ||
| 13 | for (auto* event : m_vsync_events) { | ||
| 14 | event->Signal(); | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | void VsyncManager::LinkVsyncEvent(Event* event) { | ||
| 19 | m_vsync_events.insert(event); | ||
| 20 | } | ||
| 21 | |||
| 22 | void VsyncManager::UnlinkVsyncEvent(Event* event) { | ||
| 23 | m_vsync_events.erase(event); | ||
| 24 | } | ||
| 25 | |||
| 26 | } // namespace Service::VI | ||
diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h new file mode 100644 index 000000000..5d45bb5ee --- /dev/null +++ b/src/core/hle/service/vi/vsync_manager.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <set> | ||
| 7 | |||
| 8 | namespace Service { | ||
| 9 | class Event; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Service::VI { | ||
| 13 | |||
| 14 | class DisplayList; | ||
| 15 | |||
| 16 | class VsyncManager { | ||
| 17 | public: | ||
| 18 | explicit VsyncManager(); | ||
| 19 | ~VsyncManager(); | ||
| 20 | |||
| 21 | void SignalVsync(); | ||
| 22 | void LinkVsyncEvent(Event* event); | ||
| 23 | void UnlinkVsyncEvent(Event* event); | ||
| 24 | |||
| 25 | private: | ||
| 26 | std::set<Event*> m_vsync_events; | ||
| 27 | }; | ||
| 28 | |||
| 29 | } // namespace Service::VI | ||