From 30b07878ba5487155bb6de2c91d27ed5b9b1c122 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Fri, 1 Apr 2022 22:58:02 -0700
Subject: [PATCH] hle: service: nvflinger: buffer_queue_producer: Cleanup & add
 GetReleasedBuffers.

---
 .../nvflinger/buffer_queue_consumer.cpp       | 44 +++++++++++++++----
 .../service/nvflinger/buffer_queue_consumer.h |  4 +-
 2 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
index 41fbba219..c527c577e 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp
@@ -18,8 +18,7 @@ BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
 BufferQueueConsumer::~BufferQueueConsumer() = default;
 
 Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
-                                          std::chrono::nanoseconds expected_present,
-                                          u64 max_frame_number) {
+                                          std::chrono::nanoseconds expected_present) {
     std::scoped_lock lock(core->mutex);
 
     // Check that the consumer doesn't currently have the maximum number of buffers acquired.
@@ -50,12 +49,6 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
         while (core->queue.size() > 1 && !core->queue[0].is_auto_timestamp) {
             const auto& buffer_item{core->queue[1]};
 
-            // If dropping entry[0] would leave us with a buffer that the consumer is not yet ready
-            // for, don't drop it.
-            if (max_frame_number && buffer_item.frame_number > max_frame_number) {
-                break;
-            }
-
             // If entry[1] is timely, drop entry[0] (and repeat).
             const auto desired_present = buffer_item.timestamp;
             if (desired_present < expected_present.count() - MAX_REASONABLE_NSEC ||
@@ -200,4 +193,39 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_
     return Status::NoError;
 }
 
+Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
+    if (out_slot_mask == nullptr) {
+        LOG_ERROR(Service_NVFlinger, "out_slot_mask may not be nullptr");
+        return Status::BadValue;
+    }
+
+    std::scoped_lock lock(core->mutex);
+
+    if (core->is_abandoned) {
+        LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
+        return Status::NoInit;
+    }
+
+    u64 mask = 0;
+    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+        if (!slots[s].acquire_called) {
+            mask |= (1ULL << s);
+        }
+    }
+
+    // Remove from the mask queued buffers for which acquire has been called, since the consumer
+    // will not receive their buffer addresses and so must retain their cached information
+    auto current(core->queue.begin());
+    while (current != core->queue.end()) {
+        if (current->acquire_called) {
+            mask &= ~(1ULL << current->slot);
+        }
+        ++current;
+    }
+
+    LOG_DEBUG(Service_NVFlinger, "returning mask {}", mask);
+    *out_slot_mask = mask;
+    return Status::NoError;
+}
+
 } // namespace Service::android
diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.h b/src/core/hle/service/nvflinger/buffer_queue_consumer.h
index f22854394..8a047fe06 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.h
@@ -24,10 +24,10 @@ public:
     explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
     ~BufferQueueConsumer();
 
-    Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present,
-                         u64 max_frame_number = 0);
+    Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
     Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
     Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
+    Status GetReleasedBuffers(u64* out_slot_mask);
 
 private:
     std::shared_ptr<BufferQueueCore> core;