From 486a42c45acf8dd85b426b00b524c372a9cae1df Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 10 Apr 2020 16:36:59 -0400 Subject: Buffer queue: Correct behavior of free buffer. This corrects the behavior of free buffer after witnessing it in an unrelated hardware test. I haven't found any games affected by it but in name of better accuracy we'll correct such behavior. --- src/core/hle/service/nvflinger/buffer_queue.cpp | 41 +++++++++++++++++++------ src/core/hle/service/nvflinger/buffer_queue.h | 1 + 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 32b6f4b27..9bcafa5fc 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -28,6 +28,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) buffer.slot = slot; buffer.igbp_buffer = igbp_buffer; buffer.status = Buffer::Status::Free; + free_buffers.push_back(slot); queue.emplace_back(buffer); buffer_wait_event.writable->Signal(); @@ -35,16 +36,37 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) std::optional> BufferQueue::DequeueBuffer(u32 width, u32 height) { - auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { - // Only consider free buffers. Buffers become free once again after they've been Acquired - // and Released by the compositor, see the NVFlinger::Compose method. - if (buffer.status != Buffer::Status::Free) { - return false; - } - // Make sure that the parameters match. - return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height; - }); + if (free_buffers.empty()) { + return {}; + } + + auto f_itr = free_buffers.begin(); + auto itr = queue.end(); + + while (f_itr != free_buffers.end()) { + auto slot = *f_itr; + itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { + // Only consider free buffers. Buffers become free once again after they've been + // Acquired and Released by the compositor, see the NVFlinger::Compose method. + if (buffer.status != Buffer::Status::Free) { + return false; + } + + if (buffer.slot != slot) { + return false; + } + + // Make sure that the parameters match. + return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height; + }); + + if (itr != queue.end()) { + free_buffers.erase(f_itr); + break; + } + ++f_itr; + } if (itr == queue.end()) { return {}; @@ -99,6 +121,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) { ASSERT(itr != queue.end()); ASSERT(itr->status == Buffer::Status::Acquired); itr->status = Buffer::Status::Free; + free_buffers.push_back(slot); buffer_wait_event.writable->Signal(); } diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index f4bbfd945..f674823b0 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -101,6 +101,7 @@ private: u32 id; u64 layer_id; + std::list free_buffers; std::vector queue; std::list queue_sequence; Kernel::EventPair buffer_wait_event; -- cgit v1.2.3