From 170e19d4eab455ad4d28ad72799cc6687692392d Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 17 Jul 2018 00:05:13 -0400 Subject: nvflinger: Fix for BufferQueue event handling. --- src/core/hle/kernel/hle_ipc.cpp | 10 ++++++++-- src/core/hle/kernel/hle_ipc.h | 4 +++- src/core/hle/service/nvflinger/buffer_queue.cpp | 20 ++++---------------- src/core/hle/service/nvflinger/buffer_queue.h | 8 ++------ src/core/hle/service/nvflinger/nvflinger.cpp | 3 --- src/core/hle/service/vi/vi.cpp | 8 ++++---- 6 files changed, 21 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 2532dd450..b1e6f565b 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -29,7 +29,8 @@ void SessionRequestHandler::ClientDisconnected(SharedPtr server_s SharedPtr HLERequestContext::SleepClientThread(SharedPtr thread, const std::string& reason, u64 timeout, - WakeupCallback&& callback) { + WakeupCallback&& callback, + Kernel::SharedPtr event) { // Put the client thread to sleep until the wait event is signaled or the timeout expires. thread->wakeup_callback = @@ -41,7 +42,12 @@ SharedPtr HLERequestContext::SleepClientThread(SharedPtr thread, return true; }; - auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason); + if (!event) { + // Create event if not provided + event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason); + } + + event->Clear(); thread->status = THREADSTATUS_WAIT_HLE_EVENT; thread->wait_objects = {event}; event->AddWaitingThread(thread); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 376263eac..c6eca7404 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -118,10 +118,12 @@ public: * @param callback Callback to be invoked when the thread is resumed. This callback must write * the entire command response once again, regardless of the state of it before this function * was called. + * @param event Event to use to wake up the thread. If unspecified, an event will be created. * @returns Event that when signaled will resume the thread and call the callback function. */ SharedPtr SleepClientThread(SharedPtr thread, const std::string& reason, - u64 timeout, WakeupCallback&& callback); + u64 timeout, WakeupCallback&& callback, + Kernel::SharedPtr event = nullptr); void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming); diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index f7f2fe1b2..a181cd2dc 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -13,8 +13,8 @@ namespace Service { namespace NVFlinger { BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { - native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); - native_handle->Signal(); + buffer_wait_event = + Kernel::Event::Create(Kernel::ResetType::Sticky, "BufferQueue NativeHandle"); } void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { @@ -26,10 +26,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { LOG_WARNING(Service, "Adding graphics buffer {}", slot); queue.emplace_back(buffer); - - if (buffer_wait_event) { - buffer_wait_event->Signal(); - } + buffer_wait_event->Signal(); } boost::optional BufferQueue::DequeueBuffer(u32 width, u32 height) { @@ -48,8 +45,6 @@ boost::optional BufferQueue::DequeueBuffer(u32 width, u32 height) { return boost::none; } - buffer_wait_event = nullptr; - itr->status = Buffer::Status::Dequeued; return itr->slot; } @@ -88,9 +83,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) { ASSERT(itr->status == Buffer::Status::Acquired); itr->status = Buffer::Status::Free; - if (buffer_wait_event) { - buffer_wait_event->Signal(); - } + buffer_wait_event->Signal(); } u32 BufferQueue::Query(QueryType type) { @@ -106,10 +99,5 @@ u32 BufferQueue::Query(QueryType type) { return 0; } -void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr&& wait_event) { - ASSERT_MSG(!buffer_wait_event, "buffer_wait_event only supports a single waiting thread!"); - buffer_wait_event = std::move(wait_event); -} - } // namespace NVFlinger } // namespace Service diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 1de5767cb..1e55b487e 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -77,14 +77,13 @@ public: boost::optional AcquireBuffer(); void ReleaseBuffer(u32 slot); u32 Query(QueryType type); - void SetBufferWaitEvent(Kernel::SharedPtr&& wait_event); u32 GetId() const { return id; } - Kernel::SharedPtr GetNativeHandle() const { - return native_handle; + Kernel::SharedPtr GetBufferWaitEvent() const { + return buffer_wait_event; } private: @@ -92,9 +91,6 @@ private: u64 layer_id; std::vector queue; - Kernel::SharedPtr native_handle; - - /// Used to signal waiting thread when no buffers are available Kernel::SharedPtr buffer_wait_event; }; diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index ef3c2cc98..826646b7d 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -152,9 +152,6 @@ void NVFlinger::Compose() { igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform); buffer_queue->ReleaseBuffer(buffer->slot); - - // TODO(Subv): Figure out when we should actually signal this event. - buffer_queue->GetNativeHandle()->Signal(); } } diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index f3765b555..e094510bf 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -495,7 +495,7 @@ private: ctx.WriteBuffer(response.Serialize()); } else { // Wait the current thread until a buffer becomes available - auto wait_event = ctx.SleepClientThread( + ctx.SleepClientThread( Kernel::GetCurrentThread(), "IHOSBinderDriver::DequeueBuffer", -1, [=](Kernel::SharedPtr thread, Kernel::HLERequestContext& ctx, ThreadWakeupReason reason) { @@ -506,8 +506,8 @@ private: ctx.WriteBuffer(response.Serialize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - }); - buffer_queue->SetBufferWaitEvent(std::move(wait_event)); + }, + buffer_queue->GetBufferWaitEvent()); } } else if (transaction == TransactionId::RequestBuffer) { IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()}; @@ -565,7 +565,7 @@ private: LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(buffer_queue->GetNativeHandle()); + rb.PushCopyObjects(buffer_queue->GetBufferWaitEvent()); } std::shared_ptr nv_flinger; -- cgit v1.2.3