diff options
Diffstat (limited to 'src/core/hle/service/nvflinger/buffer_queue.cpp')
-rw-r--r-- | src/core/hle/service/nvflinger/buffer_queue.cpp | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 377f47e8e..c68905e19 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -25,7 +25,12 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) ASSERT(slot < buffer_slots); LOG_WARNING(Service, "Adding graphics buffer {}", slot); - free_buffers.push_back(slot); + { + std::unique_lock lock{free_buffers_mutex}; + free_buffers.push_back(slot); + } + free_buffers_condition.notify_one(); + buffers[slot] = { .slot = slot, .status = Buffer::Status::Free, @@ -41,10 +46,20 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, u32 height) { + // Wait for first request before trying to dequeue + { + std::unique_lock lock{free_buffers_mutex}; + free_buffers_condition.wait(lock, [this] { return !free_buffers.empty() || !is_connect; }); + } - if (free_buffers.empty()) { + if (!is_connect) { + // Buffer was disconnected while the thread was blocked, this is most likely due to + // emulation being stopped return std::nullopt; } + + std::unique_lock lock{free_buffers_mutex}; + auto f_itr = free_buffers.begin(); auto slot = buffers.size(); @@ -85,6 +100,7 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, buffers[slot].crop_rect = crop_rect; buffers[slot].swap_interval = swap_interval; buffers[slot].multi_fence = multi_fence; + std::unique_lock lock{queue_sequence_mutex}; queue_sequence.push_back(slot); } @@ -97,12 +113,17 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult buffers[slot].multi_fence = multi_fence; buffers[slot].swap_interval = 0; - free_buffers.push_back(slot); + { + std::unique_lock lock{free_buffers_mutex}; + free_buffers.push_back(slot); + } + free_buffers_condition.notify_one(); buffer_wait_event.writable->Signal(); } std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { + std::unique_lock lock{queue_sequence_mutex}; std::size_t buffer_slot = buffers.size(); // Iterate to find a queued buffer matching the requested slot. while (buffer_slot == buffers.size() && !queue_sequence.empty()) { @@ -127,15 +148,30 @@ void BufferQueue::ReleaseBuffer(u32 slot) { ASSERT(buffers[slot].slot == slot); buffers[slot].status = Buffer::Status::Free; - free_buffers.push_back(slot); + { + std::unique_lock lock{free_buffers_mutex}; + free_buffers.push_back(slot); + } + free_buffers_condition.notify_one(); buffer_wait_event.writable->Signal(); } +void BufferQueue::Connect() { + std::unique_lock lock{queue_sequence_mutex}; + queue_sequence.clear(); + is_connect = true; +} + void BufferQueue::Disconnect() { buffers.fill({}); - queue_sequence.clear(); + { + std::unique_lock lock{queue_sequence_mutex}; + queue_sequence.clear(); + } buffer_wait_event.writable->Signal(); + is_connect = false; + free_buffers_condition.notify_one(); } u32 BufferQueue::Query(QueryType type) { |