From 873ad1272efca634eb1e3ccc53e1ede79022d66c Mon Sep 17 00:00:00 2001
From: ameerj <52414509+ameerj@users.noreply.github.com>
Date: Fri, 18 Dec 2020 00:12:14 -0500
Subject: [PATCH] buffer_queue: better use of std::array

---
 .../hle/service/nvflinger/buffer_queue.cpp    | 105 ++++++++----------
 1 file changed, 46 insertions(+), 59 deletions(-)

diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 101b004926..377f47e8ef 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -22,6 +22,7 @@ BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
 BufferQueue::~BufferQueue() = default;
 
 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);
@@ -44,73 +45,57 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue
     if (free_buffers.empty()) {
         return std::nullopt;
     }
-
     auto f_itr = free_buffers.begin();
-    auto itr = buffers.end();
+    auto slot = buffers.size();
 
     while (f_itr != free_buffers.end()) {
-        auto slot = *f_itr;
-        itr = std::find_if(buffers.begin(), buffers.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 != buffers.end()) {
+        const Buffer& buffer = buffers[*f_itr];
+        if (buffer.status == Buffer::Status::Free && buffer.igbp_buffer.width == width &&
+            buffer.igbp_buffer.height == height) {
+            slot = *f_itr;
             free_buffers.erase(f_itr);
             break;
         }
         ++f_itr;
     }
-
-    if (itr == buffers.end()) {
+    if (slot == buffers.size()) {
         return std::nullopt;
     }
-
-    itr->status = Buffer::Status::Dequeued;
-    return {{itr->slot, &itr->multi_fence}};
+    buffers[slot].status = Buffer::Status::Dequeued;
+    return {{buffers[slot].slot, &buffers[slot].multi_fence}};
 }
 
 const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
-    auto itr = std::find_if(buffers.begin(), buffers.end(),
-                            [&](const Buffer& buffer) { return buffer.slot == slot; });
-    ASSERT(itr != buffers.end());
-    ASSERT(itr->status == Buffer::Status::Dequeued);
-    return itr->igbp_buffer;
+    ASSERT(slot < buffers.size());
+    ASSERT(buffers[slot].status == Buffer::Status::Dequeued);
+    ASSERT(buffers[slot].slot == slot);
+
+    return buffers[slot].igbp_buffer;
 }
 
 void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
                               const Common::Rectangle<int>& crop_rect, u32 swap_interval,
                               Service::Nvidia::MultiFence& multi_fence) {
-    auto itr = std::find_if(buffers.begin(), buffers.end(),
-                            [&](const Buffer& buffer) { return buffer.slot == slot; });
-    ASSERT(itr != buffers.end());
-    ASSERT(itr->status == Buffer::Status::Dequeued);
-    itr->status = Buffer::Status::Queued;
-    itr->transform = transform;
-    itr->crop_rect = crop_rect;
-    itr->swap_interval = swap_interval;
-    itr->multi_fence = multi_fence;
+    ASSERT(slot < buffers.size());
+    ASSERT(buffers[slot].status == Buffer::Status::Dequeued);
+    ASSERT(buffers[slot].slot == slot);
+
+    buffers[slot].status = Buffer::Status::Queued;
+    buffers[slot].transform = transform;
+    buffers[slot].crop_rect = crop_rect;
+    buffers[slot].swap_interval = swap_interval;
+    buffers[slot].multi_fence = multi_fence;
     queue_sequence.push_back(slot);
 }
 
 void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) {
-    const auto itr = std::find_if(buffers.begin(), buffers.end(),
-                                  [slot](const Buffer& buffer) { return buffer.slot == slot; });
-    ASSERT(itr != buffers.end());
-    ASSERT(itr->status != Buffer::Status::Free);
-    itr->status = Buffer::Status::Free;
-    itr->multi_fence = multi_fence;
-    itr->swap_interval = 0;
+    ASSERT(slot < buffers.size());
+    ASSERT(buffers[slot].status != Buffer::Status::Free);
+    ASSERT(buffers[slot].slot == slot);
+
+    buffers[slot].status = Buffer::Status::Free;
+    buffers[slot].multi_fence = multi_fence;
+    buffers[slot].swap_interval = 0;
 
     free_buffers.push_back(slot);
 
@@ -118,28 +103,30 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
 }
 
 std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
-    auto itr = buffers.end();
+    std::size_t buffer_slot = buffers.size();
     // Iterate to find a queued buffer matching the requested slot.
-    while (itr == buffers.end() && !queue_sequence.empty()) {
-        const u32 slot = queue_sequence.front();
-        itr = std::find_if(buffers.begin(), buffers.end(), [&slot](const Buffer& buffer) {
-            return buffer.status == Buffer::Status::Queued && buffer.slot == slot;
-        });
+    while (buffer_slot == buffers.size() && !queue_sequence.empty()) {
+        const auto slot = static_cast<std::size_t>(queue_sequence.front());
+        ASSERT(slot < buffers.size());
+        if (buffers[slot].status == Buffer::Status::Queued) {
+            ASSERT(buffers[slot].slot == slot);
+            buffer_slot = slot;
+        }
         queue_sequence.pop_front();
     }
-    if (itr == buffers.end()) {
+    if (buffer_slot == buffers.size()) {
         return std::nullopt;
     }
-    itr->status = Buffer::Status::Acquired;
-    return *itr;
+    buffers[buffer_slot].status = Buffer::Status::Acquired;
+    return {{buffers[buffer_slot]}};
 }
 
 void BufferQueue::ReleaseBuffer(u32 slot) {
-    auto itr = std::find_if(buffers.begin(), buffers.end(),
-                            [&](const Buffer& buffer) { return buffer.slot == slot; });
-    ASSERT(itr != buffers.end());
-    ASSERT(itr->status == Buffer::Status::Acquired);
-    itr->status = Buffer::Status::Free;
+    ASSERT(slot < buffers.size());
+    ASSERT(buffers[slot].status == Buffer::Status::Acquired);
+    ASSERT(buffers[slot].slot == slot);
+
+    buffers[slot].status = Buffer::Status::Free;
     free_buffers.push_back(slot);
 
     buffer_wait_event.writable->Signal();