diff options
Diffstat (limited to 'src')
58 files changed, 1180 insertions, 115 deletions
diff --git a/src/audio_core/renderer/command/mix/depop_prepare.h b/src/audio_core/renderer/command/mix/depop_prepare.h index 161a94461..a0cc228f7 100644 --- a/src/audio_core/renderer/command/mix/depop_prepare.h +++ b/src/audio_core/renderer/command/mix/depop_prepare.h | |||
| @@ -16,7 +16,7 @@ namespace AudioCore::Renderer { | |||
| 16 | 16 | ||
| 17 | /** | 17 | /** |
| 18 | * AudioRenderer command for preparing depop. | 18 | * AudioRenderer command for preparing depop. |
| 19 | * Adds the previusly output last samples to the depop buffer. | 19 | * Adds the previously output last samples to the depop buffer. |
| 20 | */ | 20 | */ |
| 21 | struct DepopPrepareCommand : ICommand { | 21 | struct DepopPrepareCommand : ICommand { |
| 22 | /** | 22 | /** |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index feab1653d..4c7aba3f5 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -135,6 +135,11 @@ std::u16string UTF8ToUTF16(std::string_view input) { | |||
| 135 | return convert.from_bytes(input.data(), input.data() + input.size()); | 135 | return convert.from_bytes(input.data(), input.data() + input.size()); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | std::u32string UTF8ToUTF32(std::string_view input) { | ||
| 139 | std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; | ||
| 140 | return convert.from_bytes(input.data(), input.data() + input.size()); | ||
| 141 | } | ||
| 142 | |||
| 138 | #ifdef _WIN32 | 143 | #ifdef _WIN32 |
| 139 | static std::wstring CPToUTF16(u32 code_page, std::string_view input) { | 144 | static std::wstring CPToUTF16(u32 code_page, std::string_view input) { |
| 140 | const auto size = | 145 | const auto size = |
diff --git a/src/common/string_util.h b/src/common/string_util.h index c351f1a0c..9da1ca4e9 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h | |||
| @@ -38,6 +38,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ | |||
| 38 | 38 | ||
| 39 | [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); | 39 | [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); |
| 40 | [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); | 40 | [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); |
| 41 | [[nodiscard]] std::u32string UTF8ToUTF32(std::string_view input); | ||
| 41 | 42 | ||
| 42 | #ifdef _WIN32 | 43 | #ifdef _WIN32 |
| 43 | [[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input); | 44 | [[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input); |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d0f76e57e..e02ededfc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -698,6 +698,8 @@ add_library(core STATIC | |||
| 698 | hle/service/nvnflinger/consumer_base.cpp | 698 | hle/service/nvnflinger/consumer_base.cpp |
| 699 | hle/service/nvnflinger/consumer_base.h | 699 | hle/service/nvnflinger/consumer_base.h |
| 700 | hle/service/nvnflinger/consumer_listener.h | 700 | hle/service/nvnflinger/consumer_listener.h |
| 701 | hle/service/nvnflinger/fb_share_buffer_manager.cpp | ||
| 702 | hle/service/nvnflinger/fb_share_buffer_manager.h | ||
| 701 | hle/service/nvnflinger/graphic_buffer_producer.cpp | 703 | hle/service/nvnflinger/graphic_buffer_producer.cpp |
| 702 | hle/service/nvnflinger/graphic_buffer_producer.h | 704 | hle/service/nvnflinger/graphic_buffer_producer.h |
| 703 | hle/service/nvnflinger/hos_binder_driver_server.cpp | 705 | hle/service/nvnflinger/hos_binder_driver_server.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 08cbb8978..0ab2e3b76 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -1078,6 +1078,10 @@ void System::ApplySettings() { | |||
| 1078 | impl->RefreshTime(); | 1078 | impl->RefreshTime(); |
| 1079 | 1079 | ||
| 1080 | if (IsPoweredOn()) { | 1080 | if (IsPoweredOn()) { |
| 1081 | if (Settings::values.custom_rtc_enabled) { | ||
| 1082 | const s64 posix_time{Settings::values.custom_rtc.GetValue()}; | ||
| 1083 | GetTimeManager().UpdateLocalSystemClockTime(posix_time); | ||
| 1084 | } | ||
| 1081 | Renderer().RefreshBaseSettings(); | 1085 | Renderer().RefreshBaseSettings(); |
| 1082 | } | 1086 | } |
| 1083 | } | 1087 | } |
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index e55831f27..82964f0a1 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <atomic> | 4 | #include <atomic> |
| 5 | #include <codecvt> | ||
| 6 | #include <locale> | ||
| 5 | #include <numeric> | 7 | #include <numeric> |
| 6 | #include <optional> | 8 | #include <optional> |
| 7 | #include <thread> | 9 | #include <thread> |
| @@ -12,6 +14,7 @@ | |||
| 12 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 13 | #include "common/scope_exit.h" | 15 | #include "common/scope_exit.h" |
| 14 | #include "common/settings.h" | 16 | #include "common/settings.h" |
| 17 | #include "common/string_util.h" | ||
| 15 | #include "core/arm/arm_interface.h" | 18 | #include "core/arm/arm_interface.h" |
| 16 | #include "core/core.h" | 19 | #include "core/core.h" |
| 17 | #include "core/debugger/gdbstub.h" | 20 | #include "core/debugger/gdbstub.h" |
| @@ -68,10 +71,16 @@ static std::string EscapeGDB(std::string_view data) { | |||
| 68 | } | 71 | } |
| 69 | 72 | ||
| 70 | static std::string EscapeXML(std::string_view data) { | 73 | static std::string EscapeXML(std::string_view data) { |
| 74 | std::u32string converted = U"[Encoding error]"; | ||
| 75 | try { | ||
| 76 | converted = Common::UTF8ToUTF32(data); | ||
| 77 | } catch (std::range_error&) { | ||
| 78 | } | ||
| 79 | |||
| 71 | std::string escaped; | 80 | std::string escaped; |
| 72 | escaped.reserve(data.size()); | 81 | escaped.reserve(data.size()); |
| 73 | 82 | ||
| 74 | for (char c : data) { | 83 | for (char32_t c : converted) { |
| 75 | switch (c) { | 84 | switch (c) { |
| 76 | case '&': | 85 | case '&': |
| 77 | escaped += "&"; | 86 | escaped += "&"; |
| @@ -86,7 +95,11 @@ static std::string EscapeXML(std::string_view data) { | |||
| 86 | escaped += ">"; | 95 | escaped += ">"; |
| 87 | break; | 96 | break; |
| 88 | default: | 97 | default: |
| 89 | escaped += c; | 98 | if (c > 0x7f) { |
| 99 | escaped += fmt::format("&#{};", static_cast<u32>(c)); | ||
| 100 | } else { | ||
| 101 | escaped += static_cast<char>(c); | ||
| 102 | } | ||
| 90 | break; | 103 | break; |
| 91 | } | 104 | } |
| 92 | } | 105 | } |
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index a93e21f67..a7cd1cae3 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h | |||
| @@ -175,7 +175,7 @@ public: | |||
| 175 | return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset); | 175 | return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | // Renames the file to name. Returns whether or not the operation was successsful. | 178 | // Renames the file to name. Returns whether or not the operation was successful. |
| 179 | virtual bool Rename(std::string_view name) = 0; | 179 | virtual bool Rename(std::string_view name) = 0; |
| 180 | 180 | ||
| 181 | // Returns the full path of this file as a string, recursively | 181 | // Returns the full path of this file as a string, recursively |
diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp index af40092c0..bec714668 100644 --- a/src/core/hle/kernel/k_memory_layout.cpp +++ b/src/core/hle/kernel/k_memory_layout.cpp | |||
| @@ -61,7 +61,7 @@ bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_at | |||
| 61 | found->Reset(address, inserted_region_last, old_pair, new_attr, type_id); | 61 | found->Reset(address, inserted_region_last, old_pair, new_attr, type_id); |
| 62 | this->insert(*found); | 62 | this->insert(*found); |
| 63 | } else { | 63 | } else { |
| 64 | // If we can't re-use, adjust the old region. | 64 | // If we can't reuse, adjust the old region. |
| 65 | found->Reset(old_address, address - 1, old_pair, old_attr, old_type); | 65 | found->Reset(old_address, address - 1, old_pair, old_attr, old_type); |
| 66 | this->insert(*found); | 66 | this->insert(*found); |
| 67 | 67 | ||
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 9bfc85b34..5b51edf30 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/literals.h" | 6 | #include "common/literals.h" |
| 7 | #include "common/scope_exit.h" | 7 | #include "common/scope_exit.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "core/core.h" | 9 | #include "core/core.h" |
| 9 | #include "core/hle/kernel/k_address_space_info.h" | 10 | #include "core/hle/kernel/k_address_space_info.h" |
| 10 | #include "core/hle/kernel/k_memory_block.h" | 11 | #include "core/hle/kernel/k_memory_block.h" |
| @@ -337,11 +338,14 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type | |||
| 337 | } | 338 | } |
| 338 | 339 | ||
| 339 | void KPageTable::Finalize() { | 340 | void KPageTable::Finalize() { |
| 341 | auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { | ||
| 342 | if (Settings::IsFastmemEnabled()) { | ||
| 343 | m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size); | ||
| 344 | } | ||
| 345 | }; | ||
| 346 | |||
| 340 | // Finalize memory blocks. | 347 | // Finalize memory blocks. |
| 341 | m_memory_block_manager.Finalize(m_memory_block_slab_manager, | 348 | m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback)); |
| 342 | [&](KProcessAddress addr, u64 size) { | ||
| 343 | m_memory->UnmapRegion(*m_page_table_impl, addr, size); | ||
| 344 | }); | ||
| 345 | 349 | ||
| 346 | // Release any insecure mapped memory. | 350 | // Release any insecure mapped memory. |
| 347 | if (m_mapped_insecure_memory) { | 351 | if (m_mapped_insecure_memory) { |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a83622f7c..819dea6a7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "common/settings_enums.h" | 9 | #include "common/settings_enums.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/core_timing.h" | ||
| 11 | #include "core/file_sys/control_metadata.h" | 12 | #include "core/file_sys/control_metadata.h" |
| 12 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 13 | #include "core/file_sys/registered_cache.h" | 14 | #include "core/file_sys/registered_cache.h" |
| @@ -19,6 +20,7 @@ | |||
| 19 | #include "core/hle/service/am/am.h" | 20 | #include "core/hle/service/am/am.h" |
| 20 | #include "core/hle/service/am/applet_ae.h" | 21 | #include "core/hle/service/am/applet_ae.h" |
| 21 | #include "core/hle/service/am/applet_oe.h" | 22 | #include "core/hle/service/am/applet_oe.h" |
| 23 | #include "core/hle/service/am/applets/applet_cabinet.h" | ||
| 22 | #include "core/hle/service/am/applets/applet_mii_edit_types.h" | 24 | #include "core/hle/service/am/applets/applet_mii_edit_types.h" |
| 23 | #include "core/hle/service/am/applets/applet_profile_select.h" | 25 | #include "core/hle/service/am/applets/applet_profile_select.h" |
| 24 | #include "core/hle/service/am/applets/applet_web_browser.h" | 26 | #include "core/hle/service/am/applets/applet_web_browser.h" |
| @@ -33,11 +35,13 @@ | |||
| 33 | #include "core/hle/service/filesystem/filesystem.h" | 35 | #include "core/hle/service/filesystem/filesystem.h" |
| 34 | #include "core/hle/service/ipc_helpers.h" | 36 | #include "core/hle/service/ipc_helpers.h" |
| 35 | #include "core/hle/service/ns/ns.h" | 37 | #include "core/hle/service/ns/ns.h" |
| 38 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 36 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 39 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 37 | #include "core/hle/service/pm/pm.h" | 40 | #include "core/hle/service/pm/pm.h" |
| 38 | #include "core/hle/service/server_manager.h" | 41 | #include "core/hle/service/server_manager.h" |
| 39 | #include "core/hle/service/sm/sm.h" | 42 | #include "core/hle/service/sm/sm.h" |
| 40 | #include "core/hle/service/vi/vi.h" | 43 | #include "core/hle/service/vi/vi.h" |
| 44 | #include "core/hle/service/vi/vi_results.h" | ||
| 41 | #include "core/memory.h" | 45 | #include "core/memory.h" |
| 42 | 46 | ||
| 43 | namespace Service::AM { | 47 | namespace Service::AM { |
| @@ -190,7 +194,7 @@ IDisplayController::IDisplayController(Core::System& system_) | |||
| 190 | {4, nullptr, "UpdateCallerAppletCaptureImage"}, | 194 | {4, nullptr, "UpdateCallerAppletCaptureImage"}, |
| 191 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | 195 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, |
| 192 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | 196 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, |
| 193 | {7, nullptr, "GetCallerAppletCaptureImageEx"}, | 197 | {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"}, |
| 194 | {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, | 198 | {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, |
| 195 | {9, nullptr, "CopyBetweenCaptureBuffers"}, | 199 | {9, nullptr, "CopyBetweenCaptureBuffers"}, |
| 196 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | 200 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, |
| @@ -208,8 +212,8 @@ IDisplayController::IDisplayController(Core::System& system_) | |||
| 208 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, | 212 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, |
| 209 | {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, | 213 | {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, |
| 210 | {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, | 214 | {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, |
| 211 | {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"}, | 215 | {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"}, |
| 212 | {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"}, | 216 | {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"}, |
| 213 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | 217 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, |
| 214 | }; | 218 | }; |
| 215 | // clang-format on | 219 | // clang-format on |
| @@ -219,6 +223,15 @@ IDisplayController::IDisplayController(Core::System& system_) | |||
| 219 | 223 | ||
| 220 | IDisplayController::~IDisplayController() = default; | 224 | IDisplayController::~IDisplayController() = default; |
| 221 | 225 | ||
| 226 | void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) { | ||
| 227 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 228 | |||
| 229 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 230 | rb.Push(ResultSuccess); | ||
| 231 | rb.Push(1u); | ||
| 232 | rb.Push(0); | ||
| 233 | } | ||
| 234 | |||
| 222 | void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { | 235 | void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { |
| 223 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 236 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 224 | 237 | ||
| @@ -226,6 +239,22 @@ void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { | |||
| 226 | rb.Push(ResultSuccess); | 239 | rb.Push(ResultSuccess); |
| 227 | } | 240 | } |
| 228 | 241 | ||
| 242 | void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 243 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 244 | |||
| 245 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 246 | rb.Push(ResultSuccess); | ||
| 247 | rb.Push(1U); | ||
| 248 | rb.Push(0); | ||
| 249 | } | ||
| 250 | |||
| 251 | void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) { | ||
| 252 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 253 | |||
| 254 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 255 | rb.Push(ResultSuccess); | ||
| 256 | } | ||
| 257 | |||
| 229 | IDebugFunctions::IDebugFunctions(Core::System& system_) | 258 | IDebugFunctions::IDebugFunctions(Core::System& system_) |
| 230 | : ServiceFramework{system_, "IDebugFunctions"} { | 259 | : ServiceFramework{system_, "IDebugFunctions"} { |
| 231 | // clang-format off | 260 | // clang-format off |
| @@ -285,14 +314,14 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& | |||
| 285 | {20, nullptr, "SetDesirableKeyboardLayout"}, | 314 | {20, nullptr, "SetDesirableKeyboardLayout"}, |
| 286 | {21, nullptr, "GetScreenShotProgramId"}, | 315 | {21, nullptr, "GetScreenShotProgramId"}, |
| 287 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | 316 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, |
| 288 | {41, nullptr, "IsSystemBufferSharingEnabled"}, | 317 | {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, |
| 289 | {42, nullptr, "GetSystemSharedLayerHandle"}, | 318 | {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, |
| 290 | {43, nullptr, "GetSystemSharedBufferHandle"}, | 319 | {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, |
| 291 | {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, | 320 | {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, |
| 292 | {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, | 321 | {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, |
| 293 | {46, nullptr, "SetRecordingLayerCompositionEnabled"}, | 322 | {46, nullptr, "SetRecordingLayerCompositionEnabled"}, |
| 294 | {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, | 323 | {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, |
| 295 | {51, nullptr, "ApproveToDisplay"}, | 324 | {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, |
| 296 | {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, | 325 | {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, |
| 297 | {61, nullptr, "SetMediaPlaybackState"}, | 326 | {61, nullptr, "SetMediaPlaybackState"}, |
| 298 | {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, | 327 | {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, |
| @@ -491,6 +520,50 @@ void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { | |||
| 491 | rb.Push(*layer_id); | 520 | rb.Push(*layer_id); |
| 492 | } | 521 | } |
| 493 | 522 | ||
| 523 | void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { | ||
| 524 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 525 | |||
| 526 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 527 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 528 | } | ||
| 529 | |||
| 530 | void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { | ||
| 531 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 532 | |||
| 533 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 534 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 535 | rb.Push<s64>(system_shared_buffer_id); | ||
| 536 | rb.Push<s64>(system_shared_layer_id); | ||
| 537 | } | ||
| 538 | |||
| 539 | void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { | ||
| 540 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 541 | |||
| 542 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 543 | rb.Push(this->EnsureBufferSharingEnabled()); | ||
| 544 | rb.Push<s64>(system_shared_buffer_id); | ||
| 545 | } | ||
| 546 | |||
| 547 | Result ISelfController::EnsureBufferSharingEnabled() { | ||
| 548 | if (buffer_sharing_enabled) { | ||
| 549 | return ResultSuccess; | ||
| 550 | } | ||
| 551 | |||
| 552 | if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) { | ||
| 553 | return VI::ResultOperationFailed; | ||
| 554 | } | ||
| 555 | |||
| 556 | const auto display_id = nvnflinger.OpenDisplay("Default"); | ||
| 557 | const auto result = nvnflinger.GetSystemBufferManager().Initialize( | ||
| 558 | &system_shared_buffer_id, &system_shared_layer_id, *display_id); | ||
| 559 | |||
| 560 | if (result.IsSuccess()) { | ||
| 561 | buffer_sharing_enabled = true; | ||
| 562 | } | ||
| 563 | |||
| 564 | return result; | ||
| 565 | } | ||
| 566 | |||
| 494 | void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { | 567 | void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { |
| 495 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 568 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 496 | 569 | ||
| @@ -516,6 +589,13 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { | |||
| 516 | rb.Push(ResultSuccess); | 589 | rb.Push(ResultSuccess); |
| 517 | } | 590 | } |
| 518 | 591 | ||
| 592 | void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { | ||
| 593 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 594 | |||
| 595 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 596 | rb.Push(ResultSuccess); | ||
| 597 | } | ||
| 598 | |||
| 519 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { | 599 | void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { |
| 520 | IPC::RequestParser rp{ctx}; | 600 | IPC::RequestParser rp{ctx}; |
| 521 | idle_time_detection_extension = rp.Pop<u32>(); | 601 | idle_time_detection_extension = rp.Pop<u32>(); |
| @@ -686,7 +766,8 @@ void AppletMessageQueue::OperationModeChanged() { | |||
| 686 | 766 | ||
| 687 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, | 767 | ICommonStateGetter::ICommonStateGetter(Core::System& system_, |
| 688 | std::shared_ptr<AppletMessageQueue> msg_queue_) | 768 | std::shared_ptr<AppletMessageQueue> msg_queue_) |
| 689 | : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} { | 769 | : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)}, |
| 770 | service_context{system_, "ICommonStateGetter"} { | ||
| 690 | // clang-format off | 771 | // clang-format off |
| 691 | static const FunctionInfo functions[] = { | 772 | static const FunctionInfo functions[] = { |
| 692 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | 773 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, |
| @@ -699,10 +780,10 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, | |||
| 699 | {7, nullptr, "GetCradleStatus"}, | 780 | {7, nullptr, "GetCradleStatus"}, |
| 700 | {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, | 781 | {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, |
| 701 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | 782 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, |
| 702 | {10, nullptr, "RequestToAcquireSleepLock"}, | 783 | {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"}, |
| 703 | {11, nullptr, "ReleaseSleepLock"}, | 784 | {11, nullptr, "ReleaseSleepLock"}, |
| 704 | {12, nullptr, "ReleaseSleepLockTransiently"}, | 785 | {12, nullptr, "ReleaseSleepLockTransiently"}, |
| 705 | {13, nullptr, "GetAcquiredSleepLockEvent"}, | 786 | {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"}, |
| 706 | {14, nullptr, "GetWakeupCount"}, | 787 | {14, nullptr, "GetWakeupCount"}, |
| 707 | {20, nullptr, "PushToGeneralChannel"}, | 788 | {20, nullptr, "PushToGeneralChannel"}, |
| 708 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | 789 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, |
| @@ -745,6 +826,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, | |||
| 745 | 826 | ||
| 746 | RegisterHandlers(functions); | 827 | RegisterHandlers(functions); |
| 747 | 828 | ||
| 829 | sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent"); | ||
| 830 | |||
| 748 | // Configure applets to be in foreground state | 831 | // Configure applets to be in foreground state |
| 749 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); | 832 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); |
| 750 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); | 833 | msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); |
| @@ -793,6 +876,24 @@ void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) { | |||
| 793 | rb.Push(static_cast<u8>(FocusState::InFocus)); | 876 | rb.Push(static_cast<u8>(FocusState::InFocus)); |
| 794 | } | 877 | } |
| 795 | 878 | ||
| 879 | void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) { | ||
| 880 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 881 | |||
| 882 | // Sleep lock is acquired immediately. | ||
| 883 | sleep_lock_event->Signal(); | ||
| 884 | |||
| 885 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 886 | rb.Push(ResultSuccess); | ||
| 887 | } | ||
| 888 | |||
| 889 | void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) { | ||
| 890 | LOG_WARNING(Service_AM, "called"); | ||
| 891 | |||
| 892 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 893 | rb.Push(ResultSuccess); | ||
| 894 | rb.PushCopyObjects(sleep_lock_event->GetReadableEvent()); | ||
| 895 | } | ||
| 896 | |||
| 796 | void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { | 897 | void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { |
| 797 | LOG_DEBUG(Service_AM, "called"); | 898 | LOG_DEBUG(Service_AM, "called"); |
| 798 | 899 | ||
| @@ -1385,7 +1486,16 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) | |||
| 1385 | // clang-format on | 1486 | // clang-format on |
| 1386 | RegisterHandlers(functions); | 1487 | RegisterHandlers(functions); |
| 1387 | 1488 | ||
| 1388 | PushInShowMiiEditData(); | 1489 | switch (system.GetAppletManager().GetCurrentAppletId()) { |
| 1490 | case Applets::AppletId::Cabinet: | ||
| 1491 | PushInShowCabinetData(); | ||
| 1492 | break; | ||
| 1493 | case Applets::AppletId::MiiEdit: | ||
| 1494 | PushInShowMiiEditData(); | ||
| 1495 | break; | ||
| 1496 | default: | ||
| 1497 | break; | ||
| 1498 | } | ||
| 1389 | } | 1499 | } |
| 1390 | 1500 | ||
| 1391 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; | 1501 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; |
| @@ -1431,7 +1541,7 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) { | |||
| 1431 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 1541 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 1432 | 1542 | ||
| 1433 | const LibraryAppletInfo applet_info{ | 1543 | const LibraryAppletInfo applet_info{ |
| 1434 | .applet_id = Applets::AppletId::MiiEdit, | 1544 | .applet_id = system.GetAppletManager().GetCurrentAppletId(), |
| 1435 | .library_applet_mode = Applets::LibraryAppletMode::AllForeground, | 1545 | .library_applet_mode = Applets::LibraryAppletMode::AllForeground, |
| 1436 | }; | 1546 | }; |
| 1437 | 1547 | ||
| @@ -1459,6 +1569,35 @@ void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& | |||
| 1459 | rb.PushRaw(applet_info); | 1569 | rb.PushRaw(applet_info); |
| 1460 | } | 1570 | } |
| 1461 | 1571 | ||
| 1572 | void ILibraryAppletSelfAccessor::PushInShowCabinetData() { | ||
| 1573 | const Applets::CommonArguments arguments{ | ||
| 1574 | .arguments_version = Applets::CommonArgumentVersion::Version3, | ||
| 1575 | .size = Applets::CommonArgumentSize::Version3, | ||
| 1576 | .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1), | ||
| 1577 | .theme_color = Applets::ThemeColor::BasicBlack, | ||
| 1578 | .play_startup_sound = true, | ||
| 1579 | .system_tick = system.CoreTiming().GetClockTicks(), | ||
| 1580 | }; | ||
| 1581 | |||
| 1582 | const Applets::StartParamForAmiiboSettings amiibo_settings{ | ||
| 1583 | .param_1 = 0, | ||
| 1584 | .applet_mode = system.GetAppletManager().GetCabinetMode(), | ||
| 1585 | .flags = Applets::CabinetFlags::None, | ||
| 1586 | .amiibo_settings_1 = 0, | ||
| 1587 | .device_handle = 0, | ||
| 1588 | .tag_info{}, | ||
| 1589 | .register_info{}, | ||
| 1590 | .amiibo_settings_3{}, | ||
| 1591 | }; | ||
| 1592 | |||
| 1593 | std::vector<u8> argument_data(sizeof(arguments)); | ||
| 1594 | std::vector<u8> settings_data(sizeof(amiibo_settings)); | ||
| 1595 | std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); | ||
| 1596 | std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); | ||
| 1597 | queue_data.emplace_back(std::move(argument_data)); | ||
| 1598 | queue_data.emplace_back(std::move(settings_data)); | ||
| 1599 | } | ||
| 1600 | |||
| 1462 | void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { | 1601 | void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { |
| 1463 | struct MiiEditV3 { | 1602 | struct MiiEditV3 { |
| 1464 | Applets::MiiEditAppletInputCommon common; | 1603 | Applets::MiiEditAppletInputCommon common; |
| @@ -2235,7 +2374,7 @@ void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) { | |||
| 2235 | } | 2374 | } |
| 2236 | 2375 | ||
| 2237 | void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { | 2376 | void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { |
| 2238 | const auto applet_id = Applets::AppletId::MiiEdit; | 2377 | const auto applet_id = system.GetAppletManager().GetCurrentAppletId(); |
| 2239 | const auto applet_mode = Applets::LibraryAppletMode::AllForeground; | 2378 | const auto applet_mode = Applets::LibraryAppletMode::AllForeground; |
| 2240 | 2379 | ||
| 2241 | LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, | 2380 | LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, |
| @@ -2256,4 +2395,5 @@ void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) | |||
| 2256 | rb.Push(ResultSuccess); | 2395 | rb.Push(ResultSuccess); |
| 2257 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); | 2396 | rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); |
| 2258 | } | 2397 | } |
| 2398 | |||
| 2259 | } // namespace Service::AM | 2399 | } // namespace Service::AM |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 5b97eb5e3..349482dcc 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -122,7 +122,10 @@ public: | |||
| 122 | ~IDisplayController() override; | 122 | ~IDisplayController() override; |
| 123 | 123 | ||
| 124 | private: | 124 | private: |
| 125 | void GetCallerAppletCaptureImageEx(HLERequestContext& ctx); | ||
| 125 | void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); | 126 | void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); |
| 127 | void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 128 | void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx); | ||
| 126 | }; | 129 | }; |
| 127 | 130 | ||
| 128 | class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { | 131 | class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { |
| @@ -150,9 +153,13 @@ private: | |||
| 150 | void SetRestartMessageEnabled(HLERequestContext& ctx); | 153 | void SetRestartMessageEnabled(HLERequestContext& ctx); |
| 151 | void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); | 154 | void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); |
| 152 | void SetAlbumImageOrientation(HLERequestContext& ctx); | 155 | void SetAlbumImageOrientation(HLERequestContext& ctx); |
| 156 | void IsSystemBufferSharingEnabled(HLERequestContext& ctx); | ||
| 157 | void GetSystemSharedBufferHandle(HLERequestContext& ctx); | ||
| 158 | void GetSystemSharedLayerHandle(HLERequestContext& ctx); | ||
| 153 | void CreateManagedDisplayLayer(HLERequestContext& ctx); | 159 | void CreateManagedDisplayLayer(HLERequestContext& ctx); |
| 154 | void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); | 160 | void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); |
| 155 | void SetHandlesRequestToDisplay(HLERequestContext& ctx); | 161 | void SetHandlesRequestToDisplay(HLERequestContext& ctx); |
| 162 | void ApproveToDisplay(HLERequestContext& ctx); | ||
| 156 | void SetIdleTimeDetectionExtension(HLERequestContext& ctx); | 163 | void SetIdleTimeDetectionExtension(HLERequestContext& ctx); |
| 157 | void GetIdleTimeDetectionExtension(HLERequestContext& ctx); | 164 | void GetIdleTimeDetectionExtension(HLERequestContext& ctx); |
| 158 | void ReportUserIsActive(HLERequestContext& ctx); | 165 | void ReportUserIsActive(HLERequestContext& ctx); |
| @@ -164,6 +171,8 @@ private: | |||
| 164 | void SaveCurrentScreenshot(HLERequestContext& ctx); | 171 | void SaveCurrentScreenshot(HLERequestContext& ctx); |
| 165 | void SetRecordVolumeMuted(HLERequestContext& ctx); | 172 | void SetRecordVolumeMuted(HLERequestContext& ctx); |
| 166 | 173 | ||
| 174 | Result EnsureBufferSharingEnabled(); | ||
| 175 | |||
| 167 | enum class ScreenshotPermission : u32 { | 176 | enum class ScreenshotPermission : u32 { |
| 168 | Inherit = 0, | 177 | Inherit = 0, |
| 169 | Enable = 1, | 178 | Enable = 1, |
| @@ -179,7 +188,10 @@ private: | |||
| 179 | 188 | ||
| 180 | u32 idle_time_detection_extension = 0; | 189 | u32 idle_time_detection_extension = 0; |
| 181 | u64 num_fatal_sections_entered = 0; | 190 | u64 num_fatal_sections_entered = 0; |
| 191 | u64 system_shared_buffer_id = 0; | ||
| 192 | u64 system_shared_layer_id = 0; | ||
| 182 | bool is_auto_sleep_disabled = false; | 193 | bool is_auto_sleep_disabled = false; |
| 194 | bool buffer_sharing_enabled = false; | ||
| 183 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; | 195 | ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; |
| 184 | }; | 196 | }; |
| 185 | 197 | ||
| @@ -223,6 +235,8 @@ private: | |||
| 223 | void GetEventHandle(HLERequestContext& ctx); | 235 | void GetEventHandle(HLERequestContext& ctx); |
| 224 | void ReceiveMessage(HLERequestContext& ctx); | 236 | void ReceiveMessage(HLERequestContext& ctx); |
| 225 | void GetCurrentFocusState(HLERequestContext& ctx); | 237 | void GetCurrentFocusState(HLERequestContext& ctx); |
| 238 | void RequestToAcquireSleepLock(HLERequestContext& ctx); | ||
| 239 | void GetAcquiredSleepLockEvent(HLERequestContext& ctx); | ||
| 226 | void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); | 240 | void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); |
| 227 | void GetOperationMode(HLERequestContext& ctx); | 241 | void GetOperationMode(HLERequestContext& ctx); |
| 228 | void GetPerformanceMode(HLERequestContext& ctx); | 242 | void GetPerformanceMode(HLERequestContext& ctx); |
| @@ -240,6 +254,8 @@ private: | |||
| 240 | 254 | ||
| 241 | std::shared_ptr<AppletMessageQueue> msg_queue; | 255 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 242 | bool vr_mode_state{}; | 256 | bool vr_mode_state{}; |
| 257 | Kernel::KEvent* sleep_lock_event; | ||
| 258 | KernelHelpers::ServiceContext service_context; | ||
| 243 | }; | 259 | }; |
| 244 | 260 | ||
| 245 | class IStorageImpl { | 261 | class IStorageImpl { |
| @@ -311,6 +327,7 @@ private: | |||
| 311 | void ExitProcessAndReturn(HLERequestContext& ctx); | 327 | void ExitProcessAndReturn(HLERequestContext& ctx); |
| 312 | void GetCallerAppletIdentityInfo(HLERequestContext& ctx); | 328 | void GetCallerAppletIdentityInfo(HLERequestContext& ctx); |
| 313 | 329 | ||
| 330 | void PushInShowCabinetData(); | ||
| 314 | void PushInShowMiiEditData(); | 331 | void PushInShowMiiEditData(); |
| 315 | 332 | ||
| 316 | std::deque<std::vector<u8>> queue_data; | 333 | std::deque<std::vector<u8>> queue_data; |
diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h index b56427021..f498796f7 100644 --- a/src/core/hle/service/am/applets/applet_cabinet.h +++ b/src/core/hle/service/am/applets/applet_cabinet.h | |||
| @@ -29,6 +29,15 @@ enum class CabinetAppletVersion : u32 { | |||
| 29 | Version1 = 0x1, | 29 | Version1 = 0x1, |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | enum class CabinetFlags : u8 { | ||
| 33 | None = 0, | ||
| 34 | DeviceHandle = 1 << 0, | ||
| 35 | TagInfo = 1 << 1, | ||
| 36 | RegisterInfo = 1 << 2, | ||
| 37 | All = DeviceHandle | TagInfo | RegisterInfo, | ||
| 38 | }; | ||
| 39 | DECLARE_ENUM_FLAG_OPERATORS(CabinetFlags) | ||
| 40 | |||
| 32 | enum class CabinetResult : u8 { | 41 | enum class CabinetResult : u8 { |
| 33 | Cancel = 0, | 42 | Cancel = 0, |
| 34 | TagInfo = 1 << 1, | 43 | TagInfo = 1 << 1, |
| @@ -51,7 +60,7 @@ static_assert(sizeof(AmiiboSettingsStartParam) == 0x30, | |||
| 51 | struct StartParamForAmiiboSettings { | 60 | struct StartParamForAmiiboSettings { |
| 52 | u8 param_1; | 61 | u8 param_1; |
| 53 | Service::NFP::CabinetMode applet_mode; | 62 | Service::NFP::CabinetMode applet_mode; |
| 54 | u8 flags; | 63 | CabinetFlags flags; |
| 55 | u8 amiibo_settings_1; | 64 | u8 amiibo_settings_1; |
| 56 | u64 device_handle; | 65 | u64 device_handle; |
| 57 | Service::NFP::TagInfo tag_info; | 66 | Service::NFP::TagInfo tag_info; |
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp index 8b352020e..c0032f652 100644 --- a/src/core/hle/service/am/applets/applet_general_backend.cpp +++ b/src/core/hle/service/am/applets/applet_general_backend.cpp | |||
| @@ -223,9 +223,9 @@ void StubApplet::Initialize() { | |||
| 223 | 223 | ||
| 224 | const auto data = broker.PeekDataToAppletForDebug(); | 224 | const auto data = broker.PeekDataToAppletForDebug(); |
| 225 | system.GetReporter().SaveUnimplementedAppletReport( | 225 | system.GetReporter().SaveUnimplementedAppletReport( |
| 226 | static_cast<u32>(id), common_args.arguments_version, common_args.library_version, | 226 | static_cast<u32>(id), static_cast<u32>(common_args.arguments_version), |
| 227 | common_args.theme_color, common_args.play_startup_sound, common_args.system_tick, | 227 | common_args.library_version, static_cast<u32>(common_args.theme_color), |
| 228 | data.normal, data.interactive); | 228 | common_args.play_startup_sound, common_args.system_tick, data.normal, data.interactive); |
| 229 | 229 | ||
| 230 | LogCurrentStorage(broker, "Initialize"); | 230 | LogCurrentStorage(broker, "Initialize"); |
| 231 | } | 231 | } |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 10afbc2da..89d5434af 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -199,6 +199,14 @@ const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const { | |||
| 199 | return frontend; | 199 | return frontend; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | NFP::CabinetMode AppletManager::GetCabinetMode() const { | ||
| 203 | return cabinet_mode; | ||
| 204 | } | ||
| 205 | |||
| 206 | AppletId AppletManager::GetCurrentAppletId() const { | ||
| 207 | return current_applet_id; | ||
| 208 | } | ||
| 209 | |||
| 202 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { | 210 | void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { |
| 203 | if (set.cabinet != nullptr) { | 211 | if (set.cabinet != nullptr) { |
| 204 | frontend.cabinet = std::move(set.cabinet); | 212 | frontend.cabinet = std::move(set.cabinet); |
| @@ -237,6 +245,14 @@ void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { | |||
| 237 | } | 245 | } |
| 238 | } | 246 | } |
| 239 | 247 | ||
| 248 | void AppletManager::SetCabinetMode(NFP::CabinetMode mode) { | ||
| 249 | cabinet_mode = mode; | ||
| 250 | } | ||
| 251 | |||
| 252 | void AppletManager::SetCurrentAppletId(AppletId applet_id) { | ||
| 253 | current_applet_id = applet_id; | ||
| 254 | } | ||
| 255 | |||
| 240 | void AppletManager::SetDefaultAppletFrontendSet() { | 256 | void AppletManager::SetDefaultAppletFrontendSet() { |
| 241 | ClearAll(); | 257 | ClearAll(); |
| 242 | SetDefaultAppletsIfMissing(); | 258 | SetDefaultAppletsIfMissing(); |
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 12f374199..f02bbc450 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -34,6 +34,10 @@ class KEvent; | |||
| 34 | class KReadableEvent; | 34 | class KReadableEvent; |
| 35 | } // namespace Kernel | 35 | } // namespace Kernel |
| 36 | 36 | ||
| 37 | namespace Service::NFP { | ||
| 38 | enum class CabinetMode : u8; | ||
| 39 | } // namespace Service::NFP | ||
| 40 | |||
| 37 | namespace Service::AM { | 41 | namespace Service::AM { |
| 38 | 42 | ||
| 39 | class IStorage; | 43 | class IStorage; |
| @@ -41,6 +45,8 @@ class IStorage; | |||
| 41 | namespace Applets { | 45 | namespace Applets { |
| 42 | 46 | ||
| 43 | enum class AppletId : u32 { | 47 | enum class AppletId : u32 { |
| 48 | None = 0x00, | ||
| 49 | Application = 0x01, | ||
| 44 | OverlayDisplay = 0x02, | 50 | OverlayDisplay = 0x02, |
| 45 | QLaunch = 0x03, | 51 | QLaunch = 0x03, |
| 46 | Starter = 0x04, | 52 | Starter = 0x04, |
| @@ -71,6 +77,32 @@ enum class LibraryAppletMode : u32 { | |||
| 71 | AllForegroundInitiallyHidden = 4, | 77 | AllForegroundInitiallyHidden = 4, |
| 72 | }; | 78 | }; |
| 73 | 79 | ||
| 80 | enum class CommonArgumentVersion : u32 { | ||
| 81 | Version0, | ||
| 82 | Version1, | ||
| 83 | Version2, | ||
| 84 | Version3, | ||
| 85 | }; | ||
| 86 | |||
| 87 | enum class CommonArgumentSize : u32 { | ||
| 88 | Version3 = 0x20, | ||
| 89 | }; | ||
| 90 | |||
| 91 | enum class ThemeColor : u32 { | ||
| 92 | BasicWhite = 0, | ||
| 93 | BasicBlack = 3, | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct CommonArguments { | ||
| 97 | CommonArgumentVersion arguments_version; | ||
| 98 | CommonArgumentSize size; | ||
| 99 | u32 library_version; | ||
| 100 | ThemeColor theme_color; | ||
| 101 | bool play_startup_sound; | ||
| 102 | u64_le system_tick; | ||
| 103 | }; | ||
| 104 | static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); | ||
| 105 | |||
| 74 | class AppletDataBroker final { | 106 | class AppletDataBroker final { |
| 75 | public: | 107 | public: |
| 76 | explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_); | 108 | explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_); |
| @@ -161,16 +193,6 @@ public: | |||
| 161 | } | 193 | } |
| 162 | 194 | ||
| 163 | protected: | 195 | protected: |
| 164 | struct CommonArguments { | ||
| 165 | u32_le arguments_version; | ||
| 166 | u32_le size; | ||
| 167 | u32_le library_version; | ||
| 168 | u32_le theme_color; | ||
| 169 | bool play_startup_sound; | ||
| 170 | u64_le system_tick; | ||
| 171 | }; | ||
| 172 | static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); | ||
| 173 | |||
| 174 | CommonArguments common_args{}; | 196 | CommonArguments common_args{}; |
| 175 | AppletDataBroker broker; | 197 | AppletDataBroker broker; |
| 176 | LibraryAppletMode applet_mode; | 198 | LibraryAppletMode applet_mode; |
| @@ -219,8 +241,12 @@ public: | |||
| 219 | ~AppletManager(); | 241 | ~AppletManager(); |
| 220 | 242 | ||
| 221 | const AppletFrontendSet& GetAppletFrontendSet() const; | 243 | const AppletFrontendSet& GetAppletFrontendSet() const; |
| 244 | NFP::CabinetMode GetCabinetMode() const; | ||
| 245 | AppletId GetCurrentAppletId() const; | ||
| 222 | 246 | ||
| 223 | void SetAppletFrontendSet(AppletFrontendSet set); | 247 | void SetAppletFrontendSet(AppletFrontendSet set); |
| 248 | void SetCabinetMode(NFP::CabinetMode mode); | ||
| 249 | void SetCurrentAppletId(AppletId applet_id); | ||
| 224 | void SetDefaultAppletFrontendSet(); | 250 | void SetDefaultAppletFrontendSet(); |
| 225 | void SetDefaultAppletsIfMissing(); | 251 | void SetDefaultAppletsIfMissing(); |
| 226 | void ClearAll(); | 252 | void ClearAll(); |
| @@ -228,6 +254,9 @@ public: | |||
| 228 | std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const; | 254 | std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const; |
| 229 | 255 | ||
| 230 | private: | 256 | private: |
| 257 | AppletId current_applet_id{}; | ||
| 258 | NFP::CabinetMode cabinet_mode{}; | ||
| 259 | |||
| 231 | AppletFrontendSet frontend; | 260 | AppletFrontendSet frontend; |
| 232 | Core::System& system; | 261 | Core::System& system; |
| 233 | }; | 262 | }; |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index c2054e8a0..126cd6ffd 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -855,6 +855,9 @@ FSP_SRV::FSP_SRV(Core::System& system_) | |||
| 855 | if (Settings::values.enable_fs_access_log) { | 855 | if (Settings::values.enable_fs_access_log) { |
| 856 | access_log_mode = AccessLogMode::SdCard; | 856 | access_log_mode = AccessLogMode::SdCard; |
| 857 | } | 857 | } |
| 858 | |||
| 859 | // This should be true on creation | ||
| 860 | fsc.SetAutoSaveDataCreation(true); | ||
| 858 | } | 861 | } |
| 859 | 862 | ||
| 860 | FSP_SRV::~FSP_SRV() = default; | 863 | FSP_SRV::~FSP_SRV() = default; |
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index 9d149a7cd..7927f8264 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp | |||
| @@ -23,19 +23,39 @@ public: | |||
| 23 | explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} { | 23 | explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} { |
| 24 | // clang-format off | 24 | // clang-format off |
| 25 | static const FunctionInfo functions[] = { | 25 | static const FunctionInfo functions[] = { |
| 26 | {0, nullptr, "GetStateForMonitor"}, | 26 | {0, &IMonitorService::GetStateForMonitor, "GetStateForMonitor"}, |
| 27 | {1, nullptr, "GetNetworkInfoForMonitor"}, | 27 | {1, nullptr, "GetNetworkInfoForMonitor"}, |
| 28 | {2, nullptr, "GetIpv4AddressForMonitor"}, | 28 | {2, nullptr, "GetIpv4AddressForMonitor"}, |
| 29 | {3, nullptr, "GetDisconnectReasonForMonitor"}, | 29 | {3, nullptr, "GetDisconnectReasonForMonitor"}, |
| 30 | {4, nullptr, "GetSecurityParameterForMonitor"}, | 30 | {4, nullptr, "GetSecurityParameterForMonitor"}, |
| 31 | {5, nullptr, "GetNetworkConfigForMonitor"}, | 31 | {5, nullptr, "GetNetworkConfigForMonitor"}, |
| 32 | {100, nullptr, "InitializeMonitor"}, | 32 | {100, &IMonitorService::InitializeMonitor, "InitializeMonitor"}, |
| 33 | {101, nullptr, "FinalizeMonitor"}, | 33 | {101, nullptr, "FinalizeMonitor"}, |
| 34 | }; | 34 | }; |
| 35 | // clang-format on | 35 | // clang-format on |
| 36 | 36 | ||
| 37 | RegisterHandlers(functions); | 37 | RegisterHandlers(functions); |
| 38 | } | 38 | } |
| 39 | |||
| 40 | private: | ||
| 41 | void GetStateForMonitor(HLERequestContext& ctx) { | ||
| 42 | LOG_INFO(Service_LDN, "called"); | ||
| 43 | |||
| 44 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 45 | rb.Push(ResultSuccess); | ||
| 46 | rb.PushEnum(state); | ||
| 47 | } | ||
| 48 | |||
| 49 | void InitializeMonitor(HLERequestContext& ctx) { | ||
| 50 | LOG_INFO(Service_LDN, "called"); | ||
| 51 | |||
| 52 | state = State::Initialized; | ||
| 53 | |||
| 54 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 55 | rb.Push(ResultSuccess); | ||
| 56 | } | ||
| 57 | |||
| 58 | State state{State::None}; | ||
| 39 | }; | 59 | }; |
| 40 | 60 | ||
| 41 | class LDNM final : public ServiceFramework<LDNM> { | 61 | class LDNM final : public ServiceFramework<LDNM> { |
| @@ -731,14 +751,81 @@ public: | |||
| 731 | } | 751 | } |
| 732 | }; | 752 | }; |
| 733 | 753 | ||
| 754 | class ISfMonitorService final : public ServiceFramework<ISfMonitorService> { | ||
| 755 | public: | ||
| 756 | explicit ISfMonitorService(Core::System& system_) | ||
| 757 | : ServiceFramework{system_, "ISfMonitorService"} { | ||
| 758 | // clang-format off | ||
| 759 | static const FunctionInfo functions[] = { | ||
| 760 | {0, &ISfMonitorService::Initialize, "Initialize"}, | ||
| 761 | {288, &ISfMonitorService::GetGroupInfo, "GetGroupInfo"}, | ||
| 762 | {320, nullptr, "GetLinkLevel"}, | ||
| 763 | }; | ||
| 764 | // clang-format on | ||
| 765 | |||
| 766 | RegisterHandlers(functions); | ||
| 767 | } | ||
| 768 | |||
| 769 | private: | ||
| 770 | void Initialize(HLERequestContext& ctx) { | ||
| 771 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 772 | |||
| 773 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 774 | rb.Push(ResultSuccess); | ||
| 775 | rb.Push(0); | ||
| 776 | } | ||
| 777 | |||
| 778 | void GetGroupInfo(HLERequestContext& ctx) { | ||
| 779 | LOG_WARNING(Service_LDN, "(STUBBED) called"); | ||
| 780 | |||
| 781 | struct GroupInfo { | ||
| 782 | std::array<u8, 0x200> info; | ||
| 783 | }; | ||
| 784 | |||
| 785 | GroupInfo group_info{}; | ||
| 786 | |||
| 787 | ctx.WriteBuffer(group_info); | ||
| 788 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 789 | rb.Push(ResultSuccess); | ||
| 790 | } | ||
| 791 | }; | ||
| 792 | |||
| 793 | class LP2PM final : public ServiceFramework<LP2PM> { | ||
| 794 | public: | ||
| 795 | explicit LP2PM(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} { | ||
| 796 | // clang-format off | ||
| 797 | static const FunctionInfo functions[] = { | ||
| 798 | {0, &LP2PM::CreateMonitorService, "CreateMonitorService"}, | ||
| 799 | }; | ||
| 800 | // clang-format on | ||
| 801 | |||
| 802 | RegisterHandlers(functions); | ||
| 803 | } | ||
| 804 | |||
| 805 | private: | ||
| 806 | void CreateMonitorService(HLERequestContext& ctx) { | ||
| 807 | IPC::RequestParser rp{ctx}; | ||
| 808 | const u64 reserved_input = rp.Pop<u64>(); | ||
| 809 | |||
| 810 | LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input); | ||
| 811 | |||
| 812 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 813 | rb.Push(ResultSuccess); | ||
| 814 | rb.PushIpcInterface<ISfMonitorService>(system); | ||
| 815 | } | ||
| 816 | }; | ||
| 817 | |||
| 734 | void LoopProcess(Core::System& system) { | 818 | void LoopProcess(Core::System& system) { |
| 735 | auto server_manager = std::make_unique<ServerManager>(system); | 819 | auto server_manager = std::make_unique<ServerManager>(system); |
| 736 | 820 | ||
| 737 | server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system)); | 821 | server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system)); |
| 738 | server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system)); | 822 | server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system)); |
| 739 | server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system)); | 823 | server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system)); |
| 824 | |||
| 740 | server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system)); | 825 | server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system)); |
| 741 | server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system)); | 826 | server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system)); |
| 827 | server_manager->RegisterNamedService("lp2p:m", std::make_shared<LP2PM>(system)); | ||
| 828 | |||
| 742 | ServerManager::RunServer(std::move(server_manager)); | 829 | ServerManager::RunServer(std::move(server_manager)); |
| 743 | } | 830 | } |
| 744 | 831 | ||
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 68c407f81..e7a00deb3 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp | |||
| @@ -830,11 +830,6 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe | |||
| 830 | return ResultWrongDeviceState; | 830 | return ResultWrongDeviceState; |
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | Service::Mii::StoreData store_data{}; | ||
| 834 | Service::Mii::NfpStoreDataExtension extension{}; | ||
| 835 | store_data.BuildBase(Mii::Gender::Male); | ||
| 836 | extension.SetFromStoreData(store_data); | ||
| 837 | |||
| 838 | auto& settings = tag_data.settings; | 833 | auto& settings = tag_data.settings; |
| 839 | 834 | ||
| 840 | if (tag_data.settings.settings.amiibo_initialized == 0) { | 835 | if (tag_data.settings.settings.amiibo_initialized == 0) { |
| @@ -843,8 +838,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe | |||
| 843 | } | 838 | } |
| 844 | 839 | ||
| 845 | SetAmiiboName(settings, register_info.amiibo_name); | 840 | SetAmiiboName(settings, register_info.amiibo_name); |
| 846 | tag_data.owner_mii.BuildFromStoreData(store_data); | 841 | tag_data.owner_mii.BuildFromStoreData(register_info.mii_store_data); |
| 847 | tag_data.mii_extension = extension; | 842 | tag_data.mii_extension.SetFromStoreData(register_info.mii_store_data); |
| 848 | tag_data.unknown = 0; | 843 | tag_data.unknown = 0; |
| 849 | tag_data.unknown2 = {}; | 844 | tag_data.unknown2 = {}; |
| 850 | settings.country_code_id = 0; | 845 | settings.country_code_id = 0; |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 40c65b430..4c0cc71cd 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -45,13 +45,6 @@ public: | |||
| 45 | IsSharedMemMapped = 6 | 45 | IsSharedMemMapped = 6 |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | private: | ||
| 49 | /// Id to use for the next handle that is created. | ||
| 50 | u32 next_handle = 0; | ||
| 51 | |||
| 52 | /// Id to use for the next object that is created. | ||
| 53 | u32 next_id = 0; | ||
| 54 | |||
| 55 | struct IocCreateParams { | 48 | struct IocCreateParams { |
| 56 | // Input | 49 | // Input |
| 57 | u32_le size{}; | 50 | u32_le size{}; |
| @@ -113,6 +106,13 @@ private: | |||
| 113 | NvResult IocParam(std::span<const u8> input, std::span<u8> output); | 106 | NvResult IocParam(std::span<const u8> input, std::span<u8> output); |
| 114 | NvResult IocFree(std::span<const u8> input, std::span<u8> output); | 107 | NvResult IocFree(std::span<const u8> input, std::span<u8> output); |
| 115 | 108 | ||
| 109 | private: | ||
| 110 | /// Id to use for the next handle that is created. | ||
| 111 | u32 next_handle = 0; | ||
| 112 | |||
| 113 | /// Id to use for the next object that is created. | ||
| 114 | u32 next_id = 0; | ||
| 115 | |||
| 116 | NvCore::Container& container; | 116 | NvCore::Container& container; |
| 117 | NvCore::NvMap& file; | 117 | NvCore::NvMap& file; |
| 118 | }; | 118 | }; |
diff --git a/src/core/hle/service/nvnflinger/buffer_item.h b/src/core/hle/service/nvnflinger/buffer_item.h index 7fd808f54..3da8cc3aa 100644 --- a/src/core/hle/service/nvnflinger/buffer_item.h +++ b/src/core/hle/service/nvnflinger/buffer_item.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | namespace Service::android { | 16 | namespace Service::android { |
| 17 | 17 | ||
| 18 | class GraphicBuffer; | 18 | struct GraphicBuffer; |
| 19 | 19 | ||
| 20 | class BufferItem final { | 20 | class BufferItem final { |
| 21 | public: | 21 | public: |
diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index d25bca049..d8c9dec3b 100644 --- a/src/core/hle/service/nvnflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Service::android { | 14 | namespace Service::android { |
| 15 | 15 | ||
| 16 | class GraphicBuffer; | 16 | struct GraphicBuffer; |
| 17 | 17 | ||
| 18 | enum class BufferState : u32 { | 18 | enum class BufferState : u32 { |
| 19 | Free = 0, | 19 | Free = 0, |
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp new file mode 100644 index 000000000..469a53244 --- /dev/null +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | |||
| @@ -0,0 +1,351 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <random> | ||
| 5 | |||
| 6 | #include "core/core.h" | ||
| 7 | #include "core/hle/kernel/k_process.h" | ||
| 8 | #include "core/hle/kernel/k_system_resource.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 10 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 11 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | ||
| 12 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 13 | #include "core/hle/service/nvnflinger/pixel_format.h" | ||
| 14 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | ||
| 15 | #include "core/hle/service/vi/layer/vi_layer.h" | ||
| 16 | #include "core/hle/service/vi/vi_results.h" | ||
| 17 | |||
| 18 | namespace Service::Nvnflinger { | ||
| 19 | |||
| 20 | namespace { | ||
| 21 | |||
| 22 | Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, | ||
| 23 | std::unique_ptr<Kernel::KPageGroup>* out_page_group, | ||
| 24 | Core::System& system, u32 size) { | ||
| 25 | using Core::Memory::YUZU_PAGESIZE; | ||
| 26 | |||
| 27 | // 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. | ||
| 32 | auto& kernel = system.Kernel(); | ||
| 33 | auto* process = system.ApplicationProcess(); | ||
| 34 | auto& page_table = process->GetPageTable(); | ||
| 35 | |||
| 36 | // Hold a temporary page group reference while we try to map it. | ||
| 37 | auto pg = std::make_unique<Kernel::KPageGroup>( | ||
| 38 | kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); | ||
| 39 | |||
| 40 | // Allocate memory from secure pool. | ||
| 41 | R_TRY(kernel.MemoryManager().AllocateAndOpen( | ||
| 42 | pg.get(), size / YUZU_PAGESIZE, | ||
| 43 | Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure, | ||
| 44 | Kernel::KMemoryManager::Direction::FromBack))); | ||
| 45 | |||
| 46 | // Get bounds of where mapping is possible. | ||
| 47 | const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart()); | ||
| 48 | const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE; | ||
| 49 | const auto state = Kernel::KMemoryState::Io; | ||
| 50 | const auto perm = Kernel::KMemoryPermission::UserReadWrite; | ||
| 51 | std::mt19937_64 rng{process->GetRandomEntropy(0)}; | ||
| 52 | |||
| 53 | // Retry up to 64 times to map into alias code range. | ||
| 54 | Result res = ResultSuccess; | ||
| 55 | int i; | ||
| 56 | for (i = 0; i < 64; i++) { | ||
| 57 | *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE); | ||
| 58 | res = page_table.MapPageGroup(*out_map_address, *pg, state, perm); | ||
| 59 | if (R_SUCCEEDED(res)) { | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | // Return failure, if necessary | ||
| 65 | R_UNLESS(i < 64, res); | ||
| 66 | |||
| 67 | // Return the mapped page group. | ||
| 68 | *out_page_group = std::move(pg); | ||
| 69 | |||
| 70 | // We succeeded. | ||
| 71 | R_SUCCEED(); | ||
| 72 | } | ||
| 73 | |||
| 74 | template <typename T> | ||
| 75 | std::span<u8> SerializeIoc(T& params) { | ||
| 76 | return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T)); | ||
| 77 | } | ||
| 78 | |||
| 79 | Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { | ||
| 80 | // Create a handle. | ||
| 81 | Nvidia::Devices::nvmap::IocCreateParams create_in_params{ | ||
| 82 | .size = size, | ||
| 83 | .handle = 0, | ||
| 84 | }; | ||
| 85 | Nvidia::Devices::nvmap::IocCreateParams create_out_params{}; | ||
| 86 | R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) == | ||
| 87 | Nvidia::NvResult::Success, | ||
| 88 | VI::ResultOperationFailed); | ||
| 89 | |||
| 90 | // Assign the output handle. | ||
| 91 | *out_nv_map_handle = create_out_params.handle; | ||
| 92 | |||
| 93 | // We succeeded. | ||
| 94 | R_SUCCEED(); | ||
| 95 | } | ||
| 96 | |||
| 97 | Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | ||
| 98 | // Free the handle. | ||
| 99 | Nvidia::Devices::nvmap::IocFreeParams free_in_params{ | ||
| 100 | .handle = handle, | ||
| 101 | }; | ||
| 102 | Nvidia::Devices::nvmap::IocFreeParams free_out_params{}; | ||
| 103 | R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) == | ||
| 104 | Nvidia::NvResult::Success, | ||
| 105 | VI::ResultOperationFailed); | ||
| 106 | |||
| 107 | // We succeeded. | ||
| 108 | R_SUCCEED(); | ||
| 109 | } | ||
| 110 | |||
| 111 | Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, | ||
| 112 | u32 size) { | ||
| 113 | // Assign the allocated memory to the handle. | ||
| 114 | Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{ | ||
| 115 | .handle = handle, | ||
| 116 | .heap_mask = 0, | ||
| 117 | .flags = {}, | ||
| 118 | .align = 0, | ||
| 119 | .kind = 0, | ||
| 120 | .address = GetInteger(buffer), | ||
| 121 | }; | ||
| 122 | Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{}; | ||
| 123 | R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) == | ||
| 124 | Nvidia::NvResult::Success, | ||
| 125 | VI::ResultOperationFailed); | ||
| 126 | |||
| 127 | // We succeeded. | ||
| 128 | R_SUCCEED(); | ||
| 129 | } | ||
| 130 | |||
| 131 | Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, | ||
| 132 | Common::ProcessAddress buffer, u32 size) { | ||
| 133 | // Get the nvmap device. | ||
| 134 | auto nvmap_fd = nvdrv.Open("/dev/nvmap"); | ||
| 135 | auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); | ||
| 136 | ASSERT(nvmap != nullptr); | ||
| 137 | |||
| 138 | // Create a handle. | ||
| 139 | R_TRY(CreateNvMapHandle(out_handle, *nvmap, size)); | ||
| 140 | |||
| 141 | // Ensure we maintain a clean state on failure. | ||
| 142 | ON_RESULT_FAILURE { | ||
| 143 | ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle))); | ||
| 144 | }; | ||
| 145 | |||
| 146 | // Assign the allocated memory to the handle. | ||
| 147 | R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size)); | ||
| 148 | } | ||
| 149 | |||
| 150 | constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; | ||
| 151 | constexpr u32 SharedBufferBlockLinearBpp = 4; | ||
| 152 | |||
| 153 | constexpr u32 SharedBufferBlockLinearWidth = 1280; | ||
| 154 | constexpr u32 SharedBufferBlockLinearHeight = 768; | ||
| 155 | constexpr u32 SharedBufferBlockLinearStride = | ||
| 156 | SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp; | ||
| 157 | constexpr u32 SharedBufferNumSlots = 7; | ||
| 158 | |||
| 159 | constexpr u32 SharedBufferWidth = 1280; | ||
| 160 | constexpr u32 SharedBufferHeight = 720; | ||
| 161 | constexpr u32 SharedBufferAsync = false; | ||
| 162 | |||
| 163 | constexpr u32 SharedBufferSlotSize = | ||
| 164 | SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp; | ||
| 165 | constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots; | ||
| 166 | |||
| 167 | constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] { | ||
| 168 | SharedMemoryPoolLayout layout{}; | ||
| 169 | layout.num_slots = SharedBufferNumSlots; | ||
| 170 | |||
| 171 | for (u32 i = 0; i < SharedBufferNumSlots; i++) { | ||
| 172 | layout.slots[i].buffer_offset = i * SharedBufferSlotSize; | ||
| 173 | layout.slots[i].size = SharedBufferSlotSize; | ||
| 174 | layout.slots[i].width = SharedBufferWidth; | ||
| 175 | layout.slots[i].height = SharedBufferHeight; | ||
| 176 | } | ||
| 177 | |||
| 178 | return layout; | ||
| 179 | }(); | ||
| 180 | |||
| 181 | void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { | ||
| 182 | auto buffer = std::make_shared<android::GraphicBuffer>(); | ||
| 183 | buffer->width = SharedBufferWidth; | ||
| 184 | buffer->height = SharedBufferHeight; | ||
| 185 | buffer->stride = SharedBufferBlockLinearStride; | ||
| 186 | buffer->format = SharedBufferBlockLinearFormat; | ||
| 187 | buffer->buffer_id = handle; | ||
| 188 | buffer->offset = slot * SharedBufferSlotSize; | ||
| 189 | ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError); | ||
| 190 | } | ||
| 191 | |||
| 192 | } // namespace | ||
| 193 | |||
| 194 | FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger, | ||
| 195 | std::shared_ptr<Nvidia::Module> nvdrv) | ||
| 196 | : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {} | ||
| 197 | |||
| 198 | FbShareBufferManager::~FbShareBufferManager() = default; | ||
| 199 | |||
| 200 | Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u64 display_id) { | ||
| 201 | std::scoped_lock lk{m_guard}; | ||
| 202 | |||
| 203 | // Ensure we have not already created a buffer. | ||
| 204 | R_UNLESS(m_buffer_id == 0, VI::ResultOperationFailed); | ||
| 205 | |||
| 206 | // Allocate memory and space for the shared buffer. | ||
| 207 | Common::ProcessAddress map_address; | ||
| 208 | R_TRY(AllocateIoForProcessAddressSpace(std::addressof(map_address), | ||
| 209 | std::addressof(m_buffer_page_group), m_system, | ||
| 210 | SharedBufferSize)); | ||
| 211 | |||
| 212 | // Create an nvmap handle for the buffer and assign the memory to it. | ||
| 213 | R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, map_address, | ||
| 214 | SharedBufferSize)); | ||
| 215 | |||
| 216 | // Record the display id. | ||
| 217 | m_display_id = display_id; | ||
| 218 | |||
| 219 | // Create a layer for the display. | ||
| 220 | m_layer_id = m_flinger.CreateLayer(m_display_id).value(); | ||
| 221 | |||
| 222 | // Set up the buffer. | ||
| 223 | m_buffer_id = m_next_buffer_id++; | ||
| 224 | |||
| 225 | // Get the layer. | ||
| 226 | VI::Layer* layer = m_flinger.FindLayer(m_display_id, m_layer_id); | ||
| 227 | ASSERT(layer != nullptr); | ||
| 228 | |||
| 229 | // Get the producer and set preallocated buffers. | ||
| 230 | auto& producer = layer->GetBufferQueue(); | ||
| 231 | MakeGraphicBuffer(producer, 0, m_buffer_nvmap_handle); | ||
| 232 | MakeGraphicBuffer(producer, 1, m_buffer_nvmap_handle); | ||
| 233 | |||
| 234 | // Assign outputs. | ||
| 235 | *out_buffer_id = m_buffer_id; | ||
| 236 | *out_layer_id = m_layer_id; | ||
| 237 | |||
| 238 | // We succeeded. | ||
| 239 | R_SUCCEED(); | ||
| 240 | } | ||
| 241 | |||
| 242 | Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, | ||
| 243 | s32* out_nvmap_handle, | ||
| 244 | SharedMemoryPoolLayout* out_pool_layout, | ||
| 245 | u64 buffer_id, | ||
| 246 | u64 applet_resource_user_id) { | ||
| 247 | std::scoped_lock lk{m_guard}; | ||
| 248 | |||
| 249 | R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); | ||
| 250 | R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound); | ||
| 251 | |||
| 252 | *out_pool_layout = SharedBufferPoolLayout; | ||
| 253 | *out_buffer_size = SharedBufferSize; | ||
| 254 | *out_nvmap_handle = m_buffer_nvmap_handle; | ||
| 255 | |||
| 256 | R_SUCCEED(); | ||
| 257 | } | ||
| 258 | |||
| 259 | Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { | ||
| 260 | // Ensure the layer id is valid. | ||
| 261 | R_UNLESS(m_layer_id > 0 && layer_id == m_layer_id, VI::ResultNotFound); | ||
| 262 | |||
| 263 | // Get the layer. | ||
| 264 | VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id); | ||
| 265 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 266 | |||
| 267 | // We succeeded. | ||
| 268 | *out_layer = layer; | ||
| 269 | R_SUCCEED(); | ||
| 270 | } | ||
| 271 | |||
| 272 | Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, | ||
| 273 | std::array<s32, 4>& out_slot_indexes, | ||
| 274 | s64* out_target_slot, u64 layer_id) { | ||
| 275 | std::scoped_lock lk{m_guard}; | ||
| 276 | |||
| 277 | // Get the layer. | ||
| 278 | VI::Layer* layer; | ||
| 279 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 280 | |||
| 281 | // Get the producer. | ||
| 282 | auto& producer = layer->GetBufferQueue(); | ||
| 283 | |||
| 284 | // Get the next buffer from the producer. | ||
| 285 | s32 slot; | ||
| 286 | R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, | ||
| 287 | SharedBufferWidth, SharedBufferHeight, | ||
| 288 | SharedBufferBlockLinearFormat, 0) == android::Status::NoError, | ||
| 289 | VI::ResultOperationFailed); | ||
| 290 | |||
| 291 | // Assign remaining outputs. | ||
| 292 | *out_target_slot = slot; | ||
| 293 | out_slot_indexes = {0, 1, -1, -1}; | ||
| 294 | |||
| 295 | // We succeeded. | ||
| 296 | R_SUCCEED(); | ||
| 297 | } | ||
| 298 | |||
| 299 | Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence, | ||
| 300 | Common::Rectangle<s32> crop_region, | ||
| 301 | u32 transform, s32 swap_interval, | ||
| 302 | u64 layer_id, s64 slot) { | ||
| 303 | std::scoped_lock lk{m_guard}; | ||
| 304 | |||
| 305 | // Get the layer. | ||
| 306 | VI::Layer* layer; | ||
| 307 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 308 | |||
| 309 | // Get the producer. | ||
| 310 | auto& producer = layer->GetBufferQueue(); | ||
| 311 | |||
| 312 | // Request to queue the buffer. | ||
| 313 | std::shared_ptr<android::GraphicBuffer> buffer; | ||
| 314 | R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == | ||
| 315 | android::Status::NoError, | ||
| 316 | VI::ResultOperationFailed); | ||
| 317 | |||
| 318 | // Queue the buffer to the producer. | ||
| 319 | android::QueueBufferInput input{}; | ||
| 320 | android::QueueBufferOutput output{}; | ||
| 321 | input.crop = crop_region; | ||
| 322 | input.fence = fence; | ||
| 323 | input.transform = static_cast<android::NativeWindowTransform>(transform); | ||
| 324 | input.swap_interval = swap_interval; | ||
| 325 | R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == | ||
| 326 | android::Status::NoError, | ||
| 327 | VI::ResultOperationFailed); | ||
| 328 | |||
| 329 | // We succeeded. | ||
| 330 | R_SUCCEED(); | ||
| 331 | } | ||
| 332 | |||
| 333 | Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, | ||
| 334 | u64 layer_id) { | ||
| 335 | std::scoped_lock lk{m_guard}; | ||
| 336 | |||
| 337 | // Get the layer. | ||
| 338 | VI::Layer* layer; | ||
| 339 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 340 | |||
| 341 | // Get the producer. | ||
| 342 | auto& producer = layer->GetBufferQueue(); | ||
| 343 | |||
| 344 | // Set the event. | ||
| 345 | *out_event = std::addressof(producer.GetNativeHandle()); | ||
| 346 | |||
| 347 | // We succeeded. | ||
| 348 | R_SUCCEED(); | ||
| 349 | } | ||
| 350 | |||
| 351 | } // 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 new file mode 100644 index 000000000..c809c01b4 --- /dev/null +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/math_util.h" | ||
| 7 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 8 | #include "core/hle/service/nvnflinger/ui/fence.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | class KPageGroup; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Service::Nvnflinger { | ||
| 15 | |||
| 16 | struct SharedMemorySlot { | ||
| 17 | u64 buffer_offset; | ||
| 18 | u64 size; | ||
| 19 | s32 width; | ||
| 20 | s32 height; | ||
| 21 | }; | ||
| 22 | static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size"); | ||
| 23 | |||
| 24 | struct SharedMemoryPoolLayout { | ||
| 25 | s32 num_slots; | ||
| 26 | std::array<SharedMemorySlot, 0x10> slots; | ||
| 27 | }; | ||
| 28 | static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); | ||
| 29 | |||
| 30 | class FbShareBufferManager final { | ||
| 31 | public: | ||
| 32 | explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger, | ||
| 33 | std::shared_ptr<Nvidia::Module> nvdrv); | ||
| 34 | ~FbShareBufferManager(); | ||
| 35 | |||
| 36 | Result Initialize(u64* out_buffer_id, u64* out_layer_handle, u64 display_id); | ||
| 37 | Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, | ||
| 38 | SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, | ||
| 39 | u64 applet_resource_user_id); | ||
| 40 | Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots, | ||
| 41 | s64* out_target_slot, u64 layer_id); | ||
| 42 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | ||
| 43 | u32 transform, s32 swap_interval, u64 layer_id, s64 slot); | ||
| 44 | Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); | ||
| 45 | |||
| 46 | private: | ||
| 47 | Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); | ||
| 48 | |||
| 49 | private: | ||
| 50 | u64 m_next_buffer_id = 1; | ||
| 51 | u64 m_display_id = 0; | ||
| 52 | u64 m_buffer_id = 0; | ||
| 53 | u64 m_layer_id = 0; | ||
| 54 | u32 m_buffer_nvmap_handle = 0; | ||
| 55 | SharedMemoryPoolLayout m_pool_layout = {}; | ||
| 56 | |||
| 57 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; | ||
| 58 | |||
| 59 | std::mutex m_guard; | ||
| 60 | Core::System& m_system; | ||
| 61 | Nvnflinger& m_flinger; | ||
| 62 | std::shared_ptr<Nvidia::Module> m_nvdrv; | ||
| 63 | }; | ||
| 64 | |||
| 65 | } // namespace Service::Nvnflinger | ||
diff --git a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h index 21d7b31f3..5d7cff7d3 100644 --- a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h +++ b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h | |||
| @@ -19,6 +19,7 @@ class InputParcel; | |||
| 19 | #pragma pack(push, 1) | 19 | #pragma pack(push, 1) |
| 20 | struct QueueBufferInput final { | 20 | struct QueueBufferInput final { |
| 21 | explicit QueueBufferInput(InputParcel& parcel); | 21 | explicit QueueBufferInput(InputParcel& parcel); |
| 22 | explicit QueueBufferInput() = default; | ||
| 22 | 23 | ||
| 23 | void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, | 24 | void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, |
| 24 | NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, | 25 | NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, |
| @@ -34,7 +35,6 @@ struct QueueBufferInput final { | |||
| 34 | *fence_ = fence; | 35 | *fence_ = fence; |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | private: | ||
| 38 | s64 timestamp{}; | 38 | s64 timestamp{}; |
| 39 | s32 is_auto_timestamp{}; | 39 | s32 is_auto_timestamp{}; |
| 40 | Common::Rectangle<s32> crop{}; | 40 | Common::Rectangle<s32> crop{}; |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 21f31f7a0..a07c621d9 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "core/hle/service/nvdrv/nvdrv.h" | 17 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 18 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" | 18 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" |
| 19 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | 19 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" |
| 20 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 20 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | 21 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" |
| 21 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 22 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 22 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 23 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" |
| @@ -331,4 +332,14 @@ s64 Nvnflinger::GetNextTicks() const { | |||
| 331 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); | 332 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); |
| 332 | } | 333 | } |
| 333 | 334 | ||
| 335 | FbShareBufferManager& Nvnflinger::GetSystemBufferManager() { | ||
| 336 | const auto lock_guard = Lock(); | ||
| 337 | |||
| 338 | if (!system_buffer_manager) { | ||
| 339 | system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv); | ||
| 340 | } | ||
| 341 | |||
| 342 | return *system_buffer_manager; | ||
| 343 | } | ||
| 344 | |||
| 334 | } // namespace Service::Nvnflinger | 345 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index f478c2bc6..14c783582 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -45,6 +45,9 @@ class BufferQueueProducer; | |||
| 45 | 45 | ||
| 46 | namespace Service::Nvnflinger { | 46 | namespace Service::Nvnflinger { |
| 47 | 47 | ||
| 48 | class FbShareBufferManager; | ||
| 49 | class HosBinderDriverServer; | ||
| 50 | |||
| 48 | class Nvnflinger final { | 51 | class Nvnflinger final { |
| 49 | public: | 52 | public: |
| 50 | explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); | 53 | explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); |
| @@ -90,12 +93,16 @@ public: | |||
| 90 | 93 | ||
| 91 | [[nodiscard]] s64 GetNextTicks() const; | 94 | [[nodiscard]] s64 GetNextTicks() const; |
| 92 | 95 | ||
| 96 | FbShareBufferManager& GetSystemBufferManager(); | ||
| 97 | |||
| 93 | private: | 98 | private: |
| 94 | struct Layer { | 99 | struct Layer { |
| 95 | std::unique_ptr<android::BufferQueueCore> core; | 100 | std::unique_ptr<android::BufferQueueCore> core; |
| 96 | std::unique_ptr<android::BufferQueueProducer> producer; | 101 | std::unique_ptr<android::BufferQueueProducer> producer; |
| 97 | }; | 102 | }; |
| 98 | 103 | ||
| 104 | friend class FbShareBufferManager; | ||
| 105 | |||
| 99 | private: | 106 | private: |
| 100 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { | 107 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { |
| 101 | return std::unique_lock{*guard}; | 108 | return std::unique_lock{*guard}; |
| @@ -140,6 +147,8 @@ private: | |||
| 140 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; | 147 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; |
| 141 | std::shared_ptr<Core::Timing::EventType> single_composition_event; | 148 | std::shared_ptr<Core::Timing::EventType> single_composition_event; |
| 142 | 149 | ||
| 150 | std::unique_ptr<FbShareBufferManager> system_buffer_manager; | ||
| 151 | |||
| 143 | std::shared_ptr<std::mutex> guard; | 152 | std::shared_ptr<std::mutex> guard; |
| 144 | 153 | ||
| 145 | Core::System& system; | 154 | Core::System& system; |
diff --git a/src/core/hle/service/nvnflinger/ui/fence.h b/src/core/hle/service/nvnflinger/ui/fence.h index 536e8156d..177aed758 100644 --- a/src/core/hle/service/nvnflinger/ui/fence.h +++ b/src/core/hle/service/nvnflinger/ui/fence.h | |||
| @@ -20,6 +20,9 @@ public: | |||
| 20 | static constexpr Fence NoFence() { | 20 | static constexpr Fence NoFence() { |
| 21 | Fence fence; | 21 | Fence fence; |
| 22 | fence.fences[0].id = -1; | 22 | fence.fences[0].id = -1; |
| 23 | fence.fences[1].id = -1; | ||
| 24 | fence.fences[2].id = -1; | ||
| 25 | fence.fences[3].id = -1; | ||
| 23 | return fence; | 26 | return fence; |
| 24 | } | 27 | } |
| 25 | 28 | ||
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h index 75d1705a8..3eac5cedd 100644 --- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h +++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h | |||
| @@ -12,8 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Service::android { | 13 | namespace Service::android { |
| 14 | 14 | ||
| 15 | class GraphicBuffer final { | 15 | struct GraphicBuffer final { |
| 16 | public: | ||
| 17 | constexpr GraphicBuffer() = default; | 16 | constexpr GraphicBuffer() = default; |
| 18 | 17 | ||
| 19 | constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) | 18 | constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) |
| @@ -77,7 +76,6 @@ public: | |||
| 77 | return false; | 76 | return false; |
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | private: | ||
| 81 | u32 magic{}; | 79 | u32 magic{}; |
| 82 | s32 width{}; | 80 | s32 width{}; |
| 83 | s32 height{}; | 81 | s32 height{}; |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 2eb978379..b1bfb9898 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -20,9 +20,12 @@ | |||
| 20 | #include "core/hle/kernel/k_readable_event.h" | 20 | #include "core/hle/kernel/k_readable_event.h" |
| 21 | #include "core/hle/kernel/k_thread.h" | 21 | #include "core/hle/kernel/k_thread.h" |
| 22 | #include "core/hle/service/ipc_helpers.h" | 22 | #include "core/hle/service/ipc_helpers.h" |
| 23 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 23 | #include "core/hle/service/nvdrv/nvdata.h" | 24 | #include "core/hle/service/nvdrv/nvdata.h" |
| 25 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 24 | #include "core/hle/service/nvnflinger/binder.h" | 26 | #include "core/hle/service/nvnflinger/binder.h" |
| 25 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | 27 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" |
| 28 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 26 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | 29 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" |
| 27 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 30 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 28 | #include "core/hle/service/nvnflinger/parcel.h" | 31 | #include "core/hle/service/nvnflinger/parcel.h" |
| @@ -131,8 +134,9 @@ private: | |||
| 131 | 134 | ||
| 132 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | 135 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { |
| 133 | public: | 136 | public: |
| 134 | explicit ISystemDisplayService(Core::System& system_) | 137 | explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) |
| 135 | : ServiceFramework{system_, "ISystemDisplayService"} { | 138 | : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { |
| 139 | // clang-format off | ||
| 136 | static const FunctionInfo functions[] = { | 140 | static const FunctionInfo functions[] = { |
| 137 | {1200, nullptr, "GetZOrderCountMin"}, | 141 | {1200, nullptr, "GetZOrderCountMin"}, |
| 138 | {1202, nullptr, "GetZOrderCountMax"}, | 142 | {1202, nullptr, "GetZOrderCountMax"}, |
| @@ -170,22 +174,126 @@ public: | |||
| 170 | {3217, nullptr, "SetDisplayCmuLuma"}, | 174 | {3217, nullptr, "SetDisplayCmuLuma"}, |
| 171 | {3218, nullptr, "SetDisplayCrcMode"}, | 175 | {3218, nullptr, "SetDisplayCrcMode"}, |
| 172 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | 176 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, |
| 173 | {8225, nullptr, "GetSharedBufferMemoryHandleId"}, | 177 | {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, |
| 174 | {8250, nullptr, "OpenSharedLayer"}, | 178 | {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, |
| 175 | {8251, nullptr, "CloseSharedLayer"}, | 179 | {8251, nullptr, "CloseSharedLayer"}, |
| 176 | {8252, nullptr, "ConnectSharedLayer"}, | 180 | {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, |
| 177 | {8253, nullptr, "DisconnectSharedLayer"}, | 181 | {8253, nullptr, "DisconnectSharedLayer"}, |
| 178 | {8254, nullptr, "AcquireSharedFrameBuffer"}, | 182 | {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, |
| 179 | {8255, nullptr, "PresentSharedFrameBuffer"}, | 183 | {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, |
| 180 | {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, | 184 | {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, |
| 181 | {8257, nullptr, "FillSharedFrameBufferColor"}, | 185 | {8257, nullptr, "FillSharedFrameBufferColor"}, |
| 182 | {8258, nullptr, "CancelSharedFrameBuffer"}, | 186 | {8258, nullptr, "CancelSharedFrameBuffer"}, |
| 183 | {9000, nullptr, "GetDp2hdmiController"}, | 187 | {9000, nullptr, "GetDp2hdmiController"}, |
| 184 | }; | 188 | }; |
| 189 | // clang-format on | ||
| 185 | RegisterHandlers(functions); | 190 | RegisterHandlers(functions); |
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | private: | 193 | private: |
| 194 | void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { | ||
| 195 | IPC::RequestParser rp{ctx}; | ||
| 196 | const u64 buffer_id = rp.PopRaw<u64>(); | ||
| 197 | |||
| 198 | LOG_INFO(Service_VI, "called. buffer_id={:#x}", buffer_id); | ||
| 199 | |||
| 200 | struct OutputParameters { | ||
| 201 | s32 nvmap_handle; | ||
| 202 | u64 size; | ||
| 203 | }; | ||
| 204 | |||
| 205 | OutputParameters out{}; | ||
| 206 | Nvnflinger::SharedMemoryPoolLayout layout{}; | ||
| 207 | const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||
| 208 | &out.size, &out.nvmap_handle, &layout, buffer_id, 0); | ||
| 209 | |||
| 210 | ctx.WriteBuffer(&layout, sizeof(layout)); | ||
| 211 | |||
| 212 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 213 | rb.Push(result); | ||
| 214 | rb.PushRaw(out); | ||
| 215 | } | ||
| 216 | |||
| 217 | void OpenSharedLayer(HLERequestContext& ctx) { | ||
| 218 | IPC::RequestParser rp{ctx}; | ||
| 219 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 220 | |||
| 221 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||
| 222 | |||
| 223 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 224 | rb.Push(ResultSuccess); | ||
| 225 | } | ||
| 226 | |||
| 227 | void ConnectSharedLayer(HLERequestContext& ctx) { | ||
| 228 | IPC::RequestParser rp{ctx}; | ||
| 229 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 230 | |||
| 231 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||
| 232 | |||
| 233 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 234 | rb.Push(ResultSuccess); | ||
| 235 | } | ||
| 236 | |||
| 237 | void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { | ||
| 238 | LOG_DEBUG(Service_VI, "called"); | ||
| 239 | |||
| 240 | IPC::RequestParser rp{ctx}; | ||
| 241 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 242 | |||
| 243 | Kernel::KReadableEvent* event{}; | ||
| 244 | const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( | ||
| 245 | &event, layer_id); | ||
| 246 | |||
| 247 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 248 | rb.Push(result); | ||
| 249 | rb.PushCopyObjects(event); | ||
| 250 | } | ||
| 251 | |||
| 252 | void AcquireSharedFrameBuffer(HLERequestContext& ctx) { | ||
| 253 | LOG_DEBUG(Service_VI, "called"); | ||
| 254 | |||
| 255 | IPC::RequestParser rp{ctx}; | ||
| 256 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 257 | |||
| 258 | struct OutputParameters { | ||
| 259 | android::Fence fence; | ||
| 260 | std::array<s32, 4> slots; | ||
| 261 | s64 target_slot; | ||
| 262 | }; | ||
| 263 | static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); | ||
| 264 | |||
| 265 | OutputParameters out{}; | ||
| 266 | const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||
| 267 | &out.fence, out.slots, &out.target_slot, layer_id); | ||
| 268 | |||
| 269 | IPC::ResponseBuilder rb{ctx, 18}; | ||
| 270 | rb.Push(result); | ||
| 271 | rb.PushRaw(out); | ||
| 272 | } | ||
| 273 | |||
| 274 | void PresentSharedFrameBuffer(HLERequestContext& ctx) { | ||
| 275 | LOG_DEBUG(Service_VI, "called"); | ||
| 276 | |||
| 277 | struct InputParameters { | ||
| 278 | android::Fence fence; | ||
| 279 | Common::Rectangle<s32> crop_region; | ||
| 280 | u32 window_transform; | ||
| 281 | s32 swap_interval; | ||
| 282 | u64 layer_id; | ||
| 283 | s64 surface_id; | ||
| 284 | }; | ||
| 285 | static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); | ||
| 286 | |||
| 287 | IPC::RequestParser rp{ctx}; | ||
| 288 | auto input = rp.PopRaw<InputParameters>(); | ||
| 289 | |||
| 290 | const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||
| 291 | input.fence, input.crop_region, input.window_transform, input.swap_interval, | ||
| 292 | input.layer_id, input.surface_id); | ||
| 293 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 294 | rb.Push(result); | ||
| 295 | } | ||
| 296 | |||
| 189 | void SetLayerZ(HLERequestContext& ctx) { | 297 | void SetLayerZ(HLERequestContext& ctx) { |
| 190 | IPC::RequestParser rp{ctx}; | 298 | IPC::RequestParser rp{ctx}; |
| 191 | const u64 layer_id = rp.Pop<u64>(); | 299 | const u64 layer_id = rp.Pop<u64>(); |
| @@ -228,6 +336,9 @@ private: | |||
| 228 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. | 336 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. |
| 229 | rb.Push<u32>(0); | 337 | rb.Push<u32>(0); |
| 230 | } | 338 | } |
| 339 | |||
| 340 | private: | ||
| 341 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 231 | }; | 342 | }; |
| 232 | 343 | ||
| 233 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | 344 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { |
| @@ -453,7 +564,7 @@ private: | |||
| 453 | 564 | ||
| 454 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 565 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 455 | rb.Push(ResultSuccess); | 566 | rb.Push(ResultSuccess); |
| 456 | rb.PushIpcInterface<ISystemDisplayService>(system); | 567 | rb.PushIpcInterface<ISystemDisplayService>(system, nv_flinger); |
| 457 | } | 568 | } |
| 458 | 569 | ||
| 459 | void GetManagerDisplayService(HLERequestContext& ctx) { | 570 | void GetManagerDisplayService(HLERequestContext& ctx) { |
diff --git a/src/input_common/drivers/virtual_gamepad.h b/src/input_common/drivers/virtual_gamepad.h index dfbc45a28..3a40e3fd3 100644 --- a/src/input_common/drivers/virtual_gamepad.h +++ b/src/input_common/drivers/virtual_gamepad.h | |||
| @@ -67,7 +67,7 @@ public: | |||
| 67 | * @param player_index the player number that will take this action | 67 | * @param player_index the player number that will take this action |
| 68 | * @param delta_timestamp time passed since last reading | 68 | * @param delta_timestamp time passed since last reading |
| 69 | * @param gyro_x,gyro_y,gyro_z the gyro sensor readings | 69 | * @param gyro_x,gyro_y,gyro_z the gyro sensor readings |
| 70 | * @param accel_x,accel_y,accel_z the acelerometer reading | 70 | * @param accel_x,accel_y,accel_z the accelerometer reading |
| 71 | */ | 71 | */ |
| 72 | void SetMotionState(std::size_t player_index, u64 delta_timestamp, float gyro_x, float gyro_y, | 72 | void SetMotionState(std::size_t player_index, u64 delta_timestamp, float gyro_x, float gyro_y, |
| 73 | float gyro_z, float accel_x, float accel_y, float accel_z); | 73 | float gyro_z, float accel_x, float accel_y, float accel_z); |
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.h b/src/input_common/helpers/joycon_protocol/generic_functions.h index 90fcd17f6..b94567f82 100644 --- a/src/input_common/helpers/joycon_protocol/generic_functions.h +++ b/src/input_common/helpers/joycon_protocol/generic_functions.h | |||
| @@ -55,7 +55,7 @@ public: | |||
| 55 | 55 | ||
| 56 | /** | 56 | /** |
| 57 | * Configures the motion sensor with the specified parameters | 57 | * Configures the motion sensor with the specified parameters |
| 58 | * @param gsen gyroscope sensor sensitvity in degrees per second | 58 | * @param gsen gyroscope sensor sensitivity in degrees per second |
| 59 | * @param gfrec gyroscope sensor frequency in hertz | 59 | * @param gfrec gyroscope sensor frequency in hertz |
| 60 | * @param asen accelerometer sensitivity in G force | 60 | * @param asen accelerometer sensitivity in G force |
| 61 | * @param afrec accelerometer frequency in hertz | 61 | * @param afrec accelerometer frequency in hertz |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp index d508ee567..4e8ba4ae6 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp | |||
| @@ -55,7 +55,7 @@ void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, Objec | |||
| 55 | "MOV.{} {}.{},{};", | 55 | "MOV.{} {}.{},{};", |
| 56 | type, ret, composite, type, ret, swizzle, object); | 56 | type, ret, composite, type, ret, swizzle, object); |
| 57 | } else { | 57 | } else { |
| 58 | // The return value is alised so we can just insert the object, it doesn't matter if it's | 58 | // The return value is aliased so we can just insert the object, it doesn't matter if it's |
| 59 | // aliased | 59 | // aliased |
| 60 | ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object); | 60 | ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object); |
| 61 | } | 61 | } |
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h index c9fab2d90..e46a8fa5c 100644 --- a/src/video_core/dma_pusher.h +++ b/src/video_core/dma_pusher.h | |||
| @@ -161,7 +161,7 @@ private: | |||
| 161 | u32 method_count; ///< Current method count | 161 | u32 method_count; ///< Current method count |
| 162 | u32 length_pending; ///< Large NI command length pending | 162 | u32 length_pending; ///< Large NI command length pending |
| 163 | GPUVAddr dma_get; ///< Currently read segment | 163 | GPUVAddr dma_get; ///< Currently read segment |
| 164 | u64 dma_word_offset; ///< Current word ofset from address | 164 | u64 dma_word_offset; ///< Current word offset from address |
| 165 | bool non_incrementing; ///< Current command's NI flag | 165 | bool non_incrementing; ///< Current command's NI flag |
| 166 | bool is_last_call; | 166 | bool is_last_call; |
| 167 | }; | 167 | }; |
diff --git a/src/video_core/query_cache/bank_base.h b/src/video_core/query_cache/bank_base.h index 420927091..44769ea97 100644 --- a/src/video_core/query_cache/bank_base.h +++ b/src/video_core/query_cache/bank_base.h | |||
| @@ -82,6 +82,7 @@ public: | |||
| 82 | size_t new_index = bank_indices.front(); | 82 | size_t new_index = bank_indices.front(); |
| 83 | bank_indices.pop_front(); | 83 | bank_indices.pop_front(); |
| 84 | bank_pool[new_index].Reset(); | 84 | bank_pool[new_index].Reset(); |
| 85 | bank_indices.push_back(new_index); | ||
| 85 | return new_index; | 86 | return new_index; |
| 86 | } | 87 | } |
| 87 | size_t new_index = bank_pool.size(); | 88 | size_t new_index = bank_pool.size(); |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index c7dc7e0a1..5ea9e2378 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -116,6 +116,7 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB | |||
| 116 | {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT | 116 | {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT |
| 117 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT | 117 | {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT |
| 118 | {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM | 118 | {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM |
| 119 | {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8}, // X8_D24_UNORM | ||
| 119 | {GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT | 120 | {GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT |
| 120 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT | 121 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT |
| 121 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM | 122 | {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 208e88533..a08f2f67f 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -214,8 +214,9 @@ struct FormatTuple { | |||
| 214 | {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT | 214 | {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT |
| 215 | 215 | ||
| 216 | // Depth formats | 216 | // Depth formats |
| 217 | {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT | 217 | {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT |
| 218 | {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM | 218 | {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM |
| 219 | {VK_FORMAT_X8_D24_UNORM_PACK32, Attachable}, // X8_D24_UNORM | ||
| 219 | 220 | ||
| 220 | // Stencil formats | 221 | // Stencil formats |
| 221 | {VK_FORMAT_S8_UINT, Attachable}, // S8_UINT | 222 | {VK_FORMAT_S8_UINT, Attachable}, // S8_UINT |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 31928bb94..52fc142d1 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -96,6 +96,7 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) { | |||
| 96 | VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { | 96 | VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { |
| 97 | switch (framebuffer.pixel_format) { | 97 | switch (framebuffer.pixel_format) { |
| 98 | case Service::android::PixelFormat::Rgba8888: | 98 | case Service::android::PixelFormat::Rgba8888: |
| 99 | case Service::android::PixelFormat::Rgbx8888: | ||
| 99 | return VK_FORMAT_A8B8G8R8_UNORM_PACK32; | 100 | return VK_FORMAT_A8B8G8R8_UNORM_PACK32; |
| 100 | case Service::android::PixelFormat::Rgb565: | 101 | case Service::android::PixelFormat::Rgb565: |
| 101 | return VK_FORMAT_R5G6B5_UNORM_PACK16; | 102 | return VK_FORMAT_R5G6B5_UNORM_PACK16; |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 17b2587ad..2edaafa7e 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp | |||
| @@ -506,6 +506,7 @@ private: | |||
| 506 | SetAccumulationValue(query->value); | 506 | SetAccumulationValue(query->value); |
| 507 | Free(index); | 507 | Free(index); |
| 508 | }); | 508 | }); |
| 509 | rasterizer->SyncOperation(std::move(func)); | ||
| 509 | } | 510 | } |
| 510 | 511 | ||
| 511 | template <bool is_resolve> | 512 | template <bool is_resolve> |
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index ce92f66ab..b278614e6 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp | |||
| @@ -24,25 +24,38 @@ using namespace Common::Literals; | |||
| 24 | 24 | ||
| 25 | // Maximum potential alignment of a Vulkan buffer | 25 | // Maximum potential alignment of a Vulkan buffer |
| 26 | constexpr VkDeviceSize MAX_ALIGNMENT = 256; | 26 | constexpr VkDeviceSize MAX_ALIGNMENT = 256; |
| 27 | // Maximum size to put elements in the stream buffer | ||
| 28 | constexpr VkDeviceSize MAX_STREAM_BUFFER_REQUEST_SIZE = 8_MiB; | ||
| 29 | // Stream buffer size in bytes | 27 | // Stream buffer size in bytes |
| 30 | constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; | 28 | constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB; |
| 31 | constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS; | ||
| 32 | 29 | ||
| 33 | size_t Region(size_t iterator) noexcept { | 30 | size_t GetStreamBufferSize(const Device& device) { |
| 34 | return iterator / REGION_SIZE; | 31 | VkDeviceSize size{0}; |
| 32 | if (device.HasDebuggingToolAttached()) { | ||
| 33 | ForEachDeviceLocalHostVisibleHeap(device, [&size](size_t index, VkMemoryHeap& heap) { | ||
| 34 | size = std::max(size, heap.size); | ||
| 35 | }); | ||
| 36 | // If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be | ||
| 37 | // loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue | ||
| 38 | // as the heap will be much larger. | ||
| 39 | if (size <= 256_MiB) { | ||
| 40 | size = size * 40 / 100; | ||
| 41 | } | ||
| 42 | } else { | ||
| 43 | size = MAX_STREAM_BUFFER_SIZE; | ||
| 44 | } | ||
| 45 | return std::min(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE); | ||
| 35 | } | 46 | } |
| 36 | } // Anonymous namespace | 47 | } // Anonymous namespace |
| 37 | 48 | ||
| 38 | StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, | 49 | StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, |
| 39 | Scheduler& scheduler_) | 50 | Scheduler& scheduler_) |
| 40 | : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} { | 51 | : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, |
| 52 | stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size / | ||
| 53 | StagingBufferPool::NUM_SYNCS} { | ||
| 41 | VkBufferCreateInfo stream_ci = { | 54 | VkBufferCreateInfo stream_ci = { |
| 42 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 55 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 43 | .pNext = nullptr, | 56 | .pNext = nullptr, |
| 44 | .flags = 0, | 57 | .flags = 0, |
| 45 | .size = STREAM_BUFFER_SIZE, | 58 | .size = stream_buffer_size, |
| 46 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | | 59 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | |
| 47 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, | 60 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, |
| 48 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 61 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| @@ -63,7 +76,7 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem | |||
| 63 | StagingBufferPool::~StagingBufferPool() = default; | 76 | StagingBufferPool::~StagingBufferPool() = default; |
| 64 | 77 | ||
| 65 | StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) { | 78 | StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) { |
| 66 | if (!deferred && usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) { | 79 | if (!deferred && usage == MemoryUsage::Upload && size <= region_size) { |
| 67 | return GetStreamBuffer(size); | 80 | return GetStreamBuffer(size); |
| 68 | } | 81 | } |
| 69 | return GetStagingBuffer(size, usage, deferred); | 82 | return GetStagingBuffer(size, usage, deferred); |
| @@ -101,7 +114,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { | |||
| 101 | used_iterator = iterator; | 114 | used_iterator = iterator; |
| 102 | free_iterator = std::max(free_iterator, iterator + size); | 115 | free_iterator = std::max(free_iterator, iterator + size); |
| 103 | 116 | ||
| 104 | if (iterator + size >= STREAM_BUFFER_SIZE) { | 117 | if (iterator + size >= stream_buffer_size) { |
| 105 | std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, | 118 | std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, |
| 106 | current_tick); | 119 | current_tick); |
| 107 | used_iterator = 0; | 120 | used_iterator = 0; |
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h index 5f69f08b1..d3deb9072 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h | |||
| @@ -90,6 +90,9 @@ private: | |||
| 90 | void ReleaseCache(MemoryUsage usage); | 90 | void ReleaseCache(MemoryUsage usage); |
| 91 | 91 | ||
| 92 | void ReleaseLevel(StagingBuffersCache& cache, size_t log2); | 92 | void ReleaseLevel(StagingBuffersCache& cache, size_t log2); |
| 93 | size_t Region(size_t iter) const noexcept { | ||
| 94 | return iter / region_size; | ||
| 95 | } | ||
| 93 | 96 | ||
| 94 | const Device& device; | 97 | const Device& device; |
| 95 | MemoryAllocator& memory_allocator; | 98 | MemoryAllocator& memory_allocator; |
| @@ -97,6 +100,8 @@ private: | |||
| 97 | 100 | ||
| 98 | vk::Buffer stream_buffer; | 101 | vk::Buffer stream_buffer; |
| 99 | std::span<u8> stream_pointer; | 102 | std::span<u8> stream_pointer; |
| 103 | VkDeviceSize stream_buffer_size; | ||
| 104 | VkDeviceSize region_size; | ||
| 100 | 105 | ||
| 101 | size_t iterator = 0; | 106 | size_t iterator = 0; |
| 102 | size_t used_iterator = 0; | 107 | size_t used_iterator = 0; |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 71fdec809..e266c1dbe 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -238,6 +238,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 238 | return any_r ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; | 238 | return any_r ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; |
| 239 | case PixelFormat::D16_UNORM: | 239 | case PixelFormat::D16_UNORM: |
| 240 | case PixelFormat::D32_FLOAT: | 240 | case PixelFormat::D32_FLOAT: |
| 241 | case PixelFormat::X8_D24_UNORM: | ||
| 241 | return VK_IMAGE_ASPECT_DEPTH_BIT; | 242 | return VK_IMAGE_ASPECT_DEPTH_BIT; |
| 242 | case PixelFormat::S8_UINT: | 243 | case PixelFormat::S8_UINT: |
| 243 | return VK_IMAGE_ASPECT_STENCIL_BIT; | 244 | return VK_IMAGE_ASPECT_STENCIL_BIT; |
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index e16cd5e73..5b3c7aa5a 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp | |||
| @@ -85,6 +85,8 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { | |||
| 85 | return PixelFormat::S8_UINT; | 85 | return PixelFormat::S8_UINT; |
| 86 | case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT: | 86 | case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT: |
| 87 | return PixelFormat::D32_FLOAT_S8_UINT; | 87 | return PixelFormat::D32_FLOAT_S8_UINT; |
| 88 | case Tegra::DepthFormat::X8Z24_UNORM: | ||
| 89 | return PixelFormat::X8_D24_UNORM; | ||
| 88 | default: | 90 | default: |
| 89 | UNIMPLEMENTED_MSG("Unimplemented format={}", format); | 91 | UNIMPLEMENTED_MSG("Unimplemented format={}", format); |
| 90 | return PixelFormat::S8_UINT_D24_UNORM; | 92 | return PixelFormat::S8_UINT_D24_UNORM; |
| @@ -202,6 +204,7 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) | |||
| 202 | PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format) { | 204 | PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format) { |
| 203 | switch (format) { | 205 | switch (format) { |
| 204 | case Service::android::PixelFormat::Rgba8888: | 206 | case Service::android::PixelFormat::Rgba8888: |
| 207 | case Service::android::PixelFormat::Rgbx8888: | ||
| 205 | return PixelFormat::A8B8G8R8_UNORM; | 208 | return PixelFormat::A8B8G8R8_UNORM; |
| 206 | case Service::android::PixelFormat::Rgb565: | 209 | case Service::android::PixelFormat::Rgb565: |
| 207 | return PixelFormat::R5G6B5_UNORM; | 210 | return PixelFormat::R5G6B5_UNORM; |
diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 9b9c4d9bc..a5e8e2f62 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h | |||
| @@ -115,6 +115,7 @@ enum class PixelFormat { | |||
| 115 | // Depth formats | 115 | // Depth formats |
| 116 | D32_FLOAT = MaxColorFormat, | 116 | D32_FLOAT = MaxColorFormat, |
| 117 | D16_UNORM, | 117 | D16_UNORM, |
| 118 | X8_D24_UNORM, | ||
| 118 | 119 | ||
| 119 | MaxDepthFormat, | 120 | MaxDepthFormat, |
| 120 | 121 | ||
| @@ -251,6 +252,7 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_WIDTH_TABLE = {{ | |||
| 251 | 1, // E5B9G9R9_FLOAT | 252 | 1, // E5B9G9R9_FLOAT |
| 252 | 1, // D32_FLOAT | 253 | 1, // D32_FLOAT |
| 253 | 1, // D16_UNORM | 254 | 1, // D16_UNORM |
| 255 | 1, // X8_D24_UNORM | ||
| 254 | 1, // S8_UINT | 256 | 1, // S8_UINT |
| 255 | 1, // D24_UNORM_S8_UINT | 257 | 1, // D24_UNORM_S8_UINT |
| 256 | 1, // S8_UINT_D24_UNORM | 258 | 1, // S8_UINT_D24_UNORM |
| @@ -360,6 +362,7 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_HEIGHT_TABLE = {{ | |||
| 360 | 1, // E5B9G9R9_FLOAT | 362 | 1, // E5B9G9R9_FLOAT |
| 361 | 1, // D32_FLOAT | 363 | 1, // D32_FLOAT |
| 362 | 1, // D16_UNORM | 364 | 1, // D16_UNORM |
| 365 | 1, // X8_D24_UNORM | ||
| 363 | 1, // S8_UINT | 366 | 1, // S8_UINT |
| 364 | 1, // D24_UNORM_S8_UINT | 367 | 1, // D24_UNORM_S8_UINT |
| 365 | 1, // S8_UINT_D24_UNORM | 368 | 1, // S8_UINT_D24_UNORM |
| @@ -469,6 +472,7 @@ constexpr std::array<u8, MaxPixelFormat> BITS_PER_BLOCK_TABLE = {{ | |||
| 469 | 32, // E5B9G9R9_FLOAT | 472 | 32, // E5B9G9R9_FLOAT |
| 470 | 32, // D32_FLOAT | 473 | 32, // D32_FLOAT |
| 471 | 16, // D16_UNORM | 474 | 16, // D16_UNORM |
| 475 | 32, // X8_D24_UNORM | ||
| 472 | 8, // S8_UINT | 476 | 8, // S8_UINT |
| 473 | 32, // D24_UNORM_S8_UINT | 477 | 32, // D24_UNORM_S8_UINT |
| 474 | 32, // S8_UINT_D24_UNORM | 478 | 32, // S8_UINT_D24_UNORM |
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp index 56307d030..3162c8f5e 100644 --- a/src/video_core/texture_cache/format_lookup_table.cpp +++ b/src/video_core/texture_cache/format_lookup_table.cpp | |||
| @@ -142,6 +142,10 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red, | |||
| 142 | return PixelFormat::D16_UNORM; | 142 | return PixelFormat::D16_UNORM; |
| 143 | case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR): | 143 | case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR): |
| 144 | return PixelFormat::D16_UNORM; | 144 | return PixelFormat::D16_UNORM; |
| 145 | case Hash(TextureFormat::X8Z24, UNORM): | ||
| 146 | return PixelFormat::X8_D24_UNORM; | ||
| 147 | case Hash(TextureFormat::X8Z24, UNORM, UINT, UINT, UINT, LINEAR): | ||
| 148 | return PixelFormat::X8_D24_UNORM; | ||
| 145 | case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR): | 149 | case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR): |
| 146 | return PixelFormat::S8_UINT_D24_UNORM; | 150 | return PixelFormat::S8_UINT_D24_UNORM; |
| 147 | case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR): | 151 | case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR): |
diff --git a/src/video_core/texture_cache/formatter.h b/src/video_core/texture_cache/formatter.h index 9ee57a076..cabbfcb2d 100644 --- a/src/video_core/texture_cache/formatter.h +++ b/src/video_core/texture_cache/formatter.h | |||
| @@ -211,6 +211,8 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str | |||
| 211 | return "D32_FLOAT"; | 211 | return "D32_FLOAT"; |
| 212 | case PixelFormat::D16_UNORM: | 212 | case PixelFormat::D16_UNORM: |
| 213 | return "D16_UNORM"; | 213 | return "D16_UNORM"; |
| 214 | case PixelFormat::X8_D24_UNORM: | ||
| 215 | return "X8_D24_UNORM"; | ||
| 214 | case PixelFormat::S8_UINT: | 216 | case PixelFormat::S8_UINT: |
| 215 | return "S8_UINT"; | 217 | return "S8_UINT"; |
| 216 | case PixelFormat::D24_UNORM_S8_UINT: | 218 | case PixelFormat::D24_UNORM_S8_UINT: |
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 55d49d017..0587d7b72 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h | |||
| @@ -41,7 +41,7 @@ enum class ImageFlagBits : u32 { | |||
| 41 | IsRescalable = 1 << 15, | 41 | IsRescalable = 1 << 15, |
| 42 | 42 | ||
| 43 | AsynchronousDecode = 1 << 16, | 43 | AsynchronousDecode = 1 << 16, |
| 44 | IsDecoding = 1 << 17, ///< Is currently being decoded asynchornously. | 44 | IsDecoding = 1 << 17, ///< Is currently being decoded asynchronously. |
| 45 | }; | 45 | }; |
| 46 | DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) | 46 | DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) |
| 47 | 47 | ||
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index 0c5f4450d..18b9250f9 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp | |||
| @@ -85,6 +85,7 @@ bool ImageViewBase::SupportsAnisotropy() const noexcept { | |||
| 85 | // Depth formats | 85 | // Depth formats |
| 86 | case PixelFormat::D32_FLOAT: | 86 | case PixelFormat::D32_FLOAT: |
| 87 | case PixelFormat::D16_UNORM: | 87 | case PixelFormat::D16_UNORM: |
| 88 | case PixelFormat::X8_D24_UNORM: | ||
| 88 | // Stencil formats | 89 | // Stencil formats |
| 89 | case PixelFormat::S8_UINT: | 90 | case PixelFormat::S8_UINT: |
| 90 | // DepthStencil formats | 91 | // DepthStencil formats |
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index a83f5d41c..0a86ce139 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -1195,7 +1195,7 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const | |||
| 1195 | return std::nullopt; | 1195 | return std::nullopt; |
| 1196 | } | 1196 | } |
| 1197 | } else { | 1197 | } else { |
| 1198 | // Format comaptibility is not relaxed, ensure we are creating a view on a compatible format | 1198 | // Format compatibility is not relaxed, ensure we are creating a view on a compatible format |
| 1199 | if (!IsViewCompatible(existing.format, candidate.format, broken_views, native_bgr)) { | 1199 | if (!IsViewCompatible(existing.format, candidate.format, broken_views, native_bgr)) { |
| 1200 | return std::nullopt; | 1200 | return std::nullopt; |
| 1201 | } | 1201 | } |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 3960b135a..876cec2e8 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -84,9 +84,12 @@ constexpr std::array VK_FORMAT_A4B4G4R4_UNORM_PACK16{ | |||
| 84 | } // namespace Alternatives | 84 | } // namespace Alternatives |
| 85 | 85 | ||
| 86 | enum class NvidiaArchitecture { | 86 | enum class NvidiaArchitecture { |
| 87 | AmpereOrNewer, | 87 | KeplerOrOlder, |
| 88 | Maxwell, | ||
| 89 | Pascal, | ||
| 90 | Volta, | ||
| 88 | Turing, | 91 | Turing, |
| 89 | VoltaOrOlder, | 92 | AmpereOrNewer, |
| 90 | }; | 93 | }; |
| 91 | 94 | ||
| 92 | template <typename T> | 95 | template <typename T> |
| @@ -200,6 +203,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica | |||
| 200 | VK_FORMAT_BC7_UNORM_BLOCK, | 203 | VK_FORMAT_BC7_UNORM_BLOCK, |
| 201 | VK_FORMAT_D16_UNORM, | 204 | VK_FORMAT_D16_UNORM, |
| 202 | VK_FORMAT_D16_UNORM_S8_UINT, | 205 | VK_FORMAT_D16_UNORM_S8_UINT, |
| 206 | VK_FORMAT_X8_D24_UNORM_PACK32, | ||
| 203 | VK_FORMAT_D24_UNORM_S8_UINT, | 207 | VK_FORMAT_D24_UNORM_S8_UINT, |
| 204 | VK_FORMAT_D32_SFLOAT, | 208 | VK_FORMAT_D32_SFLOAT, |
| 205 | VK_FORMAT_D32_SFLOAT_S8_UINT, | 209 | VK_FORMAT_D32_SFLOAT_S8_UINT, |
| @@ -321,13 +325,38 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, | |||
| 321 | physical.GetProperties2(physical_properties); | 325 | physical.GetProperties2(physical_properties); |
| 322 | if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) { | 326 | if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) { |
| 323 | // Only Ampere and newer support this feature | 327 | // Only Ampere and newer support this feature |
| 328 | // TODO: Find a way to differentiate Ampere and Ada | ||
| 324 | return NvidiaArchitecture::AmpereOrNewer; | 329 | return NvidiaArchitecture::AmpereOrNewer; |
| 325 | } | 330 | } |
| 326 | } | ||
| 327 | if (exts.contains(VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME)) { | ||
| 328 | return NvidiaArchitecture::Turing; | 331 | return NvidiaArchitecture::Turing; |
| 329 | } | 332 | } |
| 330 | return NvidiaArchitecture::VoltaOrOlder; | 333 | |
| 334 | if (exts.contains(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME)) { | ||
| 335 | VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT advanced_blending_props{}; | ||
| 336 | advanced_blending_props.sType = | ||
| 337 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT; | ||
| 338 | VkPhysicalDeviceProperties2 physical_properties{}; | ||
| 339 | physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; | ||
| 340 | physical_properties.pNext = &advanced_blending_props; | ||
| 341 | physical.GetProperties2(physical_properties); | ||
| 342 | if (advanced_blending_props.advancedBlendMaxColorAttachments == 1) { | ||
| 343 | return NvidiaArchitecture::Maxwell; | ||
| 344 | } | ||
| 345 | |||
| 346 | if (exts.contains(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME)) { | ||
| 347 | VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_raster_props{}; | ||
| 348 | conservative_raster_props.sType = | ||
| 349 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT; | ||
| 350 | physical_properties.pNext = &conservative_raster_props; | ||
| 351 | physical.GetProperties2(physical_properties); | ||
| 352 | if (conservative_raster_props.degenerateLinesRasterized) { | ||
| 353 | return NvidiaArchitecture::Volta; | ||
| 354 | } | ||
| 355 | return NvidiaArchitecture::Pascal; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | return NvidiaArchitecture::KeplerOrOlder; | ||
| 331 | } | 360 | } |
| 332 | 361 | ||
| 333 | std::vector<const char*> ExtensionListForVulkan( | 362 | std::vector<const char*> ExtensionListForVulkan( |
| @@ -504,19 +533,14 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 504 | if (is_nvidia) { | 533 | if (is_nvidia) { |
| 505 | const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; | 534 | const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; |
| 506 | const auto arch = GetNvidiaArchitecture(physical, supported_extensions); | 535 | const auto arch = GetNvidiaArchitecture(physical, supported_extensions); |
| 507 | switch (arch) { | 536 | if (arch >= NvidiaArchitecture::AmpereOrNewer) { |
| 508 | case NvidiaArchitecture::AmpereOrNewer: | ||
| 509 | LOG_WARNING(Render_Vulkan, "Ampere and newer have broken float16 math"); | 537 | LOG_WARNING(Render_Vulkan, "Ampere and newer have broken float16 math"); |
| 510 | features.shader_float16_int8.shaderFloat16 = false; | 538 | features.shader_float16_int8.shaderFloat16 = false; |
| 511 | break; | 539 | } else if (arch <= NvidiaArchitecture::Volta) { |
| 512 | case NvidiaArchitecture::Turing: | ||
| 513 | break; | ||
| 514 | case NvidiaArchitecture::VoltaOrOlder: | ||
| 515 | if (nv_major_version < 527) { | 540 | if (nv_major_version < 527) { |
| 516 | LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor"); | 541 | LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor"); |
| 517 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | 542 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| 518 | } | 543 | } |
| 519 | break; | ||
| 520 | } | 544 | } |
| 521 | if (nv_major_version >= 510) { | 545 | if (nv_major_version >= 510) { |
| 522 | LOG_WARNING(Render_Vulkan, "NVIDIA Drivers >= 510 do not support MSAA image blits"); | 546 | LOG_WARNING(Render_Vulkan, "NVIDIA Drivers >= 510 do not support MSAA image blits"); |
| @@ -661,7 +685,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 661 | "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor"); | 685 | "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor"); |
| 662 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | 686 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| 663 | } | 687 | } |
| 688 | } else if (extensions.push_descriptor && is_nvidia) { | ||
| 689 | const auto arch = GetNvidiaArchitecture(physical, supported_extensions); | ||
| 690 | if (arch <= NvidiaArchitecture::Pascal) { | ||
| 691 | LOG_WARNING(Render_Vulkan, | ||
| 692 | "Pascal and older architectures have broken VK_KHR_push_descriptor"); | ||
| 693 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | ||
| 694 | } | ||
| 664 | } | 695 | } |
| 696 | |||
| 665 | if (is_mvk) { | 697 | if (is_mvk) { |
| 666 | LOG_WARNING(Render_Vulkan, | 698 | LOG_WARNING(Render_Vulkan, |
| 667 | "MVK driver breaks when using more than 16 vertex attributes/bindings"); | 699 | "MVK driver breaks when using more than 16 vertex attributes/bindings"); |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 9be612392..282a2925d 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -314,7 +314,7 @@ public: | |||
| 314 | return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; | 314 | return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | /// Returns true if the device suppors float64 natively. | 317 | /// Returns true if the device supports float64 natively. |
| 318 | bool IsFloat64Supported() const { | 318 | bool IsFloat64Supported() const { |
| 319 | return features.features.shaderFloat64; | 319 | return features.features.shaderFloat64; |
| 320 | } | 320 | } |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 3ef381a38..82767fdf0 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/alignment.h" | 9 | #include "common/alignment.h" |
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/literals.h" | ||
| 12 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 13 | #include "common/polyfill_ranges.h" | 14 | #include "common/polyfill_ranges.h" |
| 14 | #include "video_core/vulkan_common/vma.h" | 15 | #include "video_core/vulkan_common/vma.h" |
| @@ -69,8 +70,7 @@ struct Range { | |||
| 69 | case MemoryUsage::Download: | 70 | case MemoryUsage::Download: |
| 70 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; | 71 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; |
| 71 | case MemoryUsage::DeviceLocal: | 72 | case MemoryUsage::DeviceLocal: |
| 72 | return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | | 73 | return {}; |
| 73 | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT; | ||
| 74 | } | 74 | } |
| 75 | return {}; | 75 | return {}; |
| 76 | } | 76 | } |
| @@ -212,7 +212,20 @@ MemoryAllocator::MemoryAllocator(const Device& device_) | |||
| 212 | : device{device_}, allocator{device.GetAllocator()}, | 212 | : device{device_}, allocator{device.GetAllocator()}, |
| 213 | properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, | 213 | properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, |
| 214 | buffer_image_granularity{ | 214 | buffer_image_granularity{ |
| 215 | device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} | 215 | device_.GetPhysical().GetProperties().limits.bufferImageGranularity} { |
| 216 | // GPUs not supporting rebar may only have a region with less than 256MB host visible/device | ||
| 217 | // local memory. In that case, opening 2 RenderDoc captures side-by-side is not possible due to | ||
| 218 | // the heap running out of memory. With RenderDoc attached and only a small host/device region, | ||
| 219 | // only allow the stream buffer in this memory heap. | ||
| 220 | if (device.HasDebuggingToolAttached()) { | ||
| 221 | using namespace Common::Literals; | ||
| 222 | ForEachDeviceLocalHostVisibleHeap(device, [this](size_t index, VkMemoryHeap& heap) { | ||
| 223 | if (heap.size <= 256_MiB) { | ||
| 224 | valid_memory_types &= ~(1u << index); | ||
| 225 | } | ||
| 226 | }); | ||
| 227 | } | ||
| 228 | } | ||
| 216 | 229 | ||
| 217 | MemoryAllocator::~MemoryAllocator() = default; | 230 | MemoryAllocator::~MemoryAllocator() = default; |
| 218 | 231 | ||
| @@ -244,7 +257,7 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsa | |||
| 244 | .usage = MemoryUsageVma(usage), | 257 | .usage = MemoryUsageVma(usage), |
| 245 | .requiredFlags = 0, | 258 | .requiredFlags = 0, |
| 246 | .preferredFlags = MemoryUsagePreferedVmaFlags(usage), | 259 | .preferredFlags = MemoryUsagePreferedVmaFlags(usage), |
| 247 | .memoryTypeBits = 0, | 260 | .memoryTypeBits = usage == MemoryUsage::Stream ? 0u : valid_memory_types, |
| 248 | .pool = VK_NULL_HANDLE, | 261 | .pool = VK_NULL_HANDLE, |
| 249 | .pUserData = nullptr, | 262 | .pUserData = nullptr, |
| 250 | .priority = 0.f, | 263 | .priority = 0.f, |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h index f449bc8d0..38a182bcb 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.h +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <span> | 7 | #include <span> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 10 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 11 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 11 | 12 | ||
| 12 | VK_DEFINE_HANDLE(VmaAllocator) | 13 | VK_DEFINE_HANDLE(VmaAllocator) |
| @@ -26,6 +27,18 @@ enum class MemoryUsage { | |||
| 26 | Stream, ///< Requests device local host visible buffer, falling back host memory. | 27 | Stream, ///< Requests device local host visible buffer, falling back host memory. |
| 27 | }; | 28 | }; |
| 28 | 29 | ||
| 30 | template <typename F> | ||
| 31 | void ForEachDeviceLocalHostVisibleHeap(const Device& device, F&& f) { | ||
| 32 | auto memory_props = device.GetPhysical().GetMemoryProperties().memoryProperties; | ||
| 33 | for (size_t i = 0; i < memory_props.memoryTypeCount; i++) { | ||
| 34 | auto& memory_type = memory_props.memoryTypes[i]; | ||
| 35 | if ((memory_type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) && | ||
| 36 | (memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { | ||
| 37 | f(memory_type.heapIndex, memory_props.memoryHeaps[memory_type.heapIndex]); | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 29 | /// Ownership handle of a memory commitment. | 42 | /// Ownership handle of a memory commitment. |
| 30 | /// Points to a subregion of a memory allocation. | 43 | /// Points to a subregion of a memory allocation. |
| 31 | class MemoryCommit { | 44 | class MemoryCommit { |
| @@ -124,6 +137,7 @@ private: | |||
| 124 | std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. | 137 | std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. |
| 125 | VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers | 138 | VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers |
| 126 | // and optimal images | 139 | // and optimal images |
| 140 | u32 valid_memory_types{~0u}; | ||
| 127 | }; | 141 | }; |
| 128 | 142 | ||
| 129 | } // namespace Vulkan | 143 | } // namespace Vulkan |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 9ccfb2435..81dd51ad3 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -42,6 +42,9 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 42 | for (auto* setting : Settings::values.linkage.by_category[category]) { | 42 | for (auto* setting : Settings::values.linkage.by_category[category]) { |
| 43 | settings.push_back(setting); | 43 | settings.push_back(setting); |
| 44 | } | 44 | } |
| 45 | for (auto* setting : UISettings::values.linkage.by_category[category]) { | ||
| 46 | settings.push_back(setting); | ||
| 47 | } | ||
| 45 | }; | 48 | }; |
| 46 | 49 | ||
| 47 | push(Settings::Category::Audio); | 50 | push(Settings::Category::Audio); |
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp index 276bdbaba..a4e8af1b4 100644 --- a/src/yuzu/configuration/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp | |||
| @@ -29,9 +29,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) { | |||
| 29 | INSERT(Settings, sink_id, "Output Engine:", ""); | 29 | INSERT(Settings, sink_id, "Output Engine:", ""); |
| 30 | INSERT(Settings, audio_output_device_id, "Output Device:", ""); | 30 | INSERT(Settings, audio_output_device_id, "Output Device:", ""); |
| 31 | INSERT(Settings, audio_input_device_id, "Input Device:", ""); | 31 | INSERT(Settings, audio_input_device_id, "Input Device:", ""); |
| 32 | INSERT(Settings, audio_muted, "Mute audio when in background", ""); | 32 | INSERT(Settings, audio_muted, "Mute audio", ""); |
| 33 | INSERT(Settings, volume, "Volume:", ""); | 33 | INSERT(Settings, volume, "Volume:", ""); |
| 34 | INSERT(Settings, dump_audio_commands, "", ""); | 34 | INSERT(Settings, dump_audio_commands, "", ""); |
| 35 | INSERT(UISettings, mute_when_in_background, "Mute audio when in background", ""); | ||
| 35 | 36 | ||
| 36 | // Core | 37 | // Core |
| 37 | INSERT(Settings, use_multi_core, "Multicore CPU Emulation", ""); | 38 | INSERT(Settings, use_multi_core, "Multicore CPU Emulation", ""); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index adb7b332f..1753fec12 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include <sys/socket.h> | 18 | #include <sys/socket.h> |
| 19 | #endif | 19 | #endif |
| 20 | 20 | ||
| 21 | #include <boost/container/flat_set.hpp> | ||
| 22 | |||
| 21 | // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. | 23 | // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. |
| 22 | #include "applets/qt_amiibo_settings.h" | 24 | #include "applets/qt_amiibo_settings.h" |
| 23 | #include "applets/qt_controller.h" | 25 | #include "applets/qt_controller.h" |
| @@ -1445,6 +1447,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) { | |||
| 1445 | Settings::values.audio_muted = false; | 1447 | Settings::values.audio_muted = false; |
| 1446 | auto_muted = false; | 1448 | auto_muted = false; |
| 1447 | } | 1449 | } |
| 1450 | UpdateVolumeUI(); | ||
| 1448 | } | 1451 | } |
| 1449 | } | 1452 | } |
| 1450 | 1453 | ||
| @@ -1551,6 +1554,14 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 1551 | // Tools | 1554 | // Tools |
| 1552 | connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, | 1555 | connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, |
| 1553 | ReinitializeKeyBehavior::Warning)); | 1556 | ReinitializeKeyBehavior::Warning)); |
| 1557 | connect_menu(ui->action_Load_Cabinet_Nickname_Owner, | ||
| 1558 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); }); | ||
| 1559 | connect_menu(ui->action_Load_Cabinet_Eraser, | ||
| 1560 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartGameDataEraser); }); | ||
| 1561 | connect_menu(ui->action_Load_Cabinet_Restorer, | ||
| 1562 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); }); | ||
| 1563 | connect_menu(ui->action_Load_Cabinet_Formatter, | ||
| 1564 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); }); | ||
| 1554 | connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); | 1565 | connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); |
| 1555 | connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); | 1566 | connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); |
| 1556 | 1567 | ||
| @@ -1568,6 +1579,7 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 1568 | 1579 | ||
| 1569 | void GMainWindow::UpdateMenuState() { | 1580 | void GMainWindow::UpdateMenuState() { |
| 1570 | const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning(); | 1581 | const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning(); |
| 1582 | const bool is_firmware_available = CheckFirmwarePresence(); | ||
| 1571 | 1583 | ||
| 1572 | const std::array running_actions{ | 1584 | const std::array running_actions{ |
| 1573 | ui->action_Stop, | 1585 | ui->action_Stop, |
| @@ -1578,10 +1590,22 @@ void GMainWindow::UpdateMenuState() { | |||
| 1578 | ui->action_Pause, | 1590 | ui->action_Pause, |
| 1579 | }; | 1591 | }; |
| 1580 | 1592 | ||
| 1593 | const std::array applet_actions{ | ||
| 1594 | ui->action_Load_Cabinet_Nickname_Owner, | ||
| 1595 | ui->action_Load_Cabinet_Eraser, | ||
| 1596 | ui->action_Load_Cabinet_Restorer, | ||
| 1597 | ui->action_Load_Cabinet_Formatter, | ||
| 1598 | ui->action_Load_Mii_Edit, | ||
| 1599 | }; | ||
| 1600 | |||
| 1581 | for (QAction* action : running_actions) { | 1601 | for (QAction* action : running_actions) { |
| 1582 | action->setEnabled(emulation_running); | 1602 | action->setEnabled(emulation_running); |
| 1583 | } | 1603 | } |
| 1584 | 1604 | ||
| 1605 | for (QAction* action : applet_actions) { | ||
| 1606 | action->setEnabled(is_firmware_available && !emulation_running); | ||
| 1607 | } | ||
| 1608 | |||
| 1585 | ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused); | 1609 | ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused); |
| 1586 | 1610 | ||
| 1587 | if (emulation_running && is_paused) { | 1611 | if (emulation_running && is_paused) { |
| @@ -1591,8 +1615,6 @@ void GMainWindow::UpdateMenuState() { | |||
| 1591 | } | 1615 | } |
| 1592 | 1616 | ||
| 1593 | multiplayer_state->UpdateNotificationStatus(); | 1617 | multiplayer_state->UpdateNotificationStatus(); |
| 1594 | |||
| 1595 | ui->action_Load_Mii_Edit->setEnabled(CheckFirmwarePresence()); | ||
| 1596 | } | 1618 | } |
| 1597 | 1619 | ||
| 1598 | void GMainWindow::OnDisplayTitleBars(bool show) { | 1620 | void GMainWindow::OnDisplayTitleBars(bool show) { |
| @@ -2103,6 +2125,8 @@ void GMainWindow::OnEmulationStopped() { | |||
| 2103 | OnTasStateChanged(); | 2125 | OnTasStateChanged(); |
| 2104 | render_window->FinalizeCamera(); | 2126 | render_window->FinalizeCamera(); |
| 2105 | 2127 | ||
| 2128 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::None); | ||
| 2129 | |||
| 2106 | // Enable all controllers | 2130 | // Enable all controllers |
| 2107 | system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); | 2131 | system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); |
| 2108 | 2132 | ||
| @@ -4134,6 +4158,30 @@ void GMainWindow::OnToggleStatusBar() { | |||
| 4134 | statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); | 4158 | statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); |
| 4135 | } | 4159 | } |
| 4136 | 4160 | ||
| 4161 | void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { | ||
| 4162 | constexpr u64 CabinetId = 0x0100000000001002ull; | ||
| 4163 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | ||
| 4164 | if (!bis_system) { | ||
| 4165 | QMessageBox::warning(this, tr("No firmware available"), | ||
| 4166 | tr("Please install the firmware to use the Cabinet applet.")); | ||
| 4167 | return; | ||
| 4168 | } | ||
| 4169 | |||
| 4170 | auto cabinet_nca = bis_system->GetEntry(CabinetId, FileSys::ContentRecordType::Program); | ||
| 4171 | if (!cabinet_nca) { | ||
| 4172 | QMessageBox::warning(this, tr("Cabinet Applet"), | ||
| 4173 | tr("Cabinet applet is not available. Please reinstall firmware.")); | ||
| 4174 | return; | ||
| 4175 | } | ||
| 4176 | |||
| 4177 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Cabinet); | ||
| 4178 | system->GetAppletManager().SetCabinetMode(mode); | ||
| 4179 | |||
| 4180 | const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); | ||
| 4181 | UISettings::values.roms_path = QFileInfo(filename).path(); | ||
| 4182 | BootGame(filename); | ||
| 4183 | } | ||
| 4184 | |||
| 4137 | void GMainWindow::OnMiiEdit() { | 4185 | void GMainWindow::OnMiiEdit() { |
| 4138 | constexpr u64 MiiEditId = 0x0100000000001009ull; | 4186 | constexpr u64 MiiEditId = 0x0100000000001009ull; |
| 4139 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4187 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| @@ -4150,6 +4198,8 @@ void GMainWindow::OnMiiEdit() { | |||
| 4150 | return; | 4198 | return; |
| 4151 | } | 4199 | } |
| 4152 | 4200 | ||
| 4201 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit); | ||
| 4202 | |||
| 4153 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); | 4203 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); |
| 4154 | UISettings::values.roms_path = QFileInfo(filename).path(); | 4204 | UISettings::values.roms_path = QFileInfo(filename).path(); |
| 4155 | BootGame(filename); | 4205 | BootGame(filename); |
| @@ -4602,8 +4652,8 @@ bool GMainWindow::CheckFirmwarePresence() { | |||
| 4602 | 4652 | ||
| 4603 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, | 4653 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, |
| 4604 | u64* selected_title_id, u8* selected_content_record_type) { | 4654 | u64* selected_title_id, u8* selected_content_record_type) { |
| 4605 | using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>; | 4655 | using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>; |
| 4606 | boost::container::flat_map<u64, ContentInfo> available_title_ids; | 4656 | boost::container::flat_set<ContentInfo> available_title_ids; |
| 4607 | 4657 | ||
| 4608 | const auto RetrieveEntries = [&](FileSys::TitleType title_type, | 4658 | const auto RetrieveEntries = [&](FileSys::TitleType title_type, |
| 4609 | FileSys::ContentRecordType record_type) { | 4659 | FileSys::ContentRecordType record_type) { |
| @@ -4611,12 +4661,14 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe | |||
| 4611 | for (const auto& entry : entries) { | 4661 | for (const auto& entry : entries) { |
| 4612 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id && | 4662 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id && |
| 4613 | installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) { | 4663 | installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) { |
| 4614 | available_title_ids[entry.title_id] = {title_type, record_type}; | 4664 | available_title_ids.insert({entry.title_id, title_type, record_type}); |
| 4615 | } | 4665 | } |
| 4616 | } | 4666 | } |
| 4617 | }; | 4667 | }; |
| 4618 | 4668 | ||
| 4619 | RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program); | 4669 | RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program); |
| 4670 | RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::HtmlDocument); | ||
| 4671 | RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::LegalInformation); | ||
| 4620 | RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | 4672 | RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); |
| 4621 | 4673 | ||
| 4622 | if (available_title_ids.empty()) { | 4674 | if (available_title_ids.empty()) { |
| @@ -4627,10 +4679,14 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe | |||
| 4627 | 4679 | ||
| 4628 | if (available_title_ids.size() > 1) { | 4680 | if (available_title_ids.size() > 1) { |
| 4629 | QStringList list; | 4681 | QStringList list; |
| 4630 | for (auto& [title_id, content_info] : available_title_ids) { | 4682 | for (auto& [title_id, title_type, record_type] : available_title_ids) { |
| 4631 | const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id)); | 4683 | const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id)); |
| 4632 | if (content_info.first == FileSys::TitleType::Application) { | 4684 | if (record_type == FileSys::ContentRecordType::Program) { |
| 4633 | list.push_back(QStringLiteral("Application [%1]").arg(hex_title_id)); | 4685 | list.push_back(QStringLiteral("Program [%1]").arg(hex_title_id)); |
| 4686 | } else if (record_type == FileSys::ContentRecordType::HtmlDocument) { | ||
| 4687 | list.push_back(QStringLiteral("HTML document [%1]").arg(hex_title_id)); | ||
| 4688 | } else if (record_type == FileSys::ContentRecordType::LegalInformation) { | ||
| 4689 | list.push_back(QStringLiteral("Legal information [%1]").arg(hex_title_id)); | ||
| 4634 | } else { | 4690 | } else { |
| 4635 | list.push_back( | 4691 | list.push_back( |
| 4636 | QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id)); | 4692 | QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id)); |
| @@ -4648,9 +4704,9 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe | |||
| 4648 | title_index = list.indexOf(res); | 4704 | title_index = list.indexOf(res); |
| 4649 | } | 4705 | } |
| 4650 | 4706 | ||
| 4651 | const auto selected_info = available_title_ids.nth(title_index); | 4707 | const auto& [title_id, title_type, record_type] = *available_title_ids.nth(title_index); |
| 4652 | *selected_title_id = selected_info->first; | 4708 | *selected_title_id = title_id; |
| 4653 | *selected_content_record_type = static_cast<u8>(selected_info->second.second); | 4709 | *selected_content_record_type = static_cast<u8>(record_type); |
| 4654 | return true; | 4710 | return true; |
| 4655 | } | 4711 | } |
| 4656 | 4712 | ||
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index ba318eb11..52028234c 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -102,6 +102,10 @@ namespace Service::NFC { | |||
| 102 | class NfcDevice; | 102 | class NfcDevice; |
| 103 | } // namespace Service::NFC | 103 | } // namespace Service::NFC |
| 104 | 104 | ||
| 105 | namespace Service::NFP { | ||
| 106 | enum class CabinetMode : u8; | ||
| 107 | } // namespace Service::NFP | ||
| 108 | |||
| 105 | namespace Ui { | 109 | namespace Ui { |
| 106 | class MainWindow; | 110 | class MainWindow; |
| 107 | } | 111 | } |
| @@ -365,6 +369,7 @@ private slots: | |||
| 365 | void ResetWindowSize720(); | 369 | void ResetWindowSize720(); |
| 366 | void ResetWindowSize900(); | 370 | void ResetWindowSize900(); |
| 367 | void ResetWindowSize1080(); | 371 | void ResetWindowSize1080(); |
| 372 | void OnCabinet(Service::NFP::CabinetMode mode); | ||
| 368 | void OnMiiEdit(); | 373 | void OnMiiEdit(); |
| 369 | void OnCaptureScreenshot(); | 374 | void OnCaptureScreenshot(); |
| 370 | void OnReinitializeKeys(ReinitializeKeyBehavior behavior); | 375 | void OnReinitializeKeys(ReinitializeKeyBehavior behavior); |
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 91d6c5ef3..31c3de9ef 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui | |||
| @@ -137,6 +137,15 @@ | |||
| 137 | <property name="title"> | 137 | <property name="title"> |
| 138 | <string>&Tools</string> | 138 | <string>&Tools</string> |
| 139 | </property> | 139 | </property> |
| 140 | <widget class="QMenu" name="menu_cabinet_applet"> | ||
| 141 | <property name="title"> | ||
| 142 | <string>&Amiibo</string> | ||
| 143 | </property> | ||
| 144 | <addaction name="action_Load_Cabinet_Nickname_Owner"/> | ||
| 145 | <addaction name="action_Load_Cabinet_Eraser"/> | ||
| 146 | <addaction name="action_Load_Cabinet_Restorer"/> | ||
| 147 | <addaction name="action_Load_Cabinet_Formatter"/> | ||
| 148 | </widget> | ||
| 140 | <widget class="QMenu" name="menuTAS"> | 149 | <widget class="QMenu" name="menuTAS"> |
| 141 | <property name="title"> | 150 | <property name="title"> |
| 142 | <string>&TAS</string> | 151 | <string>&TAS</string> |
| @@ -150,6 +159,7 @@ | |||
| 150 | <addaction name="action_Rederive"/> | 159 | <addaction name="action_Rederive"/> |
| 151 | <addaction name="action_Verify_installed_contents"/> | 160 | <addaction name="action_Verify_installed_contents"/> |
| 152 | <addaction name="separator"/> | 161 | <addaction name="separator"/> |
| 162 | <addaction name="menu_cabinet_applet"/> | ||
| 153 | <addaction name="action_Load_Mii_Edit"/> | 163 | <addaction name="action_Load_Mii_Edit"/> |
| 154 | <addaction name="separator"/> | 164 | <addaction name="separator"/> |
| 155 | <addaction name="action_Capture_Screenshot"/> | 165 | <addaction name="action_Capture_Screenshot"/> |
| @@ -370,6 +380,26 @@ | |||
| 370 | <string>&Capture Screenshot</string> | 380 | <string>&Capture Screenshot</string> |
| 371 | </property> | 381 | </property> |
| 372 | </action> | 382 | </action> |
| 383 | <action name="action_Load_Cabinet_Nickname_Owner"> | ||
| 384 | <property name="text"> | ||
| 385 | <string>&Set Nickname and Owner</string> | ||
| 386 | </property> | ||
| 387 | </action> | ||
| 388 | <action name="action_Load_Cabinet_Eraser"> | ||
| 389 | <property name="text"> | ||
| 390 | <string>&Delete Game Data</string> | ||
| 391 | </property> | ||
| 392 | </action> | ||
| 393 | <action name="action_Load_Cabinet_Restorer"> | ||
| 394 | <property name="text"> | ||
| 395 | <string>&Restore Amiibo</string> | ||
| 396 | </property> | ||
| 397 | </action> | ||
| 398 | <action name="action_Load_Cabinet_Formatter"> | ||
| 399 | <property name="text"> | ||
| 400 | <string>&Format Amiibo</string> | ||
| 401 | </property> | ||
| 402 | </action> | ||
| 373 | <action name="action_Load_Mii_Edit"> | 403 | <action name="action_Load_Mii_Edit"> |
| 374 | <property name="text"> | 404 | <property name="text"> |
| 375 | <string>Open &Mii Editor</string> | 405 | <string>Open &Mii Editor</string> |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 8efd63f31..8a2caa9dd 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -103,7 +103,7 @@ struct Values { | |||
| 103 | true, | 103 | true, |
| 104 | true}; | 104 | true}; |
| 105 | Setting<bool> mute_when_in_background{ | 105 | Setting<bool> mute_when_in_background{ |
| 106 | linkage, false, "muteWhenInBackground", Category::Ui, Settings::Specialization::Default, | 106 | linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default, |
| 107 | true, true}; | 107 | true, true}; |
| 108 | Setting<bool> hide_mouse{ | 108 | Setting<bool> hide_mouse{ |
| 109 | linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, | 109 | linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, |