From fb3e9314b9438bb3439e75218b38636bc3040c50 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sat, 7 Aug 2021 01:05:46 -0700
Subject: [PATCH] core: hle: service: nvflinger/vi: Improve management of
 KEvent.

---
 src/core/hle/service/nvflinger/nvflinger.cpp   | 13 +++++++------
 src/core/hle/service/nvflinger/nvflinger.h     |  3 +++
 src/core/hle/service/vi/display/vi_display.cpp | 17 ++++++++++-------
 src/core/hle/service/vi/display/vi_display.h   | 13 ++++++++++---
 4 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 9417489705..32d4e360a8 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -61,12 +61,13 @@ void NVFlinger::SplitVSync() {
     }
 }
 
-NVFlinger::NVFlinger(Core::System& system_) : system(system_) {
-    displays.emplace_back(0, "Default", system);
-    displays.emplace_back(1, "External", system);
-    displays.emplace_back(2, "Edid", system);
-    displays.emplace_back(3, "Internal", system);
-    displays.emplace_back(4, "Null", system);
+NVFlinger::NVFlinger(Core::System& system_)
+    : system(system_), service_context(system_, "nvflinger") {
+    displays.emplace_back(0, "Default", service_context, system);
+    displays.emplace_back(1, "External", service_context, system);
+    displays.emplace_back(2, "Edid", service_context, system);
+    displays.emplace_back(3, "Internal", service_context, system);
+    displays.emplace_back(4, "Null", service_context, system);
     guard = std::make_shared<std::mutex>();
 
     // Schedule the screen composition events
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index d80fd07ef7..6d84cafb49 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include "common/common_types.h"
+#include "core/hle/service/kernel_helpers.h"
 
 namespace Common {
 class Event;
@@ -135,6 +136,8 @@ private:
     std::unique_ptr<std::thread> vsync_thread;
     std::unique_ptr<Common::Event> wait_event;
     std::atomic<bool> is_running{};
+
+    KernelHelpers::ServiceContext service_context;
 };
 
 } // namespace Service::NVFlinger
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 0dd342dbfb..b7705c02a4 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -12,18 +12,21 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_writable_event.h"
+#include "core/hle/service/kernel_helpers.h"
 #include "core/hle/service/vi/display/vi_display.h"
 #include "core/hle/service/vi/layer/vi_layer.h"
 
 namespace Service::VI {
 
-Display::Display(u64 id, std::string name_, Core::System& system)
-    : display_id{id}, name{std::move(name_)}, vsync_event{system.Kernel()} {
-    Kernel::KAutoObject::Create(std::addressof(vsync_event));
-    vsync_event.Initialize(fmt::format("Display VSync Event {}", id));
+Display::Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_,
+                 Core::System& system_)
+    : display_id{id}, name{std::move(name_)}, service_context{service_context_} {
+    vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id));
 }
 
-Display::~Display() = default;
+Display::~Display() {
+    service_context.CloseEvent(vsync_event);
+}
 
 Layer& Display::GetLayer(std::size_t index) {
     return *layers.at(index);
@@ -34,11 +37,11 @@ const Layer& Display::GetLayer(std::size_t index) const {
 }
 
 Kernel::KReadableEvent& Display::GetVSyncEvent() {
-    return vsync_event.GetReadableEvent();
+    return vsync_event->GetReadableEvent();
 }
 
 void Display::SignalVSyncEvent() {
-    vsync_event.GetWritableEvent().Signal();
+    vsync_event->GetWritableEvent().Signal();
 }
 
 void Display::CreateLayer(u64 layer_id, NVFlinger::BufferQueue& buffer_queue) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 166f2a4cce..0979fc421f 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -18,6 +18,9 @@ class KEvent;
 namespace Service::NVFlinger {
 class BufferQueue;
 }
+namespace Service::KernelHelpers {
+class ServiceContext;
+} // namespace Service::KernelHelpers
 
 namespace Service::VI {
 
@@ -31,10 +34,13 @@ class Display {
 public:
     /// Constructs a display with a given unique ID and name.
     ///
-    /// @param id   The unique ID for this display.
+    /// @param id The unique ID for this display.
+    /// @param service_context_ The ServiceContext for the owning service.
     /// @param name_ The name for this display.
+    /// @param system_ The global system instance.
     ///
-    Display(u64 id, std::string name_, Core::System& system);
+    Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_,
+            Core::System& system_);
     ~Display();
 
     /// Gets the unique ID assigned to this display.
@@ -98,9 +104,10 @@ public:
 private:
     u64 display_id;
     std::string name;
+    KernelHelpers::ServiceContext& service_context;
 
     std::vector<std::shared_ptr<Layer>> layers;
-    Kernel::KEvent vsync_event;
+    Kernel::KEvent* vsync_event{};
 };
 
 } // namespace Service::VI