diff options
23 files changed, 985 insertions, 60 deletions
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/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/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/yuzu/main.cpp b/src/yuzu/main.cpp index adb7b332f..ec27361d5 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -1551,6 +1551,14 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 1551 | // Tools | 1551 | // Tools |
| 1552 | connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, | 1552 | connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, |
| 1553 | ReinitializeKeyBehavior::Warning)); | 1553 | ReinitializeKeyBehavior::Warning)); |
| 1554 | connect_menu(ui->action_Load_Cabinet_Nickname_Owner, | ||
| 1555 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); }); | ||
| 1556 | connect_menu(ui->action_Load_Cabinet_Eraser, | ||
| 1557 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartGameDataEraser); }); | ||
| 1558 | connect_menu(ui->action_Load_Cabinet_Restorer, | ||
| 1559 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); }); | ||
| 1560 | connect_menu(ui->action_Load_Cabinet_Formatter, | ||
| 1561 | [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); }); | ||
| 1554 | connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); | 1562 | connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); |
| 1555 | connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); | 1563 | connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); |
| 1556 | 1564 | ||
| @@ -1568,6 +1576,7 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 1568 | 1576 | ||
| 1569 | void GMainWindow::UpdateMenuState() { | 1577 | void GMainWindow::UpdateMenuState() { |
| 1570 | const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning(); | 1578 | const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning(); |
| 1579 | const bool is_firmware_available = CheckFirmwarePresence(); | ||
| 1571 | 1580 | ||
| 1572 | const std::array running_actions{ | 1581 | const std::array running_actions{ |
| 1573 | ui->action_Stop, | 1582 | ui->action_Stop, |
| @@ -1578,10 +1587,22 @@ void GMainWindow::UpdateMenuState() { | |||
| 1578 | ui->action_Pause, | 1587 | ui->action_Pause, |
| 1579 | }; | 1588 | }; |
| 1580 | 1589 | ||
| 1590 | const std::array applet_actions{ | ||
| 1591 | ui->action_Load_Cabinet_Nickname_Owner, | ||
| 1592 | ui->action_Load_Cabinet_Eraser, | ||
| 1593 | ui->action_Load_Cabinet_Restorer, | ||
| 1594 | ui->action_Load_Cabinet_Formatter, | ||
| 1595 | ui->action_Load_Mii_Edit, | ||
| 1596 | }; | ||
| 1597 | |||
| 1581 | for (QAction* action : running_actions) { | 1598 | for (QAction* action : running_actions) { |
| 1582 | action->setEnabled(emulation_running); | 1599 | action->setEnabled(emulation_running); |
| 1583 | } | 1600 | } |
| 1584 | 1601 | ||
| 1602 | for (QAction* action : applet_actions) { | ||
| 1603 | action->setEnabled(is_firmware_available && !emulation_running); | ||
| 1604 | } | ||
| 1605 | |||
| 1585 | ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused); | 1606 | ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused); |
| 1586 | 1607 | ||
| 1587 | if (emulation_running && is_paused) { | 1608 | if (emulation_running && is_paused) { |
| @@ -1591,8 +1612,6 @@ void GMainWindow::UpdateMenuState() { | |||
| 1591 | } | 1612 | } |
| 1592 | 1613 | ||
| 1593 | multiplayer_state->UpdateNotificationStatus(); | 1614 | multiplayer_state->UpdateNotificationStatus(); |
| 1594 | |||
| 1595 | ui->action_Load_Mii_Edit->setEnabled(CheckFirmwarePresence()); | ||
| 1596 | } | 1615 | } |
| 1597 | 1616 | ||
| 1598 | void GMainWindow::OnDisplayTitleBars(bool show) { | 1617 | void GMainWindow::OnDisplayTitleBars(bool show) { |
| @@ -2103,6 +2122,8 @@ void GMainWindow::OnEmulationStopped() { | |||
| 2103 | OnTasStateChanged(); | 2122 | OnTasStateChanged(); |
| 2104 | render_window->FinalizeCamera(); | 2123 | render_window->FinalizeCamera(); |
| 2105 | 2124 | ||
| 2125 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::None); | ||
| 2126 | |||
| 2106 | // Enable all controllers | 2127 | // Enable all controllers |
| 2107 | system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); | 2128 | system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); |
| 2108 | 2129 | ||
| @@ -4134,6 +4155,30 @@ void GMainWindow::OnToggleStatusBar() { | |||
| 4134 | statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); | 4155 | statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); |
| 4135 | } | 4156 | } |
| 4136 | 4157 | ||
| 4158 | void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { | ||
| 4159 | constexpr u64 CabinetId = 0x0100000000001002ull; | ||
| 4160 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | ||
| 4161 | if (!bis_system) { | ||
| 4162 | QMessageBox::warning(this, tr("No firmware available"), | ||
| 4163 | tr("Please install the firmware to use the Cabinet applet.")); | ||
| 4164 | return; | ||
| 4165 | } | ||
| 4166 | |||
| 4167 | auto cabinet_nca = bis_system->GetEntry(CabinetId, FileSys::ContentRecordType::Program); | ||
| 4168 | if (!cabinet_nca) { | ||
| 4169 | QMessageBox::warning(this, tr("Cabinet Applet"), | ||
| 4170 | tr("Cabinet applet is not available. Please reinstall firmware.")); | ||
| 4171 | return; | ||
| 4172 | } | ||
| 4173 | |||
| 4174 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Cabinet); | ||
| 4175 | system->GetAppletManager().SetCabinetMode(mode); | ||
| 4176 | |||
| 4177 | const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); | ||
| 4178 | UISettings::values.roms_path = QFileInfo(filename).path(); | ||
| 4179 | BootGame(filename); | ||
| 4180 | } | ||
| 4181 | |||
| 4137 | void GMainWindow::OnMiiEdit() { | 4182 | void GMainWindow::OnMiiEdit() { |
| 4138 | constexpr u64 MiiEditId = 0x0100000000001009ull; | 4183 | constexpr u64 MiiEditId = 0x0100000000001009ull; |
| 4139 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4184 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| @@ -4150,6 +4195,8 @@ void GMainWindow::OnMiiEdit() { | |||
| 4150 | return; | 4195 | return; |
| 4151 | } | 4196 | } |
| 4152 | 4197 | ||
| 4198 | system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit); | ||
| 4199 | |||
| 4153 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); | 4200 | const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); |
| 4154 | UISettings::values.roms_path = QFileInfo(filename).path(); | 4201 | UISettings::values.roms_path = QFileInfo(filename).path(); |
| 4155 | BootGame(filename); | 4202 | BootGame(filename); |
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> |