diff options
| author | 2022-09-25 21:20:36 -0400 | |
|---|---|---|
| committer | 2022-09-25 21:33:36 -0400 | |
| commit | 41e855bd427e07ade6b9292e12bbe5a7c4e76a69 (patch) | |
| tree | a270ca94eabc45a52af899e70c1d72e8ab5b18be /src/core/hle/service/vi | |
| parent | service: vi: Move VI results into its own file (diff) | |
| download | yuzu-41e855bd427e07ade6b9292e12bbe5a7c4e76a69.tar.gz yuzu-41e855bd427e07ade6b9292e12bbe5a7c4e76a69.tar.xz yuzu-41e855bd427e07ade6b9292e12bbe5a7c4e76a69.zip | |
service: vi: Retrieve vsync event once per display
The display vsync event can only be retrieved once per display. Returns VI::ResultPermissionDenied if we attempt to retrieve the vsync event for the same display.
Prevents games such as .hack//G.U. Last Recode from consuming all the handles in the handle table by spamming vsync event retrievals and allows it to go in game.
Diffstat (limited to 'src/core/hle/service/vi')
| -rw-r--r-- | src/core/hle/service/vi/display/vi_display.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/service/vi/display/vi_display.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 14 |
3 files changed, 34 insertions, 9 deletions
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index b34febb50..aa49aa775 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "core/hle/service/nvflinger/hos_binder_driver_server.h" | 19 | #include "core/hle/service/nvflinger/hos_binder_driver_server.h" |
| 20 | #include "core/hle/service/vi/display/vi_display.h" | 20 | #include "core/hle/service/vi/display/vi_display.h" |
| 21 | #include "core/hle/service/vi/layer/vi_layer.h" | 21 | #include "core/hle/service/vi/layer/vi_layer.h" |
| 22 | #include "core/hle/service/vi/vi_results.h" | ||
| 22 | 23 | ||
| 23 | namespace Service::VI { | 24 | namespace Service::VI { |
| 24 | 25 | ||
| @@ -55,8 +56,18 @@ const Layer& Display::GetLayer(std::size_t index) const { | |||
| 55 | return *layers.at(index); | 56 | return *layers.at(index); |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | Kernel::KReadableEvent& Display::GetVSyncEvent() { | 59 | ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() { |
| 59 | return vsync_event->GetReadableEvent(); | 60 | if (got_vsync_event) { |
| 61 | return ResultPermissionDenied; | ||
| 62 | } | ||
| 63 | |||
| 64 | got_vsync_event = true; | ||
| 65 | |||
| 66 | return GetVSyncEventUnchecked(); | ||
| 67 | } | ||
| 68 | |||
| 69 | Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { | ||
| 70 | return &vsync_event->GetReadableEvent(); | ||
| 60 | } | 71 | } |
| 61 | 72 | ||
| 62 | void Display::SignalVSyncEvent() { | 73 | void Display::SignalVSyncEvent() { |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 3838bb599..8dbb0ef80 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "core/hle/result.h" | ||
| 12 | 13 | ||
| 13 | namespace Kernel { | 14 | namespace Kernel { |
| 14 | class KEvent; | 15 | class KEvent; |
| @@ -73,8 +74,16 @@ public: | |||
| 73 | return layers.size(); | 74 | return layers.size(); |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | /// Gets the readable vsync event. | 77 | /** |
| 77 | Kernel::KReadableEvent& GetVSyncEvent(); | 78 | * Gets the internal vsync event. |
| 79 | * | ||
| 80 | * @returns The internal Vsync event if it has not yet been retrieved, | ||
| 81 | * VI::ResultPermissionDenied otherwise. | ||
| 82 | */ | ||
| 83 | [[nodiscard]] ResultVal<Kernel::KReadableEvent*> GetVSyncEvent(); | ||
| 84 | |||
| 85 | /// Gets the internal vsync event. | ||
| 86 | Kernel::KReadableEvent* GetVSyncEventUnchecked(); | ||
| 78 | 87 | ||
| 79 | /// Signals the internal vsync event. | 88 | /// Signals the internal vsync event. |
| 80 | void SignalVSyncEvent(); | 89 | void SignalVSyncEvent(); |
| @@ -118,6 +127,7 @@ private: | |||
| 118 | 127 | ||
| 119 | std::vector<std::unique_ptr<Layer>> layers; | 128 | std::vector<std::unique_ptr<Layer>> layers; |
| 120 | Kernel::KEvent* vsync_event{}; | 129 | Kernel::KEvent* vsync_event{}; |
| 130 | bool got_vsync_event{false}; | ||
| 121 | }; | 131 | }; |
| 122 | 132 | ||
| 123 | } // namespace Service::VI | 133 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 0a347a0e9..f083811ec 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -671,19 +671,23 @@ private: | |||
| 671 | IPC::RequestParser rp{ctx}; | 671 | IPC::RequestParser rp{ctx}; |
| 672 | const u64 display_id = rp.Pop<u64>(); | 672 | const u64 display_id = rp.Pop<u64>(); |
| 673 | 673 | ||
| 674 | LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); | 674 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 675 | 675 | ||
| 676 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); | 676 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); |
| 677 | if (!vsync_event) { | 677 | if (vsync_event.Failed()) { |
| 678 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | 678 | const auto result = vsync_event.Code(); |
| 679 | if (result == ResultNotFound) { | ||
| 680 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||
| 681 | } | ||
| 682 | |||
| 679 | IPC::ResponseBuilder rb{ctx, 2}; | 683 | IPC::ResponseBuilder rb{ctx, 2}; |
| 680 | rb.Push(ResultNotFound); | 684 | rb.Push(result); |
| 681 | return; | 685 | return; |
| 682 | } | 686 | } |
| 683 | 687 | ||
| 684 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 688 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 685 | rb.Push(ResultSuccess); | 689 | rb.Push(ResultSuccess); |
| 686 | rb.PushCopyObjects(vsync_event); | 690 | rb.PushCopyObjects(*vsync_event); |
| 687 | } | 691 | } |
| 688 | 692 | ||
| 689 | void ConvertScalingMode(Kernel::HLERequestContext& ctx) { | 693 | void ConvertScalingMode(Kernel::HLERequestContext& ctx) { |