summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2022-10-02 03:02:59 -0700
committerGravatar GitHub2022-10-02 03:02:59 -0700
commit80a3a731237472d8d2141243ca322ccf3276483c (patch)
treeeafea51bbdb8d7ceb9e69cd2d9b1156f1f3c3b9b /src
parentMerge pull request #6598 from FernandoS27/falklands-are-british (diff)
parentservice: vi: Retrieve vsync event once per display (diff)
downloadyuzu-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 'src')
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp7
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h6
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp15
-rw-r--r--src/core/hle/service/vi/display/vi_display.h14
-rw-r--r--src/core/hle/service/vi/vi.cpp40
-rw-r--r--src/core/hle/service/vi/vi_results.h13
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
27namespace Service::NVFlinger { 28namespace 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
166Kernel::KReadableEvent* NVFlinger::FindVsyncEvent(u64 display_id) { 167ResultVal<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
177VI::Display* NVFlinger::FindDisplay(u64 display_id) { 178VI::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
16namespace Common { 17namespace 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
23namespace Service::VI { 24namespace 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
58Kernel::KReadableEvent& Display::GetVSyncEvent() { 59ResultVal<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
69Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
70 return &vsync_event->GetReadableEvent();
60} 71}
61 72
62void Display::SignalVSyncEvent() { 73void 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
13namespace Kernel { 14namespace Kernel {
14class KEvent; 15class 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
35namespace Service::VI { 36namespace Service::VI {
36 37
37constexpr Result ERR_OPERATION_FAILED{ErrorModule::VI, 1};
38constexpr Result ERR_PERMISSION_DENIED{ErrorModule::VI, 5};
39constexpr Result ERR_UNSUPPORTED{ErrorModule::VI, 6};
40constexpr Result ERR_NOT_FOUND{ErrorModule::VI, 7};
41
42struct DisplayInfo { 38struct 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
6namespace Service::VI {
7
8constexpr Result ResultOperationFailed{ErrorModule::VI, 1};
9constexpr Result ResultPermissionDenied{ErrorModule::VI, 5};
10constexpr Result ResultNotSupported{ErrorModule::VI, 6};
11constexpr Result ResultNotFound{ErrorModule::VI, 7};
12
13} // namespace Service::VI