From 69fa2e652560dd72f7b53d44fec9d7fe4aa0ffb9 Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Thu, 26 Sep 2019 18:11:27 -0400
Subject: [PATCH] Nvdrv: Correct Event setup in Nvdrv

Events are supposed to be cleared on quering. This fixes that issue.
---
 .../hle/service/nvdrv/devices/nvhost_ctrl.cpp | 33 +++++++------------
 src/core/hle/service/nvdrv/interface.cpp      |  4 ++-
 2 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index ff6b1abaeb..708469bd5f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -62,16 +62,26 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
         return NvResult::BadParameter;
     }
 
+    u32 event_id = params.value & 0x00FF;
+
+    if (event_id >= MaxNvEvents) {
+        std::memcpy(output.data(), &params, sizeof(params));
+        return NvResult::BadParameter;
+    }
+
+    auto event = events_interface.events[event_id];
     auto& gpu = system.GPU();
     // This is mostly to take into account unimplemented features. As synced
     // gpu is always synced.
     if (!gpu.IsAsync()) {
+        event.writable->Signal();
         return NvResult::Success;
     }
     auto lock = gpu.LockSync();
     const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id);
     const s32 diff = current_syncpoint_value - params.threshold;
     if (diff >= 0) {
+        event.writable->Signal();
         params.value = current_syncpoint_value;
         std::memcpy(output.data(), &params, sizeof(params));
         return NvResult::Success;
@@ -87,27 +97,6 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
         return NvResult::Timeout;
     }
 
-    u32 event_id;
-    if (is_async) {
-        event_id = params.value & 0x00FF;
-        if (event_id >= MaxNvEvents) {
-            std::memcpy(output.data(), &params, sizeof(params));
-            return NvResult::BadParameter;
-        }
-    } else {
-        if (ctrl.fresh_call) {
-            const auto result = events_interface.GetFreeEvent();
-            if (result) {
-                event_id = *result;
-            } else {
-                LOG_CRITICAL(Service_NVDRV, "No Free Events available!");
-                event_id = params.value & 0x00FF;
-            }
-        } else {
-            event_id = ctrl.event_id;
-        }
-    }
-
     EventState status = events_interface.status[event_id];
     if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) {
         events_interface.SetEventStatus(event_id, EventState::Waiting);
@@ -119,7 +108,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
             params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
         }
         params.value |= event_id;
-        events_interface.events[event_id].writable->Clear();
+        event.writable->Clear();
         gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
         if (!is_async && ctrl.fresh_call) {
             ctrl.must_delay = true;
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 5e0c23602f..68d139cfb8 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -134,7 +134,9 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 3, 1};
     rb.Push(RESULT_SUCCESS);
     if (event_id < MaxNvEvents) {
-        rb.PushCopyObjects(nvdrv->GetEvent(event_id));
+        auto event = nvdrv->GetEvent(event_id);
+        event->Clear();
+        rb.PushCopyObjects(event);
         rb.Push<u32>(NvResult::Success);
     } else {
         rb.Push<u32>(0);
-- 
GitLab