From e05bfd2f542ae32aec87c24b9b59684b4ecf5f45 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sat, 7 Aug 2021 01:17:13 -0700
Subject: [PATCH] core: hle: service: buffer_queue: Improve management of
 KEvent.

---
 .../hle/service/nvflinger/buffer_queue.cpp    | 25 +++++++++++--------
 src/core/hle/service/nvflinger/buffer_queue.h | 11 ++++++--
 src/core/hle/service/nvflinger/nvflinger.cpp  |  2 +-
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 59ddf62981..b4c3a6099f 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -9,17 +9,20 @@
 #include "core/core.h"
 #include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
+#include "core/hle/service/kernel_helpers.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
 
 namespace Service::NVFlinger {
 
-BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_)
-    : id(id_), layer_id(layer_id_), buffer_wait_event{kernel} {
-    Kernel::KAutoObject::Create(std::addressof(buffer_wait_event));
-    buffer_wait_event.Initialize("BufferQueue:WaitEvent");
+BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
+                         KernelHelpers::ServiceContext& service_context_)
+    : id(id_), layer_id(layer_id_), service_context{service_context_} {
+    buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
 }
 
-BufferQueue::~BufferQueue() = default;
+BufferQueue::~BufferQueue() {
+    service_context.CloseEvent(buffer_wait_event);
+}
 
 void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
     ASSERT(slot < buffer_slots);
@@ -41,7 +44,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
         .multi_fence = {},
     };
 
-    buffer_wait_event.GetWritableEvent().Signal();
+    buffer_wait_event->GetWritableEvent().Signal();
 }
 
 std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +122,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
     }
     free_buffers_condition.notify_one();
 
-    buffer_wait_event.GetWritableEvent().Signal();
+    buffer_wait_event->GetWritableEvent().Signal();
 }
 
 std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +157,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
     }
     free_buffers_condition.notify_one();
 
-    buffer_wait_event.GetWritableEvent().Signal();
+    buffer_wait_event->GetWritableEvent().Signal();
 }
 
 void BufferQueue::Connect() {
@@ -169,7 +172,7 @@ void BufferQueue::Disconnect() {
         std::unique_lock lock{queue_sequence_mutex};
         queue_sequence.clear();
     }
-    buffer_wait_event.GetWritableEvent().Signal();
+    buffer_wait_event->GetWritableEvent().Signal();
     is_connect = false;
     free_buffers_condition.notify_one();
 }
@@ -189,11 +192,11 @@ u32 BufferQueue::Query(QueryType type) {
 }
 
 Kernel::KWritableEvent& BufferQueue::GetWritableBufferWaitEvent() {
-    return buffer_wait_event.GetWritableEvent();
+    return buffer_wait_event->GetWritableEvent();
 }
 
 Kernel::KReadableEvent& BufferQueue::GetBufferWaitEvent() {
-    return buffer_wait_event.GetReadableEvent();
+    return buffer_wait_event->GetReadableEvent();
 }
 
 } // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 61e337ac52..759247eb01 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -24,6 +24,10 @@ class KReadableEvent;
 class KWritableEvent;
 } // namespace Kernel
 
+namespace Service::KernelHelpers {
+class ServiceContext;
+} // namespace Service::KernelHelpers
+
 namespace Service::NVFlinger {
 
 constexpr u32 buffer_slots = 0x40;
@@ -54,7 +58,8 @@ public:
         NativeWindowFormat = 2,
     };
 
-    explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_);
+    explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
+                         KernelHelpers::ServiceContext& service_context_);
     ~BufferQueue();
 
     enum class BufferTransformFlags : u32 {
@@ -130,12 +135,14 @@ private:
     std::list<u32> free_buffers;
     std::array<Buffer, buffer_slots> buffers;
     std::list<u32> queue_sequence;
-    Kernel::KEvent buffer_wait_event;
+    Kernel::KEvent* buffer_wait_event{};
 
     std::mutex free_buffers_mutex;
     std::condition_variable free_buffers_condition;
 
     std::mutex queue_sequence_mutex;
+
+    KernelHelpers::ServiceContext& service_context;
 };
 
 } // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 32d4e360a8..00bff8caf7 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -147,7 +147,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
 void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
     const u32 buffer_queue_id = next_buffer_queue_id++;
     buffer_queues.emplace_back(
-        std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id));
+        std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id, service_context));
     display.CreateLayer(layer_id, *buffer_queues.back());
 }