summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt32
-rw-r--r--src/core/core.cpp11
-rw-r--r--src/core/hle/service/am/am.cpp10
-rw-r--r--src/core/hle/service/am/am.h6
-rw-r--r--src/core/hle/service/am/applet.h6
-rw-r--r--src/core/hle/service/am/display_layer_manager.cpp151
-rw-r--r--src/core/hle/service/am/display_layer_manager.h62
-rw-r--r--src/core/hle/service/am/managed_layer_holder.cpp59
-rw-r--r--src/core/hle/service/am/managed_layer_holder.h32
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.cpp13
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.h8
-rw-r--r--src/core/hle/service/am/service/application_proxy.cpp9
-rw-r--r--src/core/hle/service/am/service/application_proxy.h3
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.cpp7
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.h7
-rw-r--r--src/core/hle/service/am/service/display_controller.cpp6
-rw-r--r--src/core/hle/service/am/service/library_applet_creator.cpp2
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.cpp10
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.h3
-rw-r--r--src/core/hle/service/am/service/self_controller.cpp53
-rw-r--r--src/core/hle/service/am/service/self_controller.h3
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.cpp10
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.h3
-rw-r--r--src/core/hle/service/am/service/window_controller.cpp2
-rw-r--r--src/core/hle/service/am/system_buffer_manager.cpp80
-rw-r--r--src/core/hle/service/am/system_buffer_manager.h52
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp3
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h9
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp6
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.h4
-rw-r--r--src/core/hle/service/nvnflinger/binder.h23
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item_consumer.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item_consumer.h2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp76
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.h10
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.cpp32
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.h8
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.h4
-rw-r--r--src/core/hle/service/nvnflinger/display.h55
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.cpp65
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.h20
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.cpp (renamed from src/core/hle/service/vi/hos_binder_driver.cpp)31
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.h (renamed from src/core/hle/service/vi/hos_binder_driver.h)30
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp22
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver_server.h16
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp333
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h166
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.cpp124
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.h65
-rw-r--r--src/core/hle/service/service.cpp136
-rw-r--r--src/core/hle/service/service.h21
-rw-r--r--src/core/hle/service/services.cpp136
-rw-r--r--src/core/hle/service/services.h22
-rw-r--r--src/core/hle/service/vi/application_display_service.cpp123
-rw-r--r--src/core/hle/service/vi/application_display_service.h34
-rw-r--r--src/core/hle/service/vi/application_root_service.cpp13
-rw-r--r--src/core/hle/service/vi/application_root_service.h12
-rw-r--r--src/core/hle/service/vi/conductor.cpp114
-rw-r--r--src/core/hle/service/vi/conductor.h57
-rw-r--r--src/core/hle/service/vi/container.cpp228
-rw-r--r--src/core/hle/service/vi/container.h92
-rw-r--r--src/core/hle/service/vi/display.h44
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp143
-rw-r--r--src/core/hle/service/vi/display/vi_display.h143
-rw-r--r--src/core/hle/service/vi/display_list.h83
-rw-r--r--src/core/hle/service/vi/layer.h79
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp18
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h118
-rw-r--r--src/core/hle/service/vi/layer_list.h69
-rw-r--r--src/core/hle/service/vi/manager_display_service.cpp46
-rw-r--r--src/core/hle/service/vi/manager_display_service.h21
-rw-r--r--src/core/hle/service/vi/manager_root_service.cpp14
-rw-r--r--src/core/hle/service/vi/manager_root_service.h14
-rw-r--r--src/core/hle/service/vi/service_creator.cpp5
-rw-r--r--src/core/hle/service/vi/service_creator.h9
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.cpp (renamed from src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp)136
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.h (renamed from src/core/hle/service/nvnflinger/fb_share_buffer_manager.h)46
-rw-r--r--src/core/hle/service/vi/system_display_service.cpp66
-rw-r--r--src/core/hle/service/vi/system_display_service.h20
-rw-r--r--src/core/hle/service/vi/system_root_service.cpp11
-rw-r--r--src/core/hle/service/vi/system_root_service.h12
-rw-r--r--src/core/hle/service/vi/vi.cpp21
-rw-r--r--src/core/hle/service/vi/vi.h10
-rw-r--r--src/core/hle/service/vi/vi_types.h10
-rw-r--r--src/core/hle/service/vi/vsync_manager.cpp26
-rw-r--r--src/core/hle/service/vi/vsync_manager.h29
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
9namespace Service::AM { 9namespace Service::AM {
10 10
11void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { 11void 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 {
7class System; 7class System;
8} 8}
9 9
10namespace Service::Nvnflinger {
11class Nvnflinger;
12}
13
14namespace Service::AM { 10namespace Service::AM {
15 11
16void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); 12void 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
22namespace Service::AM { 21namespace 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
15namespace Service::AM {
16
17DisplayLayerManager::DisplayLayerManager() = default;
18DisplayLayerManager::~DisplayLayerManager() {
19 this->Finalize();
20}
21
22void 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
38void 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
61Result 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
77Result 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
91Result 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
112Result 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
122void 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
140bool DisplayLayerManager::GetWindowVisibility() const {
141 return m_visible;
142}
143
144Result 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
12namespace Core {
13class System;
14}
15
16namespace Kernel {
17class KProcess;
18}
19
20namespace Service::VI {
21class IApplicationDisplayService;
22class IManagerDisplayService;
23} // namespace Service::VI
24
25namespace Service::AM {
26
27class DisplayLayerManager {
28public:
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
48private:
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
7namespace Service::AM {
8
9ManagedLayerHolder::ManagedLayerHolder() = default;
10ManagedLayerHolder::~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
26void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) {
27 m_nvnflinger = nvnflinger;
28}
29
30void 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
41void 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
11namespace Service::Nvnflinger {
12class Nvnflinger;
13}
14
15namespace Service::AM {
16
17class ManagedLayerHolder {
18public:
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
26private:
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
11namespace Service::AM { 11namespace Service::AM {
12 12
13IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_, 13IAllSystemAppletProxiesService::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
9namespace Service { 9namespace Service {
10 10
11namespace Nvnflinger {
12class Nvnflinger;
13}
14
15namespace AM { 11namespace AM {
16 12
17struct Applet; 13struct Applet;
@@ -22,8 +18,7 @@ class ISystemAppletProxy;
22class IAllSystemAppletProxiesService final 18class IAllSystemAppletProxiesService final
23 : public ServiceFramework<IAllSystemAppletProxiesService> { 19 : public ServiceFramework<IAllSystemAppletProxiesService> {
24public: 20public:
25 explicit IAllSystemAppletProxiesService(Core::System& system_, 21 explicit IAllSystemAppletProxiesService(Core::System& system_);
26 Nvnflinger::Nvnflinger& nvnflinger);
27 ~IAllSystemAppletProxiesService() override; 22 ~IAllSystemAppletProxiesService() override;
28 23
29private: 24private:
@@ -40,7 +35,6 @@ private:
40 35
41private: 36private:
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 @@
17namespace Service::AM { 17namespace Service::AM {
18 18
19IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, 19IApplicationProxy::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(
77Result IApplicationProxy::GetSelfController( 77Result 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;
22class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { 22class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
23public: 23public:
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
28private: 28private:
@@ -40,7 +40,6 @@ private:
40 Out<SharedPointer<IApplicationFunctions>> out_application_functions); 40 Out<SharedPointer<IApplicationFunctions>> out_application_functions);
41 41
42private: 42private:
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
11namespace Service::AM { 11namespace Service::AM {
12 12
13IApplicationProxyService::IApplicationProxyService(Core::System& system_, 13IApplicationProxyService::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
9namespace Service { 9namespace Service {
10 10
11namespace Nvnflinger {
12class Nvnflinger;
13}
14
15namespace AM { 11namespace AM {
16 12
17struct Applet; 13struct Applet;
@@ -19,7 +15,7 @@ class IApplicationProxy;
19 15
20class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> { 16class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
21public: 17public:
22 explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); 18 explicit IApplicationProxyService(Core::System& system_);
23 ~IApplicationProxyService() override; 19 ~IApplicationProxyService() override;
24 20
25private: 21private:
@@ -28,7 +24,6 @@ private:
28 24
29private: 25private:
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
69Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( 69Result 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() {
81Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( 81Result 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() {
93Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( 93Result 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 @@
19namespace Service::AM { 19namespace Service::AM {
20 20
21ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, 21ILibraryAppletProxy::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(
83Result ILibraryAppletProxy::GetSelfController( 82Result 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;
25class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { 25class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
26public: 26public:
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
31private: 31private:
@@ -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 @@
15namespace Service::AM { 15namespace Service::AM {
16 16
17ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet, 17ISelfController::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
77ISelfController::~ISelfController() = default; 81ISelfController::~ISelfController() {
82 std::scoped_lock lk{m_applet->lock};
83 m_applet->display_layer_manager.Finalize();
84}
78 85
79Result ISelfController::Exit() { 86Result ISelfController::Exit() {
80 LOG_DEBUG(Service_AM, "called"); 87 LOG_DEBUG(Service_AM, "called");
@@ -212,48 +219,42 @@ Result ISelfController::SetAlbumImageOrientation(
212 219
213Result ISelfController::IsSystemBufferSharingEnabled() { 220Result 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
220Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) { 227Result 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
230Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) { 236Result 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
239Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) { 244Result 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
248Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id, 251Result 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
259Result ISelfController::SetHandlesRequestToDisplay(bool enable) { 260Result 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;
23class ISelfController final : public ServiceFramework<ISelfController> { 23class ISelfController final : public ServiceFramework<ISelfController> {
24public: 24public:
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
29private: 29private:
@@ -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 @@
19namespace Service::AM { 19namespace Service::AM {
20 20
21ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, 21ISystemAppletProxy::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(
83Result ISystemAppletProxy::GetSelfController( 82Result 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;
25class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { 25class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
26public: 26public:
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
31private: 31private:
@@ -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
65Result IWindowController::SetAppletWindowVisibility(bool visible) { 65Result 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
9namespace Service::AM {
10
11SystemBufferManager::SystemBufferManager() = default;
12
13SystemBufferManager::~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
24bool 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
58void 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
70Result 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
13namespace Kernel {
14class KProcess;
15}
16
17namespace Service::Nvnflinger {
18class Nvnflinger;
19}
20
21union Result;
22
23namespace Service::AM {
24
25class SystemBufferManager {
26public:
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
43private:
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
45void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { 45void 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
22namespace Core { 20namespace Core {
@@ -27,10 +25,6 @@ namespace Kernel {
27class KEvent; 25class KEvent;
28} 26}
29 27
30namespace Service::Nvnflinger {
31class Nvnflinger;
32}
33
34namespace Service::Nvidia { 28namespace Service::Nvidia {
35 29
36namespace NvCore { 30namespace NvCore {
@@ -99,7 +93,6 @@ public:
99 93
100private: 94private:
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
121void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system); 114void 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
265NVDRV::~NVDRV() { 265NVDRV::~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
19private: 23private:
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
21namespace Service::android { 21namespace Service::android {
22 22
23enum 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
40class IBinder { 23class IBinder {
41public: 24public:
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
13namespace Service::android { 13namespace Service::android {
14 14
15BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_) 15BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_)
16 : ConsumerBase{std::move(consumer_)} {} 16 : ConsumerBase{std::move(consumer_)} {}
17 17
18Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when, 18Status 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
20class BufferItemConsumer final : public ConsumerBase { 20class BufferItemConsumer final : public ConsumerBase {
21public: 21public:
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
14namespace Service::android { 15namespace 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
258void 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
326Kernel::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;
19class BufferQueueCore; 20class BufferQueueCore;
20class IConsumerListener; 21class IConsumerListener;
21 22
22class BufferQueueConsumer final { 23class BufferQueueConsumer final : public IBinder {
23public: 24public:
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
33private: 39private:
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
24namespace Service::android { 20namespace 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
810void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data, 806void 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
926Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { 940Kernel::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
55public: 55public:
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
15namespace Service::android { 15namespace Service::android {
16 16
17ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_) 17ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_)
18 : consumer{std::move(consumer_)} {} 18 : consumer{std::move(consumer_)} {}
19 19
20ConsumerBase::~ConsumerBase() { 20ConsumerBase::~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
29protected: 29protected:
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
11namespace Service::Nvnflinger {
12
13struct 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
28struct LayerStack {
29 std::list<Layer> layers;
30};
31
32struct 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
16namespace Service::Nvnflinger { 14namespace Service::Nvnflinger {
17 15
@@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) {
44HardwareComposer::HardwareComposer() = default; 42HardwareComposer::HardwareComposer() = default;
45HardwareComposer::~HardwareComposer() = default; 43HardwareComposer::~HardwareComposer() = default;
46 44
47u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, 45u32 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
149void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) { 148void 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
166bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) { 165bool 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
181HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer, 180HardwareComposer::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
11namespace Service::Nvidia::Devices { 11namespace Service::Nvidia::Devices {
12class nvdisp_disp0; 12class nvdisp_disp0;
13} 13}
14 14
15namespace Service::VI {
16class Display;
17class Layer;
18} // namespace Service::VI
19
20namespace Service::Nvnflinger { 15namespace Service::Nvnflinger {
21 16
22using LayerId = u64; 17using ConsumerId = s32;
23 18
24class HardwareComposer { 19class HardwareComposer {
25public: 20public:
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
33private: 28private:
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
37private: 31private:
@@ -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
54private: 48private:
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
9namespace Service::VI { 9namespace Service::Nvnflinger {
10 10
11IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server) 11IHOSBinderDriver::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
22IHOSBinderDriver::~IHOSBinderDriver() = default; 25IHOSBinderDriver::~IHOSBinderDriver() = default;
23 26
24Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id, 27Result 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) {
39Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, 47Result 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
46Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, 59Result 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
8namespace Service::VI { 7namespace Kernel {
8class KReadableEvent;
9}
10
11namespace Service::Nvnflinger {
12
13class HosBinderDriverServer;
14class SurfaceFlinger;
9 15
10class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { 16class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
11public: 17public:
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
15private: 30private:
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
26private: 41private:
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
9namespace Service::Nvnflinger { 9namespace Service::Nvnflinger {
10 10
11HosBinderDriverServer::HosBinderDriverServer(Core::System& system_) 11HosBinderDriverServer::HosBinderDriverServer() = default;
12 : service_context(system_, "HosBinderDriverServer") {} 12HosBinderDriverServer::~HosBinderDriverServer() = default;
13 13
14HosBinderDriverServer::~HosBinderDriverServer() {} 14s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) {
15
16u64 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
26android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) { 24void HosBinderDriverServer::UnregisterBinder(s32 binder_id) {
25 std::scoped_lock lk{lock};
26
27 binders.erase(binder_id);
28}
29
30std::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
14namespace Core { 13namespace Core {
@@ -19,19 +18,18 @@ namespace Service::Nvnflinger {
19 18
20class HosBinderDriverServer final { 19class HosBinderDriverServer final {
21public: 20public:
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
29private: 29private:
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
32namespace Service::Nvnflinger { 12namespace Service::Nvnflinger {
33 13
34constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; 14void LoopProcess(Core::System& system) {
35 15 const auto binder_server = std::make_shared<HosBinderDriverServer>();
36void 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
58Nvnflinger::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
95Nvnflinger::~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
111void 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
126void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
127 nvdrv = std::move(instance);
128 disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
129}
130
131std::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
147bool 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
160std::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
173void 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
179bool 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
191bool 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
203void 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
213void 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
221std::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
232Result 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
244VI::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
256const 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
268VI::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
278void 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
299s64 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
325FbShareBufferManager& 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> 6namespace Core {
7#include <memory> 7class 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
20namespace Common {
21class Event;
22} // namespace Common
23
24namespace Core::Timing {
25class CoreTiming;
26struct EventType;
27} // namespace Core::Timing
28
29namespace Kernel {
30class KReadableEvent;
31} // namespace Kernel
32
33namespace Service::Nvidia {
34class Module;
35} // namespace Service::Nvidia
36
37namespace Service::VI {
38class Display;
39class Layer;
40} // namespace Service::VI
41
42namespace Service::android {
43class BufferQueueCore;
44class BufferQueueProducer;
45} // namespace Service::android
46 9
47namespace Service::Nvnflinger { 10namespace Service::Nvnflinger {
48 11
49class FbShareBufferManager; 12void LoopProcess(Core::System& system);
50class HardwareComposer;
51class HosBinderDriverServer;
52
53class Nvnflinger final {
54public:
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
110private:
111 struct Layer {
112 std::unique_ptr<android::BufferQueueCore> core;
113 std::unique_ptr<android::BufferQueueProducer> producer;
114 };
115
116 friend class FbShareBufferManager;
117
118private:
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
16namespace Service::Nvnflinger {
17
18SurfaceFlinger::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
24SurfaceFlinger::~SurfaceFlinger() {
25 nvdrv->Close(disp_fd);
26}
27
28void SurfaceFlinger::AddDisplay(u64 display_id) {
29 m_displays.emplace_back(display_id);
30}
31
32void SurfaceFlinger::RemoveDisplay(u64 display_id) {
33 std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; });
34}
35
36bool 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
49void 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
64void 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
75void 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
82void 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
89Display* 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
99Layer* 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
109void 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
119void 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
12namespace Core {
13class System;
14}
15
16namespace Service::Nvidia {
17class Module;
18}
19
20// TODO: ISurfaceComposer
21// TODO: ISurfaceComposerClient
22
23namespace Service::Nvnflinger {
24
25struct Display;
26class HosBinderDriverServer;
27enum class LayerBlending : u32;
28struct Layer;
29
30class SurfaceFlinger {
31public:
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
45private:
46 Display* FindDisplay(u64 display_id);
47 Layer* FindLayer(s32 consumer_binder_id);
48
49public:
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
54private:
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
74namespace Service { 16namespace Service {
@@ -209,82 +151,4 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
209 return result; 151 return result;
210} 152}
211 153
212/// Initialize Services
213Services::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
284Services::~Services() = default;
285
286void 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 {
28class FileSystemController; 28class FileSystemController;
29} 29}
30 30
31namespace Nvnflinger {
32class HosBinderDriverServer;
33class Nvnflinger;
34} // namespace Nvnflinger
35
36namespace SM { 31namespace SM {
37class ServiceManager; 32class 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 */
243class Services final {
244public:
245 explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
246 ~Services();
247
248 void KillNVNFlinger();
249
250private:
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
65namespace Service {
66
67Services::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
134Services::~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
9namespace 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 */
15class Services final {
16public:
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
13namespace Service::VI { 14namespace Service::VI {
14 15
15IApplicationDisplayService::IApplicationDisplayService( 16IApplicationDisplayService::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
50IApplicationDisplayService::~IApplicationDisplayService() { 49IApplicationDisplayService::~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
56Result IApplicationDisplayService::GetRelayService( 61Result 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
63Result IApplicationDisplayService::GetSystemDisplayService( 67Result 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
70Result IApplicationDisplayService::GetManagerDisplayService( 74Result 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
77Result IApplicationDisplayService::GetIndirectDisplayTransactionService( 81Result 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
85Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { 87Result 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
102Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { 97Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
@@ -106,8 +101,7 @@ Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
106 101
107Result IApplicationDisplayService::CloseDisplay(u64 display_id) { 102Result 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
113Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { 107Result 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,
199Result IApplicationDisplayService::CloseLayer(u64 layer_id) { 187Result 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
210Result IApplicationDisplayService::CreateStrayLayer( 199Result 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
241Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { 222Result 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
247Result IApplicationDisplayService::GetDisplayVsyncEvent( 234Result 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 {
9class KReadableEvent; 14class KReadableEvent;
10} 15}
11 16
17namespace Service::Nvnflinger {
18class IHOSBinderDriver;
19}
20
12namespace Service::VI { 21namespace Service::VI {
13 22
14class IHOSBinderDriver; 23class Container;
15class IManagerDisplayService; 24class IManagerDisplayService;
16class ISystemDisplayService; 25class ISystemDisplayService;
17 26
18class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { 27class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
19public: 28public:
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
24private: 32 std::shared_ptr<Container> GetContainer() const {
25 Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service); 33 return m_container;
34 }
35
36public:
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
58private: 70private:
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
11namespace Service::VI { 12namespace Service::VI {
12 13
13IApplicationRootService::IApplicationRootService( 14IApplicationRootService::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;
27Result IApplicationRootService::GetDisplayService( 26Result 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 {
10class System; 10class System;
11} 11}
12 12
13namespace Service::Nvnflinger {
14class HosBinderDriverServer;
15class Nvnflinger;
16} // namespace Service::Nvnflinger
17
18namespace Service::VI { 13namespace Service::VI {
19 14
15class Container;
20class IApplicationDisplayService; 16class IApplicationDisplayService;
21enum class Policy : u32; 17enum class Policy : u32;
22 18
23class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { 19class IApplicationRootService final : public ServiceFramework<IApplicationRootService> {
24public: 20public:
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
29private: 24private:
@@ -32,8 +27,7 @@ private:
32 Policy policy); 27 Policy policy);
33 28
34private: 29private:
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
12constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60};
13
14namespace Service::VI {
15
16Conductor::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
46Conductor::~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
55void 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
61void 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
67void 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
74void 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
88s64 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
13namespace Core {
14class System;
15}
16
17namespace Core::Timing {
18struct EventType;
19}
20
21namespace Service {
22class Event;
23}
24
25namespace Service::VI {
26
27class Container;
28class DisplayList;
29class VsyncManager;
30
31class Conductor {
32public:
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
39private:
40 void ProcessVsync();
41 void VsyncThread(std::stop_token token);
42 s64 GetNextTicks() const;
43
44private:
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
52private:
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
14namespace Service::VI {
15
16Container::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
37Container::~Container() {
38 this->OnTerminate();
39}
40
41void 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
56SharedBufferManager* Container::GetSharedBufferManager() {
57 return std::addressof(*m_shared_buffer_manager);
58}
59
60Result Container::GetBinderDriver(
61 std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver) {
62 *out_binder_driver = m_binder_driver;
63 R_SUCCEED();
64}
65
66Result 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
80Result 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
88Result Container::CloseDisplay(u64 display_id) {
89 R_SUCCEED();
90}
91
92Result 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
97Result 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
106Result 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
111Result Container::CloseLayer(u64 layer_id) {
112 std::scoped_lock lk{m_lock};
113 R_RETURN(this->CloseLayerLocked(layer_id));
114}
115
116Result 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
126Result 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
138void Container::LinkVsyncEvent(u64 display_id, Event* event) {
139 std::scoped_lock lk{m_lock};
140 m_conductor->LinkVsyncEvent(display_id, event);
141}
142
143void Container::UnlinkVsyncEvent(u64 display_id, Event* event) {
144 std::scoped_lock lk{m_lock};
145 m_conductor->UnlinkVsyncEvent(display_id, event);
146}
147
148Result 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
154Result 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
160Result 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
171Result Container::DestroyLayerLocked(u64 layer_id) {
172 R_SUCCEED_IF(m_layers.DestroyLayer(layer_id));
173 R_THROW(VI::ResultNotFound);
174}
175
176Result 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
190Result 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
200void 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
210void 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
221bool 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
15union Result;
16
17namespace Service::android {
18class BufferQueueProducer;
19}
20
21namespace Service::Nvnflinger {
22class IHOSBinderDriver;
23class SurfaceFlinger;
24} // namespace Service::Nvnflinger
25
26namespace Service {
27class Event;
28}
29
30namespace Service::VI {
31
32class SharedBufferManager;
33
34class Container {
35public:
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
69private:
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
78public:
79 bool ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id);
80
81private:
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
8namespace Service::VI {
9
10class Display {
11public:
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
38private:
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
25namespace Service::VI {
26
27struct BufferQueue {
28 std::shared_ptr<android::BufferQueueCore> core;
29 std::unique_ptr<android::BufferQueueProducer> producer;
30 std::unique_ptr<android::BufferQueueConsumer> consumer;
31};
32
33static 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
42Display::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
51Display::~Display() {
52 service_context.CloseEvent(vsync_event);
53}
54
55Layer& 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
72size_t Display::GetNumLayers() const {
73 return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); });
74}
75
76Kernel::KReadableEvent* Display::GetVSyncEvent() {
77 return &vsync_event->GetReadableEvent();
78}
79
80void Display::SignalVSyncEvent() {
81 vsync_event->Signal();
82}
83
84void 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
101void 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
110void Display::Abandon() {
111 for (auto& layer : layers) {
112 layer->GetConsumer().Abandon();
113 }
114 is_abandoned = true;
115}
116
117Layer* 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
130const 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
14namespace Core {
15class System;
16}
17
18namespace Kernel {
19class KEvent;
20class KReadableEvent;
21} // namespace Kernel
22
23namespace Service::android {
24class BufferQueueProducer;
25}
26
27namespace Service::KernelHelpers {
28class ServiceContext;
29}
30
31namespace Service::Nvnflinger {
32class HardwareComposer;
33class HosBinderDriverServer;
34} // namespace Service::Nvnflinger
35
36namespace Service::Nvidia::NvCore {
37class Container;
38class NvMap;
39} // namespace Service::Nvidia::NvCore
40
41namespace Service::VI {
42
43class Layer;
44
45/// Represents a single display type
46class Display {
47public:
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
131private:
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
10namespace Service::VI {
11
12class DisplayList {
13public:
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
67private:
68 Display* GetFreeDisplay() {
69 for (auto& display : m_displays) {
70 if (!display.IsInitialized()) {
71 return &display;
72 }
73 }
74
75 return nullptr;
76 }
77
78private:
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
8namespace Service::VI {
9
10class Display;
11
12class Layer {
13public:
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
69private:
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
7namespace Service::VI {
8
9Layer::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
16Layer::~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
11namespace Service::android {
12class BufferItemConsumer;
13class BufferQueueCore;
14class BufferQueueProducer;
15} // namespace Service::android
16
17namespace Service::Nvnflinger {
18enum class LayerBlending : u32;
19}
20
21namespace Service::VI {
22
23/// Represents a single display layer.
24class Layer {
25public:
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
107private:
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
8namespace Service::VI {
9
10class LayerList {
11public:
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
53private:
54 Layer* GetFreeLayer() {
55 for (auto& layer : m_layers) {
56 if (!layer.IsInitialized()) {
57 return &layer;
58 }
59 }
60
61 return nullptr;
62 }
63
64private:
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
9namespace Service::VI { 8namespace Service::VI {
10 9
11IManagerDisplayService::IManagerDisplayService(Core::System& system_, 10IManagerDisplayService::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
103IManagerDisplayService::~IManagerDisplayService() = default; 102IManagerDisplayService::~IManagerDisplayService() = default;
104 103
105Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, 104Result 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); 111void 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; 115Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) {
117 R_SUCCEED(); 116 R_RETURN(m_container->SetLayerBlending(layer_id, enabled));
117}
118
119Result 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
125Result 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
120Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { 130Result 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
125Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { 135Result 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
7namespace Kernel {
8class KProcess;
9}
10
7namespace Service::VI { 11namespace Service::VI {
8 12
13class Container;
14
9class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { 15class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
10public: 16public:
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
14private: 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
26public:
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
20private: 33private:
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
11namespace Service::VI { 13namespace Service::VI {
12 14
13IManagerRootService::IManagerRootService( 15IManagerRootService::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;
31Result IManagerRootService::GetDisplayService( 31Result 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 {
10class System; 10class System;
11} 11}
12 12
13namespace Service::Nvnflinger {
14class HosBinderDriverServer;
15class Nvnflinger;
16} // namespace Service::Nvnflinger
17
18namespace Service::VI { 13namespace Service::VI {
19 14
15class Container;
20class IApplicationDisplayService; 16class IApplicationDisplayService;
21enum class Policy : u32; 17enum class Policy : u32;
22 18
23class IManagerRootService final : public ServiceFramework<IManagerRootService> { 19class IManagerRootService final : public ServiceFramework<IManagerRootService> {
24public: 20public:
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
29private:
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; 28private:
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
23Result GetApplicationDisplayService( 23Result 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 {
11class System; 11class System;
12} 12}
13 13
14namespace Service::Nvnflinger {
15class HosBinderDriverServer;
16class Nvnflinger;
17} // namespace Service::Nvnflinger
18
19union Result; 14union Result;
20 15
21namespace Service::VI { 16namespace Service::VI {
22 17
18class Container;
23class IApplicationDisplayService; 19class IApplicationDisplayService;
24enum class Permission; 20enum class Permission;
25enum class Policy : u32; 21enum class Policy : u32;
26 22
27Result GetApplicationDisplayService( 23Result 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
20namespace Service::Nvnflinger { 20namespace Service::VI {
21 21
22namespace { 22namespace {
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
207FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger, 206SharedBufferManager::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
211FbShareBufferManager::~FbShareBufferManager() = default; 210SharedBufferManager::~SharedBufferManager() = default;
212 211
213Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, 212Result 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
272void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) { 272void 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
304Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, 304Result 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
322Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { 322Result 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
335Result 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
362Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence, 346Result 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
400Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, 381Result 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
395Result 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
418Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { 410Result 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
15namespace Kernel { 14namespace Kernel {
16class KPageGroup; 15class KPageGroup;
16class KReadableEvent;
17} // namespace Kernel
18
19namespace Service::android {
20class BufferQueueProducer;
21}
22
23namespace Service::Nvidia {
24class Module;
17} 25}
18 26
19namespace Service::Nvnflinger { 27union Result;
28
29namespace Service::VI {
30
31class Container;
20 32
21struct SharedMemorySlot { 33struct SharedMemorySlot {
22 u64 buffer_offset; 34 u64 buffer_offset;
@@ -32,17 +44,17 @@ struct SharedMemoryPoolLayout {
32}; 44};
33static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); 45static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
34 46
35struct FbShareSession; 47struct SharedBufferSession;
36 48
37class FbShareBufferManager final { 49class SharedBufferManager final {
38public: 50public:
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
58private: 71private:
59 Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id);
60
61private:
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
75struct FbShareSession { 85struct 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
10namespace Service::VI { 10namespace Service::VI {
11 11
12ISystemDisplayService::ISystemDisplayService(Core::System& system_, 12ISystemDisplayService::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
83Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_height, 83Result 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
103Result 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
101Result ISystemDisplayService::GetSharedBufferMemoryHandleId( 120Result 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
138Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( 157Result 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
164Result 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"
9namespace Service::Nvnflinger {
10struct SharedMemoryPoolLayout;
11}
12 9
13namespace Service::VI { 10namespace Service::VI {
11struct DisplayMode;
12
13class Container;
14 14
15class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { 15class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
16public: 16public:
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
20private: 20private:
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
41private: 43private:
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
11namespace Service::VI { 12namespace Service::VI {
12 13
13ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, 14ISystemRootService::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;
26Result ISystemRootService::GetDisplayService( 25Result 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 {
10class System; 10class System;
11} 11}
12 12
13namespace Service::Nvnflinger {
14class HosBinderDriverServer;
15class Nvnflinger;
16} // namespace Service::Nvnflinger
17
18namespace Service::VI { 13namespace Service::VI {
19 14
15class Container;
20class IApplicationDisplayService; 16class IApplicationDisplayService;
21enum class Policy : u32; 17enum class Policy : u32;
22 18
23class ISystemRootService final : public ServiceFramework<ISystemRootService> { 19class ISystemRootService final : public ServiceFramework<ISystemRootService> {
24public: 20public:
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
29private: 24private:
@@ -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
11namespace Service::VI { 12namespace Service::VI {
12 13
13void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, 14void 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
6namespace Core { 8namespace Core {
7class System; 9class System;
8} 10}
9 11
10namespace Service::Nvnflinger {
11class HosBinderDriverServer;
12class Nvnflinger;
13} // namespace Service::Nvnflinger
14
15namespace Service::VI { 12namespace Service::VI {
16 13
17void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, 14void 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};
67static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); 67static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
68 68
69struct DisplayMode {
70 u32 width;
71 u32 height;
72 f32 refresh_rate;
73 u32 unknown;
74};
75static_assert(sizeof(DisplayMode) == 0x10, "DisplayMode has wrong size");
76
69class NativeWindow final { 77class NativeWindow final {
70public: 78public:
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
74private: 82private:
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
7namespace Service::VI {
8
9VsyncManager::VsyncManager() = default;
10VsyncManager::~VsyncManager() = default;
11
12void VsyncManager::SignalVsync() {
13 for (auto* event : m_vsync_events) {
14 event->Signal();
15 }
16}
17
18void VsyncManager::LinkVsyncEvent(Event* event) {
19 m_vsync_events.insert(event);
20}
21
22void 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
8namespace Service {
9class Event;
10}
11
12namespace Service::VI {
13
14class DisplayList;
15
16class VsyncManager {
17public:
18 explicit VsyncManager();
19 ~VsyncManager();
20
21 void SignalVsync();
22 void LinkVsyncEvent(Event* event);
23 void UnlinkVsyncEvent(Event* event);
24
25private:
26 std::set<Event*> m_vsync_events;
27};
28
29} // namespace Service::VI