diff options
| author | 2022-10-02 03:02:59 -0700 | |
|---|---|---|
| committer | 2022-10-02 03:02:59 -0700 | |
| commit | 80a3a731237472d8d2141243ca322ccf3276483c (patch) | |
| tree | eafea51bbdb8d7ceb9e69cd2d9b1156f1f3c3b9b | |
| parent | Merge pull request #6598 from FernandoS27/falklands-are-british (diff) | |
| parent | service: vi: Retrieve vsync event once per display (diff) | |
| download | yuzu-80a3a731237472d8d2141243ca322ccf3276483c.tar.gz yuzu-80a3a731237472d8d2141243ca322ccf3276483c.tar.xz yuzu-80a3a731237472d8d2141243ca322ccf3276483c.zip | |
Merge pull request #8992 from Morph1984/vi-vsync-event
service: vi: Retrieve vsync event once per display
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 7 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.h | 6 | ||||
| -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 | 40 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi_results.h | 13 |
6 files changed, 66 insertions, 29 deletions
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 9b382bf56..93057e800 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "core/hle/service/nvflinger/ui/graphic_buffer.h" | 22 | #include "core/hle/service/nvflinger/ui/graphic_buffer.h" |
| 23 | #include "core/hle/service/vi/display/vi_display.h" | 23 | #include "core/hle/service/vi/display/vi_display.h" |
| 24 | #include "core/hle/service/vi/layer/vi_layer.h" | 24 | #include "core/hle/service/vi/layer/vi_layer.h" |
| 25 | #include "core/hle/service/vi/vi_results.h" | ||
| 25 | #include "video_core/gpu.h" | 26 | #include "video_core/gpu.h" |
| 26 | 27 | ||
| 27 | namespace Service::NVFlinger { | 28 | namespace Service::NVFlinger { |
| @@ -163,15 +164,15 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) { | |||
| 163 | return layer->GetBinderId(); | 164 | return layer->GetBinderId(); |
| 164 | } | 165 | } |
| 165 | 166 | ||
| 166 | Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) { | 167 | ResultVal<Kernel::KReadableEvent*> NVFlinger::FindVsyncEvent(u64 display_id) { |
| 167 | const auto lock_guard = Lock(); | 168 | const auto lock_guard = Lock(); |
| 168 | auto* const display = FindDisplay(display_id); | 169 | auto* const display = FindDisplay(display_id); |
| 169 | 170 | ||
| 170 | if (display == nullptr) { | 171 | if (display == nullptr) { |
| 171 | return nullptr; | 172 | return VI::ResultNotFound; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | return &display->GetVSyncEvent(); | 175 | return display->GetVSyncEvent(); |
| 175 | } | 176 | } |
| 176 | 177 | ||
| 177 | VI::Display* NVFlinger::FindDisplay(u64 display_id) { | 178 | VI::Display* NVFlinger::FindDisplay(u64 display_id) { |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 044ac6ac8..3bbe5d92b 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | 12 | ||
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "core/hle/result.h" | ||
| 14 | #include "core/hle/service/kernel_helpers.h" | 15 | #include "core/hle/service/kernel_helpers.h" |
| 15 | 16 | ||
| 16 | namespace Common { | 17 | namespace Common { |
| @@ -71,8 +72,9 @@ public: | |||
| 71 | 72 | ||
| 72 | /// Gets the vsync event for the specified display. | 73 | /// Gets the vsync event for the specified display. |
| 73 | /// | 74 | /// |
| 74 | /// If an invalid display ID is provided, then nullptr is returned. | 75 | /// If an invalid display ID is provided, then VI::ResultNotFound is returned. |
| 75 | [[nodiscard]] Kernel::KReadableEvent* FindVsyncEvent(u64 display_id); | 76 | /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. |
| 77 | [[nodiscard]] ResultVal<Kernel::KReadableEvent*> FindVsyncEvent(u64 display_id); | ||
| 76 | 78 | ||
| 77 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when | 79 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when |
| 78 | /// finished. | 80 | /// finished. |
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 546879648..f083811ec 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -29,16 +29,12 @@ | |||
| 29 | #include "core/hle/service/service.h" | 29 | #include "core/hle/service/service.h" |
| 30 | #include "core/hle/service/vi/vi.h" | 30 | #include "core/hle/service/vi/vi.h" |
| 31 | #include "core/hle/service/vi/vi_m.h" | 31 | #include "core/hle/service/vi/vi_m.h" |
| 32 | #include "core/hle/service/vi/vi_results.h" | ||
| 32 | #include "core/hle/service/vi/vi_s.h" | 33 | #include "core/hle/service/vi/vi_s.h" |
| 33 | #include "core/hle/service/vi/vi_u.h" | 34 | #include "core/hle/service/vi/vi_u.h" |
| 34 | 35 | ||
| 35 | namespace Service::VI { | 36 | namespace Service::VI { |
| 36 | 37 | ||
| 37 | constexpr Result ERR_OPERATION_FAILED{ErrorModule::VI, 1}; | ||
| 38 | constexpr Result ERR_PERMISSION_DENIED{ErrorModule::VI, 5}; | ||
| 39 | constexpr Result ERR_UNSUPPORTED{ErrorModule::VI, 6}; | ||
| 40 | constexpr Result ERR_NOT_FOUND{ErrorModule::VI, 7}; | ||
| 41 | |||
| 42 | struct DisplayInfo { | 38 | struct DisplayInfo { |
| 43 | /// The name of this particular display. | 39 | /// The name of this particular display. |
| 44 | char display_name[0x40]{"Default"}; | 40 | char display_name[0x40]{"Default"}; |
| @@ -348,7 +344,7 @@ private: | |||
| 348 | if (!layer_id) { | 344 | if (!layer_id) { |
| 349 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); | 345 | LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); |
| 350 | IPC::ResponseBuilder rb{ctx, 2}; | 346 | IPC::ResponseBuilder rb{ctx, 2}; |
| 351 | rb.Push(ERR_NOT_FOUND); | 347 | rb.Push(ResultNotFound); |
| 352 | return; | 348 | return; |
| 353 | } | 349 | } |
| 354 | 350 | ||
| @@ -498,7 +494,7 @@ private: | |||
| 498 | if (!display_id) { | 494 | if (!display_id) { |
| 499 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); | 495 | LOG_ERROR(Service_VI, "Display not found! display_name={}", name); |
| 500 | IPC::ResponseBuilder rb{ctx, 2}; | 496 | IPC::ResponseBuilder rb{ctx, 2}; |
| 501 | rb.Push(ERR_NOT_FOUND); | 497 | rb.Push(ResultNotFound); |
| 502 | return; | 498 | return; |
| 503 | } | 499 | } |
| 504 | 500 | ||
| @@ -554,14 +550,14 @@ private: | |||
| 554 | 550 | ||
| 555 | if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { | 551 | if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { |
| 556 | LOG_ERROR(Service_VI, "Invalid scaling mode provided."); | 552 | LOG_ERROR(Service_VI, "Invalid scaling mode provided."); |
| 557 | rb.Push(ERR_OPERATION_FAILED); | 553 | rb.Push(ResultOperationFailed); |
| 558 | return; | 554 | return; |
| 559 | } | 555 | } |
| 560 | 556 | ||
| 561 | if (scaling_mode != NintendoScaleMode::ScaleToWindow && | 557 | if (scaling_mode != NintendoScaleMode::ScaleToWindow && |
| 562 | scaling_mode != NintendoScaleMode::PreserveAspectRatio) { | 558 | scaling_mode != NintendoScaleMode::PreserveAspectRatio) { |
| 563 | LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); | 559 | LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); |
| 564 | rb.Push(ERR_UNSUPPORTED); | 560 | rb.Push(ResultNotSupported); |
| 565 | return; | 561 | return; |
| 566 | } | 562 | } |
| 567 | 563 | ||
| @@ -594,7 +590,7 @@ private: | |||
| 594 | if (!display_id) { | 590 | if (!display_id) { |
| 595 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | 591 | LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); |
| 596 | IPC::ResponseBuilder rb{ctx, 2}; | 592 | IPC::ResponseBuilder rb{ctx, 2}; |
| 597 | rb.Push(ERR_NOT_FOUND); | 593 | rb.Push(ResultNotFound); |
| 598 | return; | 594 | return; |
| 599 | } | 595 | } |
| 600 | 596 | ||
| @@ -602,7 +598,7 @@ private: | |||
| 602 | if (!buffer_queue_id) { | 598 | if (!buffer_queue_id) { |
| 603 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | 599 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); |
| 604 | IPC::ResponseBuilder rb{ctx, 2}; | 600 | IPC::ResponseBuilder rb{ctx, 2}; |
| 605 | rb.Push(ERR_NOT_FOUND); | 601 | rb.Push(ResultNotFound); |
| 606 | return; | 602 | return; |
| 607 | } | 603 | } |
| 608 | 604 | ||
| @@ -640,7 +636,7 @@ private: | |||
| 640 | if (!layer_id) { | 636 | if (!layer_id) { |
| 641 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | 637 | LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); |
| 642 | IPC::ResponseBuilder rb{ctx, 2}; | 638 | IPC::ResponseBuilder rb{ctx, 2}; |
| 643 | rb.Push(ERR_NOT_FOUND); | 639 | rb.Push(ResultNotFound); |
| 644 | return; | 640 | return; |
| 645 | } | 641 | } |
| 646 | 642 | ||
| @@ -648,7 +644,7 @@ private: | |||
| 648 | if (!buffer_queue_id) { | 644 | if (!buffer_queue_id) { |
| 649 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | 645 | LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); |
| 650 | IPC::ResponseBuilder rb{ctx, 2}; | 646 | IPC::ResponseBuilder rb{ctx, 2}; |
| 651 | rb.Push(ERR_NOT_FOUND); | 647 | rb.Push(ResultNotFound); |
| 652 | return; | 648 | return; |
| 653 | } | 649 | } |
| 654 | 650 | ||
| @@ -675,19 +671,23 @@ private: | |||
| 675 | IPC::RequestParser rp{ctx}; | 671 | IPC::RequestParser rp{ctx}; |
| 676 | const u64 display_id = rp.Pop<u64>(); | 672 | const u64 display_id = rp.Pop<u64>(); |
| 677 | 673 | ||
| 678 | LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); | 674 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 679 | 675 | ||
| 680 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); | 676 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); |
| 681 | if (!vsync_event) { | 677 | if (vsync_event.Failed()) { |
| 682 | 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 | |||
| 683 | IPC::ResponseBuilder rb{ctx, 2}; | 683 | IPC::ResponseBuilder rb{ctx, 2}; |
| 684 | rb.Push(ERR_NOT_FOUND); | 684 | rb.Push(result); |
| 685 | return; | 685 | return; |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 688 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 689 | rb.Push(ResultSuccess); | 689 | rb.Push(ResultSuccess); |
| 690 | rb.PushCopyObjects(vsync_event); | 690 | rb.PushCopyObjects(*vsync_event); |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | void ConvertScalingMode(Kernel::HLERequestContext& ctx) { | 693 | void ConvertScalingMode(Kernel::HLERequestContext& ctx) { |
| @@ -764,7 +764,7 @@ private: | |||
| 764 | return ConvertedScaleMode::PreserveAspectRatio; | 764 | return ConvertedScaleMode::PreserveAspectRatio; |
| 765 | default: | 765 | default: |
| 766 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | 766 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); |
| 767 | return ERR_OPERATION_FAILED; | 767 | return ResultOperationFailed; |
| 768 | } | 768 | } |
| 769 | } | 769 | } |
| 770 | 770 | ||
| @@ -794,7 +794,7 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& | |||
| 794 | if (!IsValidServiceAccess(permission, policy)) { | 794 | if (!IsValidServiceAccess(permission, policy)) { |
| 795 | LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); | 795 | LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); |
| 796 | IPC::ResponseBuilder rb{ctx, 2}; | 796 | IPC::ResponseBuilder rb{ctx, 2}; |
| 797 | rb.Push(ERR_PERMISSION_DENIED); | 797 | rb.Push(ResultPermissionDenied); |
| 798 | return; | 798 | return; |
| 799 | } | 799 | } |
| 800 | 800 | ||
diff --git a/src/core/hle/service/vi/vi_results.h b/src/core/hle/service/vi/vi_results.h new file mode 100644 index 000000000..a46c247d2 --- /dev/null +++ b/src/core/hle/service/vi/vi_results.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/result.h" | ||
| 5 | |||
| 6 | namespace Service::VI { | ||
| 7 | |||
| 8 | constexpr Result ResultOperationFailed{ErrorModule::VI, 1}; | ||
| 9 | constexpr Result ResultPermissionDenied{ErrorModule::VI, 5}; | ||
| 10 | constexpr Result ResultNotSupported{ErrorModule::VI, 6}; | ||
| 11 | constexpr Result ResultNotFound{ErrorModule::VI, 7}; | ||
| 12 | |||
| 13 | } // namespace Service::VI | ||