diff options
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 33 | ||||
| -rw-r--r-- | 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 ff6b1abae..708469bd5 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>& | |||
| 62 | return NvResult::BadParameter; | 62 | return NvResult::BadParameter; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | u32 event_id = params.value & 0x00FF; | ||
| 66 | |||
| 67 | if (event_id >= MaxNvEvents) { | ||
| 68 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 69 | return NvResult::BadParameter; | ||
| 70 | } | ||
| 71 | |||
| 72 | auto event = events_interface.events[event_id]; | ||
| 65 | auto& gpu = system.GPU(); | 73 | auto& gpu = system.GPU(); |
| 66 | // This is mostly to take into account unimplemented features. As synced | 74 | // This is mostly to take into account unimplemented features. As synced |
| 67 | // gpu is always synced. | 75 | // gpu is always synced. |
| 68 | if (!gpu.IsAsync()) { | 76 | if (!gpu.IsAsync()) { |
| 77 | event.writable->Signal(); | ||
| 69 | return NvResult::Success; | 78 | return NvResult::Success; |
| 70 | } | 79 | } |
| 71 | auto lock = gpu.LockSync(); | 80 | auto lock = gpu.LockSync(); |
| 72 | const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); | 81 | const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id); |
| 73 | const s32 diff = current_syncpoint_value - params.threshold; | 82 | const s32 diff = current_syncpoint_value - params.threshold; |
| 74 | if (diff >= 0) { | 83 | if (diff >= 0) { |
| 84 | event.writable->Signal(); | ||
| 75 | params.value = current_syncpoint_value; | 85 | params.value = current_syncpoint_value; |
| 76 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 86 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 77 | return NvResult::Success; | 87 | return NvResult::Success; |
| @@ -87,27 +97,6 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | |||
| 87 | return NvResult::Timeout; | 97 | return NvResult::Timeout; |
| 88 | } | 98 | } |
| 89 | 99 | ||
| 90 | u32 event_id; | ||
| 91 | if (is_async) { | ||
| 92 | event_id = params.value & 0x00FF; | ||
| 93 | if (event_id >= MaxNvEvents) { | ||
| 94 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 95 | return NvResult::BadParameter; | ||
| 96 | } | ||
| 97 | } else { | ||
| 98 | if (ctrl.fresh_call) { | ||
| 99 | const auto result = events_interface.GetFreeEvent(); | ||
| 100 | if (result) { | ||
| 101 | event_id = *result; | ||
| 102 | } else { | ||
| 103 | LOG_CRITICAL(Service_NVDRV, "No Free Events available!"); | ||
| 104 | event_id = params.value & 0x00FF; | ||
| 105 | } | ||
| 106 | } else { | ||
| 107 | event_id = ctrl.event_id; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | EventState status = events_interface.status[event_id]; | 100 | EventState status = events_interface.status[event_id]; |
| 112 | if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) { | 101 | if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) { |
| 113 | events_interface.SetEventStatus(event_id, EventState::Waiting); | 102 | events_interface.SetEventStatus(event_id, EventState::Waiting); |
| @@ -119,7 +108,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& | |||
| 119 | params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; | 108 | params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; |
| 120 | } | 109 | } |
| 121 | params.value |= event_id; | 110 | params.value |= event_id; |
| 122 | events_interface.events[event_id].writable->Clear(); | 111 | event.writable->Clear(); |
| 123 | gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); | 112 | gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); |
| 124 | if (!is_async && ctrl.fresh_call) { | 113 | if (!is_async && ctrl.fresh_call) { |
| 125 | ctrl.must_delay = true; | 114 | ctrl.must_delay = true; |
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 5e0c23602..68d139cfb 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) { | |||
| 134 | IPC::ResponseBuilder rb{ctx, 3, 1}; | 134 | IPC::ResponseBuilder rb{ctx, 3, 1}; |
| 135 | rb.Push(RESULT_SUCCESS); | 135 | rb.Push(RESULT_SUCCESS); |
| 136 | if (event_id < MaxNvEvents) { | 136 | if (event_id < MaxNvEvents) { |
| 137 | rb.PushCopyObjects(nvdrv->GetEvent(event_id)); | 137 | auto event = nvdrv->GetEvent(event_id); |
| 138 | event->Clear(); | ||
| 139 | rb.PushCopyObjects(event); | ||
| 138 | rb.Push<u32>(NvResult::Success); | 140 | rb.Push<u32>(NvResult::Success); |
| 139 | } else { | 141 | } else { |
| 140 | rb.Push<u32>(0); | 142 | rb.Push<u32>(0); |