From ea710e652398f0646aeb1a1cdf78cee9691440e8 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Sat, 6 Jan 2024 23:58:04 -0500
Subject: [PATCH] vi: connect vsync event handle lifetime to application
 display service interface

---
 src/core/hle/service/nvnflinger/nvnflinger.cpp |  3 ++-
 src/core/hle/service/vi/display/vi_display.cpp | 13 +------------
 src/core/hle/service/vi/display/vi_display.h   | 12 +-----------
 src/core/hle/service/vi/vi.cpp                 |  7 +++++++
 4 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index aa8aaa2d9..0469110e8 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -223,7 +223,8 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64
         return VI::ResultNotFound;
     }
 
-    return display->GetVSyncEvent(out_vsync_event);
+    *out_vsync_event = display->GetVSyncEvent();
+    return ResultSuccess;
 }
 
 VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 71ce9be50..e2d9cd98a 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -71,18 +71,7 @@ size_t Display::GetNumLayers() const {
     return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); });
 }
 
-Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) {
-    if (got_vsync_event) {
-        return ResultPermissionDenied;
-    }
-
-    got_vsync_event = true;
-
-    *out_vsync_event = GetVSyncEventUnchecked();
-    return ResultSuccess;
-}
-
-Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {
+Kernel::KReadableEvent* Display::GetVSyncEvent() {
     return &vsync_event->GetReadableEvent();
 }
 
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 1d9360b96..7e68ee79b 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -74,16 +74,8 @@ public:
 
     std::size_t GetNumLayers() const;
 
-    /**
-     * Gets the internal vsync event.
-     *
-     * @returns The internal Vsync event if it has not yet been retrieved,
-     *          VI::ResultPermissionDenied otherwise.
-     */
-    [[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event);
-
     /// Gets the internal vsync event.
-    Kernel::KReadableEvent* GetVSyncEventUnchecked();
+    Kernel::KReadableEvent* GetVSyncEvent();
 
     /// Signals the internal vsync event.
     void SignalVSyncEvent();
@@ -104,7 +96,6 @@ public:
     /// Resets the display for a new connection.
     void Reset() {
         layers.clear();
-        got_vsync_event = false;
     }
 
     /// Attempts to find a layer with the given ID.
@@ -133,7 +124,6 @@ private:
 
     std::vector<std::unique_ptr<Layer>> layers;
     Kernel::KEvent* vsync_event{};
-    bool got_vsync_event{false};
 };
 
 } // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 29471abfe..39d5be90d 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -808,6 +808,12 @@ private:
             rb.Push(result);
             return;
         }
+        if (vsync_event_fetched) {
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(VI::ResultPermissionDenied);
+            return;
+        }
+        vsync_event_fetched = true;
 
         IPC::ResponseBuilder rb{ctx, 2, 1};
         rb.Push(ResultSuccess);
@@ -901,6 +907,7 @@ private:
 
     Nvnflinger::Nvnflinger& nvnflinger;
     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
+    bool vsync_event_fetched{false};
 };
 
 static bool IsValidServiceAccess(Permission permission, Policy policy) {