diff options
Diffstat (limited to 'src/core')
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 | ||
| 175 | u8 NCA::GetKeyGeneration() const { | ||
| 176 | return reader->GetKeyGeneration(); | ||
| 177 | } | ||
| 178 | |||
| 175 | bool NCA::IsUpdate() const { | 179 | bool 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 | ||
| 131 | enum class LibraryAppletMode : u32 { | 131 | enum 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 | ||
| 246 | void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mode) { | 246 | void 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 | ||
| 17 | namespace { | 18 | namespace { |
| 18 | 19 | ||
| 20 | bool 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 | |||
| 19 | AppletProgramId AppletIdToProgramId(AppletId applet_id) { | 48 | AppletProgramId 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( | 95 | std::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( | 152 | std::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 | ||
| 23 | bool Process::Initialize(u64 program_id) { | 24 | bool 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 | ||
| 290 | Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { | 293 | Result 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 | ||
| 330 | void 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 | |||
| 326 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { | 340 | void 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 | ||
| 23 | bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process, | 24 | bool 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 | ||
| 63 | Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, | 70 | Result 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 | ||
| 115 | void Container::CloseSession(SessionId session_id) { | 117 | void 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 | ||
| 51 | class Container { | 52 | class 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 | ||
| 16 | namespace Service::Nvidia::Devices { | 16 | namespace Service::Nvidia::Devices { |
| 17 | 17 | ||
| 18 | namespace { | ||
| 19 | |||
| 20 | Tegra::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 | |||
| 18 | nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core) | 34 | nvdisp_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()} {} |
| 20 | nvdisp_disp0::~nvdisp_disp0() = default; | 36 | nvdisp_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 | ||
| 18 | namespace Service::Nvnflinger { | 20 | namespace Service::Nvnflinger { |
| 19 | 21 | ||
| 20 | namespace { | 22 | namespace { |
| 21 | 23 | ||
| 22 | Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, | 24 | Result 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 | |||
| 59 | Result 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 | ||
| 155 | void 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 | |||
| 138 | constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; | 162 | constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; |
| 139 | constexpr u32 SharedBufferBlockLinearBpp = 4; | 163 | constexpr u32 SharedBufferBlockLinearBpp = 4; |
| 140 | 164 | ||
| @@ -186,53 +210,97 @@ FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& fli | |||
| 186 | 210 | ||
| 187 | FbShareBufferManager::~FbShareBufferManager() = default; | 211 | FbShareBufferManager::~FbShareBufferManager() = default; |
| 188 | 212 | ||
| 189 | Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u64 display_id) { | 213 | Result 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 | ||
| 272 | void 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 | |||
| 236 | Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, | 304 | Result 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 | ||
| 253 | Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { | 322 | Result 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 | ||
| 418 | Result 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 | }; |
| 30 | static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); | 33 | static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); |
| 31 | 34 | ||
| 35 | struct FbShareSession; | ||
| 36 | |||
| 32 | class FbShareBufferManager final { | 37 | class FbShareBufferManager final { |
| 33 | public: | 38 | public: |
| 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 | |||
| 48 | private: | 58 | private: |
| 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 | ||
| 75 | struct 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 | ||
| 12 | namespace Service::Nvnflinger { | 12 | namespace Service::Nvnflinger { |
| 13 | 13 | ||
| 14 | // hwc_layer_t::blending values | ||
| 15 | enum 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 | |||
| 14 | struct HwcLayer { | 26 | struct 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 | ||
| 160 | std::optional<u64> Nvnflinger::CreateLayer(u64 display_id) { | 160 | std::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 | ||
| 173 | void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { | 173 | void 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 | ||
| 178 | bool Nvnflinger::OpenLayer(u64 layer_id) { | 179 | bool 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 | ||
| 19 | namespace Common { | 20 | namespace Common { |
| 20 | class Event; | 21 | class 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 | ||
| 6 | namespace Service::VI { | 7 | namespace Service::VI { |
| @@ -8,8 +9,9 @@ namespace Service::VI { | |||
| 8 | Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_, | 9 | Layer::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 | ||
| 14 | Layer::~Layer() = default; | 16 | Layer::~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; | |||
| 14 | class BufferQueueProducer; | 14 | class BufferQueueProducer; |
| 15 | } // namespace Service::android | 15 | } // namespace Service::android |
| 16 | 16 | ||
| 17 | namespace Service::Nvnflinger { | ||
| 18 | enum class LayerBlending : u32; | ||
| 19 | } | ||
| 20 | |||
| 17 | namespace Service::VI { | 21 | namespace 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 | |||
| 95 | private: | 107 | private: |
| 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 | }; |