summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/file_sys/content_archive.cpp4
-rw-r--r--src/core/file_sys/content_archive.h1
-rw-r--r--src/core/hle/kernel/k_process.cpp7
-rw-r--r--src/core/hle/service/am/am_types.h6
-rw-r--r--src/core/hle/service/am/frontend/applet_software_keyboard.cpp12
-rw-r--r--src/core/hle/service/am/frontend/applet_software_keyboard.h2
-rw-r--r--src/core/hle/service/am/library_applet_creator.cpp81
-rw-r--r--src/core/hle/service/am/process.cpp23
-rw-r--r--src/core/hle/service/am/process.h2
-rw-r--r--src/core/hle/service/am/self_controller.cpp18
-rw-r--r--src/core/hle/service/am/self_controller.h2
-rw-r--r--src/core/hle/service/am/system_buffer_manager.cpp19
-rw-r--r--src/core/hle/service/am/system_buffer_manager.h3
-rw-r--r--src/core/hle/service/am/window_controller.cpp4
-rw-r--r--src/core/hle/service/nvdrv/core/container.cpp7
-rw-r--r--src/core/hle/service/nvdrv/core/container.h1
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp17
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp176
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.h24
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.cpp1
-rw-r--r--src/core/hle/service/nvnflinger/hwc_layer.h13
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp7
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h6
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp6
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h13
26 files changed, 364 insertions, 99 deletions
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 285fe4db6..665252358 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -172,6 +172,10 @@ u32 NCA::GetSDKVersion() const {
172 return reader->GetSdkAddonVersion(); 172 return reader->GetSdkAddonVersion();
173} 173}
174 174
175u8 NCA::GetKeyGeneration() const {
176 return reader->GetKeyGeneration();
177}
178
175bool NCA::IsUpdate() const { 179bool NCA::IsUpdate() const {
176 return is_update; 180 return is_update;
177} 181}
diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h
index f68464eb0..8560617f5 100644
--- a/src/core/file_sys/content_archive.h
+++ b/src/core/file_sys/content_archive.h
@@ -77,6 +77,7 @@ public:
77 u64 GetTitleId() const; 77 u64 GetTitleId() const;
78 RightsId GetRightsId() const; 78 RightsId GetRightsId() const;
79 u32 GetSDKVersion() const; 79 u32 GetSDKVersion() const;
80 u8 GetKeyGeneration() const;
80 bool IsUpdate() const; 81 bool IsUpdate() const;
81 82
82 VirtualFile GetRomFS() const; 83 VirtualFile GetRomFS() const;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 0b08e877e..1bcc42890 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -4,8 +4,9 @@
4#include <random> 4#include <random>
5#include "common/scope_exit.h" 5#include "common/scope_exit.h"
6#include "common/settings.h" 6#include "common/settings.h"
7#include "core/arm/dynarmic/arm_dynarmic.h"
8#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
7#include "core/core.h" 9#include "core/core.h"
8#include "core/gpu_dirty_memory_manager.h"
9#include "core/hle/kernel/k_process.h" 10#include "core/hle/kernel/k_process.h"
10#include "core/hle/kernel/k_scoped_resource_reservation.h" 11#include "core/hle/kernel/k_scoped_resource_reservation.h"
11#include "core/hle/kernel/k_shared_memory.h" 12#include "core/hle/kernel/k_shared_memory.h"
@@ -1258,6 +1259,10 @@ void KProcess::InitializeInterfaces() {
1258 1259
1259#ifdef HAS_NCE 1260#ifdef HAS_NCE
1260 if (this->IsApplication() && Settings::IsNceEnabled()) { 1261 if (this->IsApplication() && Settings::IsNceEnabled()) {
1262 // Register the scoped JIT handler before creating any NCE instances
1263 // so that its signal handler will appear first in the signal chain.
1264 Core::ScopedJitExecution::RegisterHandler();
1265
1261 for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 1266 for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
1262 m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i); 1267 m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i);
1263 } 1268 }
diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h
index a2b852b12..8c33feb15 100644
--- a/src/core/hle/service/am/am_types.h
+++ b/src/core/hle/service/am/am_types.h
@@ -130,9 +130,9 @@ enum class AppletProgramId : u64 {
130 130
131enum class LibraryAppletMode : u32 { 131enum class LibraryAppletMode : u32 {
132 AllForeground = 0, 132 AllForeground = 0,
133 Background = 1, 133 PartialForeground = 1,
134 NoUI = 2, 134 NoUi = 2,
135 BackgroundIndirectDisplay = 3, 135 PartialForegroundIndirectDisplay = 3,
136 AllForegroundInitiallyHidden = 4, 136 AllForegroundInitiallyHidden = 4,
137}; 137};
138 138
diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
index fbf75d379..034c62f32 100644
--- a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
@@ -68,9 +68,9 @@ void SoftwareKeyboard::Initialize() {
68 case LibraryAppletMode::AllForeground: 68 case LibraryAppletMode::AllForeground:
69 InitializeForeground(); 69 InitializeForeground();
70 break; 70 break;
71 case LibraryAppletMode::Background: 71 case LibraryAppletMode::PartialForeground:
72 case LibraryAppletMode::BackgroundIndirectDisplay: 72 case LibraryAppletMode::PartialForegroundIndirectDisplay:
73 InitializeBackground(applet_mode); 73 InitializePartialForeground(applet_mode);
74 break; 74 break;
75 default: 75 default:
76 ASSERT_MSG(false, "Invalid LibraryAppletMode={}", applet_mode); 76 ASSERT_MSG(false, "Invalid LibraryAppletMode={}", applet_mode);
@@ -243,7 +243,7 @@ void SoftwareKeyboard::InitializeForeground() {
243 InitializeFrontendNormalKeyboard(); 243 InitializeFrontendNormalKeyboard();
244} 244}
245 245
246void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mode) { 246void SoftwareKeyboard::InitializePartialForeground(LibraryAppletMode library_applet_mode) {
247 LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet."); 247 LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet.");
248 248
249 is_background = true; 249 is_background = true;
@@ -258,9 +258,9 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mod
258 swkbd_inline_initialize_arg.size()); 258 swkbd_inline_initialize_arg.size());
259 259
260 if (swkbd_initialize_arg.library_applet_mode_flag) { 260 if (swkbd_initialize_arg.library_applet_mode_flag) {
261 ASSERT(library_applet_mode == LibraryAppletMode::Background); 261 ASSERT(library_applet_mode == LibraryAppletMode::PartialForeground);
262 } else { 262 } else {
263 ASSERT(library_applet_mode == LibraryAppletMode::BackgroundIndirectDisplay); 263 ASSERT(library_applet_mode == LibraryAppletMode::PartialForegroundIndirectDisplay);
264 } 264 }
265} 265}
266 266
diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.h b/src/core/hle/service/am/frontend/applet_software_keyboard.h
index f464b7e15..2a7d01b96 100644
--- a/src/core/hle/service/am/frontend/applet_software_keyboard.h
+++ b/src/core/hle/service/am/frontend/applet_software_keyboard.h
@@ -62,7 +62,7 @@ private:
62 void InitializeForeground(); 62 void InitializeForeground();
63 63
64 /// Initializes the inline software keyboard. 64 /// Initializes the inline software keyboard.
65 void InitializeBackground(LibraryAppletMode library_applet_mode); 65 void InitializePartialForeground(LibraryAppletMode library_applet_mode);
66 66
67 /// Processes the text check sent by the application. 67 /// Processes the text check sent by the application.
68 void ProcessTextCheck(); 68 void ProcessTextCheck();
diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp
index 47bab7528..00d5a0705 100644
--- a/src/core/hle/service/am/library_applet_creator.cpp
+++ b/src/core/hle/service/am/library_applet_creator.cpp
@@ -1,6 +1,7 @@
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 "common/settings.h"
4#include "core/hle/kernel/k_transfer_memory.h" 5#include "core/hle/kernel/k_transfer_memory.h"
5#include "core/hle/service/am/applet_data_broker.h" 6#include "core/hle/service/am/applet_data_broker.h"
6#include "core/hle/service/am/applet_manager.h" 7#include "core/hle/service/am/applet_manager.h"
@@ -16,6 +17,34 @@ namespace Service::AM {
16 17
17namespace { 18namespace {
18 19
20bool ShouldCreateGuestApplet(AppletId applet_id) {
21#define X(Name, name) \
22 if (applet_id == AppletId::Name && \
23 Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \
24 return false; \
25 }
26
27 X(Cabinet, cabinet)
28 X(Controller, controller)
29 X(DataErase, data_erase)
30 X(Error, error)
31 X(NetConnect, net_connect)
32 X(ProfileSelect, player_select)
33 X(SoftwareKeyboard, swkbd)
34 X(MiiEdit, mii_edit)
35 X(Web, web)
36 X(Shop, shop)
37 X(PhotoViewer, photo_viewer)
38 X(OfflineWeb, offline_web)
39 X(LoginShare, login_share)
40 X(WebAuth, wifi_web_auth)
41 X(MyPage, my_page)
42
43#undef X
44
45 return true;
46}
47
19AppletProgramId AppletIdToProgramId(AppletId applet_id) { 48AppletProgramId AppletIdToProgramId(AppletId applet_id) {
20 switch (applet_id) { 49 switch (applet_id) {
21 case AppletId::OverlayDisplay: 50 case AppletId::OverlayDisplay:
@@ -63,17 +92,26 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
63 } 92 }
64} 93}
65 94
66[[maybe_unused]] std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet( 95std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
67 Core::System& system, std::shared_ptr<Applet> caller_applet, AppletId applet_id, 96 std::shared_ptr<Applet> caller_applet,
68 LibraryAppletMode mode) { 97 AppletId applet_id,
98 LibraryAppletMode mode) {
69 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); 99 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
70 if (program_id == 0) { 100 if (program_id == 0) {
71 // Unknown applet 101 // Unknown applet
72 return {}; 102 return {};
73 } 103 }
74 104
105 // TODO: enable other versions of applets
106 enum : u8 {
107 Firmware1400 = 14,
108 Firmware1500 = 15,
109 Firmware1600 = 16,
110 Firmware1700 = 17,
111 };
112
75 auto process = std::make_unique<Process>(system); 113 auto process = std::make_unique<Process>(system);
76 if (!process->Initialize(program_id)) { 114 if (!process->Initialize(program_id, Firmware1400, Firmware1700)) {
77 // Couldn't initialize the guest process 115 // Couldn't initialize the guest process
78 return {}; 116 return {};
79 } 117 }
@@ -87,24 +125,18 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
87 // Set focus state 125 // Set focus state
88 switch (mode) { 126 switch (mode) {
89 case LibraryAppletMode::AllForeground: 127 case LibraryAppletMode::AllForeground:
90 case LibraryAppletMode::NoUI: 128 case LibraryAppletMode::NoUi:
91 applet->focus_state = FocusState::InFocus; 129 case LibraryAppletMode::PartialForeground:
130 case LibraryAppletMode::PartialForegroundIndirectDisplay:
92 applet->hid_registration.EnableAppletToGetInput(true); 131 applet->hid_registration.EnableAppletToGetInput(true);
132 applet->focus_state = FocusState::InFocus;
93 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); 133 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
94 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
95 break; 134 break;
96 case LibraryAppletMode::AllForegroundInitiallyHidden: 135 case LibraryAppletMode::AllForegroundInitiallyHidden:
97 applet->system_buffer_manager.SetWindowVisibility(false);
98 applet->focus_state = FocusState::NotInFocus;
99 applet->hid_registration.EnableAppletToGetInput(false); 136 applet->hid_registration.EnableAppletToGetInput(false);
100 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); 137 applet->focus_state = FocusState::NotInFocus;
101 break; 138 applet->system_buffer_manager.SetWindowVisibility(false);
102 case LibraryAppletMode::Background: 139 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground);
103 case LibraryAppletMode::BackgroundIndirectDisplay:
104 default:
105 applet->focus_state = FocusState::Background;
106 applet->hid_registration.EnableAppletToGetInput(true);
107 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
108 break; 140 break;
109 } 141 }
110 142
@@ -117,9 +149,10 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
117 return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); 149 return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
118} 150}
119 151
120[[maybe_unused]] std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet( 152std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
121 Core::System& system, std::shared_ptr<Applet> caller_applet, AppletId applet_id, 153 std::shared_ptr<Applet> caller_applet,
122 LibraryAppletMode mode) { 154 AppletId applet_id,
155 LibraryAppletMode mode) {
123 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); 156 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
124 157
125 auto process = std::make_unique<Process>(system); 158 auto process = std::make_unique<Process>(system);
@@ -163,7 +196,13 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
163 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id, 196 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
164 applet_mode); 197 applet_mode);
165 198
166 auto library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode); 199 std::shared_ptr<ILibraryAppletAccessor> library_applet;
200 if (ShouldCreateGuestApplet(applet_id)) {
201 library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode);
202 }
203 if (!library_applet) {
204 library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode);
205 }
167 if (!library_applet) { 206 if (!library_applet) {
168 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); 207 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
169 208
diff --git a/src/core/hle/service/am/process.cpp b/src/core/hle/service/am/process.cpp
index 16b685f86..992c50713 100644
--- a/src/core/hle/service/am/process.cpp
+++ b/src/core/hle/service/am/process.cpp
@@ -3,6 +3,7 @@
3 3
4#include "common/scope_exit.h" 4#include "common/scope_exit.h"
5 5
6#include "core/file_sys/content_archive.h"
6#include "core/file_sys/nca_metadata.h" 7#include "core/file_sys/nca_metadata.h"
7#include "core/file_sys/registered_cache.h" 8#include "core/file_sys/registered_cache.h"
8#include "core/hle/kernel/k_process.h" 9#include "core/hle/kernel/k_process.h"
@@ -20,7 +21,7 @@ Process::~Process() {
20 this->Finalize(); 21 this->Finalize();
21} 22}
22 23
23bool Process::Initialize(u64 program_id) { 24bool Process::Initialize(u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation) {
24 // First, ensure we are not holding another process. 25 // First, ensure we are not holding another process.
25 this->Finalize(); 26 this->Finalize();
26 27
@@ -29,21 +30,33 @@ bool Process::Initialize(u64 program_id) {
29 30
30 // Attempt to load program NCA. 31 // Attempt to load program NCA.
31 const FileSys::RegisteredCache* bis_system{}; 32 const FileSys::RegisteredCache* bis_system{};
32 FileSys::VirtualFile nca{}; 33 FileSys::VirtualFile nca_raw{};
33 34
34 // Get the program NCA from built-in storage. 35 // Get the program NCA from built-in storage.
35 bis_system = fsc.GetSystemNANDContents(); 36 bis_system = fsc.GetSystemNANDContents();
36 if (bis_system) { 37 if (bis_system) {
37 nca = bis_system->GetEntryRaw(program_id, FileSys::ContentRecordType::Program); 38 nca_raw = bis_system->GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
38 } 39 }
39 40
40 // Ensure we retrieved a program NCA. 41 // Ensure we retrieved a program NCA.
41 if (!nca) { 42 if (!nca_raw) {
42 return false; 43 return false;
43 } 44 }
44 45
46 // Ensure we have a suitable version.
47 if (minimum_key_generation > 0) {
48 FileSys::NCA nca(nca_raw);
49 if (nca.GetStatus() == Loader::ResultStatus::Success &&
50 (nca.GetKeyGeneration() < minimum_key_generation ||
51 nca.GetKeyGeneration() > maximum_key_generation)) {
52 LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id,
53 nca.GetKeyGeneration());
54 return false;
55 }
56 }
57
45 // Get the appropriate loader to parse this NCA. 58 // Get the appropriate loader to parse this NCA.
46 auto app_loader = Loader::GetLoader(m_system, nca, program_id, 0); 59 auto app_loader = Loader::GetLoader(m_system, nca_raw, program_id, 0);
47 60
48 // Ensure we have a loader which can parse the NCA. 61 // Ensure we have a loader which can parse the NCA.
49 if (!app_loader) { 62 if (!app_loader) {
diff --git a/src/core/hle/service/am/process.h b/src/core/hle/service/am/process.h
index 4b908ade4..4b8102fb6 100644
--- a/src/core/hle/service/am/process.h
+++ b/src/core/hle/service/am/process.h
@@ -21,7 +21,7 @@ public:
21 explicit Process(Core::System& system); 21 explicit Process(Core::System& system);
22 ~Process(); 22 ~Process();
23 23
24 bool Initialize(u64 program_id); 24 bool Initialize(u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation);
25 void Finalize(); 25 void Finalize();
26 26
27 bool Run(); 27 bool Run();
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp
index 0289f5cf1..65e249c0c 100644
--- a/src/core/hle/service/am/self_controller.cpp
+++ b/src/core/hle/service/am/self_controller.cpp
@@ -1,10 +1,13 @@
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 "common/logging/log.h"
5#include "core/hle/result.h"
4#include "core/hle/service/am/am_results.h" 6#include "core/hle/service/am/am_results.h"
5#include "core/hle/service/am/frontend/applets.h" 7#include "core/hle/service/am/frontend/applets.h"
6#include "core/hle/service/am/self_controller.h" 8#include "core/hle/service/am/self_controller.h"
7#include "core/hle/service/caps/caps_su.h" 9#include "core/hle/service/caps/caps_su.h"
10#include "core/hle/service/hle_ipc.h"
8#include "core/hle/service/ipc_helpers.h" 11#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" 12#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
10#include "core/hle/service/nvnflinger/nvnflinger.h" 13#include "core/hle/service/nvnflinger/nvnflinger.h"
@@ -47,7 +50,7 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
47 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, 50 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
48 {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, 51 {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
49 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, 52 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
50 {61, nullptr, "SetMediaPlaybackState"}, 53 {61, &ISelfController::SetMediaPlaybackState, "SetMediaPlaybackState"},
51 {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, 54 {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
52 {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, 55 {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
53 {64, nullptr, "SetInputDetectionSourceSet"}, 56 {64, nullptr, "SetInputDetectionSourceSet"},
@@ -288,7 +291,8 @@ void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
288} 291}
289 292
290Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { 293Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
291 if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) { 294 if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id,
295 applet->library_applet_mode)) {
292 return ResultSuccess; 296 return ResultSuccess;
293 } 297 }
294 298
@@ -323,6 +327,16 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
323 rb.Push(ResultSuccess); 327 rb.Push(ResultSuccess);
324} 328}
325 329
330void ISelfController::SetMediaPlaybackState(HLERequestContext& ctx) {
331 IPC::RequestParser rp{ctx};
332 const u8 state = rp.Pop<u8>();
333
334 LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
335
336 IPC::ResponseBuilder rb{ctx, 2};
337 rb.Push(ResultSuccess);
338}
339
326void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { 340void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
327 IPC::RequestParser rp{ctx}; 341 IPC::RequestParser rp{ctx};
328 342
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h
index a63bc2e74..ab21a1881 100644
--- a/src/core/hle/service/am/self_controller.h
+++ b/src/core/hle/service/am/self_controller.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/hle_ipc.h"
6#include "core/hle/service/kernel_helpers.h" 7#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
8 9
@@ -38,6 +39,7 @@ private:
38 void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); 39 void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
39 void SetHandlesRequestToDisplay(HLERequestContext& ctx); 40 void SetHandlesRequestToDisplay(HLERequestContext& ctx);
40 void ApproveToDisplay(HLERequestContext& ctx); 41 void ApproveToDisplay(HLERequestContext& ctx);
42 void SetMediaPlaybackState(HLERequestContext& ctx);
41 void SetIdleTimeDetectionExtension(HLERequestContext& ctx); 43 void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
42 void GetIdleTimeDetectionExtension(HLERequestContext& ctx); 44 void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
43 void ReportUserIsActive(HLERequestContext& ctx); 45 void ReportUserIsActive(HLERequestContext& ctx);
diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp
index 60a9afc9d..48923fe41 100644
--- a/src/core/hle/service/am/system_buffer_manager.cpp
+++ b/src/core/hle/service/am/system_buffer_manager.cpp
@@ -17,11 +17,12 @@ SystemBufferManager::~SystemBufferManager() {
17 17
18 // Clean up shared layers. 18 // Clean up shared layers.
19 if (m_buffer_sharing_enabled) { 19 if (m_buffer_sharing_enabled) {
20 m_nvnflinger->GetSystemBufferManager().Finalize(m_process);
20 } 21 }
21} 22}
22 23
23bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, 24bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process,
24 AppletId applet_id) { 25 AppletId applet_id, LibraryAppletMode mode) {
25 if (m_nvnflinger) { 26 if (m_nvnflinger) {
26 return m_buffer_sharing_enabled; 27 return m_buffer_sharing_enabled;
27 } 28 }
@@ -36,9 +37,15 @@ bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel:
36 return false; 37 return false;
37 } 38 }
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
39 const auto display_id = m_nvnflinger->OpenDisplay("Default").value(); 46 const auto display_id = m_nvnflinger->OpenDisplay("Default").value();
40 const auto res = m_nvnflinger->GetSystemBufferManager().Initialize( 47 const auto res = m_nvnflinger->GetSystemBufferManager().Initialize(
41 &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id); 48 m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending);
42 49
43 if (res.IsSuccess()) { 50 if (res.IsSuccess()) {
44 m_buffer_sharing_enabled = true; 51 m_buffer_sharing_enabled = true;
@@ -62,8 +69,12 @@ void SystemBufferManager::SetWindowVisibility(bool visible) {
62 69
63Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, 70Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written,
64 s32* out_fbshare_layer_index) { 71 s32* out_fbshare_layer_index) {
65 // TODO 72 if (!m_buffer_sharing_enabled) {
66 R_SUCCEED(); 73 return VI::ResultPermissionDenied;
74 }
75
76 return m_nvnflinger->GetSystemBufferManager().WriteAppletCaptureBuffer(out_was_written,
77 out_fbshare_layer_index);
67} 78}
68 79
69} // namespace Service::AM 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
index 98c3cf055..0690f68b6 100644
--- a/src/core/hle/service/am/system_buffer_manager.h
+++ b/src/core/hle/service/am/system_buffer_manager.h
@@ -27,7 +27,8 @@ public:
27 SystemBufferManager(); 27 SystemBufferManager();
28 ~SystemBufferManager(); 28 ~SystemBufferManager();
29 29
30 bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id); 30 bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id,
31 LibraryAppletMode mode);
31 32
32 void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id, 33 void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
33 u64* out_system_shared_layer_id) { 34 u64* out_system_shared_layer_id) {
diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp
index f00957f83..c07ef228b 100644
--- a/src/core/hle/service/am/window_controller.cpp
+++ b/src/core/hle/service/am/window_controller.cpp
@@ -62,12 +62,12 @@ void IWindowController::SetAppletWindowVisibility(HLERequestContext& ctx) {
62 applet->hid_registration.EnableAppletToGetInput(visible); 62 applet->hid_registration.EnableAppletToGetInput(visible);
63 63
64 if (visible) { 64 if (visible) {
65 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
66 applet->focus_state = FocusState::InFocus; 65 applet->focus_state = FocusState::InFocus;
66 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
67 } else { 67 } else {
68 applet->focus_state = FocusState::NotInFocus; 68 applet->focus_state = FocusState::NotInFocus;
69 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground);
69 } 70 }
70 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
71 71
72 IPC::ResponseBuilder rb{ctx, 2}; 72 IPC::ResponseBuilder rb{ctx, 2};
73 rb.Push(ResultSuccess); 73 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp
index e89cca6f2..9edce03f6 100644
--- a/src/core/hle/service/nvdrv/core/container.cpp
+++ b/src/core/hle/service/nvdrv/core/container.cpp
@@ -49,6 +49,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
49 continue; 49 continue;
50 } 50 }
51 if (session.process == process) { 51 if (session.process == process) {
52 session.ref_count++;
52 return session.id; 53 return session.id;
53 } 54 }
54 } 55 }
@@ -66,6 +67,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
66 } 67 }
67 auto& session = impl->sessions[new_id]; 68 auto& session = impl->sessions[new_id];
68 session.is_active = true; 69 session.is_active = true;
70 session.ref_count = 1;
69 // Optimization 71 // Optimization
70 if (process->IsApplication()) { 72 if (process->IsApplication()) {
71 auto& page_table = process->GetPageTable().GetBasePageTable(); 73 auto& page_table = process->GetPageTable().GetBasePageTable();
@@ -114,8 +116,11 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
114 116
115void Container::CloseSession(SessionId session_id) { 117void Container::CloseSession(SessionId session_id) {
116 std::scoped_lock lk(impl->session_guard); 118 std::scoped_lock lk(impl->session_guard);
117 impl->file.UnmapAllHandles(session_id);
118 auto& session = impl->sessions[session_id.id]; 119 auto& session = impl->sessions[session_id.id];
120 if (--session.ref_count > 0) {
121 return;
122 }
123 impl->file.UnmapAllHandles(session_id);
119 auto& smmu = impl->host1x.MemoryManager(); 124 auto& smmu = impl->host1x.MemoryManager();
120 if (session.has_preallocated_area) { 125 if (session.has_preallocated_area) {
121 const DAddr region_start = session.mapper->GetRegionStart(); 126 const DAddr region_start = session.mapper->GetRegionStart();
diff --git a/src/core/hle/service/nvdrv/core/container.h b/src/core/hle/service/nvdrv/core/container.h
index b4d3938a8..f159ced09 100644
--- a/src/core/hle/service/nvdrv/core/container.h
+++ b/src/core/hle/service/nvdrv/core/container.h
@@ -46,6 +46,7 @@ struct Session {
46 bool has_preallocated_area{}; 46 bool has_preallocated_area{};
47 std::unique_ptr<HeapMapper> mapper{}; 47 std::unique_ptr<HeapMapper> mapper{};
48 bool is_active{}; 48 bool is_active{};
49 s32 ref_count{};
49}; 50};
50 51
51class Container { 52class Container {
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index bc1c033c6..453cb5831 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -333,9 +333,13 @@ void NvMap::UnmapAllHandles(NvCore::SessionId session_id) {
333 }(); 333 }();
334 334
335 for (auto& [id, handle] : handles_copy) { 335 for (auto& [id, handle] : handles_copy) {
336 if (handle->session_id.id == session_id.id) { 336 {
337 FreeHandle(id, false); 337 std::scoped_lock lk{handle->mutex};
338 if (handle->session_id.id != session_id.id || handle->dupes <= 0) {
339 continue;
340 }
338 } 341 }
342 FreeHandle(id, false);
339 } 343 }
340} 344}
341 345
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index abe95303e..995646e25 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -15,6 +15,22 @@
15 15
16namespace Service::Nvidia::Devices { 16namespace Service::Nvidia::Devices {
17 17
18namespace {
19
20Tegra::BlendMode ConvertBlending(Service::Nvnflinger::LayerBlending blending) {
21 switch (blending) {
22 case Service::Nvnflinger::LayerBlending::None:
23 default:
24 return Tegra::BlendMode::Opaque;
25 case Service::Nvnflinger::LayerBlending::Premultiplied:
26 return Tegra::BlendMode::Premultiplied;
27 case Service::Nvnflinger::LayerBlending::Coverage:
28 return Tegra::BlendMode::Coverage;
29 }
30}
31
32} // namespace
33
18nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core) 34nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core)
19 : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {} 35 : nvdevice{system_}, container{core}, nvmap{core.GetNvMapFile()} {}
20nvdisp_disp0::~nvdisp_disp0() = default; 36nvdisp_disp0::~nvdisp_disp0() = default;
@@ -56,6 +72,7 @@ void nvdisp_disp0::Composite(std::span<const Nvnflinger::HwcLayer> sorted_layers
56 .pixel_format = layer.format, 72 .pixel_format = layer.format,
57 .transform_flags = layer.transform, 73 .transform_flags = layer.transform,
58 .crop_rect = layer.crop_rect, 74 .crop_rect = layer.crop_rect,
75 .blending = ConvertBlending(layer.blending),
59 }); 76 });
60 77
61 for (size_t i = 0; i < layer.acquire_fence.num_fences; i++) { 78 for (size_t i = 0; i < layer.acquire_fence.num_fences; i++) {
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
index e71652cdf..90f7248a0 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -14,24 +14,20 @@
14#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" 14#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
15#include "core/hle/service/vi/layer/vi_layer.h" 15#include "core/hle/service/vi/layer/vi_layer.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"
18#include "video_core/host1x/host1x.h"
17 19
18namespace Service::Nvnflinger { 20namespace Service::Nvnflinger {
19 21
20namespace { 22namespace {
21 23
22Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, 24Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group,
23 std::unique_ptr<Kernel::KPageGroup>* out_page_group, 25 Core::System& system, u32 size) {
24 Core::System& system, u32 size) {
25 using Core::Memory::YUZU_PAGESIZE; 26 using Core::Memory::YUZU_PAGESIZE;
26 27
27 // Allocate memory for the system shared buffer. 28 // Allocate memory for the system shared buffer.
28 // FIXME: Because the gmmu can only point to cpu addresses, we need
29 // to map this in the application space to allow it to be used.
30 // FIXME: Add proper smmu emulation.
31 // FIXME: This memory belongs to vi's .data section. 29 // FIXME: This memory belongs to vi's .data section.
32 auto& kernel = system.Kernel(); 30 auto& kernel = system.Kernel();
33 auto* process = system.ApplicationProcess();
34 auto& page_table = process->GetPageTable();
35 31
36 // Hold a temporary page group reference while we try to map it. 32 // Hold a temporary page group reference while we try to map it.
37 auto pg = std::make_unique<Kernel::KPageGroup>( 33 auto pg = std::make_unique<Kernel::KPageGroup>(
@@ -43,6 +39,30 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address,
43 Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure, 39 Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,
44 Kernel::KMemoryManager::Direction::FromBack))); 40 Kernel::KMemoryManager::Direction::FromBack)));
45 41
42 // Fill the output data with red.
43 for (auto& block : *pg) {
44 u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
45 u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
46
47 for (; start < end; start++) {
48 *start = 0xFF0000FF;
49 }
50 }
51
52 // Return the mapped page group.
53 *out_page_group = std::move(pg);
54
55 // We succeeded.
56 R_SUCCEED();
57}
58
59Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address,
60 std::unique_ptr<Kernel::KPageGroup>& pg,
61 Kernel::KProcess* process, Core::System& system) {
62 using Core::Memory::YUZU_PAGESIZE;
63
64 auto& page_table = process->GetPageTable();
65
46 // Get bounds of where mapping is possible. 66 // Get bounds of where mapping is possible.
47 const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart()); 67 const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart());
48 const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE; 68 const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE;
@@ -64,9 +84,6 @@ Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address,
64 // Return failure, if necessary 84 // Return failure, if necessary
65 R_UNLESS(i < 64, res); 85 R_UNLESS(i < 64, res);
66 86
67 // Return the mapped page group.
68 *out_page_group = std::move(pg);
69
70 // We succeeded. 87 // We succeeded.
71 R_SUCCEED(); 88 R_SUCCEED();
72} 89}
@@ -135,6 +152,13 @@ Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::D
135 R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd)); 152 R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd));
136} 153}
137 154
155void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) {
156 auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
157 ASSERT(nvmap != nullptr);
158
159 R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd));
160}
161
138constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; 162constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;
139constexpr u32 SharedBufferBlockLinearBpp = 4; 163constexpr u32 SharedBufferBlockLinearBpp = 4;
140 164
@@ -186,53 +210,97 @@ FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& fli
186 210
187FbShareBufferManager::~FbShareBufferManager() = default; 211FbShareBufferManager::~FbShareBufferManager() = default;
188 212
189Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u64 display_id) { 213Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id,
214 u64* out_layer_handle, u64 display_id,
215 LayerBlending blending) {
190 std::scoped_lock lk{m_guard}; 216 std::scoped_lock lk{m_guard};
191 217
192 // Ensure we have not already created a buffer. 218 // Ensure we haven't already created.
193 R_UNLESS(m_buffer_id == 0, VI::ResultOperationFailed); 219 const u64 aruid = owner_process->GetProcessId();
220 R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied);
221
222 // Allocate memory for the shared buffer if needed.
223 if (!m_buffer_page_group) {
224 R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system,
225 SharedBufferSize));
226
227 // Record buffer id.
228 m_buffer_id = m_next_buffer_id++;
229
230 // Record display id.
231 m_display_id = display_id;
232 }
233
234 // Map into process.
235 Common::ProcessAddress map_address{};
236 R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group,
237 owner_process, m_system));
194 238
195 // Allocate memory and space for the shared buffer. 239 // Create new session.
196 Common::ProcessAddress map_address; 240 auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{});
197 R_TRY(AllocateIoForProcessAddressSpace(std::addressof(map_address), 241 auto& session = it->second;
198 std::addressof(m_buffer_page_group), m_system,
199 SharedBufferSize));
200 242
201 auto& container = m_nvdrv->GetContainer(); 243 auto& container = m_nvdrv->GetContainer();
202 m_session_id = container.OpenSession(m_system.ApplicationProcess()); 244 session.session_id = container.OpenSession(owner_process);
203 m_nvmap_fd = m_nvdrv->Open("/dev/nvmap", m_session_id); 245 session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);
204 246
205 // Create an nvmap handle for the buffer and assign the memory to it. 247 // Create an nvmap handle for the buffer and assign the memory to it.
206 R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, m_nvmap_fd, 248 R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv,
207 map_address, SharedBufferSize)); 249 session.nvmap_fd, map_address, SharedBufferSize));
208
209 // Record the display id.
210 m_display_id = display_id;
211 250
212 // Create and open a layer for the display. 251 // Create and open a layer for the display.
213 m_layer_id = m_flinger.CreateLayer(m_display_id).value(); 252 session.layer_id = m_flinger.CreateLayer(m_display_id, blending).value();
214 m_flinger.OpenLayer(m_layer_id); 253 m_flinger.OpenLayer(session.layer_id);
215
216 // Set up the buffer.
217 m_buffer_id = m_next_buffer_id++;
218 254
219 // Get the layer. 255 // Get the layer.
220 VI::Layer* layer = m_flinger.FindLayer(m_display_id, m_layer_id); 256 VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id);
221 ASSERT(layer != nullptr); 257 ASSERT(layer != nullptr);
222 258
223 // Get the producer and set preallocated buffers. 259 // Get the producer and set preallocated buffers.
224 auto& producer = layer->GetBufferQueue(); 260 auto& producer = layer->GetBufferQueue();
225 MakeGraphicBuffer(producer, 0, m_buffer_nvmap_handle); 261 MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle);
226 MakeGraphicBuffer(producer, 1, m_buffer_nvmap_handle); 262 MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle);
227 263
228 // Assign outputs. 264 // Assign outputs.
229 *out_buffer_id = m_buffer_id; 265 *out_buffer_id = m_buffer_id;
230 *out_layer_id = m_layer_id; 266 *out_layer_handle = session.layer_id;
231 267
232 // We succeeded. 268 // We succeeded.
233 R_SUCCEED(); 269 R_SUCCEED();
234} 270}
235 271
272void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
273 std::scoped_lock lk{m_guard};
274
275 if (m_buffer_id == 0) {
276 return;
277 }
278
279 const u64 aruid = owner_process->GetProcessId();
280 const auto it = m_sessions.find(aruid);
281 if (it == m_sessions.end()) {
282 return;
283 }
284
285 auto& session = it->second;
286
287 // Destroy the layer.
288 m_flinger.DestroyLayer(session.layer_id);
289
290 // Close nvmap handle.
291 FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd);
292
293 // Close nvmap device.
294 m_nvdrv->Close(session.nvmap_fd);
295
296 // Close session.
297 auto& container = m_nvdrv->GetContainer();
298 container.CloseSession(session.session_id);
299
300 // Erase.
301 m_sessions.erase(it);
302}
303
236Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, 304Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
237 s32* out_nvmap_handle, 305 s32* out_nvmap_handle,
238 SharedMemoryPoolLayout* out_pool_layout, 306 SharedMemoryPoolLayout* out_pool_layout,
@@ -242,17 +310,18 @@ Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
242 310
243 R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); 311 R_UNLESS(m_buffer_id > 0, VI::ResultNotFound);
244 R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound); 312 R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound);
313 R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound);
245 314
246 *out_pool_layout = SharedBufferPoolLayout; 315 *out_pool_layout = SharedBufferPoolLayout;
247 *out_buffer_size = SharedBufferSize; 316 *out_buffer_size = SharedBufferSize;
248 *out_nvmap_handle = m_buffer_nvmap_handle; 317 *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle;
249 318
250 R_SUCCEED(); 319 R_SUCCEED();
251} 320}
252 321
253Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { 322Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) {
254 // Ensure the layer id is valid. 323 // Ensure the layer id is valid.
255 R_UNLESS(m_layer_id > 0 && layer_id == m_layer_id, VI::ResultNotFound); 324 R_UNLESS(layer_id > 0, VI::ResultNotFound);
256 325
257 // Get the layer. 326 // Get the layer.
258 VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id); 327 VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id);
@@ -309,6 +378,10 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
309 android::Status::NoError, 378 android::Status::NoError,
310 VI::ResultOperationFailed); 379 VI::ResultOperationFailed);
311 380
381 ON_RESULT_FAILURE {
382 producer.CancelBuffer(static_cast<s32>(slot), fence);
383 };
384
312 // Queue the buffer to the producer. 385 // Queue the buffer to the producer.
313 android::QueueBufferInput input{}; 386 android::QueueBufferInput input{};
314 android::QueueBufferOutput output{}; 387 android::QueueBufferOutput output{};
@@ -342,4 +415,33 @@ Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadab
342 R_SUCCEED(); 415 R_SUCCEED();
343} 416}
344 417
418Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
419 std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
420 Common::ScratchBuffer<u32> scratch;
421
422 // TODO: this could be optimized
423 s64 e = -1280 * 768 * 4;
424 for (auto& block : *m_buffer_page_group) {
425 u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
426 u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
427
428 for (; start < end; start++) {
429 *start = 0;
430
431 if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
432 *start = capture_buffer[e];
433 }
434 e++;
435 }
436
437 m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
438 m_system.GPU().InvalidateRegion(addr, end - start);
439 });
440 }
441
442 *out_was_written = true;
443 *out_layer_index = 1;
444 R_SUCCEED();
445}
446
345} // namespace Service::Nvnflinger 447} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
index 033bf4bbe..b79a7d23a 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
@@ -3,9 +3,12 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <map>
7
6#include "common/math_util.h" 8#include "common/math_util.h"
7#include "core/hle/service/nvdrv/core/container.h" 9#include "core/hle/service/nvdrv/core/container.h"
8#include "core/hle/service/nvdrv/nvdata.h" 10#include "core/hle/service/nvdrv/nvdata.h"
11#include "core/hle/service/nvnflinger/hwc_layer.h"
9#include "core/hle/service/nvnflinger/nvnflinger.h" 12#include "core/hle/service/nvnflinger/nvnflinger.h"
10#include "core/hle/service/nvnflinger/ui/fence.h" 13#include "core/hle/service/nvnflinger/ui/fence.h"
11 14
@@ -29,13 +32,18 @@ struct SharedMemoryPoolLayout {
29}; 32};
30static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); 33static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
31 34
35struct FbShareSession;
36
32class FbShareBufferManager final { 37class FbShareBufferManager final {
33public: 38public:
34 explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger, 39 explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
35 std::shared_ptr<Nvidia::Module> nvdrv); 40 std::shared_ptr<Nvidia::Module> nvdrv);
36 ~FbShareBufferManager(); 41 ~FbShareBufferManager();
37 42
38 Result Initialize(u64* out_buffer_id, u64* out_layer_handle, u64 display_id); 43 Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle,
44 u64 display_id, LayerBlending blending);
45 void Finalize(Kernel::KProcess* owner_process);
46
39 Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, 47 Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,
40 SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, 48 SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id,
41 u64 applet_resource_user_id); 49 u64 applet_resource_user_id);
@@ -45,6 +53,8 @@ public:
45 u32 transform, s32 swap_interval, u64 layer_id, s64 slot); 53 u32 transform, s32 swap_interval, u64 layer_id, s64 slot);
46 Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); 54 Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
47 55
56 Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index);
57
48private: 58private:
49 Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); 59 Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id);
50 60
@@ -52,11 +62,8 @@ private:
52 u64 m_next_buffer_id = 1; 62 u64 m_next_buffer_id = 1;
53 u64 m_display_id = 0; 63 u64 m_display_id = 0;
54 u64 m_buffer_id = 0; 64 u64 m_buffer_id = 0;
55 u64 m_layer_id = 0;
56 u32 m_buffer_nvmap_handle = 0;
57 SharedMemoryPoolLayout m_pool_layout = {}; 65 SharedMemoryPoolLayout m_pool_layout = {};
58 Nvidia::DeviceFD m_nvmap_fd = {}; 66 std::map<u64, FbShareSession> m_sessions;
59 Nvidia::NvCore::SessionId m_session_id = {};
60 std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; 67 std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
61 68
62 std::mutex m_guard; 69 std::mutex m_guard;
@@ -65,4 +72,11 @@ private:
65 std::shared_ptr<Nvidia::Module> m_nvdrv; 72 std::shared_ptr<Nvidia::Module> m_nvdrv;
66}; 73};
67 74
75struct FbShareSession {
76 Nvidia::DeviceFD nvmap_fd = {};
77 Nvidia::NvCore::SessionId session_id = {};
78 u64 layer_id = {};
79 u32 buffer_nvmap_handle = 0;
80};
81
68} // namespace Service::Nvnflinger 82} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp
index ba2b5c28c..be7eb97a3 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.cpp
+++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp
@@ -86,6 +86,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
86 .height = igbp_buffer.Height(), 86 .height = igbp_buffer.Height(),
87 .stride = igbp_buffer.Stride(), 87 .stride = igbp_buffer.Stride(),
88 .z_index = 0, 88 .z_index = 0,
89 .blending = layer.GetBlending(),
89 .transform = static_cast<android::BufferTransformFlags>(item.transform), 90 .transform = static_cast<android::BufferTransformFlags>(item.transform),
90 .crop_rect = item.crop, 91 .crop_rect = item.crop,
91 .acquire_fence = item.fence, 92 .acquire_fence = item.fence,
diff --git a/src/core/hle/service/nvnflinger/hwc_layer.h b/src/core/hle/service/nvnflinger/hwc_layer.h
index 3af668a25..f71a5d822 100644
--- a/src/core/hle/service/nvnflinger/hwc_layer.h
+++ b/src/core/hle/service/nvnflinger/hwc_layer.h
@@ -11,6 +11,18 @@
11 11
12namespace Service::Nvnflinger { 12namespace Service::Nvnflinger {
13 13
14// hwc_layer_t::blending values
15enum class LayerBlending : u32 {
16 // No blending
17 None = 0x100,
18
19 // ONE / ONE_MINUS_SRC_ALPHA
20 Premultiplied = 0x105,
21
22 // SRC_ALPHA / ONE_MINUS_SRC_ALPHA
23 Coverage = 0x405,
24};
25
14struct HwcLayer { 26struct HwcLayer {
15 u32 buffer_handle; 27 u32 buffer_handle;
16 u32 offset; 28 u32 offset;
@@ -19,6 +31,7 @@ struct HwcLayer {
19 u32 height; 31 u32 height;
20 u32 stride; 32 u32 stride;
21 s32 z_index; 33 s32 z_index;
34 LayerBlending blending;
22 android::BufferTransformFlags transform; 35 android::BufferTransformFlags transform;
23 Common::Rectangle<int> crop_rect; 36 Common::Rectangle<int> crop_rect;
24 android::Fence acquire_fence; 37 android::Fence acquire_fence;
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index d8ba89d43..687ccc9f9 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -157,7 +157,7 @@ bool Nvnflinger::CloseDisplay(u64 display_id) {
157 return true; 157 return true;
158} 158}
159 159
160std::optional<u64> Nvnflinger::CreateLayer(u64 display_id) { 160std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) {
161 const auto lock_guard = Lock(); 161 const auto lock_guard = Lock();
162 auto* const display = FindDisplay(display_id); 162 auto* const display = FindDisplay(display_id);
163 163
@@ -166,13 +166,14 @@ std::optional<u64> Nvnflinger::CreateLayer(u64 display_id) {
166 } 166 }
167 167
168 const u64 layer_id = next_layer_id++; 168 const u64 layer_id = next_layer_id++;
169 CreateLayerAtId(*display, layer_id); 169 CreateLayerAtId(*display, layer_id, blending);
170 return layer_id; 170 return layer_id;
171} 171}
172 172
173void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { 173void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) {
174 const auto buffer_id = next_buffer_queue_id++; 174 const auto buffer_id = next_buffer_queue_id++;
175 display.CreateLayer(layer_id, buffer_id, nvdrv->container); 175 display.CreateLayer(layer_id, buffer_id, nvdrv->container);
176 display.FindLayer(layer_id)->SetBlending(blending);
176} 177}
177 178
178bool Nvnflinger::OpenLayer(u64 layer_id) { 179bool Nvnflinger::OpenLayer(u64 layer_id) {
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index c984d55a0..4cf4f069d 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -15,6 +15,7 @@
15#include "common/thread.h" 15#include "common/thread.h"
16#include "core/hle/result.h" 16#include "core/hle/result.h"
17#include "core/hle/service/kernel_helpers.h" 17#include "core/hle/service/kernel_helpers.h"
18#include "core/hle/service/nvnflinger/hwc_layer.h"
18 19
19namespace Common { 20namespace Common {
20class Event; 21class Event;
@@ -72,7 +73,8 @@ public:
72 /// Creates a layer on the specified display and returns the layer ID. 73 /// Creates a layer on the specified display and returns the layer ID.
73 /// 74 ///
74 /// If an invalid display ID is specified, then an empty optional is returned. 75 /// If an invalid display ID is specified, then an empty optional is returned.
75 [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); 76 [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id,
77 LayerBlending blending = LayerBlending::None);
76 78
77 /// Opens a layer on all displays for the given layer ID. 79 /// Opens a layer on all displays for the given layer ID.
78 bool OpenLayer(u64 layer_id); 80 bool OpenLayer(u64 layer_id);
@@ -128,7 +130,7 @@ private:
128 [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); 130 [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
129 131
130 /// Creates a layer with the specified layer ID in the desired display. 132 /// Creates a layer with the specified layer ID in the desired display.
131 void CreateLayerAtId(VI::Display& display, u64 layer_id); 133 void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending);
132 134
133 void SplitVSync(std::stop_token stop_token); 135 void SplitVSync(std::stop_token stop_token);
134 136
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp
index 493bd6e9e..eca35d82a 100644
--- a/src/core/hle/service/vi/layer/vi_layer.cpp
+++ b/src/core/hle/service/vi/layer/vi_layer.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2019 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/hle/service/nvnflinger/hwc_layer.h"
4#include "core/hle/service/vi/layer/vi_layer.h" 5#include "core/hle/service/vi/layer/vi_layer.h"
5 6
6namespace Service::VI { 7namespace Service::VI {
@@ -8,8 +9,9 @@ namespace Service::VI {
8Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, 9Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
9 android::BufferQueueProducer& binder_, 10 android::BufferQueueProducer& binder_,
10 std::shared_ptr<android::BufferItemConsumer>&& consumer_) 11 std::shared_ptr<android::BufferItemConsumer>&& consumer_)
11 : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, 12 : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move(
12 consumer{std::move(consumer_)}, open{false}, visible{true} {} 13 consumer_)},
14 blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {}
13 15
14Layer::~Layer() = default; 16Layer::~Layer() = default;
15 17
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h
index b4b031ee7..14e229903 100644
--- a/src/core/hle/service/vi/layer/vi_layer.h
+++ b/src/core/hle/service/vi/layer/vi_layer.h
@@ -14,6 +14,10 @@ class BufferQueueCore;
14class BufferQueueProducer; 14class BufferQueueProducer;
15} // namespace Service::android 15} // namespace Service::android
16 16
17namespace Service::Nvnflinger {
18enum class LayerBlending : u32;
19}
20
17namespace Service::VI { 21namespace Service::VI {
18 22
19/// Represents a single display layer. 23/// Represents a single display layer.
@@ -92,12 +96,21 @@ public:
92 return !std::exchange(open, true); 96 return !std::exchange(open, true);
93 } 97 }
94 98
99 Nvnflinger::LayerBlending GetBlending() {
100 return blending;
101 }
102
103 void SetBlending(Nvnflinger::LayerBlending b) {
104 blending = b;
105 }
106
95private: 107private:
96 const u64 layer_id; 108 const u64 layer_id;
97 const u32 binder_id; 109 const u32 binder_id;
98 android::BufferQueueCore& core; 110 android::BufferQueueCore& core;
99 android::BufferQueueProducer& binder; 111 android::BufferQueueProducer& binder;
100 std::shared_ptr<android::BufferItemConsumer> consumer; 112 std::shared_ptr<android::BufferItemConsumer> consumer;
113 Service::Nvnflinger::LayerBlending blending;
101 bool open; 114 bool open;
102 bool visible; 115 bool visible;
103}; 116};