diff options
87 files changed, 2105 insertions, 1824 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c2bdc0b1a..fa5c4de37 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -423,12 +423,12 @@ add_library(core STATIC | |||
| 423 | hle/service/am/applet_manager.h | 423 | hle/service/am/applet_manager.h |
| 424 | hle/service/am/applet_message_queue.cpp | 424 | hle/service/am/applet_message_queue.cpp |
| 425 | hle/service/am/applet_message_queue.h | 425 | hle/service/am/applet_message_queue.h |
| 426 | hle/service/am/display_layer_manager.cpp | ||
| 427 | hle/service/am/display_layer_manager.h | ||
| 426 | hle/service/am/hid_registration.cpp | 428 | hle/service/am/hid_registration.cpp |
| 427 | hle/service/am/hid_registration.h | 429 | hle/service/am/hid_registration.h |
| 428 | hle/service/am/library_applet_storage.cpp | 430 | hle/service/am/library_applet_storage.cpp |
| 429 | hle/service/am/library_applet_storage.h | 431 | hle/service/am/library_applet_storage.h |
| 430 | hle/service/am/managed_layer_holder.cpp | ||
| 431 | hle/service/am/managed_layer_holder.h | ||
| 432 | hle/service/am/process.cpp | 432 | hle/service/am/process.cpp |
| 433 | hle/service/am/process.h | 433 | hle/service/am/process.h |
| 434 | hle/service/am/service/all_system_applet_proxies_service.cpp | 434 | hle/service/am/service/all_system_applet_proxies_service.cpp |
| @@ -481,8 +481,6 @@ add_library(core STATIC | |||
| 481 | hle/service/am/service/system_applet_proxy.h | 481 | hle/service/am/service/system_applet_proxy.h |
| 482 | hle/service/am/service/window_controller.cpp | 482 | hle/service/am/service/window_controller.cpp |
| 483 | hle/service/am/service/window_controller.h | 483 | hle/service/am/service/window_controller.h |
| 484 | hle/service/am/system_buffer_manager.cpp | ||
| 485 | hle/service/am/system_buffer_manager.h | ||
| 486 | hle/service/aoc/aoc_u.cpp | 484 | hle/service/aoc/aoc_u.cpp |
| 487 | hle/service/aoc/aoc_u.h | 485 | hle/service/aoc/aoc_u.h |
| 488 | hle/service/apm/apm.cpp | 486 | hle/service/apm/apm.cpp |
| @@ -833,12 +831,12 @@ add_library(core STATIC | |||
| 833 | hle/service/nvnflinger/consumer_base.cpp | 831 | hle/service/nvnflinger/consumer_base.cpp |
| 834 | hle/service/nvnflinger/consumer_base.h | 832 | hle/service/nvnflinger/consumer_base.h |
| 835 | hle/service/nvnflinger/consumer_listener.h | 833 | hle/service/nvnflinger/consumer_listener.h |
| 836 | hle/service/nvnflinger/fb_share_buffer_manager.cpp | ||
| 837 | hle/service/nvnflinger/fb_share_buffer_manager.h | ||
| 838 | hle/service/nvnflinger/graphic_buffer_producer.cpp | 834 | hle/service/nvnflinger/graphic_buffer_producer.cpp |
| 839 | hle/service/nvnflinger/graphic_buffer_producer.h | 835 | hle/service/nvnflinger/graphic_buffer_producer.h |
| 840 | hle/service/nvnflinger/hos_binder_driver_server.cpp | 836 | hle/service/nvnflinger/hos_binder_driver_server.cpp |
| 841 | hle/service/nvnflinger/hos_binder_driver_server.h | 837 | hle/service/nvnflinger/hos_binder_driver_server.h |
| 838 | hle/service/nvnflinger/hos_binder_driver.cpp | ||
| 839 | hle/service/nvnflinger/hos_binder_driver.h | ||
| 842 | hle/service/nvnflinger/hardware_composer.cpp | 840 | hle/service/nvnflinger/hardware_composer.cpp |
| 843 | hle/service/nvnflinger/hardware_composer.h | 841 | hle/service/nvnflinger/hardware_composer.h |
| 844 | hle/service/nvnflinger/hwc_layer.h | 842 | hle/service/nvnflinger/hwc_layer.h |
| @@ -848,6 +846,8 @@ add_library(core STATIC | |||
| 848 | hle/service/nvnflinger/pixel_format.h | 846 | hle/service/nvnflinger/pixel_format.h |
| 849 | hle/service/nvnflinger/producer_listener.h | 847 | hle/service/nvnflinger/producer_listener.h |
| 850 | hle/service/nvnflinger/status.h | 848 | hle/service/nvnflinger/status.h |
| 849 | hle/service/nvnflinger/surface_flinger.cpp | ||
| 850 | hle/service/nvnflinger/surface_flinger.h | ||
| 851 | hle/service/nvnflinger/ui/fence.h | 851 | hle/service/nvnflinger/ui/fence.h |
| 852 | hle/service/nvnflinger/ui/graphic_buffer.cpp | 852 | hle/service/nvnflinger/ui/graphic_buffer.cpp |
| 853 | hle/service/nvnflinger/ui/graphic_buffer.h | 853 | hle/service/nvnflinger/ui/graphic_buffer.h |
| @@ -941,6 +941,8 @@ add_library(core STATIC | |||
| 941 | hle/service/server_manager.h | 941 | hle/service/server_manager.h |
| 942 | hle/service/service.cpp | 942 | hle/service/service.cpp |
| 943 | hle/service/service.h | 943 | hle/service/service.h |
| 944 | hle/service/services.cpp | ||
| 945 | hle/service/services.h | ||
| 944 | hle/service/set/setting_formats/appln_settings.cpp | 946 | hle/service/set/setting_formats/appln_settings.cpp |
| 945 | hle/service/set/setting_formats/appln_settings.h | 947 | hle/service/set/setting_formats/appln_settings.h |
| 946 | hle/service/set/setting_formats/device_settings.cpp | 948 | hle/service/set/setting_formats/device_settings.cpp |
| @@ -988,22 +990,26 @@ add_library(core STATIC | |||
| 988 | hle/service/ssl/ssl_backend.h | 990 | hle/service/ssl/ssl_backend.h |
| 989 | hle/service/usb/usb.cpp | 991 | hle/service/usb/usb.cpp |
| 990 | hle/service/usb/usb.h | 992 | hle/service/usb/usb.h |
| 991 | hle/service/vi/display/vi_display.cpp | ||
| 992 | hle/service/vi/display/vi_display.h | ||
| 993 | hle/service/vi/layer/vi_layer.cpp | ||
| 994 | hle/service/vi/layer/vi_layer.h | ||
| 995 | hle/service/vi/application_display_service.cpp | 993 | hle/service/vi/application_display_service.cpp |
| 996 | hle/service/vi/application_display_service.h | 994 | hle/service/vi/application_display_service.h |
| 997 | hle/service/vi/application_root_service.cpp | 995 | hle/service/vi/application_root_service.cpp |
| 998 | hle/service/vi/application_root_service.h | 996 | hle/service/vi/application_root_service.h |
| 999 | hle/service/vi/hos_binder_driver.cpp | 997 | hle/service/vi/conductor.cpp |
| 1000 | hle/service/vi/hos_binder_driver.h | 998 | hle/service/vi/conductor.h |
| 999 | hle/service/vi/container.cpp | ||
| 1000 | hle/service/vi/container.h | ||
| 1001 | hle/service/vi/display_list.h | ||
| 1002 | hle/service/vi/display.h | ||
| 1003 | hle/service/vi/layer_list.h | ||
| 1004 | hle/service/vi/layer.h | ||
| 1001 | hle/service/vi/manager_display_service.cpp | 1005 | hle/service/vi/manager_display_service.cpp |
| 1002 | hle/service/vi/manager_display_service.h | 1006 | hle/service/vi/manager_display_service.h |
| 1003 | hle/service/vi/manager_root_service.cpp | 1007 | hle/service/vi/manager_root_service.cpp |
| 1004 | hle/service/vi/manager_root_service.h | 1008 | hle/service/vi/manager_root_service.h |
| 1005 | hle/service/vi/service_creator.cpp | 1009 | hle/service/vi/service_creator.cpp |
| 1006 | hle/service/vi/service_creator.h | 1010 | hle/service/vi/service_creator.h |
| 1011 | hle/service/vi/shared_buffer_manager.cpp | ||
| 1012 | hle/service/vi/shared_buffer_manager.h | ||
| 1007 | hle/service/vi/system_display_service.cpp | 1013 | hle/service/vi/system_display_service.cpp |
| 1008 | hle/service/vi/system_display_service.h | 1014 | hle/service/vi/system_display_service.h |
| 1009 | hle/service/vi/system_root_service.cpp | 1015 | hle/service/vi/system_root_service.cpp |
| @@ -1012,6 +1018,8 @@ add_library(core STATIC | |||
| 1012 | hle/service/vi/vi_types.h | 1018 | hle/service/vi/vi_types.h |
| 1013 | hle/service/vi/vi.cpp | 1019 | hle/service/vi/vi.cpp |
| 1014 | hle/service/vi/vi.h | 1020 | hle/service/vi/vi.h |
| 1021 | hle/service/vi/vsync_manager.cpp | ||
| 1022 | hle/service/vi/vsync_manager.h | ||
| 1015 | internal_network/network.cpp | 1023 | internal_network/network.cpp |
| 1016 | internal_network/network.h | 1024 | internal_network/network.h |
| 1017 | internal_network/network_interface.cpp | 1025 | internal_network/network_interface.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index bd5f11d53..9e8936728 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include "core/hle/service/psc/time/system_clock.h" | 47 | #include "core/hle/service/psc/time/system_clock.h" |
| 48 | #include "core/hle/service/psc/time/time_zone_service.h" | 48 | #include "core/hle/service/psc/time/time_zone_service.h" |
| 49 | #include "core/hle/service/service.h" | 49 | #include "core/hle/service/service.h" |
| 50 | #include "core/hle/service/services.h" | ||
| 50 | #include "core/hle/service/set/system_settings_server.h" | 51 | #include "core/hle/service/set/system_settings_server.h" |
| 51 | #include "core/hle/service/sm/sm.h" | 52 | #include "core/hle/service/sm/sm.h" |
| 52 | #include "core/internal_network/network.h" | 53 | #include "core/internal_network/network.h" |
| @@ -310,7 +311,8 @@ struct System::Impl { | |||
| 310 | audio_core = std::make_unique<AudioCore::AudioCore>(system); | 311 | audio_core = std::make_unique<AudioCore::AudioCore>(system); |
| 311 | 312 | ||
| 312 | service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); | 313 | service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); |
| 313 | services = std::make_unique<Service::Services>(service_manager, system); | 314 | services = |
| 315 | std::make_unique<Service::Services>(service_manager, system, stop_event.get_token()); | ||
| 314 | 316 | ||
| 315 | is_powered_on = true; | 317 | is_powered_on = true; |
| 316 | exit_locked = false; | 318 | exit_locked = false; |
| @@ -458,11 +460,10 @@ struct System::Impl { | |||
| 458 | gpu_core->NotifyShutdown(); | 460 | gpu_core->NotifyShutdown(); |
| 459 | } | 461 | } |
| 460 | 462 | ||
| 463 | stop_event.request_stop(); | ||
| 464 | core_timing.SyncPause(false); | ||
| 461 | Network::CancelPendingSocketOperations(); | 465 | Network::CancelPendingSocketOperations(); |
| 462 | kernel.SuspendEmulation(true); | 466 | kernel.SuspendEmulation(true); |
| 463 | if (services) { | ||
| 464 | services->KillNVNFlinger(); | ||
| 465 | } | ||
| 466 | kernel.CloseServices(); | 467 | kernel.CloseServices(); |
| 467 | kernel.ShutdownCores(); | 468 | kernel.ShutdownCores(); |
| 468 | applet_manager.Reset(); | 469 | applet_manager.Reset(); |
| @@ -480,6 +481,7 @@ struct System::Impl { | |||
| 480 | cpu_manager.Shutdown(); | 481 | cpu_manager.Shutdown(); |
| 481 | debugger.reset(); | 482 | debugger.reset(); |
| 482 | kernel.Shutdown(); | 483 | kernel.Shutdown(); |
| 484 | stop_event = {}; | ||
| 483 | Network::RestartSocketOperations(); | 485 | Network::RestartSocketOperations(); |
| 484 | 486 | ||
| 485 | if (auto room_member = room_network.GetRoomMember().lock()) { | 487 | if (auto room_member = room_network.GetRoomMember().lock()) { |
| @@ -615,6 +617,7 @@ struct System::Impl { | |||
| 615 | 617 | ||
| 616 | ExecuteProgramCallback execute_program_callback; | 618 | ExecuteProgramCallback execute_program_callback; |
| 617 | ExitCallback exit_callback; | 619 | ExitCallback exit_callback; |
| 620 | std::stop_source stop_event; | ||
| 618 | 621 | ||
| 619 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | 622 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; |
| 620 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; | 623 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9dc710ba9..8c4e14f08 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -8,13 +8,13 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::AM { | 9 | namespace Service::AM { |
| 10 | 10 | ||
| 11 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | 11 | void LoopProcess(Core::System& system) { |
| 12 | auto server_manager = std::make_unique<ServerManager>(system); | 12 | auto server_manager = std::make_unique<ServerManager>(system); |
| 13 | 13 | ||
| 14 | server_manager->RegisterNamedService( | 14 | server_manager->RegisterNamedService("appletAE", |
| 15 | "appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger)); | 15 | std::make_shared<IAllSystemAppletProxiesService>(system)); |
| 16 | server_manager->RegisterNamedService( | 16 | server_manager->RegisterNamedService("appletOE", |
| 17 | "appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger)); | 17 | std::make_shared<IApplicationProxyService>(system)); |
| 18 | ServerManager::RunServer(std::move(server_manager)); | 18 | ServerManager::RunServer(std::move(server_manager)); |
| 19 | } | 19 | } |
| 20 | 20 | ||
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 4a2d797bd..1afe253ae 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -7,12 +7,8 @@ namespace Core { | |||
| 7 | class System; | 7 | class System; |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | namespace Service::Nvnflinger { | ||
| 11 | class Nvnflinger; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Service::AM { | 10 | namespace Service::AM { |
| 15 | 11 | ||
| 16 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); | 12 | void LoopProcess(Core::System& system); |
| 17 | 13 | ||
| 18 | } // namespace Service::AM | 14 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h index 4f34d4811..ad602153e 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h | |||
| @@ -14,10 +14,9 @@ | |||
| 14 | 14 | ||
| 15 | #include "core/hle/service/am/am_types.h" | 15 | #include "core/hle/service/am/am_types.h" |
| 16 | #include "core/hle/service/am/applet_message_queue.h" | 16 | #include "core/hle/service/am/applet_message_queue.h" |
| 17 | #include "core/hle/service/am/display_layer_manager.h" | ||
| 17 | #include "core/hle/service/am/hid_registration.h" | 18 | #include "core/hle/service/am/hid_registration.h" |
| 18 | #include "core/hle/service/am/managed_layer_holder.h" | ||
| 19 | #include "core/hle/service/am/process.h" | 19 | #include "core/hle/service/am/process.h" |
| 20 | #include "core/hle/service/am/system_buffer_manager.h" | ||
| 21 | 20 | ||
| 22 | namespace Service::AM { | 21 | namespace Service::AM { |
| 23 | 22 | ||
| @@ -54,8 +53,7 @@ struct Applet { | |||
| 54 | HidRegistration hid_registration; | 53 | HidRegistration hid_registration; |
| 55 | 54 | ||
| 56 | // vi state | 55 | // vi state |
| 57 | SystemBufferManager system_buffer_manager{}; | 56 | DisplayLayerManager display_layer_manager{}; |
| 58 | ManagedLayerHolder managed_layer_holder{}; | ||
| 59 | 57 | ||
| 60 | // Applet common functions | 58 | // Applet common functions |
| 61 | Result terminate_result{}; | 59 | Result terminate_result{}; |
diff --git a/src/core/hle/service/am/display_layer_manager.cpp b/src/core/hle/service/am/display_layer_manager.cpp new file mode 100644 index 000000000..85ff6fb88 --- /dev/null +++ b/src/core/hle/service/am/display_layer_manager.cpp | |||
| @@ -0,0 +1,151 @@ | |||
| 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/am/display_layer_manager.h" | ||
| 6 | #include "core/hle/service/sm/sm.h" | ||
| 7 | #include "core/hle/service/vi/application_display_service.h" | ||
| 8 | #include "core/hle/service/vi/container.h" | ||
| 9 | #include "core/hle/service/vi/manager_display_service.h" | ||
| 10 | #include "core/hle/service/vi/manager_root_service.h" | ||
| 11 | #include "core/hle/service/vi/shared_buffer_manager.h" | ||
| 12 | #include "core/hle/service/vi/vi_results.h" | ||
| 13 | #include "core/hle/service/vi/vi_types.h" | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | DisplayLayerManager::DisplayLayerManager() = default; | ||
| 18 | DisplayLayerManager::~DisplayLayerManager() { | ||
| 19 | this->Finalize(); | ||
| 20 | } | ||
| 21 | |||
| 22 | void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process, | ||
| 23 | AppletId applet_id, LibraryAppletMode mode) { | ||
| 24 | R_ASSERT(system.ServiceManager() | ||
| 25 | .GetService<VI::IManagerRootService>("vi:m", true) | ||
| 26 | ->GetDisplayService(&m_display_service, VI::Policy::Compositor)); | ||
| 27 | R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service)); | ||
| 28 | |||
| 29 | m_process = process; | ||
| 30 | m_system_shared_buffer_id = 0; | ||
| 31 | m_system_shared_layer_id = 0; | ||
| 32 | m_applet_id = applet_id; | ||
| 33 | m_buffer_sharing_enabled = false; | ||
| 34 | m_blending_enabled = mode == LibraryAppletMode::PartialForeground || | ||
| 35 | mode == LibraryAppletMode::PartialForegroundIndirectDisplay; | ||
| 36 | } | ||
| 37 | |||
| 38 | void DisplayLayerManager::Finalize() { | ||
| 39 | if (!m_manager_display_service) { | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | |||
| 43 | // Clean up managed layers. | ||
| 44 | for (const auto& layer : m_managed_display_layers) { | ||
| 45 | m_manager_display_service->DestroyManagedLayer(layer); | ||
| 46 | } | ||
| 47 | |||
| 48 | for (const auto& layer : m_managed_display_recording_layers) { | ||
| 49 | m_manager_display_service->DestroyManagedLayer(layer); | ||
| 50 | } | ||
| 51 | |||
| 52 | // Clean up shared layers. | ||
| 53 | if (m_buffer_sharing_enabled) { | ||
| 54 | m_manager_display_service->DestroySharedLayerSession(m_process); | ||
| 55 | } | ||
| 56 | |||
| 57 | m_manager_display_service = nullptr; | ||
| 58 | m_display_service = nullptr; | ||
| 59 | } | ||
| 60 | |||
| 61 | Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) { | ||
| 62 | R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); | ||
| 63 | |||
| 64 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 65 | // create the layer in the Default display. | ||
| 66 | u64 display_id; | ||
| 67 | R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"})); | ||
| 68 | R_TRY(m_manager_display_service->CreateManagedLayer( | ||
| 69 | out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()})); | ||
| 70 | |||
| 71 | m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id); | ||
| 72 | m_managed_display_layers.emplace(*out_layer_id); | ||
| 73 | |||
| 74 | R_SUCCEED(); | ||
| 75 | } | ||
| 76 | |||
| 77 | Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id, | ||
| 78 | u64* out_recording_layer_id) { | ||
| 79 | R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); | ||
| 80 | |||
| 81 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 82 | // create the layer in the Default display. | ||
| 83 | // This calls nn::vi::CreateRecordingLayer() which creates another layer. | ||
| 84 | // Currently we do not support more than 1 layer per display, output 1 layer id for now. | ||
| 85 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | ||
| 86 | // side effects. | ||
| 87 | *out_recording_layer_id = 0; | ||
| 88 | R_RETURN(this->CreateManagedDisplayLayer(out_layer_id)); | ||
| 89 | } | ||
| 90 | |||
| 91 | Result DisplayLayerManager::IsSystemBufferSharingEnabled() { | ||
| 92 | // Succeed if already enabled. | ||
| 93 | R_SUCCEED_IF(m_buffer_sharing_enabled); | ||
| 94 | |||
| 95 | // Ensure we can access shared layers. | ||
| 96 | R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed); | ||
| 97 | R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied); | ||
| 98 | |||
| 99 | // Create the shared layer. | ||
| 100 | u64 display_id; | ||
| 101 | R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"})); | ||
| 102 | R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id, | ||
| 103 | &m_system_shared_layer_id, display_id, | ||
| 104 | m_blending_enabled)); | ||
| 105 | |||
| 106 | // We succeeded, so set up remaining state. | ||
| 107 | m_buffer_sharing_enabled = true; | ||
| 108 | m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); | ||
| 109 | R_SUCCEED(); | ||
| 110 | } | ||
| 111 | |||
| 112 | Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, | ||
| 113 | u64* out_system_shared_layer_id) { | ||
| 114 | R_TRY(this->IsSystemBufferSharingEnabled()); | ||
| 115 | |||
| 116 | *out_system_shared_buffer_id = m_system_shared_buffer_id; | ||
| 117 | *out_system_shared_layer_id = m_system_shared_layer_id; | ||
| 118 | |||
| 119 | R_SUCCEED(); | ||
| 120 | } | ||
| 121 | |||
| 122 | void DisplayLayerManager::SetWindowVisibility(bool visible) { | ||
| 123 | if (m_visible == visible) { | ||
| 124 | return; | ||
| 125 | } | ||
| 126 | |||
| 127 | m_visible = visible; | ||
| 128 | |||
| 129 | if (m_manager_display_service) { | ||
| 130 | if (m_system_shared_layer_id) { | ||
| 131 | m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); | ||
| 132 | } | ||
| 133 | |||
| 134 | for (const auto layer_id : m_managed_display_layers) { | ||
| 135 | m_manager_display_service->SetLayerVisibility(m_visible, layer_id); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | bool DisplayLayerManager::GetWindowVisibility() const { | ||
| 141 | return m_visible; | ||
| 142 | } | ||
| 143 | |||
| 144 | Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written, | ||
| 145 | s32* out_fbshare_layer_index) { | ||
| 146 | R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied); | ||
| 147 | R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer( | ||
| 148 | out_was_written, out_fbshare_layer_index)); | ||
| 149 | } | ||
| 150 | |||
| 151 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/display_layer_manager.h b/src/core/hle/service/am/display_layer_manager.h new file mode 100644 index 000000000..a66509c04 --- /dev/null +++ b/src/core/hle/service/am/display_layer_manager.h | |||
| @@ -0,0 +1,62 @@ | |||
| 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 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/result.h" | ||
| 10 | #include "core/hle/service/am/am_types.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Kernel { | ||
| 17 | class KProcess; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Service::VI { | ||
| 21 | class IApplicationDisplayService; | ||
| 22 | class IManagerDisplayService; | ||
| 23 | } // namespace Service::VI | ||
| 24 | |||
| 25 | namespace Service::AM { | ||
| 26 | |||
| 27 | class DisplayLayerManager { | ||
| 28 | public: | ||
| 29 | explicit DisplayLayerManager(); | ||
| 30 | ~DisplayLayerManager(); | ||
| 31 | |||
| 32 | void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id, | ||
| 33 | LibraryAppletMode mode); | ||
| 34 | void Finalize(); | ||
| 35 | |||
| 36 | Result CreateManagedDisplayLayer(u64* out_layer_id); | ||
| 37 | Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id); | ||
| 38 | |||
| 39 | Result IsSystemBufferSharingEnabled(); | ||
| 40 | Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, | ||
| 41 | u64* out_system_shared_layer_id); | ||
| 42 | |||
| 43 | void SetWindowVisibility(bool visible); | ||
| 44 | bool GetWindowVisibility() const; | ||
| 45 | |||
| 46 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); | ||
| 47 | |||
| 48 | private: | ||
| 49 | Kernel::KProcess* m_process{}; | ||
| 50 | std::shared_ptr<VI::IApplicationDisplayService> m_display_service{}; | ||
| 51 | std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{}; | ||
| 52 | std::set<u64> m_managed_display_layers{}; | ||
| 53 | std::set<u64> m_managed_display_recording_layers{}; | ||
| 54 | u64 m_system_shared_buffer_id{}; | ||
| 55 | u64 m_system_shared_layer_id{}; | ||
| 56 | AppletId m_applet_id{}; | ||
| 57 | bool m_buffer_sharing_enabled{}; | ||
| 58 | bool m_blending_enabled{}; | ||
| 59 | bool m_visible{true}; | ||
| 60 | }; | ||
| 61 | |||
| 62 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp deleted file mode 100644 index 61eb8641a..000000000 --- a/src/core/hle/service/am/managed_layer_holder.cpp +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/managed_layer_holder.h" | ||
| 5 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | ManagedLayerHolder::ManagedLayerHolder() = default; | ||
| 10 | ManagedLayerHolder::~ManagedLayerHolder() { | ||
| 11 | if (!m_nvnflinger) { | ||
| 12 | return; | ||
| 13 | } | ||
| 14 | |||
| 15 | for (const auto& layer : m_managed_display_layers) { | ||
| 16 | m_nvnflinger->DestroyLayer(layer); | ||
| 17 | } | ||
| 18 | |||
| 19 | for (const auto& layer : m_managed_display_recording_layers) { | ||
| 20 | m_nvnflinger->DestroyLayer(layer); | ||
| 21 | } | ||
| 22 | |||
| 23 | m_nvnflinger = nullptr; | ||
| 24 | } | ||
| 25 | |||
| 26 | void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) { | ||
| 27 | m_nvnflinger = nvnflinger; | ||
| 28 | } | ||
| 29 | |||
| 30 | void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) { | ||
| 31 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 32 | // create the layer in the Default display. | ||
| 33 | const auto display_id = m_nvnflinger->OpenDisplay("Default"); | ||
| 34 | const auto layer_id = m_nvnflinger->CreateLayer(*display_id); | ||
| 35 | |||
| 36 | m_managed_display_layers.emplace(*layer_id); | ||
| 37 | |||
| 38 | *out_layer = *layer_id; | ||
| 39 | } | ||
| 40 | |||
| 41 | void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer, | ||
| 42 | u64* out_recording_layer) { | ||
| 43 | // TODO(Subv): Find out how AM determines the display to use, for now just | ||
| 44 | // create the layer in the Default display. | ||
| 45 | // This calls nn::vi::CreateRecordingLayer() which creates another layer. | ||
| 46 | // Currently we do not support more than 1 layer per display, output 1 layer id for now. | ||
| 47 | // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse | ||
| 48 | // side effects. | ||
| 49 | // TODO: Support multiple layers | ||
| 50 | const auto display_id = m_nvnflinger->OpenDisplay("Default"); | ||
| 51 | const auto layer_id = m_nvnflinger->CreateLayer(*display_id); | ||
| 52 | |||
| 53 | m_managed_display_layers.emplace(*layer_id); | ||
| 54 | |||
| 55 | *out_layer = *layer_id; | ||
| 56 | *out_recording_layer = 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h deleted file mode 100644 index f7fe03f24..000000000 --- a/src/core/hle/service/am/managed_layer_holder.h +++ /dev/null | |||
| @@ -1,32 +0,0 @@ | |||
| 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 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace Service::Nvnflinger { | ||
| 12 | class Nvnflinger; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Service::AM { | ||
| 16 | |||
| 17 | class ManagedLayerHolder { | ||
| 18 | public: | ||
| 19 | ManagedLayerHolder(); | ||
| 20 | ~ManagedLayerHolder(); | ||
| 21 | |||
| 22 | void Initialize(Nvnflinger::Nvnflinger* nvnflinger); | ||
| 23 | void CreateManagedDisplayLayer(u64* out_layer); | ||
| 24 | void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer); | ||
| 25 | |||
| 26 | private: | ||
| 27 | Nvnflinger::Nvnflinger* m_nvnflinger{}; | ||
| 28 | std::set<u64> m_managed_display_layers{}; | ||
| 29 | std::set<u64> m_managed_display_recording_layers{}; | ||
| 30 | }; | ||
| 31 | |||
| 32 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp index eebd90ba2..21747783a 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp | |||
| @@ -10,9 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | namespace Service::AM { | 11 | namespace Service::AM { |
| 12 | 12 | ||
| 13 | IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_, | 13 | IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_) |
| 14 | Nvnflinger::Nvnflinger& nvnflinger) | 14 | : ServiceFramework{system_, "appletAE"} { |
| 15 | : ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} { | ||
| 16 | // clang-format off | 15 | // clang-format off |
| 17 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 18 | {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, | 17 | {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, |
| @@ -37,8 +36,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy( | |||
| 37 | LOG_DEBUG(Service_AM, "called"); | 36 | LOG_DEBUG(Service_AM, "called"); |
| 38 | 37 | ||
| 39 | if (const auto applet = this->GetAppletFromProcessId(pid); applet) { | 38 | if (const auto applet = this->GetAppletFromProcessId(pid); applet) { |
| 40 | *out_system_applet_proxy = std::make_shared<ISystemAppletProxy>( | 39 | *out_system_applet_proxy = |
| 41 | system, applet, process_handle.Get(), m_nvnflinger); | 40 | std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get()); |
| 42 | R_SUCCEED(); | 41 | R_SUCCEED(); |
| 43 | } else { | 42 | } else { |
| 44 | UNIMPLEMENTED(); | 43 | UNIMPLEMENTED(); |
| @@ -53,8 +52,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy( | |||
| 53 | LOG_DEBUG(Service_AM, "called"); | 52 | LOG_DEBUG(Service_AM, "called"); |
| 54 | 53 | ||
| 55 | if (const auto applet = this->GetAppletFromProcessId(pid); applet) { | 54 | if (const auto applet = this->GetAppletFromProcessId(pid); applet) { |
| 56 | *out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>( | 55 | *out_library_applet_proxy = |
| 57 | system, applet, process_handle.Get(), m_nvnflinger); | 56 | std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get()); |
| 58 | R_SUCCEED(); | 57 | R_SUCCEED(); |
| 59 | } else { | 58 | } else { |
| 60 | UNIMPLEMENTED(); | 59 | UNIMPLEMENTED(); |
diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.h b/src/core/hle/service/am/service/all_system_applet_proxies_service.h index 38b1ca2ea..0e2dcb86d 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.h +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h | |||
| @@ -8,10 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | 10 | ||
| 11 | namespace Nvnflinger { | ||
| 12 | class Nvnflinger; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace AM { | 11 | namespace AM { |
| 16 | 12 | ||
| 17 | struct Applet; | 13 | struct Applet; |
| @@ -22,8 +18,7 @@ class ISystemAppletProxy; | |||
| 22 | class IAllSystemAppletProxiesService final | 18 | class IAllSystemAppletProxiesService final |
| 23 | : public ServiceFramework<IAllSystemAppletProxiesService> { | 19 | : public ServiceFramework<IAllSystemAppletProxiesService> { |
| 24 | public: | 20 | public: |
| 25 | explicit IAllSystemAppletProxiesService(Core::System& system_, | 21 | explicit IAllSystemAppletProxiesService(Core::System& system_); |
| 26 | Nvnflinger::Nvnflinger& nvnflinger); | ||
| 27 | ~IAllSystemAppletProxiesService() override; | 22 | ~IAllSystemAppletProxiesService() override; |
| 28 | 23 | ||
| 29 | private: | 24 | private: |
| @@ -40,7 +35,6 @@ private: | |||
| 40 | 35 | ||
| 41 | private: | 36 | private: |
| 42 | std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); | 37 | std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); |
| 43 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
| 44 | }; | 38 | }; |
| 45 | 39 | ||
| 46 | } // namespace AM | 40 | } // namespace AM |
diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp index 776f4552b..19d6a3b89 100644 --- a/src/core/hle/service/am/service/application_proxy.cpp +++ b/src/core/hle/service/am/service/application_proxy.cpp | |||
| @@ -17,9 +17,9 @@ | |||
| 17 | namespace Service::AM { | 17 | namespace Service::AM { |
| 18 | 18 | ||
| 19 | IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, | 19 | IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, |
| 20 | Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger) | 20 | Kernel::KProcess* process) |
| 21 | : ServiceFramework{system_, "IApplicationProxy"}, | 21 | : ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{ |
| 22 | m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { | 22 | std::move(applet)} { |
| 23 | // clang-format off | 23 | // clang-format off |
| 24 | static const FunctionInfo functions[] = { | 24 | static const FunctionInfo functions[] = { |
| 25 | {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, | 25 | {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, |
| @@ -77,8 +77,7 @@ Result IApplicationProxy::GetWindowController( | |||
| 77 | Result IApplicationProxy::GetSelfController( | 77 | Result IApplicationProxy::GetSelfController( |
| 78 | Out<SharedPointer<ISelfController>> out_self_controller) { | 78 | Out<SharedPointer<ISelfController>> out_self_controller) { |
| 79 | LOG_DEBUG(Service_AM, "called"); | 79 | LOG_DEBUG(Service_AM, "called"); |
| 80 | *out_self_controller = | 80 | *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process); |
| 81 | std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger); | ||
| 82 | R_SUCCEED(); | 81 | R_SUCCEED(); |
| 83 | } | 82 | } |
| 84 | 83 | ||
diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h index 1ebc593ba..6da350df7 100644 --- a/src/core/hle/service/am/service/application_proxy.h +++ b/src/core/hle/service/am/service/application_proxy.h | |||
| @@ -22,7 +22,7 @@ class IWindowController; | |||
| 22 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | 22 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { |
| 23 | public: | 23 | public: |
| 24 | explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, | 24 | explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, |
| 25 | Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); | 25 | Kernel::KProcess* process); |
| 26 | ~IApplicationProxy(); | 26 | ~IApplicationProxy(); |
| 27 | 27 | ||
| 28 | private: | 28 | private: |
| @@ -40,7 +40,6 @@ private: | |||
| 40 | Out<SharedPointer<IApplicationFunctions>> out_application_functions); | 40 | Out<SharedPointer<IApplicationFunctions>> out_application_functions); |
| 41 | 41 | ||
| 42 | private: | 42 | private: |
| 43 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
| 44 | Kernel::KProcess* const m_process; | 43 | Kernel::KProcess* const m_process; |
| 45 | const std::shared_ptr<Applet> m_applet; | 44 | const std::shared_ptr<Applet> m_applet; |
| 46 | }; | 45 | }; |
diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp index 36d4478df..fd66e77b9 100644 --- a/src/core/hle/service/am/service/application_proxy_service.cpp +++ b/src/core/hle/service/am/service/application_proxy_service.cpp | |||
| @@ -10,9 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | namespace Service::AM { | 11 | namespace Service::AM { |
| 12 | 12 | ||
| 13 | IApplicationProxyService::IApplicationProxyService(Core::System& system_, | 13 | IApplicationProxyService::IApplicationProxyService(Core::System& system_) |
| 14 | Nvnflinger::Nvnflinger& nvnflinger) | 14 | : ServiceFramework{system_, "appletOE"} { |
| 15 | : ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} { | ||
| 16 | static const FunctionInfo functions[] = { | 15 | static const FunctionInfo functions[] = { |
| 17 | {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"}, | 16 | {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"}, |
| 18 | }; | 17 | }; |
| @@ -28,7 +27,7 @@ Result IApplicationProxyService::OpenApplicationProxy( | |||
| 28 | 27 | ||
| 29 | if (const auto applet = this->GetAppletFromProcessId(pid)) { | 28 | if (const auto applet = this->GetAppletFromProcessId(pid)) { |
| 30 | *out_application_proxy = | 29 | *out_application_proxy = |
| 31 | std::make_shared<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger); | 30 | std::make_shared<IApplicationProxy>(system, applet, process_handle.Get()); |
| 32 | R_SUCCEED(); | 31 | R_SUCCEED(); |
| 33 | } else { | 32 | } else { |
| 34 | UNIMPLEMENTED(); | 33 | UNIMPLEMENTED(); |
diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h index 1c1d32d0b..8efafa31a 100644 --- a/src/core/hle/service/am/service/application_proxy_service.h +++ b/src/core/hle/service/am/service/application_proxy_service.h | |||
| @@ -8,10 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | 10 | ||
| 11 | namespace Nvnflinger { | ||
| 12 | class Nvnflinger; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace AM { | 11 | namespace AM { |
| 16 | 12 | ||
| 17 | struct Applet; | 13 | struct Applet; |
| @@ -19,7 +15,7 @@ class IApplicationProxy; | |||
| 19 | 15 | ||
| 20 | class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> { | 16 | class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> { |
| 21 | public: | 17 | public: |
| 22 | explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); | 18 | explicit IApplicationProxyService(Core::System& system_); |
| 23 | ~IApplicationProxyService() override; | 19 | ~IApplicationProxyService() override; |
| 24 | 20 | ||
| 25 | private: | 21 | private: |
| @@ -28,7 +24,6 @@ private: | |||
| 28 | 24 | ||
| 29 | private: | 25 | private: |
| 30 | std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); | 26 | std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); |
| 31 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
| 32 | }; | 27 | }; |
| 33 | 28 | ||
| 34 | } // namespace AM | 29 | } // namespace AM |
diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp index 249c73dfb..ed71f9093 100644 --- a/src/core/hle/service/am/service/display_controller.cpp +++ b/src/core/hle/service/am/service/display_controller.cpp | |||
| @@ -69,7 +69,7 @@ Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_i | |||
| 69 | Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( | 69 | Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( |
| 70 | Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { | 70 | Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { |
| 71 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 71 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 72 | R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, | 72 | R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, |
| 73 | out_fbshare_layer_index)); | 73 | out_fbshare_layer_index)); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| @@ -81,7 +81,7 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() { | |||
| 81 | Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( | 81 | Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( |
| 82 | Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { | 82 | Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { |
| 83 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 83 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 84 | R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, | 84 | R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, |
| 85 | out_fbshare_layer_index)); | 85 | out_fbshare_layer_index)); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| @@ -93,7 +93,7 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() { | |||
| 93 | Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( | 93 | Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( |
| 94 | Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { | 94 | Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) { |
| 95 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 95 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 96 | R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written, | 96 | R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, |
| 97 | out_fbshare_layer_index)); | 97 | out_fbshare_layer_index)); |
| 98 | } | 98 | } |
| 99 | 99 | ||
diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 166637d60..c97358d81 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp | |||
| @@ -135,7 +135,7 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, | |||
| 135 | case LibraryAppletMode::AllForegroundInitiallyHidden: | 135 | case LibraryAppletMode::AllForegroundInitiallyHidden: |
| 136 | applet->hid_registration.EnableAppletToGetInput(false); | 136 | applet->hid_registration.EnableAppletToGetInput(false); |
| 137 | applet->focus_state = FocusState::NotInFocus; | 137 | applet->focus_state = FocusState::NotInFocus; |
| 138 | applet->system_buffer_manager.SetWindowVisibility(false); | 138 | applet->display_layer_manager.SetWindowVisibility(false); |
| 139 | applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground); | 139 | applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground); |
| 140 | break; | 140 | break; |
| 141 | } | 141 | } |
diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp index bcb44a71c..58e709347 100644 --- a/src/core/hle/service/am/service/library_applet_proxy.cpp +++ b/src/core/hle/service/am/service/library_applet_proxy.cpp | |||
| @@ -19,10 +19,9 @@ | |||
| 19 | namespace Service::AM { | 19 | namespace Service::AM { |
| 20 | 20 | ||
| 21 | ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | 21 | ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, |
| 22 | Kernel::KProcess* process, | 22 | Kernel::KProcess* process) |
| 23 | Nvnflinger::Nvnflinger& nvnflinger) | 23 | : ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{ |
| 24 | : ServiceFramework{system_, "ILibraryAppletProxy"}, | 24 | std::move(applet)} { |
| 25 | m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { | ||
| 26 | // clang-format off | 25 | // clang-format off |
| 27 | static const FunctionInfo functions[] = { | 26 | static const FunctionInfo functions[] = { |
| 28 | {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, | 27 | {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, |
| @@ -83,8 +82,7 @@ Result ILibraryAppletProxy::GetWindowController( | |||
| 83 | Result ILibraryAppletProxy::GetSelfController( | 82 | Result ILibraryAppletProxy::GetSelfController( |
| 84 | Out<SharedPointer<ISelfController>> out_self_controller) { | 83 | Out<SharedPointer<ISelfController>> out_self_controller) { |
| 85 | LOG_DEBUG(Service_AM, "called"); | 84 | LOG_DEBUG(Service_AM, "called"); |
| 86 | *out_self_controller = | 85 | *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process); |
| 87 | std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger); | ||
| 88 | R_SUCCEED(); | 86 | R_SUCCEED(); |
| 89 | } | 87 | } |
| 90 | 88 | ||
diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h index 23e64e295..7d0714b85 100644 --- a/src/core/hle/service/am/service/library_applet_proxy.h +++ b/src/core/hle/service/am/service/library_applet_proxy.h | |||
| @@ -25,7 +25,7 @@ class IWindowController; | |||
| 25 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | 25 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { |
| 26 | public: | 26 | public: |
| 27 | explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | 27 | explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, |
| 28 | Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); | 28 | Kernel::KProcess* process); |
| 29 | ~ILibraryAppletProxy(); | 29 | ~ILibraryAppletProxy(); |
| 30 | 30 | ||
| 31 | private: | 31 | private: |
| @@ -47,7 +47,6 @@ private: | |||
| 47 | Result GetGlobalStateController( | 47 | Result GetGlobalStateController( |
| 48 | Out<SharedPointer<IGlobalStateController>> out_global_state_controller); | 48 | Out<SharedPointer<IGlobalStateController>> out_global_state_controller); |
| 49 | 49 | ||
| 50 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
| 51 | Kernel::KProcess* const m_process; | 50 | Kernel::KProcess* const m_process; |
| 52 | const std::shared_ptr<Applet> m_applet; | 51 | const std::shared_ptr<Applet> m_applet; |
| 53 | }; | 52 | }; |
diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 5c4c13de1..06314407c 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | namespace Service::AM { | 15 | namespace Service::AM { |
| 16 | 16 | ||
| 17 | ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, | 17 | ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, |
| 18 | Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger) | 18 | Kernel::KProcess* process) |
| 19 | : ServiceFramework{system_, "ISelfController"}, | 19 | : ServiceFramework{system_, "ISelfController"}, m_process{process}, m_applet{ |
| 20 | m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { | 20 | std::move(applet)} { |
| 21 | // clang-format off | 21 | // clang-format off |
| 22 | static const FunctionInfo functions[] = { | 22 | static const FunctionInfo functions[] = { |
| 23 | {0, D<&ISelfController::Exit>, "Exit"}, | 23 | {0, D<&ISelfController::Exit>, "Exit"}, |
| @@ -72,9 +72,16 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> | |||
| 72 | // clang-format on | 72 | // clang-format on |
| 73 | 73 | ||
| 74 | RegisterHandlers(functions); | 74 | RegisterHandlers(functions); |
| 75 | |||
| 76 | std::scoped_lock lk{m_applet->lock}; | ||
| 77 | m_applet->display_layer_manager.Initialize(system, m_process, m_applet->applet_id, | ||
| 78 | m_applet->library_applet_mode); | ||
| 75 | } | 79 | } |
| 76 | 80 | ||
| 77 | ISelfController::~ISelfController() = default; | 81 | ISelfController::~ISelfController() { |
| 82 | std::scoped_lock lk{m_applet->lock}; | ||
| 83 | m_applet->display_layer_manager.Finalize(); | ||
| 84 | } | ||
| 78 | 85 | ||
| 79 | Result ISelfController::Exit() { | 86 | Result ISelfController::Exit() { |
| 80 | LOG_DEBUG(Service_AM, "called"); | 87 | LOG_DEBUG(Service_AM, "called"); |
| @@ -212,48 +219,42 @@ Result ISelfController::SetAlbumImageOrientation( | |||
| 212 | 219 | ||
| 213 | Result ISelfController::IsSystemBufferSharingEnabled() { | 220 | Result ISelfController::IsSystemBufferSharingEnabled() { |
| 214 | LOG_INFO(Service_AM, "called"); | 221 | LOG_INFO(Service_AM, "called"); |
| 215 | R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize( | 222 | |
| 216 | &m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode)); | 223 | std::scoped_lock lk{m_applet->lock}; |
| 217 | R_THROW(VI::ResultOperationFailed); | 224 | R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled()); |
| 218 | } | 225 | } |
| 219 | 226 | ||
| 220 | Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) { | 227 | Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) { |
| 221 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 228 | LOG_INFO(Service_AM, "called"); |
| 222 | |||
| 223 | R_TRY(this->IsSystemBufferSharingEnabled()); | ||
| 224 | 229 | ||
| 225 | u64 layer_id; | 230 | u64 layer_id; |
| 226 | m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id); | 231 | |
| 227 | R_SUCCEED(); | 232 | std::scoped_lock lk{m_applet->lock}; |
| 233 | R_RETURN(m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id)); | ||
| 228 | } | 234 | } |
| 229 | 235 | ||
| 230 | Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) { | 236 | Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) { |
| 231 | LOG_INFO(Service_AM, "(STUBBED) called"); | 237 | LOG_INFO(Service_AM, "called"); |
| 232 | |||
| 233 | R_TRY(this->IsSystemBufferSharingEnabled()); | ||
| 234 | 238 | ||
| 235 | m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id); | 239 | std::scoped_lock lk{m_applet->lock}; |
| 236 | R_SUCCEED(); | 240 | R_RETURN( |
| 241 | m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id)); | ||
| 237 | } | 242 | } |
| 238 | 243 | ||
| 239 | Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) { | 244 | Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) { |
| 240 | LOG_INFO(Service_AM, "called"); | 245 | LOG_INFO(Service_AM, "called"); |
| 241 | 246 | ||
| 242 | m_applet->managed_layer_holder.Initialize(&m_nvnflinger); | 247 | std::scoped_lock lk{m_applet->lock}; |
| 243 | m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id); | 248 | R_RETURN(m_applet->display_layer_manager.CreateManagedDisplayLayer(out_layer_id)); |
| 244 | |||
| 245 | R_SUCCEED(); | ||
| 246 | } | 249 | } |
| 247 | 250 | ||
| 248 | Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id, | 251 | Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id, |
| 249 | Out<u64> out_recording_layer_id) { | 252 | Out<u64> out_recording_layer_id) { |
| 250 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 253 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 251 | 254 | ||
| 252 | m_applet->managed_layer_holder.Initialize(&m_nvnflinger); | 255 | std::scoped_lock lk{m_applet->lock}; |
| 253 | m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id, | 256 | R_RETURN(m_applet->display_layer_manager.CreateManagedDisplaySeparableLayer( |
| 254 | out_recording_layer_id); | 257 | out_layer_id, out_recording_layer_id)); |
| 255 | |||
| 256 | R_SUCCEED(); | ||
| 257 | } | 258 | } |
| 258 | 259 | ||
| 259 | Result ISelfController::SetHandlesRequestToDisplay(bool enable) { | 260 | Result ISelfController::SetHandlesRequestToDisplay(bool enable) { |
diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h index 01fa381a3..eca083cfe 100644 --- a/src/core/hle/service/am/service/self_controller.h +++ b/src/core/hle/service/am/service/self_controller.h | |||
| @@ -23,7 +23,7 @@ struct Applet; | |||
| 23 | class ISelfController final : public ServiceFramework<ISelfController> { | 23 | class ISelfController final : public ServiceFramework<ISelfController> { |
| 24 | public: | 24 | public: |
| 25 | explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, | 25 | explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, |
| 26 | Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); | 26 | Kernel::KProcess* process); |
| 27 | ~ISelfController() override; | 27 | ~ISelfController() override; |
| 28 | 28 | ||
| 29 | private: | 29 | private: |
| @@ -64,7 +64,6 @@ private: | |||
| 64 | Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option); | 64 | Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option); |
| 65 | Result SetRecordVolumeMuted(bool muted); | 65 | Result SetRecordVolumeMuted(bool muted); |
| 66 | 66 | ||
| 67 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
| 68 | Kernel::KProcess* const m_process; | 67 | Kernel::KProcess* const m_process; |
| 69 | const std::shared_ptr<Applet> m_applet; | 68 | const std::shared_ptr<Applet> m_applet; |
| 70 | }; | 69 | }; |
diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp index 5ec509d2e..d1871ef9b 100644 --- a/src/core/hle/service/am/service/system_applet_proxy.cpp +++ b/src/core/hle/service/am/service/system_applet_proxy.cpp | |||
| @@ -19,10 +19,9 @@ | |||
| 19 | namespace Service::AM { | 19 | namespace Service::AM { |
| 20 | 20 | ||
| 21 | ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | 21 | ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, |
| 22 | Kernel::KProcess* process, | 22 | Kernel::KProcess* process) |
| 23 | Nvnflinger::Nvnflinger& nvnflinger) | 23 | : ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{ |
| 24 | : ServiceFramework{system_, "ISystemAppletProxy"}, | 24 | std::move(applet)} { |
| 25 | m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} { | ||
| 26 | // clang-format off | 25 | // clang-format off |
| 27 | static const FunctionInfo functions[] = { | 26 | static const FunctionInfo functions[] = { |
| 28 | {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, | 27 | {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, |
| @@ -83,8 +82,7 @@ Result ISystemAppletProxy::GetWindowController( | |||
| 83 | Result ISystemAppletProxy::GetSelfController( | 82 | Result ISystemAppletProxy::GetSelfController( |
| 84 | Out<SharedPointer<ISelfController>> out_self_controller) { | 83 | Out<SharedPointer<ISelfController>> out_self_controller) { |
| 85 | LOG_DEBUG(Service_AM, "called"); | 84 | LOG_DEBUG(Service_AM, "called"); |
| 86 | *out_self_controller = | 85 | *out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process); |
| 87 | std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger); | ||
| 88 | R_SUCCEED(); | 86 | R_SUCCEED(); |
| 89 | } | 87 | } |
| 90 | 88 | ||
diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h index 3d5040315..67cd50e03 100644 --- a/src/core/hle/service/am/service/system_applet_proxy.h +++ b/src/core/hle/service/am/service/system_applet_proxy.h | |||
| @@ -25,7 +25,7 @@ class IWindowController; | |||
| 25 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | 25 | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { |
| 26 | public: | 26 | public: |
| 27 | explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet, | 27 | explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet, |
| 28 | Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger); | 28 | Kernel::KProcess* process); |
| 29 | ~ISystemAppletProxy(); | 29 | ~ISystemAppletProxy(); |
| 30 | 30 | ||
| 31 | private: | 31 | private: |
| @@ -46,7 +46,6 @@ private: | |||
| 46 | Result GetGlobalStateController( | 46 | Result GetGlobalStateController( |
| 47 | Out<SharedPointer<IGlobalStateController>> out_global_state_controller); | 47 | Out<SharedPointer<IGlobalStateController>> out_global_state_controller); |
| 48 | 48 | ||
| 49 | Nvnflinger::Nvnflinger& m_nvnflinger; | ||
| 50 | Kernel::KProcess* const m_process; | 49 | Kernel::KProcess* const m_process; |
| 51 | const std::shared_ptr<Applet> m_applet; | 50 | const std::shared_ptr<Applet> m_applet; |
| 52 | }; | 51 | }; |
diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp index b874ecb91..99a4f50a2 100644 --- a/src/core/hle/service/am/service/window_controller.cpp +++ b/src/core/hle/service/am/service/window_controller.cpp | |||
| @@ -63,7 +63,7 @@ Result IWindowController::RejectToChangeIntoBackground() { | |||
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | Result IWindowController::SetAppletWindowVisibility(bool visible) { | 65 | Result IWindowController::SetAppletWindowVisibility(bool visible) { |
| 66 | m_applet->system_buffer_manager.SetWindowVisibility(visible); | 66 | m_applet->display_layer_manager.SetWindowVisibility(visible); |
| 67 | m_applet->hid_registration.EnableAppletToGetInput(visible); | 67 | m_applet->hid_registration.EnableAppletToGetInput(visible); |
| 68 | 68 | ||
| 69 | if (visible) { | 69 | if (visible) { |
diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp deleted file mode 100644 index 48923fe41..000000000 --- a/src/core/hle/service/am/system_buffer_manager.cpp +++ /dev/null | |||
| @@ -1,80 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/am/system_buffer_manager.h" | ||
| 5 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 6 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 7 | #include "core/hle/service/vi/vi_results.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | SystemBufferManager::SystemBufferManager() = default; | ||
| 12 | |||
| 13 | SystemBufferManager::~SystemBufferManager() { | ||
| 14 | if (!m_nvnflinger) { | ||
| 15 | return; | ||
| 16 | } | ||
| 17 | |||
| 18 | // Clean up shared layers. | ||
| 19 | if (m_buffer_sharing_enabled) { | ||
| 20 | m_nvnflinger->GetSystemBufferManager().Finalize(m_process); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, | ||
| 25 | AppletId applet_id, LibraryAppletMode mode) { | ||
| 26 | if (m_nvnflinger) { | ||
| 27 | return m_buffer_sharing_enabled; | ||
| 28 | } | ||
| 29 | |||
| 30 | m_process = process; | ||
| 31 | m_nvnflinger = nvnflinger; | ||
| 32 | m_buffer_sharing_enabled = false; | ||
| 33 | m_system_shared_buffer_id = 0; | ||
| 34 | m_system_shared_layer_id = 0; | ||
| 35 | |||
| 36 | if (applet_id <= AppletId::Application) { | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | |||
| 40 | Nvnflinger::LayerBlending blending = Nvnflinger::LayerBlending::None; | ||
| 41 | if (mode == LibraryAppletMode::PartialForeground || | ||
| 42 | mode == LibraryAppletMode::PartialForegroundIndirectDisplay) { | ||
| 43 | blending = Nvnflinger::LayerBlending::Coverage; | ||
| 44 | } | ||
| 45 | |||
| 46 | const auto display_id = m_nvnflinger->OpenDisplay("Default").value(); | ||
| 47 | const auto res = m_nvnflinger->GetSystemBufferManager().Initialize( | ||
| 48 | m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending); | ||
| 49 | |||
| 50 | if (res.IsSuccess()) { | ||
| 51 | m_buffer_sharing_enabled = true; | ||
| 52 | m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); | ||
| 53 | } | ||
| 54 | |||
| 55 | return m_buffer_sharing_enabled; | ||
| 56 | } | ||
| 57 | |||
| 58 | void SystemBufferManager::SetWindowVisibility(bool visible) { | ||
| 59 | if (m_visible == visible) { | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | |||
| 63 | m_visible = visible; | ||
| 64 | |||
| 65 | if (m_nvnflinger) { | ||
| 66 | m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, | ||
| 71 | s32* out_fbshare_layer_index) { | ||
| 72 | if (!m_buffer_sharing_enabled) { | ||
| 73 | return VI::ResultPermissionDenied; | ||
| 74 | } | ||
| 75 | |||
| 76 | return m_nvnflinger->GetSystemBufferManager().WriteAppletCaptureBuffer(out_was_written, | ||
| 77 | out_fbshare_layer_index); | ||
| 78 | } | ||
| 79 | |||
| 80 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h deleted file mode 100644 index 0690f68b6..000000000 --- a/src/core/hle/service/am/system_buffer_manager.h +++ /dev/null | |||
| @@ -1,52 +0,0 @@ | |||
| 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 | #include "common/common_funcs.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | #include "core/hle/service/am/am_types.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | class KProcess; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Service::Nvnflinger { | ||
| 18 | class Nvnflinger; | ||
| 19 | } | ||
| 20 | |||
| 21 | union Result; | ||
| 22 | |||
| 23 | namespace Service::AM { | ||
| 24 | |||
| 25 | class SystemBufferManager { | ||
| 26 | public: | ||
| 27 | SystemBufferManager(); | ||
| 28 | ~SystemBufferManager(); | ||
| 29 | |||
| 30 | bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id, | ||
| 31 | LibraryAppletMode mode); | ||
| 32 | |||
| 33 | void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, | ||
| 34 | u64* out_system_shared_layer_id) { | ||
| 35 | *out_system_shared_buffer_id = m_system_shared_buffer_id; | ||
| 36 | *out_system_shared_layer_id = m_system_shared_layer_id; | ||
| 37 | } | ||
| 38 | |||
| 39 | void SetWindowVisibility(bool visible); | ||
| 40 | |||
| 41 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); | ||
| 42 | |||
| 43 | private: | ||
| 44 | Kernel::KProcess* m_process{}; | ||
| 45 | Nvnflinger::Nvnflinger* m_nvnflinger{}; | ||
| 46 | bool m_buffer_sharing_enabled{}; | ||
| 47 | bool m_visible{true}; | ||
| 48 | u64 m_system_shared_buffer_id{}; | ||
| 49 | u64 m_system_shared_layer_id{}; | ||
| 50 | }; | ||
| 51 | |||
| 52 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index cb256e5b4..03eb507b9 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -42,7 +42,7 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) { | |||
| 42 | module.service_context.CloseEvent(event); | 42 | module.service_context.CloseEvent(event); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | 45 | void LoopProcess(Core::System& system) { |
| 46 | auto server_manager = std::make_unique<ServerManager>(system); | 46 | auto server_manager = std::make_unique<ServerManager>(system); |
| 47 | auto module = std::make_shared<Module>(system); | 47 | auto module = std::make_shared<Module>(system); |
| 48 | const auto NvdrvInterfaceFactoryForApplication = [&, module] { | 48 | const auto NvdrvInterfaceFactoryForApplication = [&, module] { |
| @@ -62,7 +62,6 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | |||
| 62 | server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules); | 62 | server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules); |
| 63 | server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting); | 63 | server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting); |
| 64 | server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); | 64 | server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); |
| 65 | nvnflinger.SetNVDrvInstance(module); | ||
| 66 | ServerManager::RunServer(std::move(server_manager)); | 65 | ServerManager::RunServer(std::move(server_manager)); |
| 67 | } | 66 | } |
| 68 | 67 | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index c594f0e5e..b76f81e59 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -10,13 +10,11 @@ | |||
| 10 | #include <span> | 10 | #include <span> |
| 11 | #include <string> | 11 | #include <string> |
| 12 | #include <unordered_map> | 12 | #include <unordered_map> |
| 13 | #include <vector> | ||
| 14 | 13 | ||
| 15 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 16 | #include "core/hle/service/kernel_helpers.h" | 15 | #include "core/hle/service/kernel_helpers.h" |
| 17 | #include "core/hle/service/nvdrv/core/container.h" | 16 | #include "core/hle/service/nvdrv/core/container.h" |
| 18 | #include "core/hle/service/nvdrv/nvdata.h" | 17 | #include "core/hle/service/nvdrv/nvdata.h" |
| 19 | #include "core/hle/service/nvnflinger/ui/fence.h" | ||
| 20 | #include "core/hle/service/service.h" | 18 | #include "core/hle/service/service.h" |
| 21 | 19 | ||
| 22 | namespace Core { | 20 | namespace Core { |
| @@ -27,10 +25,6 @@ namespace Kernel { | |||
| 27 | class KEvent; | 25 | class KEvent; |
| 28 | } | 26 | } |
| 29 | 27 | ||
| 30 | namespace Service::Nvnflinger { | ||
| 31 | class Nvnflinger; | ||
| 32 | } | ||
| 33 | |||
| 34 | namespace Service::Nvidia { | 28 | namespace Service::Nvidia { |
| 35 | 29 | ||
| 36 | namespace NvCore { | 30 | namespace NvCore { |
| @@ -99,7 +93,6 @@ public: | |||
| 99 | 93 | ||
| 100 | private: | 94 | private: |
| 101 | friend class EventInterface; | 95 | friend class EventInterface; |
| 102 | friend class Service::Nvnflinger::Nvnflinger; | ||
| 103 | 96 | ||
| 104 | /// Manages syncpoints on the host | 97 | /// Manages syncpoints on the host |
| 105 | NvCore::Container container; | 98 | NvCore::Container container; |
| @@ -118,6 +111,6 @@ private: | |||
| 118 | std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders; | 111 | std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders; |
| 119 | }; | 112 | }; |
| 120 | 113 | ||
| 121 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); | 114 | void LoopProcess(Core::System& system); |
| 122 | 115 | ||
| 123 | } // namespace Service::Nvidia | 116 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index ffe72f281..241006cc8 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp | |||
| @@ -263,8 +263,10 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* | |||
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | NVDRV::~NVDRV() { | 265 | NVDRV::~NVDRV() { |
| 266 | auto& container = nvdrv->GetContainer(); | 266 | if (is_initialized) { |
| 267 | container.CloseSession(session_id); | 267 | auto& container = nvdrv->GetContainer(); |
| 268 | container.CloseSession(session_id); | ||
| 269 | } | ||
| 268 | } | 270 | } |
| 269 | 271 | ||
| 270 | } // namespace Service::Nvidia | 272 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index f2195ae1e..c72f92597 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h | |||
| @@ -16,6 +16,10 @@ public: | |||
| 16 | explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name); | 16 | explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name); |
| 17 | ~NVDRV() override; | 17 | ~NVDRV() override; |
| 18 | 18 | ||
| 19 | std::shared_ptr<Module> GetModule() const { | ||
| 20 | return nvdrv; | ||
| 21 | } | ||
| 22 | |||
| 19 | private: | 23 | private: |
| 20 | void Open(HLERequestContext& ctx); | 24 | void Open(HLERequestContext& ctx); |
| 21 | void Ioctl1(HLERequestContext& ctx); | 25 | void Ioctl1(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h index 179938192..124accb94 100644 --- a/src/core/hle/service/nvnflinger/binder.h +++ b/src/core/hle/service/nvnflinger/binder.h | |||
| @@ -20,29 +20,12 @@ class HLERequestContext; | |||
| 20 | 20 | ||
| 21 | namespace Service::android { | 21 | namespace Service::android { |
| 22 | 22 | ||
| 23 | enum class TransactionId { | ||
| 24 | RequestBuffer = 1, | ||
| 25 | SetBufferCount = 2, | ||
| 26 | DequeueBuffer = 3, | ||
| 27 | DetachBuffer = 4, | ||
| 28 | DetachNextBuffer = 5, | ||
| 29 | AttachBuffer = 6, | ||
| 30 | QueueBuffer = 7, | ||
| 31 | CancelBuffer = 8, | ||
| 32 | Query = 9, | ||
| 33 | Connect = 10, | ||
| 34 | Disconnect = 11, | ||
| 35 | AllocateBuffers = 13, | ||
| 36 | SetPreallocatedBuffer = 14, | ||
| 37 | GetBufferHistory = 17, | ||
| 38 | }; | ||
| 39 | |||
| 40 | class IBinder { | 23 | class IBinder { |
| 41 | public: | 24 | public: |
| 42 | virtual ~IBinder() = default; | 25 | virtual ~IBinder() = default; |
| 43 | virtual void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, | 26 | virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, |
| 44 | std::span<u8> parcel_reply) = 0; | 27 | u32 flags) = 0; |
| 45 | virtual Kernel::KReadableEvent& GetNativeHandle() = 0; | 28 | virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0; |
| 46 | }; | 29 | }; |
| 47 | 30 | ||
| 48 | } // namespace Service::android | 31 | } // namespace Service::android |
diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp index cf151ea3a..123507123 100644 --- a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Service::android { | 13 | namespace Service::android { |
| 14 | 14 | ||
| 15 | BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_) | 15 | BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_) |
| 16 | : ConsumerBase{std::move(consumer_)} {} | 16 | : ConsumerBase{std::move(consumer_)} {} |
| 17 | 17 | ||
| 18 | Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, | 18 | Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, |
diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.h b/src/core/hle/service/nvnflinger/buffer_item_consumer.h index e0c6b3604..9f95c9280 100644 --- a/src/core/hle/service/nvnflinger/buffer_item_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.h | |||
| @@ -19,7 +19,7 @@ class BufferItem; | |||
| 19 | 19 | ||
| 20 | class BufferItemConsumer final : public ConsumerBase { | 20 | class BufferItemConsumer final : public ConsumerBase { |
| 21 | public: | 21 | public: |
| 22 | explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer); | 22 | explicit BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer); |
| 23 | Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, | 23 | Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, |
| 24 | bool wait_for_fence = true); | 24 | bool wait_for_fence = true); |
| 25 | Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence); | 25 | Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence); |
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index bbe8e06d4..3bc23aa97 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp | |||
| @@ -4,12 +4,13 @@ | |||
| 4 | // Parts of this implementation were based on: | 4 | // Parts of this implementation were based on: |
| 5 | // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp | 5 | // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp |
| 6 | 6 | ||
| 7 | #include "common/assert.h" | ||
| 7 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 8 | #include "core/hle/service/nvnflinger/buffer_item.h" | 9 | #include "core/hle/service/nvnflinger/buffer_item.h" |
| 9 | #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" | 10 | #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" |
| 10 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | 11 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" |
| 12 | #include "core/hle/service/nvnflinger/parcel.h" | ||
| 11 | #include "core/hle/service/nvnflinger/producer_listener.h" | 13 | #include "core/hle/service/nvnflinger/producer_listener.h" |
| 12 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | ||
| 13 | 14 | ||
| 14 | namespace Service::android { | 15 | namespace Service::android { |
| 15 | 16 | ||
| @@ -254,4 +255,77 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { | |||
| 254 | return Status::NoError; | 255 | return Status::NoError; |
| 255 | } | 256 | } |
| 256 | 257 | ||
| 258 | void BufferQueueConsumer::Transact(u32 code, std::span<const u8> parcel_data, | ||
| 259 | std::span<u8> parcel_reply, u32 flags) { | ||
| 260 | // Values used by BnGraphicBufferConsumer onTransact | ||
| 261 | enum class TransactionId { | ||
| 262 | AcquireBuffer = 1, | ||
| 263 | DetachBuffer = 2, | ||
| 264 | AttachBuffer = 3, | ||
| 265 | ReleaseBuffer = 4, | ||
| 266 | ConsumerConnect = 5, | ||
| 267 | ConsumerDisconnect = 6, | ||
| 268 | GetReleasedBuffers = 7, | ||
| 269 | SetDefaultBufferSize = 8, | ||
| 270 | SetDefaultMaxBufferCount = 9, | ||
| 271 | DisableAsyncBuffer = 10, | ||
| 272 | SetMaxAcquiredBufferCount = 11, | ||
| 273 | SetConsumerName = 12, | ||
| 274 | SetDefaultBufferFormat = 13, | ||
| 275 | SetConsumerUsageBits = 14, | ||
| 276 | SetTransformHint = 15, | ||
| 277 | GetSidebandStream = 16, | ||
| 278 | Unknown18 = 18, | ||
| 279 | Unknown20 = 20, | ||
| 280 | }; | ||
| 281 | |||
| 282 | Status status{Status::NoError}; | ||
| 283 | InputParcel parcel_in{parcel_data}; | ||
| 284 | OutputParcel parcel_out{}; | ||
| 285 | |||
| 286 | switch (static_cast<TransactionId>(code)) { | ||
| 287 | case TransactionId::AcquireBuffer: { | ||
| 288 | BufferItem item; | ||
| 289 | const s64 present_when = parcel_in.Read<s64>(); | ||
| 290 | |||
| 291 | status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when}); | ||
| 292 | |||
| 293 | // TODO: can't write this directly, needs a flattener for the sp<GraphicBuffer> | ||
| 294 | // parcel_out.WriteFlattened(item); | ||
| 295 | UNREACHABLE(); | ||
| 296 | } | ||
| 297 | case TransactionId::ReleaseBuffer: { | ||
| 298 | const s32 slot = parcel_in.Read<s32>(); | ||
| 299 | const u64 frame_number = parcel_in.Read<u64>(); | ||
| 300 | const auto release_fence = parcel_in.ReadFlattened<Fence>(); | ||
| 301 | |||
| 302 | status = ReleaseBuffer(slot, frame_number, release_fence); | ||
| 303 | |||
| 304 | break; | ||
| 305 | } | ||
| 306 | case TransactionId::GetReleasedBuffers: { | ||
| 307 | u64 slot_mask = 0; | ||
| 308 | |||
| 309 | status = GetReleasedBuffers(&slot_mask); | ||
| 310 | |||
| 311 | parcel_out.Write(slot_mask); | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | default: | ||
| 315 | ASSERT_MSG(false, "called, code={} flags={}", code, flags); | ||
| 316 | break; | ||
| 317 | } | ||
| 318 | |||
| 319 | parcel_out.Write(status); | ||
| 320 | |||
| 321 | const auto serialized = parcel_out.Serialize(); | ||
| 322 | std::memcpy(parcel_reply.data(), serialized.data(), | ||
| 323 | std::min(parcel_reply.size(), serialized.size())); | ||
| 324 | } | ||
| 325 | |||
| 326 | Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) { | ||
| 327 | ASSERT_MSG(false, "called, type_id={}", type_id); | ||
| 328 | return nullptr; | ||
| 329 | } | ||
| 330 | |||
| 257 | } // namespace Service::android | 331 | } // namespace Service::android |
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h index 0a61e8dbd..a9226f1c3 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <memory> | 10 | #include <memory> |
| 11 | 11 | ||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/hle/service/nvnflinger/binder.h" | ||
| 13 | #include "core/hle/service/nvnflinger/buffer_queue_defs.h" | 14 | #include "core/hle/service/nvnflinger/buffer_queue_defs.h" |
| 14 | #include "core/hle/service/nvnflinger/status.h" | 15 | #include "core/hle/service/nvnflinger/status.h" |
| 15 | 16 | ||
| @@ -19,10 +20,10 @@ class BufferItem; | |||
| 19 | class BufferQueueCore; | 20 | class BufferQueueCore; |
| 20 | class IConsumerListener; | 21 | class IConsumerListener; |
| 21 | 22 | ||
| 22 | class BufferQueueConsumer final { | 23 | class BufferQueueConsumer final : public IBinder { |
| 23 | public: | 24 | public: |
| 24 | explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); | 25 | explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); |
| 25 | ~BufferQueueConsumer(); | 26 | ~BufferQueueConsumer() override; |
| 26 | 27 | ||
| 27 | Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); | 28 | Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); |
| 28 | Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); | 29 | Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); |
| @@ -30,6 +31,11 @@ public: | |||
| 30 | Status Disconnect(); | 31 | Status Disconnect(); |
| 31 | Status GetReleasedBuffers(u64* out_slot_mask); | 32 | Status GetReleasedBuffers(u64* out_slot_mask); |
| 32 | 33 | ||
| 34 | void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, | ||
| 35 | u32 flags) override; | ||
| 36 | |||
| 37 | Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; | ||
| 38 | |||
| 33 | private: | 39 | private: |
| 34 | std::shared_ptr<BufferQueueCore> core; | 40 | std::shared_ptr<BufferQueueCore> core; |
| 35 | BufferQueueDefs::SlotsType& slots; | 41 | BufferQueueDefs::SlotsType& slots; |
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index ec83beb9b..9e5091eeb 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp | |||
| @@ -6,12 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "common/settings.h" | ||
| 10 | #include "core/core.h" | ||
| 11 | #include "core/hle/kernel/k_event.h" | 9 | #include "core/hle/kernel/k_event.h" |
| 12 | #include "core/hle/kernel/k_readable_event.h" | 10 | #include "core/hle/kernel/k_readable_event.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 11 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/service/hle_ipc.h" | ||
| 15 | #include "core/hle/service/kernel_helpers.h" | 12 | #include "core/hle/service/kernel_helpers.h" |
| 16 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | 13 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" |
| 17 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | 14 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" |
| @@ -19,7 +16,6 @@ | |||
| 19 | #include "core/hle/service/nvnflinger/parcel.h" | 16 | #include "core/hle/service/nvnflinger/parcel.h" |
| 20 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 17 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" |
| 21 | #include "core/hle/service/nvnflinger/window.h" | 18 | #include "core/hle/service/nvnflinger/window.h" |
| 22 | #include "core/hle/service/vi/vi.h" | ||
| 23 | 19 | ||
| 24 | namespace Service::android { | 20 | namespace Service::android { |
| 25 | 21 | ||
| @@ -807,13 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | |||
| 807 | return Status::NoError; | 803 | return Status::NoError; |
| 808 | } | 804 | } |
| 809 | 805 | ||
| 810 | void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data, | 806 | void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data, |
| 811 | std::span<u8> parcel_reply) { | 807 | std::span<u8> parcel_reply, u32 flags) { |
| 808 | // Values used by BnGraphicBufferProducer onTransact | ||
| 809 | enum class TransactionId { | ||
| 810 | RequestBuffer = 1, | ||
| 811 | SetBufferCount = 2, | ||
| 812 | DequeueBuffer = 3, | ||
| 813 | DetachBuffer = 4, | ||
| 814 | DetachNextBuffer = 5, | ||
| 815 | AttachBuffer = 6, | ||
| 816 | QueueBuffer = 7, | ||
| 817 | CancelBuffer = 8, | ||
| 818 | Query = 9, | ||
| 819 | Connect = 10, | ||
| 820 | Disconnect = 11, | ||
| 821 | AllocateBuffers = 13, | ||
| 822 | SetPreallocatedBuffer = 14, | ||
| 823 | GetBufferHistory = 17, | ||
| 824 | }; | ||
| 825 | |||
| 812 | Status status{Status::NoError}; | 826 | Status status{Status::NoError}; |
| 813 | InputParcel parcel_in{parcel_data}; | 827 | InputParcel parcel_in{parcel_data}; |
| 814 | OutputParcel parcel_out{}; | 828 | OutputParcel parcel_out{}; |
| 815 | 829 | ||
| 816 | switch (code) { | 830 | switch (static_cast<TransactionId>(code)) { |
| 817 | case TransactionId::Connect: { | 831 | case TransactionId::Connect: { |
| 818 | const auto enable_listener = parcel_in.Read<bool>(); | 832 | const auto enable_listener = parcel_in.Read<bool>(); |
| 819 | const auto api = parcel_in.Read<NativeWindowApi>(); | 833 | const auto api = parcel_in.Read<NativeWindowApi>(); |
| @@ -923,8 +937,8 @@ void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<cons | |||
| 923 | std::min(parcel_reply.size(), serialized.size())); | 937 | std::min(parcel_reply.size(), serialized.size())); |
| 924 | } | 938 | } |
| 925 | 939 | ||
| 926 | Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { | 940 | Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) { |
| 927 | return buffer_wait_event->GetReadableEvent(); | 941 | return &buffer_wait_event->GetReadableEvent(); |
| 928 | } | 942 | } |
| 929 | 943 | ||
| 930 | } // namespace Service::android | 944 | } // namespace Service::android |
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 4682b0f84..048523514 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h | |||
| @@ -45,12 +45,12 @@ public: | |||
| 45 | explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, | 45 | explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_, |
| 46 | std::shared_ptr<BufferQueueCore> buffer_queue_core_, | 46 | std::shared_ptr<BufferQueueCore> buffer_queue_core_, |
| 47 | Service::Nvidia::NvCore::NvMap& nvmap_); | 47 | Service::Nvidia::NvCore::NvMap& nvmap_); |
| 48 | ~BufferQueueProducer(); | 48 | ~BufferQueueProducer() override; |
| 49 | 49 | ||
| 50 | void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, | 50 | void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply, |
| 51 | std::span<u8> parcel_reply) override; | 51 | u32 flags) override; |
| 52 | 52 | ||
| 53 | Kernel::KReadableEvent& GetNativeHandle() override; | 53 | Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override; |
| 54 | 54 | ||
| 55 | public: | 55 | public: |
| 56 | Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf); | 56 | Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf); |
diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp index 1059e72bf..e360ebfd8 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.cpp +++ b/src/core/hle/service/nvnflinger/consumer_base.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | namespace Service::android { | 15 | namespace Service::android { |
| 16 | 16 | ||
| 17 | ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_) | 17 | ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_) |
| 18 | : consumer{std::move(consumer_)} {} | 18 | : consumer{std::move(consumer_)} {} |
| 19 | 19 | ||
| 20 | ConsumerBase::~ConsumerBase() { | 20 | ConsumerBase::~ConsumerBase() { |
diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h index ea3e9e97a..b29c16f86 100644 --- a/src/core/hle/service/nvnflinger/consumer_base.h +++ b/src/core/hle/service/nvnflinger/consumer_base.h | |||
| @@ -27,7 +27,7 @@ public: | |||
| 27 | void Abandon(); | 27 | void Abandon(); |
| 28 | 28 | ||
| 29 | protected: | 29 | protected: |
| 30 | explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); | 30 | explicit ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_); |
| 31 | ~ConsumerBase() override; | 31 | ~ConsumerBase() override; |
| 32 | 32 | ||
| 33 | void OnFrameAvailable(const BufferItem& item) override; | 33 | void OnFrameAvailable(const BufferItem& item) override; |
| @@ -54,7 +54,7 @@ protected: | |||
| 54 | 54 | ||
| 55 | bool is_abandoned{}; | 55 | bool is_abandoned{}; |
| 56 | 56 | ||
| 57 | std::unique_ptr<BufferQueueConsumer> consumer; | 57 | std::shared_ptr<BufferQueueConsumer> consumer; |
| 58 | 58 | ||
| 59 | mutable std::mutex mutex; | 59 | mutable std::mutex mutex; |
| 60 | }; | 60 | }; |
diff --git a/src/core/hle/service/nvnflinger/display.h b/src/core/hle/service/nvnflinger/display.h new file mode 100644 index 000000000..f27cbf144 --- /dev/null +++ b/src/core/hle/service/nvnflinger/display.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <list> | ||
| 7 | |||
| 8 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" | ||
| 9 | #include "core/hle/service/nvnflinger/hwc_layer.h" | ||
| 10 | |||
| 11 | namespace Service::Nvnflinger { | ||
| 12 | |||
| 13 | struct Layer { | ||
| 14 | explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_, | ||
| 15 | s32 consumer_id_) | ||
| 16 | : buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_), | ||
| 17 | blending(LayerBlending::None), visible(true) {} | ||
| 18 | ~Layer() { | ||
| 19 | buffer_item_consumer->Abandon(); | ||
| 20 | } | ||
| 21 | |||
| 22 | std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer; | ||
| 23 | s32 consumer_id; | ||
| 24 | LayerBlending blending; | ||
| 25 | bool visible; | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct LayerStack { | ||
| 29 | std::list<Layer> layers; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct Display { | ||
| 33 | explicit Display(u64 id_) { | ||
| 34 | id = id_; | ||
| 35 | } | ||
| 36 | |||
| 37 | Layer* FindLayer(s32 consumer_id) { | ||
| 38 | for (auto& layer : stack.layers) { | ||
| 39 | if (layer.consumer_id == consumer_id) { | ||
| 40 | return &layer; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | return nullptr; | ||
| 45 | } | ||
| 46 | |||
| 47 | bool HasLayers() { | ||
| 48 | return !stack.layers.empty(); | ||
| 49 | } | ||
| 50 | |||
| 51 | u64 id; | ||
| 52 | LayerStack stack; | ||
| 53 | }; | ||
| 54 | |||
| 55 | } // namespace Service::Nvnflinger | ||
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp index be7eb97a3..02215a786 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.cpp +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp | |||
| @@ -10,8 +10,6 @@ | |||
| 10 | #include "core/hle/service/nvnflinger/hardware_composer.h" | 10 | #include "core/hle/service/nvnflinger/hardware_composer.h" |
| 11 | #include "core/hle/service/nvnflinger/hwc_layer.h" | 11 | #include "core/hle/service/nvnflinger/hwc_layer.h" |
| 12 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 12 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" |
| 13 | #include "core/hle/service/vi/display/vi_display.h" | ||
| 14 | #include "core/hle/service/vi/layer/vi_layer.h" | ||
| 15 | 13 | ||
| 16 | namespace Service::Nvnflinger { | 14 | namespace Service::Nvnflinger { |
| 17 | 15 | ||
| @@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) { | |||
| 44 | HardwareComposer::HardwareComposer() = default; | 42 | HardwareComposer::HardwareComposer() = default; |
| 45 | HardwareComposer::~HardwareComposer() = default; | 43 | HardwareComposer::~HardwareComposer() = default; |
| 46 | 44 | ||
| 47 | u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, | 45 | u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display, |
| 48 | Nvidia::Devices::nvdisp_disp0& nvdisp) { | 46 | Nvidia::Devices::nvdisp_disp0& nvdisp) { |
| 49 | boost::container::small_vector<HwcLayer, 2> composition_stack; | 47 | boost::container::small_vector<HwcLayer, 2> composition_stack; |
| 50 | 48 | ||
| @@ -56,12 +54,11 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, | |||
| 56 | bool has_acquired_buffer{}; | 54 | bool has_acquired_buffer{}; |
| 57 | 55 | ||
| 58 | // Acquire all necessary framebuffers. | 56 | // Acquire all necessary framebuffers. |
| 59 | for (size_t i = 0; i < display.GetNumLayers(); i++) { | 57 | for (auto& layer : display.stack.layers) { |
| 60 | auto& layer = display.GetLayer(i); | 58 | auto consumer_id = layer.consumer_id; |
| 61 | auto layer_id = layer.GetLayerId(); | ||
| 62 | 59 | ||
| 63 | // Try to fetch the framebuffer (either new or stale). | 60 | // Try to fetch the framebuffer (either new or stale). |
| 64 | const auto result = this->CacheFramebufferLocked(layer, layer_id); | 61 | const auto result = this->CacheFramebufferLocked(layer, consumer_id); |
| 65 | 62 | ||
| 66 | // If we failed, skip this layer. | 63 | // If we failed, skip this layer. |
| 67 | if (result == CacheStatus::NoBufferAvailable) { | 64 | if (result == CacheStatus::NoBufferAvailable) { |
| @@ -73,24 +70,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, | |||
| 73 | has_acquired_buffer = true; | 70 | has_acquired_buffer = true; |
| 74 | } | 71 | } |
| 75 | 72 | ||
| 76 | const auto& buffer = m_framebuffers[layer_id]; | 73 | const auto& buffer = m_framebuffers[consumer_id]; |
| 77 | const auto& item = buffer.item; | 74 | const auto& item = buffer.item; |
| 78 | const auto& igbp_buffer = *item.graphic_buffer; | 75 | const auto& igbp_buffer = *item.graphic_buffer; |
| 79 | 76 | ||
| 80 | // TODO: get proper Z-index from layer | 77 | // TODO: get proper Z-index from layer |
| 81 | composition_stack.emplace_back(HwcLayer{ | 78 | if (layer.visible) { |
| 82 | .buffer_handle = igbp_buffer.BufferId(), | 79 | composition_stack.emplace_back(HwcLayer{ |
| 83 | .offset = igbp_buffer.Offset(), | 80 | .buffer_handle = igbp_buffer.BufferId(), |
| 84 | .format = igbp_buffer.ExternalFormat(), | 81 | .offset = igbp_buffer.Offset(), |
| 85 | .width = igbp_buffer.Width(), | 82 | .format = igbp_buffer.ExternalFormat(), |
| 86 | .height = igbp_buffer.Height(), | 83 | .width = igbp_buffer.Width(), |
| 87 | .stride = igbp_buffer.Stride(), | 84 | .height = igbp_buffer.Height(), |
| 88 | .z_index = 0, | 85 | .stride = igbp_buffer.Stride(), |
| 89 | .blending = layer.GetBlending(), | 86 | .z_index = 0, |
| 90 | .transform = static_cast<android::BufferTransformFlags>(item.transform), | 87 | .blending = layer.blending, |
| 91 | .crop_rect = item.crop, | 88 | .transform = static_cast<android::BufferTransformFlags>(item.transform), |
| 92 | .acquire_fence = item.fence, | 89 | .crop_rect = item.crop, |
| 93 | }); | 90 | .acquire_fence = item.fence, |
| 91 | }); | ||
| 92 | } | ||
| 94 | 93 | ||
| 95 | // We need to compose again either before this frame is supposed to | 94 | // We need to compose again either before this frame is supposed to |
| 96 | // be released, or exactly on the vsync period it should be released. | 95 | // be released, or exactly on the vsync period it should be released. |
| @@ -138,7 +137,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, | |||
| 138 | if (auto* layer = display.FindLayer(layer_id); layer != nullptr) { | 137 | if (auto* layer = display.FindLayer(layer_id); layer != nullptr) { |
| 139 | // TODO: support release fence | 138 | // TODO: support release fence |
| 140 | // This is needed to prevent screen tearing | 139 | // This is needed to prevent screen tearing |
| 141 | layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence()); | 140 | layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence()); |
| 142 | framebuffer.is_acquired = false; | 141 | framebuffer.is_acquired = false; |
| 143 | } | 142 | } |
| 144 | } | 143 | } |
| @@ -146,26 +145,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, | |||
| 146 | return frame_advance; | 145 | return frame_advance; |
| 147 | } | 146 | } |
| 148 | 147 | ||
| 149 | void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) { | 148 | void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) { |
| 150 | // Check if we are tracking a slot with this layer_id. | 149 | // Check if we are tracking a slot with this consumer_id. |
| 151 | const auto it = m_framebuffers.find(layer_id); | 150 | const auto it = m_framebuffers.find(consumer_id); |
| 152 | if (it == m_framebuffers.end()) { | 151 | if (it == m_framebuffers.end()) { |
| 153 | return; | 152 | return; |
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | // Try to release the buffer item. | 155 | // Try to release the buffer item. |
| 157 | auto* const layer = display.FindLayer(layer_id); | 156 | auto* const layer = display.FindLayer(consumer_id); |
| 158 | if (layer && it->second.is_acquired) { | 157 | if (layer && it->second.is_acquired) { |
| 159 | layer->GetConsumer().ReleaseBuffer(it->second.item, android::Fence::NoFence()); | 158 | layer->buffer_item_consumer->ReleaseBuffer(it->second.item, android::Fence::NoFence()); |
| 160 | } | 159 | } |
| 161 | 160 | ||
| 162 | // Erase the slot. | 161 | // Erase the slot. |
| 163 | m_framebuffers.erase(it); | 162 | m_framebuffers.erase(it); |
| 164 | } | 163 | } |
| 165 | 164 | ||
| 166 | bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) { | 165 | bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer) { |
| 167 | // Attempt the update. | 166 | // Attempt the update. |
| 168 | const auto status = layer.GetConsumer().AcquireBuffer(&framebuffer.item, {}, false); | 167 | const auto status = layer.buffer_item_consumer->AcquireBuffer(&framebuffer.item, {}, false); |
| 169 | if (status != android::Status::NoError) { | 168 | if (status != android::Status::NoError) { |
| 170 | return false; | 169 | return false; |
| 171 | } | 170 | } |
| @@ -178,10 +177,10 @@ bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer | |||
| 178 | return true; | 177 | return true; |
| 179 | } | 178 | } |
| 180 | 179 | ||
| 181 | HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer, | 180 | HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(Layer& layer, |
| 182 | LayerId layer_id) { | 181 | ConsumerId consumer_id) { |
| 183 | // Check if this framebuffer is already present. | 182 | // Check if this framebuffer is already present. |
| 184 | const auto it = m_framebuffers.find(layer_id); | 183 | const auto it = m_framebuffers.find(consumer_id); |
| 185 | if (it != m_framebuffers.end()) { | 184 | if (it != m_framebuffers.end()) { |
| 186 | // If it's currently still acquired, we are done. | 185 | // If it's currently still acquired, we are done. |
| 187 | if (it->second.is_acquired) { | 186 | if (it->second.is_acquired) { |
| @@ -203,7 +202,7 @@ HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer | |||
| 203 | 202 | ||
| 204 | if (this->TryAcquireFramebufferLocked(layer, framebuffer)) { | 203 | if (this->TryAcquireFramebufferLocked(layer, framebuffer)) { |
| 205 | // Move the buffer item into a new slot. | 204 | // Move the buffer item into a new slot. |
| 206 | m_framebuffers.emplace(layer_id, std::move(framebuffer)); | 205 | m_framebuffers.emplace(consumer_id, std::move(framebuffer)); |
| 207 | 206 | ||
| 208 | // We succeeded. | 207 | // We succeeded. |
| 209 | return CacheStatus::BufferAcquired; | 208 | return CacheStatus::BufferAcquired; |
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.h b/src/core/hle/service/nvnflinger/hardware_composer.h index 28392c512..c5b830468 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.h +++ b/src/core/hle/service/nvnflinger/hardware_composer.h | |||
| @@ -3,35 +3,29 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | ||
| 7 | #include <boost/container/flat_map.hpp> | 6 | #include <boost/container/flat_map.hpp> |
| 8 | 7 | ||
| 9 | #include "core/hle/service/nvnflinger/buffer_item.h" | 8 | #include "core/hle/service/nvnflinger/buffer_item.h" |
| 9 | #include "core/hle/service/nvnflinger/display.h" | ||
| 10 | 10 | ||
| 11 | namespace Service::Nvidia::Devices { | 11 | namespace Service::Nvidia::Devices { |
| 12 | class nvdisp_disp0; | 12 | class nvdisp_disp0; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | namespace Service::VI { | ||
| 16 | class Display; | ||
| 17 | class Layer; | ||
| 18 | } // namespace Service::VI | ||
| 19 | |||
| 20 | namespace Service::Nvnflinger { | 15 | namespace Service::Nvnflinger { |
| 21 | 16 | ||
| 22 | using LayerId = u64; | 17 | using ConsumerId = s32; |
| 23 | 18 | ||
| 24 | class HardwareComposer { | 19 | class HardwareComposer { |
| 25 | public: | 20 | public: |
| 26 | explicit HardwareComposer(); | 21 | explicit HardwareComposer(); |
| 27 | ~HardwareComposer(); | 22 | ~HardwareComposer(); |
| 28 | 23 | ||
| 29 | u32 ComposeLocked(f32* out_speed_scale, VI::Display& display, | 24 | u32 ComposeLocked(f32* out_speed_scale, Display& display, |
| 30 | Nvidia::Devices::nvdisp_disp0& nvdisp); | 25 | Nvidia::Devices::nvdisp_disp0& nvdisp); |
| 31 | void RemoveLayerLocked(VI::Display& display, LayerId layer_id); | 26 | void RemoveLayerLocked(Display& display, ConsumerId consumer_id); |
| 32 | 27 | ||
| 33 | private: | 28 | private: |
| 34 | // TODO: do we want to track frame number in vi instead? | ||
| 35 | u64 m_frame_number{0}; | 29 | u64 m_frame_number{0}; |
| 36 | 30 | ||
| 37 | private: | 31 | private: |
| @@ -49,11 +43,11 @@ private: | |||
| 49 | CachedBufferReused, | 43 | CachedBufferReused, |
| 50 | }; | 44 | }; |
| 51 | 45 | ||
| 52 | boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{}; | 46 | boost::container::flat_map<ConsumerId, Framebuffer> m_framebuffers{}; |
| 53 | 47 | ||
| 54 | private: | 48 | private: |
| 55 | bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer); | 49 | bool TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer); |
| 56 | CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id); | 50 | CacheStatus CacheFramebufferLocked(Layer& layer, ConsumerId consumer_id); |
| 57 | }; | 51 | }; |
| 58 | 52 | ||
| 59 | } // namespace Service::Nvnflinger | 53 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/vi/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp index ba0317245..8629a2e89 100644 --- a/src/core/hle/service/vi/hos_binder_driver.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp | |||
| @@ -3,13 +3,16 @@ | |||
| 3 | 3 | ||
| 4 | #include "core/hle/service/cmif_serialization.h" | 4 | #include "core/hle/service/cmif_serialization.h" |
| 5 | #include "core/hle/service/nvnflinger/binder.h" | 5 | #include "core/hle/service/nvnflinger/binder.h" |
| 6 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" | ||
| 6 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | 7 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" |
| 7 | #include "core/hle/service/vi/hos_binder_driver.h" | ||
| 8 | 8 | ||
| 9 | namespace Service::VI { | 9 | namespace Service::Nvnflinger { |
| 10 | 10 | ||
| 11 | IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server) | 11 | IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, |
| 12 | : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server) { | 12 | std::shared_ptr<HosBinderDriverServer> server, |
| 13 | std::shared_ptr<SurfaceFlinger> surface_flinger) | ||
| 14 | : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server), | ||
| 15 | m_surface_flinger(surface_flinger) { | ||
| 13 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 14 | {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"}, | 17 | {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"}, |
| 15 | {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, | 18 | {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, |
| @@ -21,13 +24,18 @@ IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderD | |||
| 21 | 24 | ||
| 22 | IHOSBinderDriver::~IHOSBinderDriver() = default; | 25 | IHOSBinderDriver::~IHOSBinderDriver() = default; |
| 23 | 26 | ||
| 24 | Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id, | 27 | Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id, |
| 25 | InBuffer<BufferAttr_HipcMapAlias> parcel_data, | 28 | InBuffer<BufferAttr_HipcMapAlias> parcel_data, |
| 26 | OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, | 29 | OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, |
| 27 | u32 flags) { | 30 | u32 flags) { |
| 28 | LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id, | 31 | LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id, |
| 29 | flags); | 32 | flags); |
| 30 | m_server.TryGetProducer(binder_id)->Transact(transaction_id, flags, parcel_data, parcel_reply); | 33 | |
| 34 | const auto binder = m_server->TryGetBinder(binder_id); | ||
| 35 | R_SUCCEED_IF(binder == nullptr); | ||
| 36 | |||
| 37 | binder->Transact(transaction_id, parcel_data, parcel_reply, flags); | ||
| 38 | |||
| 31 | R_SUCCEED(); | 39 | R_SUCCEED(); |
| 32 | } | 40 | } |
| 33 | 41 | ||
| @@ -39,15 +47,20 @@ Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) { | |||
| 39 | Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, | 47 | Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, |
| 40 | OutCopyHandle<Kernel::KReadableEvent> out_handle) { | 48 | OutCopyHandle<Kernel::KReadableEvent> out_handle) { |
| 41 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); | 49 | LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); |
| 42 | *out_handle = &m_server.TryGetProducer(binder_id)->GetNativeHandle(); | 50 | |
| 51 | const auto binder = m_server->TryGetBinder(binder_id); | ||
| 52 | R_UNLESS(binder != nullptr, ResultUnknown); | ||
| 53 | |||
| 54 | *out_handle = binder->GetNativeHandle(type_id); | ||
| 55 | |||
| 43 | R_SUCCEED(); | 56 | R_SUCCEED(); |
| 44 | } | 57 | } |
| 45 | 58 | ||
| 46 | Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, | 59 | Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, u32 transaction_id, |
| 47 | InBuffer<BufferAttr_HipcAutoSelect> parcel_data, | 60 | InBuffer<BufferAttr_HipcAutoSelect> parcel_data, |
| 48 | OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, | 61 | OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, |
| 49 | u32 flags) { | 62 | u32 flags) { |
| 50 | R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags)); | 63 | R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags)); |
| 51 | } | 64 | } |
| 52 | 65 | ||
| 53 | } // namespace Service::VI | 66 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/vi/hos_binder_driver.h b/src/core/hle/service/nvnflinger/hos_binder_driver.h index ed6e8cdbe..b7fb07bd2 100644 --- a/src/core/hle/service/vi/hos_binder_driver.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.h | |||
| @@ -2,29 +2,45 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/cmif_types.h" | 4 | #include "core/hle/service/cmif_types.h" |
| 5 | #include "core/hle/service/nvnflinger/binder.h" | ||
| 6 | #include "core/hle/service/service.h" | 5 | #include "core/hle/service/service.h" |
| 7 | 6 | ||
| 8 | namespace Service::VI { | 7 | namespace Kernel { |
| 8 | class KReadableEvent; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::Nvnflinger { | ||
| 12 | |||
| 13 | class HosBinderDriverServer; | ||
| 14 | class SurfaceFlinger; | ||
| 9 | 15 | ||
| 10 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | 16 | class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { |
| 11 | public: | 17 | public: |
| 12 | explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server); | 18 | explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr<HosBinderDriverServer> server, |
| 19 | std::shared_ptr<SurfaceFlinger> surface_flinger); | ||
| 13 | ~IHOSBinderDriver() override; | 20 | ~IHOSBinderDriver() override; |
| 14 | 21 | ||
| 22 | std::shared_ptr<SurfaceFlinger> GetSurfaceFlinger() { | ||
| 23 | return m_surface_flinger; | ||
| 24 | } | ||
| 25 | |||
| 26 | std::shared_ptr<HosBinderDriverServer> GetServer() { | ||
| 27 | return m_server; | ||
| 28 | } | ||
| 29 | |||
| 15 | private: | 30 | private: |
| 16 | Result TransactParcel(s32 binder_id, android::TransactionId transaction_id, | 31 | Result TransactParcel(s32 binder_id, u32 transaction_id, |
| 17 | InBuffer<BufferAttr_HipcMapAlias> parcel_data, | 32 | InBuffer<BufferAttr_HipcMapAlias> parcel_data, |
| 18 | OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags); | 33 | OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags); |
| 19 | Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); | 34 | Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); |
| 20 | Result GetNativeHandle(s32 binder_id, u32 type_id, | 35 | Result GetNativeHandle(s32 binder_id, u32 type_id, |
| 21 | OutCopyHandle<Kernel::KReadableEvent> out_handle); | 36 | OutCopyHandle<Kernel::KReadableEvent> out_handle); |
| 22 | Result TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, | 37 | Result TransactParcelAuto(s32 binder_id, u32 transaction_id, |
| 23 | InBuffer<BufferAttr_HipcAutoSelect> parcel_data, | 38 | InBuffer<BufferAttr_HipcAutoSelect> parcel_data, |
| 24 | OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags); | 39 | OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags); |
| 25 | 40 | ||
| 26 | private: | 41 | private: |
| 27 | Nvnflinger::HosBinderDriverServer& m_server; | 42 | const std::shared_ptr<HosBinderDriverServer> m_server; |
| 43 | const std::shared_ptr<SurfaceFlinger> m_surface_flinger; | ||
| 28 | }; | 44 | }; |
| 29 | 45 | ||
| 30 | } // namespace Service::VI | 46 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp index b86a79ec9..29addda44 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp | |||
| @@ -8,26 +8,30 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::Nvnflinger { | 9 | namespace Service::Nvnflinger { |
| 10 | 10 | ||
| 11 | HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) | 11 | HosBinderDriverServer::HosBinderDriverServer() = default; |
| 12 | : service_context(system_, "HosBinderDriverServer") {} | 12 | HosBinderDriverServer::~HosBinderDriverServer() = default; |
| 13 | 13 | ||
| 14 | HosBinderDriverServer::~HosBinderDriverServer() {} | 14 | s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) { |
| 15 | |||
| 16 | u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) { | ||
| 17 | std::scoped_lock lk{lock}; | 15 | std::scoped_lock lk{lock}; |
| 18 | 16 | ||
| 19 | last_id++; | 17 | last_id++; |
| 20 | 18 | ||
| 21 | producers[last_id] = std::move(binder); | 19 | binders[last_id] = std::move(binder); |
| 22 | 20 | ||
| 23 | return last_id; | 21 | return last_id; |
| 24 | } | 22 | } |
| 25 | 23 | ||
| 26 | android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { | 24 | void HosBinderDriverServer::UnregisterBinder(s32 binder_id) { |
| 25 | std::scoped_lock lk{lock}; | ||
| 26 | |||
| 27 | binders.erase(binder_id); | ||
| 28 | } | ||
| 29 | |||
| 30 | std::shared_ptr<android::IBinder> HosBinderDriverServer::TryGetBinder(s32 id) const { | ||
| 27 | std::scoped_lock lk{lock}; | 31 | std::scoped_lock lk{lock}; |
| 28 | 32 | ||
| 29 | if (auto search = producers.find(id); search != producers.end()) { | 33 | if (auto search = binders.find(id); search != binders.end()) { |
| 30 | return search->second.get(); | 34 | return search->second; |
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | return {}; | 37 | return {}; |
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h index 58bb9469a..d72b50833 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/service/kernel_helpers.h" | ||
| 12 | #include "core/hle/service/nvnflinger/binder.h" | 11 | #include "core/hle/service/nvnflinger/binder.h" |
| 13 | 12 | ||
| 14 | namespace Core { | 13 | namespace Core { |
| @@ -19,19 +18,18 @@ namespace Service::Nvnflinger { | |||
| 19 | 18 | ||
| 20 | class HosBinderDriverServer final { | 19 | class HosBinderDriverServer final { |
| 21 | public: | 20 | public: |
| 22 | explicit HosBinderDriverServer(Core::System& system_); | 21 | explicit HosBinderDriverServer(); |
| 23 | ~HosBinderDriverServer(); | 22 | ~HosBinderDriverServer(); |
| 24 | 23 | ||
| 25 | u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder); | 24 | s32 RegisterBinder(std::shared_ptr<android::IBinder>&& binder); |
| 25 | void UnregisterBinder(s32 binder_id); | ||
| 26 | 26 | ||
| 27 | android::IBinder* TryGetProducer(u64 id); | 27 | std::shared_ptr<android::IBinder> TryGetBinder(s32 id) const; |
| 28 | 28 | ||
| 29 | private: | 29 | private: |
| 30 | KernelHelpers::ServiceContext service_context; | 30 | std::unordered_map<s32, std::shared_ptr<android::IBinder>> binders; |
| 31 | 31 | mutable std::mutex lock; | |
| 32 | std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers; | 32 | s32 last_id{}; |
| 33 | std::mutex lock; | ||
| 34 | u64 last_id{}; | ||
| 35 | }; | 33 | }; |
| 36 | 34 | ||
| 37 | } // namespace Service::Nvnflinger | 35 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 687ccc9f9..9e3b68b8a 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -1,335 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | ||
| 5 | #include <optional> | ||
| 6 | |||
| 7 | #include "common/assert.h" | ||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "common/microprofile.h" | ||
| 10 | #include "common/scope_exit.h" | ||
| 11 | #include "common/settings.h" | ||
| 12 | #include "common/thread.h" | ||
| 13 | #include "core/core.h" | 4 | #include "core/core.h" |
| 14 | #include "core/core_timing.h" | 5 | #include "core/hle/service/nvnflinger/hos_binder_driver.h" |
| 15 | #include "core/hle/kernel/k_readable_event.h" | ||
| 16 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||
| 17 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 18 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" | ||
| 19 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | ||
| 20 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 21 | #include "core/hle/service/nvnflinger/hardware_composer.h" | ||
| 22 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | 6 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" |
| 23 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 7 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 24 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 8 | #include "core/hle/service/nvnflinger/surface_flinger.h" |
| 25 | #include "core/hle/service/vi/display/vi_display.h" | 9 | #include "core/hle/service/server_manager.h" |
| 26 | #include "core/hle/service/vi/layer/vi_layer.h" | 10 | #include "core/hle/service/sm/sm.h" |
| 27 | #include "core/hle/service/vi/vi_results.h" | ||
| 28 | #include "video_core/gpu.h" | ||
| 29 | #include "video_core/host1x/host1x.h" | ||
| 30 | #include "video_core/host1x/syncpoint_manager.h" | ||
| 31 | 11 | ||
| 32 | namespace Service::Nvnflinger { | 12 | namespace Service::Nvnflinger { |
| 33 | 13 | ||
| 34 | constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; | 14 | void LoopProcess(Core::System& system) { |
| 35 | 15 | const auto binder_server = std::make_shared<HosBinderDriverServer>(); | |
| 36 | void Nvnflinger::SplitVSync(std::stop_token stop_token) { | 16 | const auto surface_flinger = std::make_shared<SurfaceFlinger>(system, *binder_server); |
| 37 | system.RegisterHostThread(); | ||
| 38 | std::string name = "VSyncThread"; | ||
| 39 | MicroProfileOnThreadCreate(name.c_str()); | ||
| 40 | |||
| 41 | // Cleanup | ||
| 42 | SCOPE_EXIT({ MicroProfileOnThreadExit(); }); | ||
| 43 | |||
| 44 | Common::SetCurrentThreadName(name.c_str()); | ||
| 45 | Common::SetCurrentThreadPriority(Common::ThreadPriority::High); | ||
| 46 | |||
| 47 | while (!stop_token.stop_requested()) { | ||
| 48 | vsync_signal.Wait(); | ||
| 49 | |||
| 50 | const auto lock_guard = Lock(); | ||
| 51 | |||
| 52 | if (!is_abandoned) { | ||
| 53 | Compose(); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_) | ||
| 59 | : system(system_), service_context(system_, "nvnflinger"), | ||
| 60 | hos_binder_driver_server(hos_binder_driver_server_) { | ||
| 61 | displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system); | ||
| 62 | displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system); | ||
| 63 | displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system); | ||
| 64 | displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system); | ||
| 65 | displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system); | ||
| 66 | guard = std::make_shared<std::mutex>(); | ||
| 67 | |||
| 68 | // Schedule the screen composition events | ||
| 69 | multi_composition_event = Core::Timing::CreateEvent( | ||
| 70 | "ScreenComposition", | ||
| 71 | [this](s64 time, | ||
| 72 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 73 | vsync_signal.Set(); | ||
| 74 | return std::chrono::nanoseconds(GetNextTicks()); | ||
| 75 | }); | ||
| 76 | |||
| 77 | single_composition_event = Core::Timing::CreateEvent( | ||
| 78 | "ScreenComposition", | ||
| 79 | [this](s64 time, | ||
| 80 | std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { | ||
| 81 | const auto lock_guard = Lock(); | ||
| 82 | Compose(); | ||
| 83 | |||
| 84 | return std::chrono::nanoseconds(GetNextTicks()); | ||
| 85 | }); | ||
| 86 | |||
| 87 | if (system.IsMulticore()) { | ||
| 88 | system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event); | ||
| 89 | vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); | ||
| 90 | } else { | ||
| 91 | system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | Nvnflinger::~Nvnflinger() { | ||
| 96 | if (system.IsMulticore()) { | ||
| 97 | system.CoreTiming().UnscheduleEvent(multi_composition_event); | ||
| 98 | vsync_thread.request_stop(); | ||
| 99 | vsync_signal.Set(); | ||
| 100 | } else { | ||
| 101 | system.CoreTiming().UnscheduleEvent(single_composition_event); | ||
| 102 | } | ||
| 103 | |||
| 104 | ShutdownLayers(); | ||
| 105 | |||
| 106 | if (nvdrv) { | ||
| 107 | nvdrv->Close(disp_fd); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | void Nvnflinger::ShutdownLayers() { | ||
| 112 | // Abandon consumers. | ||
| 113 | { | ||
| 114 | const auto lock_guard = Lock(); | ||
| 115 | for (auto& display : displays) { | ||
| 116 | display.Abandon(); | ||
| 117 | } | ||
| 118 | |||
| 119 | is_abandoned = true; | ||
| 120 | } | ||
| 121 | |||
| 122 | // Join the vsync thread, if it exists. | ||
| 123 | vsync_thread = {}; | ||
| 124 | } | ||
| 125 | |||
| 126 | void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { | ||
| 127 | nvdrv = std::move(instance); | ||
| 128 | disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); | ||
| 129 | } | ||
| 130 | |||
| 131 | std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { | ||
| 132 | const auto lock_guard = Lock(); | ||
| 133 | |||
| 134 | LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name); | ||
| 135 | |||
| 136 | const auto itr = | ||
| 137 | std::find_if(displays.begin(), displays.end(), | ||
| 138 | [&](const VI::Display& display) { return display.GetName() == name; }); | ||
| 139 | |||
| 140 | if (itr == displays.end()) { | ||
| 141 | return std::nullopt; | ||
| 142 | } | ||
| 143 | |||
| 144 | return itr->GetID(); | ||
| 145 | } | ||
| 146 | |||
| 147 | bool Nvnflinger::CloseDisplay(u64 display_id) { | ||
| 148 | const auto lock_guard = Lock(); | ||
| 149 | auto* const display = FindDisplay(display_id); | ||
| 150 | |||
| 151 | if (display == nullptr) { | ||
| 152 | return false; | ||
| 153 | } | ||
| 154 | |||
| 155 | display->Reset(); | ||
| 156 | |||
| 157 | return true; | ||
| 158 | } | ||
| 159 | |||
| 160 | std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) { | ||
| 161 | const auto lock_guard = Lock(); | ||
| 162 | auto* const display = FindDisplay(display_id); | ||
| 163 | |||
| 164 | if (display == nullptr) { | ||
| 165 | return std::nullopt; | ||
| 166 | } | ||
| 167 | |||
| 168 | const u64 layer_id = next_layer_id++; | ||
| 169 | CreateLayerAtId(*display, layer_id, blending); | ||
| 170 | return layer_id; | ||
| 171 | } | ||
| 172 | |||
| 173 | void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) { | ||
| 174 | const auto buffer_id = next_buffer_queue_id++; | ||
| 175 | display.CreateLayer(layer_id, buffer_id, nvdrv->container); | ||
| 176 | display.FindLayer(layer_id)->SetBlending(blending); | ||
| 177 | } | ||
| 178 | |||
| 179 | bool Nvnflinger::OpenLayer(u64 layer_id) { | ||
| 180 | const auto lock_guard = Lock(); | ||
| 181 | |||
| 182 | for (auto& display : displays) { | ||
| 183 | if (auto* layer = display.FindLayer(layer_id); layer) { | ||
| 184 | return layer->Open(); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | return false; | ||
| 189 | } | ||
| 190 | |||
| 191 | bool Nvnflinger::CloseLayer(u64 layer_id) { | ||
| 192 | const auto lock_guard = Lock(); | ||
| 193 | |||
| 194 | for (auto& display : displays) { | ||
| 195 | if (auto* layer = display.FindLayer(layer_id); layer) { | ||
| 196 | return layer->Close(); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | return false; | ||
| 201 | } | ||
| 202 | |||
| 203 | void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) { | ||
| 204 | const auto lock_guard = Lock(); | ||
| 205 | |||
| 206 | for (auto& display : displays) { | ||
| 207 | if (auto* layer = display.FindLayer(layer_id); layer) { | ||
| 208 | layer->SetVisibility(visible); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | void Nvnflinger::DestroyLayer(u64 layer_id) { | ||
| 214 | const auto lock_guard = Lock(); | ||
| 215 | |||
| 216 | for (auto& display : displays) { | ||
| 217 | display.DestroyLayer(layer_id); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) { | ||
| 222 | const auto lock_guard = Lock(); | ||
| 223 | const auto* const layer = FindLayer(display_id, layer_id); | ||
| 224 | |||
| 225 | if (layer == nullptr) { | ||
| 226 | return std::nullopt; | ||
| 227 | } | ||
| 228 | |||
| 229 | return layer->GetBinderId(); | ||
| 230 | } | ||
| 231 | |||
| 232 | Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) { | ||
| 233 | const auto lock_guard = Lock(); | ||
| 234 | auto* const display = FindDisplay(display_id); | ||
| 235 | |||
| 236 | if (display == nullptr) { | ||
| 237 | return VI::ResultNotFound; | ||
| 238 | } | ||
| 239 | |||
| 240 | *out_vsync_event = display->GetVSyncEvent(); | ||
| 241 | return ResultSuccess; | ||
| 242 | } | ||
| 243 | |||
| 244 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { | ||
| 245 | const auto itr = | ||
| 246 | std::find_if(displays.begin(), displays.end(), | ||
| 247 | [&](const VI::Display& display) { return display.GetID() == display_id; }); | ||
| 248 | |||
| 249 | if (itr == displays.end()) { | ||
| 250 | return nullptr; | ||
| 251 | } | ||
| 252 | |||
| 253 | return &*itr; | ||
| 254 | } | ||
| 255 | |||
| 256 | const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const { | ||
| 257 | const auto itr = | ||
| 258 | std::find_if(displays.begin(), displays.end(), | ||
| 259 | [&](const VI::Display& display) { return display.GetID() == display_id; }); | ||
| 260 | |||
| 261 | if (itr == displays.end()) { | ||
| 262 | return nullptr; | ||
| 263 | } | ||
| 264 | |||
| 265 | return &*itr; | ||
| 266 | } | ||
| 267 | |||
| 268 | VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) { | ||
| 269 | auto* const display = FindDisplay(display_id); | ||
| 270 | |||
| 271 | if (display == nullptr) { | ||
| 272 | return nullptr; | ||
| 273 | } | ||
| 274 | |||
| 275 | return display->FindLayer(layer_id); | ||
| 276 | } | ||
| 277 | |||
| 278 | void Nvnflinger::Compose() { | ||
| 279 | for (auto& display : displays) { | ||
| 280 | // Trigger vsync for this display at the end of drawing | ||
| 281 | SCOPE_EXIT({ display.SignalVSyncEvent(); }); | ||
| 282 | |||
| 283 | // Don't do anything for displays without layers. | ||
| 284 | if (!display.HasLayers()) { | ||
| 285 | continue; | ||
| 286 | } | ||
| 287 | |||
| 288 | if (!system.IsPoweredOn()) { | ||
| 289 | return; // We are likely shutting down | ||
| 290 | } | ||
| 291 | |||
| 292 | auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); | ||
| 293 | ASSERT(nvdisp); | ||
| 294 | |||
| 295 | swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | s64 Nvnflinger::GetNextTicks() const { | ||
| 300 | const auto& settings = Settings::values; | ||
| 301 | auto speed_scale = 1.f; | ||
| 302 | if (settings.use_multi_core.GetValue()) { | ||
| 303 | if (settings.use_speed_limit.GetValue()) { | ||
| 304 | // Scales the speed based on speed_limit setting on MC. SC is handled by | ||
| 305 | // SpeedLimiter::DoSpeedLimiting. | ||
| 306 | speed_scale = 100.f / settings.speed_limit.GetValue(); | ||
| 307 | } else { | ||
| 308 | // Run at unlocked framerate. | ||
| 309 | speed_scale = 0.01f; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | // Adjust by speed limit determined during composition. | ||
| 314 | speed_scale /= compose_speed_scale; | ||
| 315 | |||
| 316 | if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { | ||
| 317 | // Run at intended presentation rate during video playback. | ||
| 318 | speed_scale = 1.f; | ||
| 319 | } | ||
| 320 | |||
| 321 | const f32 effective_fps = 60.f / static_cast<f32>(swap_interval); | ||
| 322 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); | ||
| 323 | } | ||
| 324 | |||
| 325 | FbShareBufferManager& Nvnflinger::GetSystemBufferManager() { | ||
| 326 | const auto lock_guard = Lock(); | ||
| 327 | |||
| 328 | if (!system_buffer_manager) { | ||
| 329 | system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv); | ||
| 330 | } | ||
| 331 | 17 | ||
| 332 | return *system_buffer_manager; | 18 | auto server_manager = std::make_unique<ServerManager>(system); |
| 19 | server_manager->RegisterNamedService( | ||
| 20 | "dispdrv", std::make_shared<IHOSBinderDriver>(system, binder_server, surface_flinger)); | ||
| 21 | ServerManager::RunServer(std::move(server_manager)); | ||
| 333 | } | 22 | } |
| 334 | 23 | ||
| 335 | } // namespace Service::Nvnflinger | 24 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 4cf4f069d..5c41f3013 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -3,170 +3,12 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <list> | 6 | namespace Core { |
| 7 | #include <memory> | 7 | class System; |
| 8 | #include <mutex> | 8 | } |
| 9 | #include <optional> | ||
| 10 | #include <thread> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/polyfill_thread.h" | ||
| 15 | #include "common/thread.h" | ||
| 16 | #include "core/hle/result.h" | ||
| 17 | #include "core/hle/service/kernel_helpers.h" | ||
| 18 | #include "core/hle/service/nvnflinger/hwc_layer.h" | ||
| 19 | |||
| 20 | namespace Common { | ||
| 21 | class Event; | ||
| 22 | } // namespace Common | ||
| 23 | |||
| 24 | namespace Core::Timing { | ||
| 25 | class CoreTiming; | ||
| 26 | struct EventType; | ||
| 27 | } // namespace Core::Timing | ||
| 28 | |||
| 29 | namespace Kernel { | ||
| 30 | class KReadableEvent; | ||
| 31 | } // namespace Kernel | ||
| 32 | |||
| 33 | namespace Service::Nvidia { | ||
| 34 | class Module; | ||
| 35 | } // namespace Service::Nvidia | ||
| 36 | |||
| 37 | namespace Service::VI { | ||
| 38 | class Display; | ||
| 39 | class Layer; | ||
| 40 | } // namespace Service::VI | ||
| 41 | |||
| 42 | namespace Service::android { | ||
| 43 | class BufferQueueCore; | ||
| 44 | class BufferQueueProducer; | ||
| 45 | } // namespace Service::android | ||
| 46 | 9 | ||
| 47 | namespace Service::Nvnflinger { | 10 | namespace Service::Nvnflinger { |
| 48 | 11 | ||
| 49 | class FbShareBufferManager; | 12 | void LoopProcess(Core::System& system); |
| 50 | class HardwareComposer; | ||
| 51 | class HosBinderDriverServer; | ||
| 52 | |||
| 53 | class Nvnflinger final { | ||
| 54 | public: | ||
| 55 | explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); | ||
| 56 | ~Nvnflinger(); | ||
| 57 | |||
| 58 | void ShutdownLayers(); | ||
| 59 | |||
| 60 | /// Sets the NVDrv module instance to use to send buffers to the GPU. | ||
| 61 | void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance); | ||
| 62 | |||
| 63 | /// Opens the specified display and returns the ID. | ||
| 64 | /// | ||
| 65 | /// If an invalid display name is provided, then an empty optional is returned. | ||
| 66 | [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name); | ||
| 67 | |||
| 68 | /// Closes the specified display by its ID. | ||
| 69 | /// | ||
| 70 | /// Returns false if an invalid display ID is provided. | ||
| 71 | [[nodiscard]] bool CloseDisplay(u64 display_id); | ||
| 72 | |||
| 73 | /// Creates a layer on the specified display and returns the layer ID. | ||
| 74 | /// | ||
| 75 | /// If an invalid display ID is specified, then an empty optional is returned. | ||
| 76 | [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id, | ||
| 77 | LayerBlending blending = LayerBlending::None); | ||
| 78 | |||
| 79 | /// Opens a layer on all displays for the given layer ID. | ||
| 80 | bool OpenLayer(u64 layer_id); | ||
| 81 | |||
| 82 | /// Closes a layer on all displays for the given layer ID. | ||
| 83 | bool CloseLayer(u64 layer_id); | ||
| 84 | |||
| 85 | /// Makes a layer visible on all displays for the given layer ID. | ||
| 86 | void SetLayerVisibility(u64 layer_id, bool visible); | ||
| 87 | |||
| 88 | /// Destroys the given layer ID. | ||
| 89 | void DestroyLayer(u64 layer_id); | ||
| 90 | |||
| 91 | /// Finds the buffer queue ID of the specified layer in the specified display. | ||
| 92 | /// | ||
| 93 | /// If an invalid display ID or layer ID is provided, then an empty optional is returned. | ||
| 94 | [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id); | ||
| 95 | |||
| 96 | /// Gets the vsync event for the specified display. | ||
| 97 | /// | ||
| 98 | /// If an invalid display ID is provided, then VI::ResultNotFound is returned. | ||
| 99 | /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. | ||
| 100 | [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id); | ||
| 101 | |||
| 102 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when | ||
| 103 | /// finished. | ||
| 104 | void Compose(); | ||
| 105 | |||
| 106 | [[nodiscard]] s64 GetNextTicks() const; | ||
| 107 | |||
| 108 | FbShareBufferManager& GetSystemBufferManager(); | ||
| 109 | |||
| 110 | private: | ||
| 111 | struct Layer { | ||
| 112 | std::unique_ptr<android::BufferQueueCore> core; | ||
| 113 | std::unique_ptr<android::BufferQueueProducer> producer; | ||
| 114 | }; | ||
| 115 | |||
| 116 | friend class FbShareBufferManager; | ||
| 117 | |||
| 118 | private: | ||
| 119 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { | ||
| 120 | return std::unique_lock{*guard}; | ||
| 121 | } | ||
| 122 | |||
| 123 | /// Finds the display identified by the specified ID. | ||
| 124 | [[nodiscard]] VI::Display* FindDisplay(u64 display_id); | ||
| 125 | |||
| 126 | /// Finds the display identified by the specified ID. | ||
| 127 | [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const; | ||
| 128 | |||
| 129 | /// Finds the layer identified by the specified ID in the desired display. | ||
| 130 | [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); | ||
| 131 | |||
| 132 | /// Creates a layer with the specified layer ID in the desired display. | ||
| 133 | void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending); | ||
| 134 | |||
| 135 | void SplitVSync(std::stop_token stop_token); | ||
| 136 | |||
| 137 | std::shared_ptr<Nvidia::Module> nvdrv; | ||
| 138 | s32 disp_fd; | ||
| 139 | |||
| 140 | std::list<VI::Display> displays; | ||
| 141 | |||
| 142 | /// Id to use for the next layer that is created, this counter is shared among all displays. | ||
| 143 | u64 next_layer_id = 1; | ||
| 144 | /// Id to use for the next buffer queue that is created, this counter is shared among all | ||
| 145 | /// layers. | ||
| 146 | u32 next_buffer_queue_id = 1; | ||
| 147 | |||
| 148 | s32 swap_interval = 1; | ||
| 149 | f32 compose_speed_scale = 1.0f; | ||
| 150 | |||
| 151 | bool is_abandoned = false; | ||
| 152 | |||
| 153 | /// Event that handles screen composition. | ||
| 154 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; | ||
| 155 | std::shared_ptr<Core::Timing::EventType> single_composition_event; | ||
| 156 | |||
| 157 | std::unique_ptr<FbShareBufferManager> system_buffer_manager; | ||
| 158 | |||
| 159 | std::shared_ptr<std::mutex> guard; | ||
| 160 | |||
| 161 | Core::System& system; | ||
| 162 | |||
| 163 | Common::Event vsync_signal; | ||
| 164 | |||
| 165 | std::jthread vsync_thread; | ||
| 166 | |||
| 167 | KernelHelpers::ServiceContext service_context; | ||
| 168 | |||
| 169 | HosBinderDriverServer& hos_binder_driver_server; | ||
| 170 | }; | ||
| 171 | 13 | ||
| 172 | } // namespace Service::Nvnflinger | 14 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.cpp b/src/core/hle/service/nvnflinger/surface_flinger.cpp new file mode 100644 index 000000000..41a705717 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp | |||
| @@ -0,0 +1,124 @@ | |||
| 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/devices/nvdisp_disp0.h" | ||
| 6 | #include "core/hle/service/nvdrv/nvdrv_interface.h" | ||
| 7 | #include "core/hle/service/nvnflinger/display.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 | |||
| 12 | #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" | ||
| 13 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | ||
| 14 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | ||
| 15 | |||
| 16 | namespace Service::Nvnflinger { | ||
| 17 | |||
| 18 | SurfaceFlinger::SurfaceFlinger(Core::System& system, HosBinderDriverServer& server) | ||
| 19 | : m_system(system), m_server(server), m_context(m_system, "SurfaceFlinger") { | ||
| 20 | nvdrv = m_system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); | ||
| 21 | disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); | ||
| 22 | } | ||
| 23 | |||
| 24 | SurfaceFlinger::~SurfaceFlinger() { | ||
| 25 | nvdrv->Close(disp_fd); | ||
| 26 | } | ||
| 27 | |||
| 28 | void SurfaceFlinger::AddDisplay(u64 display_id) { | ||
| 29 | m_displays.emplace_back(display_id); | ||
| 30 | } | ||
| 31 | |||
| 32 | void SurfaceFlinger::RemoveDisplay(u64 display_id) { | ||
| 33 | std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; }); | ||
| 34 | } | ||
| 35 | |||
| 36 | bool SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, | ||
| 37 | u64 display_id) { | ||
| 38 | auto* const display = this->FindDisplay(display_id); | ||
| 39 | if (!display || !display->HasLayers()) { | ||
| 40 | return false; | ||
| 41 | } | ||
| 42 | |||
| 43 | *out_swap_interval = | ||
| 44 | m_composer.ComposeLocked(out_compose_speed_scale, *display, | ||
| 45 | *nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd)); | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) { | ||
| 50 | auto* const display = this->FindDisplay(display_id); | ||
| 51 | auto binder = std::static_pointer_cast<android::BufferQueueConsumer>( | ||
| 52 | m_server.TryGetBinder(consumer_binder_id)); | ||
| 53 | |||
| 54 | if (!display || !binder) { | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | |||
| 58 | auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(binder)); | ||
| 59 | buffer_item_consumer->Connect(false); | ||
| 60 | |||
| 61 | display->stack.layers.emplace_back(std::move(buffer_item_consumer), consumer_binder_id); | ||
| 62 | } | ||
| 63 | |||
| 64 | void SurfaceFlinger::RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id) { | ||
| 65 | auto* const display = this->FindDisplay(display_id); | ||
| 66 | if (!display) { | ||
| 67 | return; | ||
| 68 | } | ||
| 69 | |||
| 70 | m_composer.RemoveLayerLocked(*display, consumer_binder_id); | ||
| 71 | std::erase_if(display->stack.layers, | ||
| 72 | [&](auto& layer) { return layer.consumer_id == consumer_binder_id; }); | ||
| 73 | } | ||
| 74 | |||
| 75 | void SurfaceFlinger::SetLayerVisibility(s32 consumer_binder_id, bool visible) { | ||
| 76 | if (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) { | ||
| 77 | layer->visible = visible; | ||
| 78 | return; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) { | ||
| 83 | if (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) { | ||
| 84 | layer->blending = blending; | ||
| 85 | return; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | Display* SurfaceFlinger::FindDisplay(u64 display_id) { | ||
| 90 | for (auto& display : m_displays) { | ||
| 91 | if (display.id == display_id) { | ||
| 92 | return &display; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | return nullptr; | ||
| 97 | } | ||
| 98 | |||
| 99 | Layer* SurfaceFlinger::FindLayer(s32 consumer_binder_id) { | ||
| 100 | for (auto& display : m_displays) { | ||
| 101 | if (auto* layer = display.FindLayer(consumer_binder_id); layer != nullptr) { | ||
| 102 | return layer; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | return nullptr; | ||
| 107 | } | ||
| 108 | |||
| 109 | void SurfaceFlinger::CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id) { | ||
| 110 | auto& nvmap = nvdrv->GetContainer().GetNvMapFile(); | ||
| 111 | auto core = std::make_shared<android::BufferQueueCore>(); | ||
| 112 | auto producer = std::make_shared<android::BufferQueueProducer>(m_context, core, nvmap); | ||
| 113 | auto consumer = std::make_shared<android::BufferQueueConsumer>(core); | ||
| 114 | |||
| 115 | *out_consumer_binder_id = m_server.RegisterBinder(std::move(consumer)); | ||
| 116 | *out_producer_binder_id = m_server.RegisterBinder(std::move(producer)); | ||
| 117 | } | ||
| 118 | |||
| 119 | void SurfaceFlinger::DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id) { | ||
| 120 | m_server.UnregisterBinder(producer_binder_id); | ||
| 121 | m_server.UnregisterBinder(consumer_binder_id); | ||
| 122 | } | ||
| 123 | |||
| 124 | } // namespace Service::Nvnflinger | ||
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.h b/src/core/hle/service/nvnflinger/surface_flinger.h new file mode 100644 index 000000000..d8c53fbda --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/service/kernel_helpers.h" | ||
| 10 | #include "core/hle/service/nvnflinger/hardware_composer.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::Nvidia { | ||
| 17 | class Module; | ||
| 18 | } | ||
| 19 | |||
| 20 | // TODO: ISurfaceComposer | ||
| 21 | // TODO: ISurfaceComposerClient | ||
| 22 | |||
| 23 | namespace Service::Nvnflinger { | ||
| 24 | |||
| 25 | struct Display; | ||
| 26 | class HosBinderDriverServer; | ||
| 27 | enum class LayerBlending : u32; | ||
| 28 | struct Layer; | ||
| 29 | |||
| 30 | class SurfaceFlinger { | ||
| 31 | public: | ||
| 32 | explicit SurfaceFlinger(Core::System& system, HosBinderDriverServer& server); | ||
| 33 | ~SurfaceFlinger(); | ||
| 34 | |||
| 35 | void AddDisplay(u64 display_id); | ||
| 36 | void RemoveDisplay(u64 display_id); | ||
| 37 | bool ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id); | ||
| 38 | |||
| 39 | void AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id); | ||
| 40 | void RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id); | ||
| 41 | |||
| 42 | void SetLayerVisibility(s32 consumer_binder_id, bool visible); | ||
| 43 | void SetLayerBlending(s32 consumer_binder_id, LayerBlending blending); | ||
| 44 | |||
| 45 | private: | ||
| 46 | Display* FindDisplay(u64 display_id); | ||
| 47 | Layer* FindLayer(s32 consumer_binder_id); | ||
| 48 | |||
| 49 | public: | ||
| 50 | // TODO: these don't belong here | ||
| 51 | void CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id); | ||
| 52 | void DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id); | ||
| 53 | |||
| 54 | private: | ||
| 55 | Core::System& m_system; | ||
| 56 | HosBinderDriverServer& m_server; | ||
| 57 | KernelHelpers::ServiceContext m_context; | ||
| 58 | |||
| 59 | std::vector<Display> m_displays; | ||
| 60 | std::shared_ptr<Nvidia::Module> nvdrv; | ||
| 61 | s32 disp_fd; | ||
| 62 | HardwareComposer m_composer; | ||
| 63 | }; | ||
| 64 | |||
| 65 | } // namespace Service::Nvnflinger | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index fbdf217ba..ce5e3b5b4 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -7,68 +7,10 @@ | |||
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/hle/ipc.h" | 9 | #include "core/hle/ipc.h" |
| 10 | #include "core/hle/kernel/k_process.h" | ||
| 11 | #include "core/hle/kernel/k_server_port.h" | ||
| 12 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/service/acc/acc.h" | ||
| 14 | #include "core/hle/service/am/am.h" | ||
| 15 | #include "core/hle/service/aoc/aoc_u.h" | ||
| 16 | #include "core/hle/service/apm/apm.h" | ||
| 17 | #include "core/hle/service/audio/audio.h" | ||
| 18 | #include "core/hle/service/bcat/bcat.h" | ||
| 19 | #include "core/hle/service/bpc/bpc.h" | ||
| 20 | #include "core/hle/service/btdrv/btdrv.h" | ||
| 21 | #include "core/hle/service/btm/btm.h" | ||
| 22 | #include "core/hle/service/caps/caps.h" | ||
| 23 | #include "core/hle/service/erpt/erpt.h" | ||
| 24 | #include "core/hle/service/es/es.h" | ||
| 25 | #include "core/hle/service/eupld/eupld.h" | ||
| 26 | #include "core/hle/service/fatal/fatal.h" | ||
| 27 | #include "core/hle/service/fgm/fgm.h" | ||
| 28 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 29 | #include "core/hle/service/friend/friend.h" | ||
| 30 | #include "core/hle/service/glue/glue.h" | ||
| 31 | #include "core/hle/service/grc/grc.h" | ||
| 32 | #include "core/hle/service/hid/hid.h" | ||
| 33 | #include "core/hle/service/ipc_helpers.h" | 11 | #include "core/hle/service/ipc_helpers.h" |
| 34 | #include "core/hle/service/jit/jit.h" | ||
| 35 | #include "core/hle/service/lbl/lbl.h" | ||
| 36 | #include "core/hle/service/ldn/ldn.h" | ||
| 37 | #include "core/hle/service/ldr/ldr.h" | ||
| 38 | #include "core/hle/service/lm/lm.h" | ||
| 39 | #include "core/hle/service/mig/mig.h" | ||
| 40 | #include "core/hle/service/mii/mii.h" | ||
| 41 | #include "core/hle/service/mm/mm_u.h" | ||
| 42 | #include "core/hle/service/mnpp/mnpp_app.h" | ||
| 43 | #include "core/hle/service/ncm/ncm.h" | ||
| 44 | #include "core/hle/service/nfc/nfc.h" | ||
| 45 | #include "core/hle/service/nfp/nfp.h" | ||
| 46 | #include "core/hle/service/ngc/ngc.h" | ||
| 47 | #include "core/hle/service/nifm/nifm.h" | ||
| 48 | #include "core/hle/service/nim/nim.h" | ||
| 49 | #include "core/hle/service/npns/npns.h" | ||
| 50 | #include "core/hle/service/ns/ns.h" | ||
| 51 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 52 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||
| 53 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 54 | #include "core/hle/service/olsc/olsc.h" | ||
| 55 | #include "core/hle/service/omm/omm.h" | ||
| 56 | #include "core/hle/service/pcie/pcie.h" | ||
| 57 | #include "core/hle/service/pctl/pctl_module.h" | ||
| 58 | #include "core/hle/service/pcv/pcv.h" | ||
| 59 | #include "core/hle/service/pm/pm.h" | ||
| 60 | #include "core/hle/service/prepo/prepo.h" | ||
| 61 | #include "core/hle/service/psc/psc.h" | ||
| 62 | #include "core/hle/service/ptm/ptm.h" | ||
| 63 | #include "core/hle/service/ro/ro.h" | ||
| 64 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 65 | #include "core/hle/service/set/settings.h" | ||
| 66 | #include "core/hle/service/sm/sm.h" | 13 | #include "core/hle/service/sm/sm.h" |
| 67 | #include "core/hle/service/sockets/sockets.h" | ||
| 68 | #include "core/hle/service/spl/spl_module.h" | ||
| 69 | #include "core/hle/service/ssl/ssl.h" | ||
| 70 | #include "core/hle/service/usb/usb.h" | ||
| 71 | #include "core/hle/service/vi/vi.h" | ||
| 72 | #include "core/reporter.h" | 14 | #include "core/reporter.h" |
| 73 | 15 | ||
| 74 | namespace Service { | 16 | namespace Service { |
| @@ -209,82 +151,4 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | |||
| 209 | return result; | 151 | return result; |
| 210 | } | 152 | } |
| 211 | 153 | ||
| 212 | /// Initialize Services | ||
| 213 | Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) | ||
| 214 | : hos_binder_driver_server{std::make_unique<Nvnflinger::HosBinderDriverServer>(system)}, | ||
| 215 | nv_flinger{std::make_unique<Nvnflinger::Nvnflinger>(system, *hos_binder_driver_server)} { | ||
| 216 | |||
| 217 | auto& kernel = system.Kernel(); | ||
| 218 | |||
| 219 | // Nvnflinger needs to be accessed by several services like Vi and AppletOE so we instantiate it | ||
| 220 | // here and pass it into the respective InstallInterfaces functions. | ||
| 221 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); | ||
| 222 | |||
| 223 | // clang-format off | ||
| 224 | kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach(); | ||
| 225 | kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach(); | ||
| 226 | kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach(); | ||
| 227 | kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach(); | ||
| 228 | kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach(); | ||
| 229 | kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach(); | ||
| 230 | kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach(); | ||
| 231 | kernel.RunOnHostCoreProcess("vi", [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach(); | ||
| 232 | |||
| 233 | kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); }); | ||
| 234 | kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); }); | ||
| 235 | kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(*nv_flinger, system); }); | ||
| 236 | kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); }); | ||
| 237 | kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); }); | ||
| 238 | kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); }); | ||
| 239 | kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); }); | ||
| 240 | kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); }); | ||
| 241 | kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); }); | ||
| 242 | kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); }); | ||
| 243 | kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); }); | ||
| 244 | kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); }); | ||
| 245 | kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); }); | ||
| 246 | kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); }); | ||
| 247 | kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); }); | ||
| 248 | kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); }); | ||
| 249 | // glue depends on settings and psc, so they must come first | ||
| 250 | kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); }); | ||
| 251 | kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); }); | ||
| 252 | kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); }); | ||
| 253 | kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); }); | ||
| 254 | kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); }); | ||
| 255 | kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); }); | ||
| 256 | kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); | ||
| 257 | kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); }); | ||
| 258 | kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); }); | ||
| 259 | kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); }); | ||
| 260 | kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); }); | ||
| 261 | kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); }); | ||
| 262 | kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); }); | ||
| 263 | kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); }); | ||
| 264 | kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); }); | ||
| 265 | kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); }); | ||
| 266 | kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); }); | ||
| 267 | kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); | ||
| 268 | kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); }); | ||
| 269 | kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); }); | ||
| 270 | kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); }); | ||
| 271 | kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); }); | ||
| 272 | kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); }); | ||
| 273 | kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); }); | ||
| 274 | kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); }); | ||
| 275 | kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); | ||
| 276 | kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); }); | ||
| 277 | kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); }); | ||
| 278 | kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); }); | ||
| 279 | kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); }); | ||
| 280 | kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); }); | ||
| 281 | // clang-format on | ||
| 282 | } | ||
| 283 | |||
| 284 | Services::~Services() = default; | ||
| 285 | |||
| 286 | void Services::KillNVNFlinger() { | ||
| 287 | nv_flinger->ShutdownLayers(); | ||
| 288 | } | ||
| 289 | |||
| 290 | } // namespace Service | 154 | } // namespace Service |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 22d1343d5..36aae1c79 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -28,11 +28,6 @@ namespace FileSystem { | |||
| 28 | class FileSystemController; | 28 | class FileSystemController; |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | namespace Nvnflinger { | ||
| 32 | class HosBinderDriverServer; | ||
| 33 | class Nvnflinger; | ||
| 34 | } // namespace Nvnflinger | ||
| 35 | |||
| 36 | namespace SM { | 31 | namespace SM { |
| 37 | class ServiceManager; | 32 | class ServiceManager; |
| 38 | } | 33 | } |
| @@ -236,20 +231,4 @@ private: | |||
| 236 | } | 231 | } |
| 237 | }; | 232 | }; |
| 238 | 233 | ||
| 239 | /** | ||
| 240 | * The purpose of this class is to own any objects that need to be shared across the other service | ||
| 241 | * implementations. Will be torn down when the global system instance is shutdown. | ||
| 242 | */ | ||
| 243 | class Services final { | ||
| 244 | public: | ||
| 245 | explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); | ||
| 246 | ~Services(); | ||
| 247 | |||
| 248 | void KillNVNFlinger(); | ||
| 249 | |||
| 250 | private: | ||
| 251 | std::unique_ptr<Nvnflinger::HosBinderDriverServer> hos_binder_driver_server; | ||
| 252 | std::unique_ptr<Nvnflinger::Nvnflinger> nv_flinger; | ||
| 253 | }; | ||
| 254 | |||
| 255 | } // namespace Service | 234 | } // namespace Service |
diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp new file mode 100644 index 000000000..d6c6eff50 --- /dev/null +++ b/src/core/hle/service/services.cpp | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/services.h" | ||
| 5 | |||
| 6 | #include "core/hle/service/acc/acc.h" | ||
| 7 | #include "core/hle/service/am/am.h" | ||
| 8 | #include "core/hle/service/aoc/aoc_u.h" | ||
| 9 | #include "core/hle/service/apm/apm.h" | ||
| 10 | #include "core/hle/service/audio/audio.h" | ||
| 11 | #include "core/hle/service/bcat/bcat.h" | ||
| 12 | #include "core/hle/service/bpc/bpc.h" | ||
| 13 | #include "core/hle/service/btdrv/btdrv.h" | ||
| 14 | #include "core/hle/service/btm/btm.h" | ||
| 15 | #include "core/hle/service/caps/caps.h" | ||
| 16 | #include "core/hle/service/erpt/erpt.h" | ||
| 17 | #include "core/hle/service/es/es.h" | ||
| 18 | #include "core/hle/service/eupld/eupld.h" | ||
| 19 | #include "core/hle/service/fatal/fatal.h" | ||
| 20 | #include "core/hle/service/fgm/fgm.h" | ||
| 21 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 22 | #include "core/hle/service/friend/friend.h" | ||
| 23 | #include "core/hle/service/glue/glue.h" | ||
| 24 | #include "core/hle/service/grc/grc.h" | ||
| 25 | #include "core/hle/service/hid/hid.h" | ||
| 26 | #include "core/hle/service/ipc_helpers.h" | ||
| 27 | #include "core/hle/service/jit/jit.h" | ||
| 28 | #include "core/hle/service/lbl/lbl.h" | ||
| 29 | #include "core/hle/service/ldn/ldn.h" | ||
| 30 | #include "core/hle/service/ldr/ldr.h" | ||
| 31 | #include "core/hle/service/lm/lm.h" | ||
| 32 | #include "core/hle/service/mig/mig.h" | ||
| 33 | #include "core/hle/service/mii/mii.h" | ||
| 34 | #include "core/hle/service/mm/mm_u.h" | ||
| 35 | #include "core/hle/service/mnpp/mnpp_app.h" | ||
| 36 | #include "core/hle/service/ncm/ncm.h" | ||
| 37 | #include "core/hle/service/nfc/nfc.h" | ||
| 38 | #include "core/hle/service/nfp/nfp.h" | ||
| 39 | #include "core/hle/service/ngc/ngc.h" | ||
| 40 | #include "core/hle/service/nifm/nifm.h" | ||
| 41 | #include "core/hle/service/nim/nim.h" | ||
| 42 | #include "core/hle/service/npns/npns.h" | ||
| 43 | #include "core/hle/service/ns/ns.h" | ||
| 44 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 45 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 46 | #include "core/hle/service/olsc/olsc.h" | ||
| 47 | #include "core/hle/service/omm/omm.h" | ||
| 48 | #include "core/hle/service/pcie/pcie.h" | ||
| 49 | #include "core/hle/service/pctl/pctl_module.h" | ||
| 50 | #include "core/hle/service/pcv/pcv.h" | ||
| 51 | #include "core/hle/service/pm/pm.h" | ||
| 52 | #include "core/hle/service/prepo/prepo.h" | ||
| 53 | #include "core/hle/service/psc/psc.h" | ||
| 54 | #include "core/hle/service/ptm/ptm.h" | ||
| 55 | #include "core/hle/service/ro/ro.h" | ||
| 56 | #include "core/hle/service/service.h" | ||
| 57 | #include "core/hle/service/set/settings.h" | ||
| 58 | #include "core/hle/service/sm/sm.h" | ||
| 59 | #include "core/hle/service/sockets/sockets.h" | ||
| 60 | #include "core/hle/service/spl/spl_module.h" | ||
| 61 | #include "core/hle/service/ssl/ssl.h" | ||
| 62 | #include "core/hle/service/usb/usb.h" | ||
| 63 | #include "core/hle/service/vi/vi.h" | ||
| 64 | |||
| 65 | namespace Service { | ||
| 66 | |||
| 67 | Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | ||
| 68 | std::stop_token token) { | ||
| 69 | auto& kernel = system.Kernel(); | ||
| 70 | |||
| 71 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); | ||
| 72 | |||
| 73 | // clang-format off | ||
| 74 | kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach(); | ||
| 75 | kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach(); | ||
| 76 | kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach(); | ||
| 77 | kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach(); | ||
| 78 | kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach(); | ||
| 79 | kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(system); }).detach(); | ||
| 80 | kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach(); | ||
| 81 | kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach(); | ||
| 82 | |||
| 83 | kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); }); | ||
| 84 | kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); }); | ||
| 85 | kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(system); }); | ||
| 86 | kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); }); | ||
| 87 | kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); }); | ||
| 88 | kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); }); | ||
| 89 | kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); }); | ||
| 90 | kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); }); | ||
| 91 | kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); }); | ||
| 92 | kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); }); | ||
| 93 | kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); }); | ||
| 94 | kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); }); | ||
| 95 | kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); }); | ||
| 96 | kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); }); | ||
| 97 | kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); }); | ||
| 98 | kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); }); | ||
| 99 | kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); }); | ||
| 100 | kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); }); | ||
| 101 | kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); }); | ||
| 102 | kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); }); | ||
| 103 | kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); }); | ||
| 104 | kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); }); | ||
| 105 | kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); }); | ||
| 106 | kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); }); | ||
| 107 | kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); }); | ||
| 108 | kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); }); | ||
| 109 | kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); }); | ||
| 110 | kernel.RunOnGuestCoreProcess("nvnflinger", [&] { Nvnflinger::LoopProcess(system); }); | ||
| 111 | kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); }); | ||
| 112 | kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); }); | ||
| 113 | kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); }); | ||
| 114 | kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); }); | ||
| 115 | kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); }); | ||
| 116 | kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); }); | ||
| 117 | kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); | ||
| 118 | kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); }); | ||
| 119 | kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); }); | ||
| 120 | kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); }); | ||
| 121 | kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); }); | ||
| 122 | kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); }); | ||
| 123 | kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); }); | ||
| 124 | kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); }); | ||
| 125 | kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); }); | ||
| 126 | kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); }); | ||
| 127 | kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); }); | ||
| 128 | kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); }); | ||
| 129 | kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); }); | ||
| 130 | kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); }); | ||
| 131 | // clang-format on | ||
| 132 | } | ||
| 133 | |||
| 134 | Services::~Services() = default; | ||
| 135 | |||
| 136 | } // namespace Service | ||
diff --git a/src/core/hle/service/services.h b/src/core/hle/service/services.h new file mode 100644 index 000000000..a99fa1e53 --- /dev/null +++ b/src/core/hle/service/services.h | |||
| @@ -0,0 +1,22 @@ | |||
| 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/polyfill_thread.h" | ||
| 7 | #include "core/hle/service/sm/sm.h" | ||
| 8 | |||
| 9 | namespace Service { | ||
| 10 | |||
| 11 | /** | ||
| 12 | * The purpose of this class is to own any objects that need to be shared across the other service | ||
| 13 | * implementations. Will be torn down when the global system instance is shutdown. | ||
| 14 | */ | ||
| 15 | class Services final { | ||
| 16 | public: | ||
| 17 | explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, | ||
| 18 | std::stop_token token); | ||
| 19 | ~Services(); | ||
| 20 | }; | ||
| 21 | |||
| 22 | } // namespace Service | ||
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp index 78229e30f..6b0bcb536 100644 --- a/src/core/hle/service/vi/application_display_service.cpp +++ b/src/core/hle/service/vi/application_display_service.cpp | |||
| @@ -2,22 +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/nvnflinger/hos_binder_driver.h" |
| 6 | #include "core/hle/service/nvnflinger/parcel.h" | 6 | #include "core/hle/service/nvnflinger/parcel.h" |
| 7 | #include "core/hle/service/os/event.h" | ||
| 7 | #include "core/hle/service/vi/application_display_service.h" | 8 | #include "core/hle/service/vi/application_display_service.h" |
| 8 | #include "core/hle/service/vi/hos_binder_driver.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_, Nvnflinger::Nvnflinger& nvnflinger, | 17 | std::shared_ptr<Container> container) |
| 17 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | 18 | : ServiceFramework{system_, "IApplicationDisplayService"}, |
| 18 | : ServiceFramework{system_, "IApplicationDisplayService"}, m_nvnflinger{nvnflinger}, | 19 | m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} { |
| 19 | m_hos_binder_driver_server{hos_binder_driver_server} { | ||
| 20 | |||
| 21 | // clang-format off | 20 | // clang-format off |
| 22 | static const FunctionInfo functions[] = { | 21 | static const FunctionInfo functions[] = { |
| 23 | {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, | 22 | {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, |
| @@ -48,38 +47,41 @@ IApplicationDisplayService::IApplicationDisplayService( | |||
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | 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 | } | ||
| 51 | for (const auto layer_id : m_stray_layer_ids) { | 56 | for (const auto layer_id : m_stray_layer_ids) { |
| 52 | m_nvnflinger.DestroyLayer(layer_id); | 57 | m_container->DestroyStrayLayer(layer_id); |
| 53 | } | 58 | } |
| 54 | } | 59 | } |
| 55 | 60 | ||
| 56 | Result IApplicationDisplayService::GetRelayService( | 61 | Result IApplicationDisplayService::GetRelayService( |
| 57 | Out<SharedPointer<IHOSBinderDriver>> out_relay_service) { | 62 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) { |
| 58 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 63 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 59 | *out_relay_service = std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); | 64 | R_RETURN(m_container->GetBinderDriver(out_relay_service)); |
| 60 | R_SUCCEED(); | ||
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | Result IApplicationDisplayService::GetSystemDisplayService( | 67 | Result IApplicationDisplayService::GetSystemDisplayService( |
| 64 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { | 68 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { |
| 65 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 69 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 66 | *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_nvnflinger); | 70 | *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_container); |
| 67 | R_SUCCEED(); | 71 | R_SUCCEED(); |
| 68 | } | 72 | } |
| 69 | 73 | ||
| 70 | Result IApplicationDisplayService::GetManagerDisplayService( | 74 | Result IApplicationDisplayService::GetManagerDisplayService( |
| 71 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { | 75 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { |
| 72 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 76 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 73 | *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_nvnflinger); | 77 | *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_container); |
| 74 | R_SUCCEED(); | 78 | R_SUCCEED(); |
| 75 | } | 79 | } |
| 76 | 80 | ||
| 77 | Result IApplicationDisplayService::GetIndirectDisplayTransactionService( | 81 | Result IApplicationDisplayService::GetIndirectDisplayTransactionService( |
| 78 | Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service) { | 82 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) { |
| 79 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 83 | LOG_WARNING(Service_VI, "(STUBBED) called"); |
| 80 | *out_indirect_display_transaction_service = | 84 | R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service)); |
| 81 | std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); | ||
| 82 | R_SUCCEED(); | ||
| 83 | } | 85 | } |
| 84 | 86 | ||
| 85 | Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { | 87 | Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { |
| @@ -89,14 +91,7 @@ Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayN | |||
| 89 | ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, | 91 | ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, |
| 90 | "Non-default displays aren't supported yet"); | 92 | "Non-default displays aren't supported yet"); |
| 91 | 93 | ||
| 92 | const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); | 94 | R_RETURN(m_container->OpenDisplay(out_display_id, display_name)); |
| 93 | if (!display_id) { | ||
| 94 | LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); | ||
| 95 | R_THROW(VI::ResultNotFound); | ||
| 96 | } | ||
| 97 | |||
| 98 | *out_display_id = *display_id; | ||
| 99 | R_SUCCEED(); | ||
| 100 | } | 95 | } |
| 101 | 96 | ||
| 102 | Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { | 97 | Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { |
| @@ -106,8 +101,7 @@ Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { | |||
| 106 | 101 | ||
| 107 | Result IApplicationDisplayService::CloseDisplay(u64 display_id) { | 102 | Result IApplicationDisplayService::CloseDisplay(u64 display_id) { |
| 108 | LOG_DEBUG(Service_VI, "called"); | 103 | LOG_DEBUG(Service_VI, "called"); |
| 109 | R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id)); | 104 | R_RETURN(m_container->CloseDisplay(display_id)); |
| 110 | R_THROW(ResultUnknown); | ||
| 111 | } | 105 | } |
| 112 | 106 | ||
| 113 | Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { | 107 | Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { |
| @@ -168,25 +162,19 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, | |||
| 168 | 162 | ||
| 169 | 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); |
| 170 | 164 | ||
| 171 | const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); | 165 | u64 display_id; |
| 172 | if (!display_id) { | 166 | R_TRY(m_container->OpenDisplay(&display_id, display_name)); |
| 173 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||
| 174 | R_THROW(VI::ResultNotFound); | ||
| 175 | } | ||
| 176 | 167 | ||
| 177 | const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id); | 168 | s32 producer_binder_id; |
| 178 | if (!buffer_queue_id) { | 169 | R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid)); |
| 179 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||
| 180 | R_THROW(VI::ResultNotFound); | ||
| 181 | } | ||
| 182 | 170 | ||
| 183 | if (!m_nvnflinger.OpenLayer(layer_id)) { | 171 | { |
| 184 | LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | 172 | std::scoped_lock lk{m_lock}; |
| 185 | R_THROW(VI::ResultOperationFailed); | 173 | m_open_layer_ids.insert(layer_id); |
| 186 | } | 174 | } |
| 187 | 175 | ||
| 188 | android::OutputParcel parcel; | 176 | android::OutputParcel parcel; |
| 189 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 177 | parcel.WriteInterface(NativeWindow{producer_binder_id}); |
| 190 | 178 | ||
| 191 | const auto buffer = parcel.Serialize(); | 179 | const auto buffer = parcel.Serialize(); |
| 192 | std::memcpy(out_native_window.data(), buffer.data(), | 180 | std::memcpy(out_native_window.data(), buffer.data(), |
| @@ -199,12 +187,13 @@ Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, | |||
| 199 | Result IApplicationDisplayService::CloseLayer(u64 layer_id) { | 187 | Result IApplicationDisplayService::CloseLayer(u64 layer_id) { |
| 200 | LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); | 188 | LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); |
| 201 | 189 | ||
| 202 | if (!m_nvnflinger.CloseLayer(layer_id)) { | 190 | { |
| 203 | LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | 191 | std::scoped_lock lk{m_lock}; |
| 204 | R_THROW(VI::ResultOperationFailed); | 192 | R_UNLESS(m_open_layer_ids.contains(layer_id), VI::ResultNotFound); |
| 193 | m_open_layer_ids.erase(layer_id); | ||
| 205 | } | 194 | } |
| 206 | 195 | ||
| 207 | R_SUCCEED(); | 196 | R_RETURN(m_container->CloseLayer(layer_id)); |
| 208 | } | 197 | } |
| 209 | 198 | ||
| 210 | Result IApplicationDisplayService::CreateStrayLayer( | 199 | Result IApplicationDisplayService::CreateStrayLayer( |
| @@ -212,27 +201,19 @@ Result IApplicationDisplayService::CreateStrayLayer( | |||
| 212 | u32 flags, u64 display_id) { | 201 | u32 flags, u64 display_id) { |
| 213 | LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); | 202 | LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); |
| 214 | 203 | ||
| 215 | const auto layer_id = m_nvnflinger.CreateLayer(display_id); | 204 | s32 producer_binder_id; |
| 216 | if (!layer_id) { | 205 | R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id)); |
| 217 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||
| 218 | R_THROW(VI::ResultNotFound); | ||
| 219 | } | ||
| 220 | 206 | ||
| 221 | m_stray_layer_ids.push_back(*layer_id); | 207 | std::scoped_lock lk{m_lock}; |
| 222 | const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id); | 208 | m_stray_layer_ids.insert(*out_layer_id); |
| 223 | if (!buffer_queue_id) { | ||
| 224 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||
| 225 | R_THROW(VI::ResultNotFound); | ||
| 226 | } | ||
| 227 | 209 | ||
| 228 | android::OutputParcel parcel; | 210 | android::OutputParcel parcel; |
| 229 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 211 | parcel.WriteInterface(NativeWindow{producer_binder_id}); |
| 230 | 212 | ||
| 231 | const auto buffer = parcel.Serialize(); | 213 | const auto buffer = parcel.Serialize(); |
| 232 | std::memcpy(out_native_window.data(), buffer.data(), | 214 | std::memcpy(out_native_window.data(), buffer.data(), |
| 233 | std::min(out_native_window.size(), buffer.size())); | 215 | std::min(out_native_window.size(), buffer.size())); |
| 234 | 216 | ||
| 235 | *out_layer_id = *layer_id; | ||
| 236 | *out_size = buffer.size(); | 217 | *out_size = buffer.size(); |
| 237 | 218 | ||
| 238 | R_SUCCEED(); | 219 | R_SUCCEED(); |
| @@ -240,25 +221,27 @@ Result IApplicationDisplayService::CreateStrayLayer( | |||
| 240 | 221 | ||
| 241 | Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { | 222 | Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { |
| 242 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | 223 | LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); |
| 243 | m_nvnflinger.DestroyLayer(layer_id); | 224 | |
| 244 | 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)); | ||
| 245 | } | 232 | } |
| 246 | 233 | ||
| 247 | Result IApplicationDisplayService::GetDisplayVsyncEvent( | 234 | Result IApplicationDisplayService::GetDisplayVsyncEvent( |
| 248 | OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { | 235 | OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { |
| 249 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | 236 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 250 | 237 | ||
| 251 | const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id); | 238 | std::scoped_lock lk{m_lock}; |
| 252 | if (result != ResultSuccess) { | ||
| 253 | if (result == ResultNotFound) { | ||
| 254 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||
| 255 | } | ||
| 256 | 239 | ||
| 257 | R_THROW(result); | 240 | auto [it, created] = m_display_vsync_events.emplace(display_id, m_context); |
| 258 | } | 241 | R_UNLESS(created, VI::ResultPermissionDenied); |
| 259 | 242 | ||
| 260 | R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); | 243 | m_container->LinkVsyncEvent(display_id, &it->second); |
| 261 | m_vsync_event_fetched = true; | 244 | *out_vsync_event = it->second.GetHandle(); |
| 262 | 245 | ||
| 263 | R_SUCCEED(); | 246 | R_SUCCEED(); |
| 264 | } | 247 | } |
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h index 5dff4bb31..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 | ||
| @@ -9,26 +14,33 @@ namespace Kernel { | |||
| 9 | class KReadableEvent; | 14 | class KReadableEvent; |
| 10 | } | 15 | } |
| 11 | 16 | ||
| 17 | namespace Service::Nvnflinger { | ||
| 18 | class IHOSBinderDriver; | ||
| 19 | } | ||
| 20 | |||
| 12 | namespace Service::VI { | 21 | namespace Service::VI { |
| 13 | 22 | ||
| 14 | class IHOSBinderDriver; | 23 | class Container; |
| 15 | class IManagerDisplayService; | 24 | class IManagerDisplayService; |
| 16 | class ISystemDisplayService; | 25 | class ISystemDisplayService; |
| 17 | 26 | ||
| 18 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | 27 | class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { |
| 19 | public: | 28 | public: |
| 20 | IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | 29 | IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container); |
| 21 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
| 22 | ~IApplicationDisplayService() override; | 30 | ~IApplicationDisplayService() override; |
| 23 | 31 | ||
| 24 | private: | 32 | std::shared_ptr<Container> GetContainer() const { |
| 25 | Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service); | 33 | return m_container; |
| 34 | } | ||
| 35 | |||
| 36 | public: | ||
| 37 | Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service); | ||
| 26 | Result GetSystemDisplayService( | 38 | Result GetSystemDisplayService( |
| 27 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service); | 39 | Out<SharedPointer<ISystemDisplayService>> out_system_display_service); |
| 28 | Result GetManagerDisplayService( | 40 | Result GetManagerDisplayService( |
| 29 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service); | 41 | Out<SharedPointer<IManagerDisplayService>> out_manager_display_service); |
| 30 | Result GetIndirectDisplayTransactionService( | 42 | Result GetIndirectDisplayTransactionService( |
| 31 | Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service); | 43 | Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service); |
| 32 | Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name); | 44 | Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name); |
| 33 | Result OpenDefaultDisplay(Out<u64> out_display_id); | 45 | Result OpenDefaultDisplay(Out<u64> out_display_id); |
| 34 | Result CloseDisplay(u64 display_id); | 46 | Result CloseDisplay(u64 display_id); |
| @@ -56,9 +68,13 @@ private: | |||
| 56 | s64 width, s64 height); | 68 | s64 width, s64 height); |
| 57 | 69 | ||
| 58 | private: | 70 | private: |
| 59 | Nvnflinger::Nvnflinger& m_nvnflinger; | 71 | const std::shared_ptr<Container> m_container; |
| 60 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | 72 | |
| 61 | std::vector<u64> m_stray_layer_ids; | 73 | KernelHelpers::ServiceContext m_context; |
| 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{}; | ||
| 62 | bool m_vsync_event_fetched{false}; | 78 | bool m_vsync_event_fetched{false}; |
| 63 | }; | 79 | }; |
| 64 | 80 | ||
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp index 7af7f062c..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_, Nvnflinger::Nvnflinger& nvnflinger, | 15 | std::shared_ptr<Container> container) |
| 15 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | 16 | : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} { |
| 16 | : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||
| 17 | hos_binder_driver_server} { | ||
| 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_nvnflinger, | 29 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, |
| 31 | m_hos_binder_driver_server, 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 9dbf28cb4..15aa4483d 100644 --- a/src/core/hle/service/vi/application_root_service.h +++ b/src/core/hle/service/vi/application_root_service.h | |||
| @@ -10,20 +10,15 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::Nvnflinger { | ||
| 14 | class HosBinderDriverServer; | ||
| 15 | class Nvnflinger; | ||
| 16 | } // namespace Service::Nvnflinger | ||
| 17 | |||
| 18 | namespace Service::VI { | 13 | namespace Service::VI { |
| 19 | 14 | ||
| 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_, Nvnflinger::Nvnflinger& nvnflinger, | 21 | explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
| 27 | ~IApplicationRootService() override; | 22 | ~IApplicationRootService() override; |
| 28 | 23 | ||
| 29 | private: | 24 | private: |
| @@ -32,8 +27,7 @@ private: | |||
| 32 | Policy policy); | 27 | Policy policy); |
| 33 | 28 | ||
| 34 | private: | 29 | private: |
| 35 | Nvnflinger::Nvnflinger& m_nvnflinger; | 30 | const std::shared_ptr<Container> m_container; |
| 36 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||
| 37 | }; | 31 | }; |
| 38 | 32 | ||
| 39 | } // 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..310a207f1 --- /dev/null +++ b/src/core/hle/service/vi/container.cpp | |||
| @@ -0,0 +1,228 @@ | |||
| 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 | bool Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, | ||
| 222 | u64 display_id) { | ||
| 223 | std::scoped_lock lk{m_lock}; | ||
| 224 | return m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale, | ||
| 225 | display_id); | ||
| 226 | } | ||
| 227 | |||
| 228 | } // 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..cd0d2ca86 --- /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 | bool 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 17f2f3b8f..9f856282e 100644 --- a/src/core/hle/service/vi/manager_display_service.cpp +++ b/src/core/hle/service/vi/manager_display_service.cpp | |||
| @@ -2,22 +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(Core::System& system_, | 10 | IManagerDisplayService::IManagerDisplayService(Core::System& system_, |
| 12 | Nvnflinger::Nvnflinger& nvnflinger) | 11 | std::shared_ptr<Container> container) |
| 13 | : ServiceFramework{system_, "IManagerDisplayService"}, m_nvnflinger{nvnflinger} { | 12 | : ServiceFramework{system_, "IManagerDisplayService"}, m_container{std::move(container)} { |
| 14 | // clang-format off | 13 | // clang-format off |
| 15 | static const FunctionInfo functions[] = { | 14 | static const FunctionInfo functions[] = { |
| 16 | {200, nullptr, "AllocateProcessHeapBlock"}, | 15 | {200, nullptr, "AllocateProcessHeapBlock"}, |
| 17 | {201, nullptr, "FreeProcessHeapBlock"}, | 16 | {201, nullptr, "FreeProcessHeapBlock"}, |
| 18 | {1102, nullptr, "GetDisplayResolution"}, | 17 | {1102, nullptr, "GetDisplayResolution"}, |
| 19 | {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, | 18 | {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"}, |
| 20 | {2011, nullptr, "DestroyManagedLayer"}, | 19 | {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"}, |
| 21 | {2012, nullptr, "CreateStrayLayer"}, | 20 | {2012, nullptr, "CreateStrayLayer"}, |
| 22 | {2050, nullptr, "CreateIndirectLayer"}, | 21 | {2050, nullptr, "CreateIndirectLayer"}, |
| 23 | {2051, nullptr, "DestroyIndirectLayer"}, | 22 | {2051, nullptr, "DestroyIndirectLayer"}, |
| @@ -102,19 +101,30 @@ IManagerDisplayService::IManagerDisplayService(Core::System& system_, | |||
| 102 | 101 | ||
| 103 | IManagerDisplayService::~IManagerDisplayService() = default; | 102 | IManagerDisplayService::~IManagerDisplayService() = default; |
| 104 | 103 | ||
| 105 | Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, | 104 | Result IManagerDisplayService::CreateSharedLayerSession(Kernel::KProcess* owner_process, |
| 106 | u64 display_id, AppletResourceUserId aruid) { | 105 | u64* out_buffer_id, u64* out_layer_handle, |
| 107 | LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, | 106 | u64 display_id, bool enable_blending) { |
| 108 | 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 | } | ||
| 109 | 110 | ||
| 110 | const auto layer_id = m_nvnflinger.CreateLayer(display_id); | 111 | void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) { |
| 111 | if (!layer_id) { | 112 | m_container->GetSharedBufferManager()->DestroySession(owner_process); |
| 112 | LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); | 113 | } |
| 113 | R_THROW(VI::ResultNotFound); | ||
| 114 | } | ||
| 115 | 114 | ||
| 116 | *out_layer_id = *layer_id; | 115 | Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) { |
| 117 | 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)); | ||
| 118 | } | 128 | } |
| 119 | 129 | ||
| 120 | Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { | 130 | Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { |
| @@ -123,8 +133,8 @@ Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { | |||
| 123 | } | 133 | } |
| 124 | 134 | ||
| 125 | Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | 135 | Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { |
| 126 | LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); | 136 | LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); |
| 127 | R_SUCCEED(); | 137 | R_RETURN(m_container->SetLayerVisibility(layer_id, visible)); |
| 128 | } | 138 | } |
| 129 | 139 | ||
| 130 | } // 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 60e646ee0..b1bdf7f41 100644 --- a/src/core/hle/service/vi/manager_display_service.h +++ b/src/core/hle/service/vi/manager_display_service.h | |||
| @@ -4,21 +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_, Nvnflinger::Nvnflinger& nvnflinger); | 17 | explicit IManagerDisplayService(Core::System& system_, std::shared_ptr<Container> container); |
| 12 | ~IManagerDisplayService() override; | 18 | ~IManagerDisplayService() override; |
| 13 | 19 | ||
| 14 | private: | 20 | Result CreateSharedLayerSession(Kernel::KProcess* owner_process, u64* out_buffer_id, |
| 15 | 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, | ||
| 16 | AppletResourceUserId aruid); | 28 | AppletResourceUserId aruid); |
| 29 | Result DestroyManagedLayer(u64 layer_id); | ||
| 17 | Result AddToLayerStack(u32 stack_id, u64 layer_id); | 30 | Result AddToLayerStack(u32 stack_id, u64 layer_id); |
| 18 | Result SetLayerVisibility(bool visible, u64 layer_id); | 31 | Result SetLayerVisibility(bool visible, u64 layer_id); |
| 19 | 32 | ||
| 20 | private: | 33 | private: |
| 21 | Nvnflinger::Nvnflinger& m_nvnflinger; | 34 | const std::shared_ptr<Container> m_container; |
| 22 | }; | 35 | }; |
| 23 | 36 | ||
| 24 | } // 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 a7eee4f04..0f16a15b4 100644 --- a/src/core/hle/service/vi/manager_root_service.cpp +++ b/src/core/hle/service/vi/manager_root_service.cpp | |||
| @@ -2,7 +2,9 @@ | |||
| 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/hos_binder_driver.h" | ||
| 5 | #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" | ||
| 6 | #include "core/hle/service/vi/manager_root_service.h" | 8 | #include "core/hle/service/vi/manager_root_service.h" |
| 7 | #include "core/hle/service/vi/service_creator.h" | 9 | #include "core/hle/service/vi/service_creator.h" |
| 8 | #include "core/hle/service/vi/vi.h" | 10 | #include "core/hle/service/vi/vi.h" |
| @@ -10,11 +12,9 @@ | |||
| 10 | 12 | ||
| 11 | namespace Service::VI { | 13 | namespace Service::VI { |
| 12 | 14 | ||
| 13 | IManagerRootService::IManagerRootService( | 15 | IManagerRootService::IManagerRootService(Core::System& system_, |
| 14 | Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | 16 | std::shared_ptr<Container> container) |
| 15 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | 17 | : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} { |
| 16 | : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||
| 17 | hos_binder_driver_server} { | ||
| 18 | static const FunctionInfo functions[] = { | 18 | static const FunctionInfo functions[] = { |
| 19 | {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, | 19 | {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, |
| 20 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 20 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
| @@ -31,8 +31,8 @@ IManagerRootService::~IManagerRootService() = default; | |||
| 31 | Result IManagerRootService::GetDisplayService( | 31 | Result IManagerRootService::GetDisplayService( |
| 32 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | 32 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { |
| 33 | LOG_DEBUG(Service_VI, "called"); | 33 | LOG_DEBUG(Service_VI, "called"); |
| 34 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | 34 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, |
| 35 | m_hos_binder_driver_server, Permission::Manager, policy)); | 35 | Permission::Manager, policy)); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | } // 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 e6cb77aeb..77cd32869 100644 --- a/src/core/hle/service/vi/manager_root_service.h +++ b/src/core/hle/service/vi/manager_root_service.h | |||
| @@ -10,29 +10,23 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::Nvnflinger { | ||
| 14 | class HosBinderDriverServer; | ||
| 15 | class Nvnflinger; | ||
| 16 | } // namespace Service::Nvnflinger | ||
| 17 | |||
| 18 | namespace Service::VI { | 13 | namespace Service::VI { |
| 19 | 14 | ||
| 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_, Nvnflinger::Nvnflinger& nvnflinger, | 21 | explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
| 27 | ~IManagerRootService() override; | 22 | ~IManagerRootService() override; |
| 28 | 23 | ||
| 29 | private: | ||
| 30 | Result GetDisplayService( | 24 | Result GetDisplayService( |
| 31 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | 25 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, |
| 32 | Policy policy); | 26 | Policy policy); |
| 33 | 27 | ||
| 34 | Nvnflinger::Nvnflinger& m_nvnflinger; | 28 | private: |
| 35 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | 29 | const std::shared_ptr<Container> m_container; |
| 36 | }; | 30 | }; |
| 37 | 31 | ||
| 38 | } // 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 1de9d61a4..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, Nvnflinger::Nvnflinger& nvnflinger, | 25 | Core::System& system, std::shared_ptr<Container> container, Permission permission, |
| 26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, 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, nvnflinger, hos_binder_driver_server); | 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 8963bcd26..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 HosBinderDriverServer; | ||
| 16 | class Nvnflinger; | ||
| 17 | } // namespace Service::Nvnflinger | ||
| 18 | |||
| 19 | union Result; | 14 | union Result; |
| 20 | 15 | ||
| 21 | namespace Service::VI { | 16 | namespace Service::VI { |
| 22 | 17 | ||
| 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, Nvnflinger::Nvnflinger& nvnflinger, | 25 | Core::System& system, std::shared_ptr<Container> container, Permission permission, |
| 30 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, 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/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index 90f7248a0..869b18961 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp | |||
| @@ -9,15 +9,15 @@ | |||
| 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 10 | #include "core/hle/service/nvdrv/nvdrv.h" | 10 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 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/fb_share_buffer_manager.h" | ||
| 13 | #include "core/hle/service/nvnflinger/pixel_format.h" | 12 | #include "core/hle/service/nvnflinger/pixel_format.h" |
| 14 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 13 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" |
| 15 | #include "core/hle/service/vi/layer/vi_layer.h" | 14 | #include "core/hle/service/vi/container.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" |
| 19 | 19 | ||
| 20 | namespace Service::Nvnflinger { | 20 | namespace Service::VI { |
| 21 | 21 | ||
| 22 | namespace { | 22 | namespace { |
| 23 | 23 | ||
| @@ -26,7 +26,6 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_ | |||
| 26 | using Core::Memory::YUZU_PAGESIZE; | 26 | using Core::Memory::YUZU_PAGESIZE; |
| 27 | 27 | ||
| 28 | // Allocate memory for the system shared buffer. | 28 | // Allocate memory for the system shared buffer. |
| 29 | // FIXME: This memory belongs to vi's .data section. | ||
| 30 | auto& kernel = system.Kernel(); | 29 | auto& kernel = system.Kernel(); |
| 31 | 30 | ||
| 32 | // Hold a temporary page group reference while we try to map it. | 31 | // Hold a temporary page group reference while we try to map it. |
| @@ -204,15 +203,15 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han | |||
| 204 | 203 | ||
| 205 | } // namespace | 204 | } // namespace |
| 206 | 205 | ||
| 207 | FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger, | 206 | SharedBufferManager::SharedBufferManager(Core::System& system, Container& container, |
| 208 | std::shared_ptr<Nvidia::Module> nvdrv) | 207 | std::shared_ptr<Nvidia::Module> nvdrv) |
| 209 | : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {} | 208 | : m_system(system), m_container(container), 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 | 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_flinger.CreateLayer(m_display_id, blending).value(); | 251 | s32 producer_binder_id; |
| 253 | m_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_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_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_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 | ||
| @@ -444,4 +436,4 @@ Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32 | |||
| 444 | R_SUCCEED(); | 436 | R_SUCCEED(); |
| 445 | } | 437 | } |
| 446 | 438 | ||
| 447 | } // namespace Service::Nvnflinger | 439 | } // namespace Service::VI |
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h index b79a7d23a..7c9bb7199 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h +++ b/src/core/hle/service/vi/shared_buffer_manager.h | |||
| @@ -8,15 +8,27 @@ | |||
| 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 | ||
| 19 | namespace Service::Nvnflinger { | 27 | union Result; |
| 28 | |||
| 29 | namespace Service::VI { | ||
| 30 | |||
| 31 | class Container; | ||
| 20 | 32 | ||
| 21 | struct SharedMemorySlot { | 33 | struct SharedMemorySlot { |
| 22 | u64 buffer_offset; | 34 | u64 buffer_offset; |
| @@ -32,17 +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, Nvnflinger& flinger, | 51 | explicit SharedBufferManager(Core::System& system, Container& container, |
| 40 | std::shared_ptr<Nvidia::Module> nvdrv); | 52 | std::shared_ptr<Nvidia::Module> nvdrv); |
| 41 | ~FbShareBufferManager(); | 53 | ~SharedBufferManager(); |
| 42 | 54 | ||
| 43 | 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, |
| 44 | u64 display_id, LayerBlending blending); | 56 | u64 display_id, bool enable_blending); |
| 45 | void Finalize(Kernel::KProcess* owner_process); | 57 | void DestroySession(Kernel::KProcess* owner_process); |
| 46 | 58 | ||
| 47 | Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, | 59 | Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, |
| 48 | SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, | 60 | SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, |
| @@ -51,32 +63,30 @@ public: | |||
| 51 | s64* out_target_slot, u64 layer_id); | 63 | s64* out_target_slot, u64 layer_id); |
| 52 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | 64 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, |
| 53 | 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); | ||
| 54 | Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); | 67 | Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); |
| 55 | 68 | ||
| 56 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); | 69 | Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); |
| 57 | 70 | ||
| 58 | private: | 71 | private: |
| 59 | Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); | ||
| 60 | |||
| 61 | private: | ||
| 62 | u64 m_next_buffer_id = 1; | 72 | u64 m_next_buffer_id = 1; |
| 63 | u64 m_display_id = 0; | 73 | u64 m_display_id = 0; |
| 64 | u64 m_buffer_id = 0; | 74 | u64 m_buffer_id = 0; |
| 65 | SharedMemoryPoolLayout m_pool_layout = {}; | 75 | SharedMemoryPoolLayout m_pool_layout = {}; |
| 66 | std::map<u64, FbShareSession> m_sessions; | 76 | std::map<u64, SharedBufferSession> m_sessions; |
| 67 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; | 77 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; |
| 68 | 78 | ||
| 69 | std::mutex m_guard; | 79 | std::mutex m_guard; |
| 70 | Core::System& m_system; | 80 | Core::System& m_system; |
| 71 | Nvnflinger& m_flinger; | 81 | Container& m_container; |
| 72 | std::shared_ptr<Nvidia::Module> m_nvdrv; | 82 | const std::shared_ptr<Nvidia::Module> m_nvdrv; |
| 73 | }; | 83 | }; |
| 74 | 84 | ||
| 75 | struct FbShareSession { | 85 | struct SharedBufferSession { |
| 76 | Nvidia::DeviceFD nvmap_fd = {}; | 86 | Nvidia::DeviceFD nvmap_fd = {}; |
| 77 | Nvidia::NvCore::SessionId session_id = {}; | 87 | Nvidia::NvCore::SessionId session_id = {}; |
| 78 | u64 layer_id = {}; | 88 | u64 layer_id = {}; |
| 79 | u32 buffer_nvmap_handle = 0; | 89 | u32 buffer_nvmap_handle = 0; |
| 80 | }; | 90 | }; |
| 81 | 91 | ||
| 82 | } // namespace Service::Nvnflinger | 92 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp index 1e1cfc817..c3c50b07b 100644 --- a/src/core/hle/service/vi/system_display_service.cpp +++ b/src/core/hle/service/vi/system_display_service.cpp | |||
| @@ -3,15 +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/nvnflinger/fb_share_buffer_manager.h" | 6 | #include "core/hle/service/vi/container.h" |
| 7 | #include "core/hle/service/vi/system_display_service.h" | 7 | #include "core/hle/service/vi/system_display_service.h" |
| 8 | #include "core/hle/service/vi/vi_types.h" | 8 | #include "core/hle/service/vi/vi_types.h" |
| 9 | 9 | ||
| 10 | namespace Service::VI { | 10 | namespace Service::VI { |
| 11 | 11 | ||
| 12 | ISystemDisplayService::ISystemDisplayService(Core::System& system_, | 12 | ISystemDisplayService::ISystemDisplayService(Core::System& system_, |
| 13 | Nvnflinger::Nvnflinger& nvnflinger) | 13 | std::shared_ptr<Container> container) |
| 14 | : ServiceFramework{system_, "ISystemDisplayService"}, m_nvnflinger{nvnflinger} { | 14 | : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} { |
| 15 | // clang-format off | 15 | // clang-format off |
| 16 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 17 | {1200, nullptr, "GetZOrderCountMin"}, | 17 | {1200, nullptr, "GetZOrderCountMin"}, |
| @@ -29,7 +29,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, | |||
| 29 | {2400, nullptr, "OpenIndirectLayer"}, | 29 | {2400, nullptr, "OpenIndirectLayer"}, |
| 30 | {2401, nullptr, "CloseIndirectLayer"}, | 30 | {2401, nullptr, "CloseIndirectLayer"}, |
| 31 | {2402, nullptr, "FlipIndirectLayer"}, | 31 | {2402, nullptr, "FlipIndirectLayer"}, |
| 32 | {3000, nullptr, "ListDisplayModes"}, | 32 | {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"}, |
| 33 | {3001, nullptr, "ListDisplayRgbRanges"}, | 33 | {3001, nullptr, "ListDisplayRgbRanges"}, |
| 34 | {3002, nullptr, "ListDisplayContentTypes"}, | 34 | {3002, nullptr, "ListDisplayContentTypes"}, |
| 35 | {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, | 35 | {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"}, |
| @@ -59,7 +59,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_, | |||
| 59 | {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, | 59 | {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, |
| 60 | {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, | 60 | {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, |
| 61 | {8257, nullptr, "FillSharedFrameBufferColor"}, | 61 | {8257, nullptr, "FillSharedFrameBufferColor"}, |
| 62 | {8258, nullptr, "CancelSharedFrameBuffer"}, | 62 | {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"}, |
| 63 | {9000, nullptr, "GetDp2hdmiController"}, | 63 | {9000, nullptr, "GetDp2hdmiController"}, |
| 64 | }; | 64 | }; |
| 65 | // clang-format on | 65 | // clang-format on |
| @@ -80,31 +80,50 @@ Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | |||
| 80 | R_SUCCEED(); | 80 | R_SUCCEED(); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_height, | 83 | Result ISystemDisplayService::ListDisplayModes( |
| 84 | Out<f32> out_refresh_rate, Out<u32> out_unknown) { | 84 | Out<u64> out_count, u64 display_id, |
| 85 | LOG_WARNING(Service_VI, "(STUBBED) called"); | 85 | OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes) { |
| 86 | LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id); | ||
| 87 | |||
| 88 | if (!out_display_modes.empty()) { | ||
| 89 | out_display_modes[0] = { | ||
| 90 | .width = 1920, | ||
| 91 | .height = 1080, | ||
| 92 | .refresh_rate = 60.f, | ||
| 93 | .unknown = {}, | ||
| 94 | }; | ||
| 95 | *out_count = 1; | ||
| 96 | } else { | ||
| 97 | *out_count = 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | R_SUCCEED(); | ||
| 101 | } | ||
| 102 | |||
| 103 | Result ISystemDisplayService::GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id) { | ||
| 104 | LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id); | ||
| 86 | 105 | ||
| 87 | if (Settings::IsDockedMode()) { | 106 | if (Settings::IsDockedMode()) { |
| 88 | *out_width = static_cast<u32>(DisplayResolution::DockedWidth); | 107 | out_display_mode->width = static_cast<u32>(DisplayResolution::DockedWidth); |
| 89 | *out_height = static_cast<u32>(DisplayResolution::DockedHeight); | 108 | out_display_mode->height = static_cast<u32>(DisplayResolution::DockedHeight); |
| 90 | } else { | 109 | } else { |
| 91 | *out_width = static_cast<u32>(DisplayResolution::UndockedWidth); | 110 | out_display_mode->width = static_cast<u32>(DisplayResolution::UndockedWidth); |
| 92 | *out_height = static_cast<u32>(DisplayResolution::UndockedHeight); | 111 | out_display_mode->height = static_cast<u32>(DisplayResolution::UndockedHeight); |
| 93 | } | 112 | } |
| 94 | 113 | ||
| 95 | *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. | 114 | out_display_mode->refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. |
| 96 | *out_unknown = 0; | 115 | out_display_mode->unknown = 0; |
| 97 | 116 | ||
| 98 | R_SUCCEED(); | 117 | R_SUCCEED(); |
| 99 | } | 118 | } |
| 100 | 119 | ||
| 101 | Result ISystemDisplayService::GetSharedBufferMemoryHandleId( | 120 | Result ISystemDisplayService::GetSharedBufferMemoryHandleId( |
| 102 | Out<s32> out_nvmap_handle, Out<u64> out_size, | 121 | Out<s32> out_nvmap_handle, Out<u64> out_size, |
| 103 | OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, | 122 | OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, u64 buffer_id, |
| 104 | u64 buffer_id, ClientAppletResourceUserId aruid) { | 123 | ClientAppletResourceUserId aruid) { |
| 105 | LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); | 124 | LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); |
| 106 | 125 | ||
| 107 | R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | 126 | R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId( |
| 108 | out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); | 127 | out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); |
| 109 | } | 128 | } |
| 110 | 129 | ||
| @@ -122,7 +141,7 @@ Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_f | |||
| 122 | Out<std::array<s32, 4>> out_slots, | 141 | Out<std::array<s32, 4>> out_slots, |
| 123 | Out<s64> out_target_slot, u64 layer_id) { | 142 | Out<s64> out_target_slot, u64 layer_id) { |
| 124 | LOG_DEBUG(Service_VI, "called"); | 143 | LOG_DEBUG(Service_VI, "called"); |
| 125 | R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | 144 | R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer( |
| 126 | out_fence, *out_slots, out_target_slot, layer_id)); | 145 | out_fence, *out_slots, out_target_slot, layer_id)); |
| 127 | } | 146 | } |
| 128 | 147 | ||
| @@ -131,15 +150,20 @@ Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, | |||
| 131 | u32 window_transform, s32 swap_interval, | 150 | u32 window_transform, s32 swap_interval, |
| 132 | u64 layer_id, s64 surface_id) { | 151 | u64 layer_id, s64 surface_id) { |
| 133 | LOG_DEBUG(Service_VI, "called"); | 152 | LOG_DEBUG(Service_VI, "called"); |
| 134 | R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | 153 | R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer( |
| 135 | fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); | 154 | fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); |
| 136 | } | 155 | } |
| 137 | 156 | ||
| 138 | Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( | 157 | Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( |
| 139 | OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { | 158 | OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { |
| 140 | LOG_DEBUG(Service_VI, "called"); | 159 | LOG_DEBUG(Service_VI, "called"); |
| 141 | R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event, | 160 | R_RETURN(m_container->GetSharedBufferManager()->GetSharedFrameBufferAcquirableEvent(out_event, |
| 142 | layer_id)); | 161 | layer_id)); |
| 162 | } | ||
| 163 | |||
| 164 | Result ISystemDisplayService::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { | ||
| 165 | LOG_DEBUG(Service_VI, "called"); | ||
| 166 | R_RETURN(m_container->GetSharedBufferManager()->CancelSharedFrameBuffer(layer_id, slot)); | ||
| 143 | } | 167 | } |
| 144 | 168 | ||
| 145 | } // namespace Service::VI | 169 | } // 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 cfcb196fd..7228d826e 100644 --- a/src/core/hle/service/vi/system_display_service.h +++ b/src/core/hle/service/vi/system_display_service.h | |||
| @@ -5,27 +5,28 @@ | |||
| 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 | 8 | #include "core/hle/service/vi/shared_buffer_manager.h" | |
| 9 | namespace Service::Nvnflinger { | ||
| 10 | struct SharedMemoryPoolLayout; | ||
| 11 | } | ||
| 12 | 9 | ||
| 13 | namespace Service::VI { | 10 | namespace Service::VI { |
| 11 | struct DisplayMode; | ||
| 12 | |||
| 13 | class Container; | ||
| 14 | 14 | ||
| 15 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | 15 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { |
| 16 | public: | 16 | public: |
| 17 | explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); | 17 | explicit ISystemDisplayService(Core::System& system_, std::shared_ptr<Container> container); |
| 18 | ~ISystemDisplayService() override; | 18 | ~ISystemDisplayService() override; |
| 19 | 19 | ||
| 20 | private: | 20 | private: |
| 21 | Result SetLayerZ(u32 z_value, u64 layer_id); | 21 | Result SetLayerZ(u32 z_value, u64 layer_id); |
| 22 | Result SetLayerVisibility(bool visible, u64 layer_id); | 22 | Result SetLayerVisibility(bool visible, u64 layer_id); |
| 23 | Result GetDisplayMode(Out<u32> out_width, Out<u32> out_height, Out<f32> out_refresh_rate, | 23 | Result ListDisplayModes(Out<u64> out_count, u64 display_id, |
| 24 | Out<u32> out_unknown); | 24 | OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes); |
| 25 | Result GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id); | ||
| 25 | 26 | ||
| 26 | Result GetSharedBufferMemoryHandleId( | 27 | Result GetSharedBufferMemoryHandleId( |
| 27 | Out<s32> out_nvmap_handle, Out<u64> out_size, | 28 | Out<s32> out_nvmap_handle, Out<u64> out_size, |
| 28 | OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, | 29 | OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, |
| 29 | u64 buffer_id, ClientAppletResourceUserId aruid); | 30 | u64 buffer_id, ClientAppletResourceUserId aruid); |
| 30 | Result OpenSharedLayer(u64 layer_id); | 31 | Result OpenSharedLayer(u64 layer_id); |
| 31 | Result ConnectSharedLayer(u64 layer_id); | 32 | Result ConnectSharedLayer(u64 layer_id); |
| @@ -37,9 +38,10 @@ private: | |||
| 37 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | 38 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, |
| 38 | u32 window_transform, s32 swap_interval, u64 layer_id, | 39 | u32 window_transform, s32 swap_interval, u64 layer_id, |
| 39 | s64 surface_id); | 40 | s64 surface_id); |
| 41 | Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); | ||
| 40 | 42 | ||
| 41 | private: | 43 | private: |
| 42 | Nvnflinger::Nvnflinger& m_nvnflinger; | 44 | const std::shared_ptr<Container> m_container; |
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | } // namespace Service::VI | 47 | } // 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 8789b4cfb..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,10 +11,8 @@ | |||
| 10 | 11 | ||
| 11 | namespace Service::VI { | 12 | namespace Service::VI { |
| 12 | 13 | ||
| 13 | ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | 14 | ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr<Container> container) |
| 14 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | 15 | : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} { |
| 15 | : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||
| 16 | hos_binder_driver_server} { | ||
| 17 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 18 | {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, | 17 | {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, |
| 19 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | 18 | {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, |
| @@ -26,8 +25,8 @@ ISystemRootService::~ISystemRootService() = default; | |||
| 26 | Result ISystemRootService::GetDisplayService( | 25 | Result ISystemRootService::GetDisplayService( |
| 27 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | 26 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { |
| 28 | LOG_DEBUG(Service_VI, "called"); | 27 | LOG_DEBUG(Service_VI, "called"); |
| 29 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | 28 | R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container, |
| 30 | m_hos_binder_driver_server, Permission::System, policy)); | 29 | Permission::System, policy)); |
| 31 | } | 30 | } |
| 32 | 31 | ||
| 33 | } // 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 2c547faa5..9d5aa53d3 100644 --- a/src/core/hle/service/vi/system_root_service.h +++ b/src/core/hle/service/vi/system_root_service.h | |||
| @@ -10,20 +10,15 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service::Nvnflinger { | ||
| 14 | class HosBinderDriverServer; | ||
| 15 | class Nvnflinger; | ||
| 16 | } // namespace Service::Nvnflinger | ||
| 17 | |||
| 18 | namespace Service::VI { | 13 | namespace Service::VI { |
| 19 | 14 | ||
| 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_, Nvnflinger::Nvnflinger& nvnflinger, | 21 | explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container); |
| 26 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
| 27 | ~ISystemRootService() override; | 22 | ~ISystemRootService() override; |
| 28 | 23 | ||
| 29 | private: | 24 | private: |
| @@ -31,8 +26,7 @@ private: | |||
| 31 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | 26 | Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, |
| 32 | Policy policy); | 27 | Policy policy); |
| 33 | 28 | ||
| 34 | Nvnflinger::Nvnflinger& m_nvnflinger; | 29 | const std::shared_ptr<Container> m_container; |
| 35 | Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||
| 36 | }; | 30 | }; |
| 37 | 31 | ||
| 38 | } // 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 304e589b7..b388efaf6 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -1,25 +1,30 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/core.h" | ||
| 4 | #include "core/hle/service/server_manager.h" | 5 | #include "core/hle/service/server_manager.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/manager_root_service.h" | 8 | #include "core/hle/service/vi/manager_root_service.h" |
| 8 | #include "core/hle/service/vi/system_root_service.h" | 9 | #include "core/hle/service/vi/system_root_service.h" |
| 9 | #include "core/hle/service/vi/vi.h" | 10 | #include "core/hle/service/vi/vi.h" |
| 10 | 11 | ||
| 11 | namespace Service::VI { | 12 | namespace Service::VI { |
| 12 | 13 | ||
| 13 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | 14 | void LoopProcess(Core::System& system, std::stop_token token) { |
| 14 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { | 15 | const auto container = std::make_shared<Container>(system); |
| 16 | |||
| 15 | auto server_manager = std::make_unique<ServerManager>(system); | 17 | auto server_manager = std::make_unique<ServerManager>(system); |
| 16 | 18 | ||
| 17 | server_manager->RegisterNamedService("vi:m", std::make_shared<IManagerRootService>( | 19 | server_manager->RegisterNamedService("vi:m", |
| 18 | system, nvnflinger, hos_binder_driver_server)); | 20 | std::make_shared<IManagerRootService>(system, container)); |
| 21 | server_manager->RegisterNamedService("vi:s", | ||
| 22 | std::make_shared<ISystemRootService>(system, container)); | ||
| 19 | server_manager->RegisterNamedService( | 23 | server_manager->RegisterNamedService( |
| 20 | "vi:s", std::make_shared<ISystemRootService>(system, nvnflinger, hos_binder_driver_server)); | 24 | "vi:u", std::make_shared<IApplicationRootService>(system, container)); |
| 21 | server_manager->RegisterNamedService("vi:u", std::make_shared<IApplicationRootService>( | 25 | |
| 22 | system, nvnflinger, hos_binder_driver_server)); | 26 | std::stop_callback cb(token, [=] { container->OnTerminate(); }); |
| 27 | |||
| 23 | ServerManager::RunServer(std::move(server_manager)); | 28 | ServerManager::RunServer(std::move(server_manager)); |
| 24 | } | 29 | } |
| 25 | 30 | ||
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 8e681370d..7c1f350d8 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -3,18 +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::Nvnflinger { | ||
| 11 | class HosBinderDriverServer; | ||
| 12 | class Nvnflinger; | ||
| 13 | } // namespace Service::Nvnflinger | ||
| 14 | |||
| 15 | namespace Service::VI { | 12 | namespace Service::VI { |
| 16 | 13 | ||
| 17 | void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | 14 | void LoopProcess(Core::System& system, std::stop_token token); |
| 18 | Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||
| 19 | 15 | ||
| 20 | } // 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..95ff66358 100644 --- a/src/core/hle/service/vi/vi_types.h +++ b/src/core/hle/service/vi/vi_types.h | |||
| @@ -66,9 +66,17 @@ struct DisplayInfo { | |||
| 66 | }; | 66 | }; |
| 67 | static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); | 67 | static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); |
| 68 | 68 | ||
| 69 | struct DisplayMode { | ||
| 70 | u32 width; | ||
| 71 | u32 height; | ||
| 72 | f32 refresh_rate; | ||
| 73 | u32 unknown; | ||
| 74 | }; | ||
| 75 | static_assert(sizeof(DisplayMode) == 0x10, "DisplayMode has wrong size"); | ||
| 76 | |||
| 69 | class NativeWindow final { | 77 | class NativeWindow final { |
| 70 | public: | 78 | public: |
| 71 | constexpr explicit NativeWindow(u32 id_) : id{id_} {} | 79 | constexpr explicit NativeWindow(s32 id_) : id{static_cast<u64>(id_)} {} |
| 72 | constexpr explicit NativeWindow(const NativeWindow& other) = default; | 80 | constexpr explicit NativeWindow(const NativeWindow& other) = default; |
| 73 | 81 | ||
| 74 | private: | 82 | 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 | ||