summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.cpp44
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_consumer.h4
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_core.cpp1
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_core.h2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.cpp101
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.h2
-rw-r--r--src/core/hle/service/nvflinger/consumer_base.cpp29
-rw-r--r--src/core/hle/service/nvflinger/consumer_base.h3
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp4
9 files changed, 99 insertions, 91 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_)
18BufferQueueConsumer::~BufferQueueConsumer() = default; 18BufferQueueConsumer::~BufferQueueConsumer() = default;
19 19
20Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, 20Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
21 std::chrono::nanoseconds expected_present, 21 std::chrono::nanoseconds expected_present) {
22 u64 max_frame_number) {
23 std::scoped_lock lock(core->mutex); 22 std::scoped_lock lock(core->mutex);
24 23
25 // Check that the consumer doesn't currently have the maximum number of buffers acquired. 24 // Check that the consumer doesn't currently have the maximum number of buffers acquired.
@@ -50,12 +49,6 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
50 while (core->queue.size() > 1 && !core->queue[0].is_auto_timestamp) { 49 while (core->queue.size() > 1 && !core->queue[0].is_auto_timestamp) {
51 const auto& buffer_item{core->queue[1]}; 50 const auto& buffer_item{core->queue[1]};
52 51
53 // If dropping entry[0] would leave us with a buffer that the consumer is not yet ready
54 // for, don't drop it.
55 if (max_frame_number && buffer_item.frame_number > max_frame_number) {
56 break;
57 }
58
59 // If entry[1] is timely, drop entry[0] (and repeat). 52 // If entry[1] is timely, drop entry[0] (and repeat).
60 const auto desired_present = buffer_item.timestamp; 53 const auto desired_present = buffer_item.timestamp;
61 if (desired_present < expected_present.count() - MAX_REASONABLE_NSEC || 54 if (desired_present < expected_present.count() - MAX_REASONABLE_NSEC ||
@@ -200,4 +193,39 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_
200 return Status::NoError; 193 return Status::NoError;
201} 194}
202 195
196Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
197 if (out_slot_mask == nullptr) {
198 LOG_ERROR(Service_NVFlinger, "out_slot_mask may not be nullptr");
199 return Status::BadValue;
200 }
201
202 std::scoped_lock lock(core->mutex);
203
204 if (core->is_abandoned) {
205 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
206 return Status::NoInit;
207 }
208
209 u64 mask = 0;
210 for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
211 if (!slots[s].acquire_called) {
212 mask |= (1ULL << s);
213 }
214 }
215
216 // Remove from the mask queued buffers for which acquire has been called, since the consumer
217 // will not receive their buffer addresses and so must retain their cached information
218 auto current(core->queue.begin());
219 while (current != core->queue.end()) {
220 if (current->acquire_called) {
221 mask &= ~(1ULL << current->slot);
222 }
223 ++current;
224 }
225
226 LOG_DEBUG(Service_NVFlinger, "returning mask {}", mask);
227 *out_slot_mask = mask;
228 return Status::NoError;
229}
230
203} // namespace Service::android 231} // 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:
24 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_); 24 explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
25 ~BufferQueueConsumer(); 25 ~BufferQueueConsumer();
26 26
27 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present, 27 Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
28 u64 max_frame_number = 0);
29 Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence); 28 Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
30 Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app); 29 Status Connect(std::shared_ptr<IConsumerListener> consumer_listener, bool controlled_by_app);
30 Status GetReleasedBuffers(u64* out_slot_mask);
31 31
32private: 32private:
33 std::shared_ptr<BufferQueueCore> core; 33 std::shared_ptr<BufferQueueCore> core;
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp
index 6082610e0..3a0481786 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp
@@ -95,7 +95,6 @@ void BufferQueueCore::FreeBufferLocked(s32 slot) {
95} 95}
96 96
97void BufferQueueCore::FreeAllBuffersLocked() { 97void BufferQueueCore::FreeAllBuffersLocked() {
98 queue.clear();
99 buffer_has_been_queued = false; 98 buffer_has_been_queued = false;
100 99
101 for (s32 slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { 100 for (s32 slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvflinger/buffer_queue_core.h
index 4dfd53387..e4e0937cb 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_core.h
+++ b/src/core/hle/service/nvflinger/buffer_queue_core.h
@@ -73,8 +73,6 @@ private:
73 u32 transform_hint{}; 73 u32 transform_hint{};
74 bool is_allocating{}; 74 bool is_allocating{};
75 mutable std::condition_variable_any is_allocating_condition; 75 mutable std::condition_variable_any is_allocating_condition;
76 bool allow_allocation{true};
77 u64 buffer_age{};
78 bool is_shutting_down{}; 76 bool is_shutting_down{};
79}; 77};
80 78
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
index 0833be57a..3d6e990c3 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -62,11 +62,12 @@ Status BufferQueueProducer::RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffe
62 62
63Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { 63Status BufferQueueProducer::SetBufferCount(s32 buffer_count) {
64 LOG_DEBUG(Service_NVFlinger, "count = {}", buffer_count); 64 LOG_DEBUG(Service_NVFlinger, "count = {}", buffer_count);
65 std::shared_ptr<IConsumerListener> listener;
66 65
66 std::shared_ptr<IConsumerListener> listener;
67 { 67 {
68 std::scoped_lock lock(core->mutex); 68 std::scoped_lock lock(core->mutex);
69 core->WaitWhileAllocatingLocked(); 69 core->WaitWhileAllocatingLocked();
70
70 if (core->is_abandoned) { 71 if (core->is_abandoned) {
71 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); 72 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
72 return Status::NoInit; 73 return Status::NoInit;
@@ -120,7 +121,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) {
120} 121}
121 122
122Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, 123Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found,
123 Status* returnFlags) const { 124 Status* return_flags) const {
124 bool try_again = true; 125 bool try_again = true;
125 126
126 while (try_again) { 127 while (try_again) {
@@ -142,10 +143,12 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found,
142 ASSERT(slots[s].buffer_state == BufferState::Free); 143 ASSERT(slots[s].buffer_state == BufferState::Free);
143 if (slots[s].graphic_buffer != nullptr) { 144 if (slots[s].graphic_buffer != nullptr) {
144 core->FreeBufferLocked(s); 145 core->FreeBufferLocked(s);
145 *returnFlags |= Status::ReleaseAllBuffers; 146 *return_flags |= Status::ReleaseAllBuffers;
146 } 147 }
147 } 148 }
148 149
150 // Look for a free buffer to give to the client
151 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
149 s32 dequeued_count{}; 152 s32 dequeued_count{};
150 s32 acquired_count{}; 153 s32 acquired_count{};
151 for (s32 s{}; s < max_buffer_count; ++s) { 154 for (s32 s{}; s < max_buffer_count; ++s) {
@@ -235,68 +238,50 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool
235 { 238 {
236 std::scoped_lock lock(core->mutex); 239 std::scoped_lock lock(core->mutex);
237 core->WaitWhileAllocatingLocked(); 240 core->WaitWhileAllocatingLocked();
241
238 if (format == PixelFormat::NoFormat) { 242 if (format == PixelFormat::NoFormat) {
239 format = core->default_buffer_format; 243 format = core->default_buffer_format;
240 } 244 }
241 245
242 // Enable the usage bits the consumer requested 246 // Enable the usage bits the consumer requested
243 usage |= core->consumer_usage_bit; 247 usage |= core->consumer_usage_bit;
244 const bool use_default_size = !width && !height; 248
245 if (use_default_size) { 249 s32 found{};
246 width = core->default_width; 250 Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags);
247 height = core->default_height; 251 if (status != Status::NoError) {
252 return status;
248 } 253 }
249 254
250 s32 found = BufferItem::INVALID_BUFFER_SLOT; 255 // This should not happen
251 while (found == BufferItem::INVALID_BUFFER_SLOT) { 256 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
252 Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags); 257 LOG_ERROR(Service_NVFlinger, "no available buffer slots");
253 if (status != Status::NoError) { 258 return Status::Busy;
254 return status; 259 }
255 }
256 260
257 // This should not happen 261 *out_slot = found;
258 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
259 LOG_DEBUG(Service_NVFlinger, "no available buffer slots");
260 return Status::Busy;
261 }
262 262
263 const std::shared_ptr<GraphicBuffer>& buffer(slots[found].graphic_buffer); 263 attached_by_consumer = slots[found].attached_by_consumer;
264 264
265 // If we are not allowed to allocate new buffers, WaitForFreeSlotThenRelock must have 265 const bool use_default_size = !width && !height;
266 // returned a slot containing a buffer. If this buffer would require reallocation to 266 if (use_default_size) {
267 // meet the requested attributes, we free it and attempt to get another one. 267 width = core->default_width;
268 if (!core->allow_allocation) { 268 height = core->default_height;
269 if (buffer->NeedsReallocation(width, height, format, usage)) {
270 core->FreeBufferLocked(found);
271 found = BufferItem::INVALID_BUFFER_SLOT;
272 continue;
273 }
274 }
275 } 269 }
276 270
277 *out_slot = found;
278 attached_by_consumer = slots[found].attached_by_consumer;
279 slots[found].buffer_state = BufferState::Dequeued; 271 slots[found].buffer_state = BufferState::Dequeued;
280 272
281 const std::shared_ptr<GraphicBuffer>& buffer(slots[found].graphic_buffer); 273 const std::shared_ptr<GraphicBuffer>& buffer(slots[found].graphic_buffer);
282 274 if ((buffer == nullptr) || (buffer->Width() != width) || (buffer->Height() != height) ||
283 if ((buffer == nullptr) || buffer->NeedsReallocation(width, height, format, usage)) { 275 (buffer->Format() != format) || ((buffer->Usage() & usage) != usage)) {
284 slots[found].acquire_called = false; 276 slots[found].acquire_called = false;
285 slots[found].graphic_buffer = nullptr; 277 slots[found].graphic_buffer = nullptr;
286 slots[found].request_buffer_called = false; 278 slots[found].request_buffer_called = false;
287 slots[found].fence = Fence::NoFence(); 279 slots[found].fence = Fence::NoFence();
288 core->buffer_age = 0; 280
289 return_flags |= Status::BufferNeedsReallocation; 281 return_flags |= Status::BufferNeedsReallocation;
290 } else {
291 // We add 1 because that will be the frame number when this buffer
292 // is queued
293 core->buffer_age = core->frame_counter + 1 - slots[found].frame_number;
294 } 282 }
295 283
296 LOG_DEBUG(Service_NVFlinger, "setting buffer age to {}", core->buffer_age);
297
298 *out_fence = slots[found].fence; 284 *out_fence = slots[found].fence;
299
300 slots[found].fence = Fence::NoFence(); 285 slots[found].fence = Fence::NoFence();
301 } 286 }
302 287
@@ -311,6 +296,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool
311 296
312 { 297 {
313 std::scoped_lock lock(core->mutex); 298 std::scoped_lock lock(core->mutex);
299
314 if (core->is_abandoned) { 300 if (core->is_abandoned) {
315 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); 301 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
316 return Status::NoInit; 302 return Status::NoInit;
@@ -327,6 +313,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool
327 313
328 LOG_DEBUG(Service_NVFlinger, "returning slot={} frame={}, flags={}", *out_slot, 314 LOG_DEBUG(Service_NVFlinger, "returning slot={} frame={}, flags={}", *out_slot,
329 slots[*out_slot].frame_number, return_flags); 315 slots[*out_slot].frame_number, return_flags);
316
330 return return_flags; 317 return return_flags;
331} 318}
332 319
@@ -334,6 +321,7 @@ Status BufferQueueProducer::DetachBuffer(s32 slot) {
334 LOG_DEBUG(Service_NVFlinger, "slot {}", slot); 321 LOG_DEBUG(Service_NVFlinger, "slot {}", slot);
335 322
336 std::scoped_lock lock(core->mutex); 323 std::scoped_lock lock(core->mutex);
324
337 if (core->is_abandoned) { 325 if (core->is_abandoned) {
338 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned"); 326 LOG_ERROR(Service_NVFlinger, "BufferQueue has been abandoned");
339 return Status::NoInit; 327 return Status::NoInit;
@@ -369,7 +357,6 @@ Status BufferQueueProducer::DetachNextBuffer(std::shared_ptr<GraphicBuffer>* out
369 } 357 }
370 358
371 std::scoped_lock lock(core->mutex); 359 std::scoped_lock lock(core->mutex);
372
373 core->WaitWhileAllocatingLocked(); 360 core->WaitWhileAllocatingLocked();
374 361
375 if (core->is_abandoned) { 362 if (core->is_abandoned) {
@@ -423,6 +410,7 @@ Status BufferQueueProducer::AttachBuffer(s32* out_slot,
423 return status; 410 return status;
424 } 411 }
425 412
413 // This should not happen
426 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { 414 if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
427 LOG_ERROR(Service_NVFlinger, "No available buffer slots"); 415 LOG_ERROR(Service_NVFlinger, "No available buffer slots");
428 return Status::Busy; 416 return Status::Busy;
@@ -466,8 +454,8 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
466 return Status::BadValue; 454 return Status::BadValue;
467 } 455 }
468 456
469 std::shared_ptr<IConsumerListener> frameAvailableListener; 457 std::shared_ptr<IConsumerListener> frame_available_listener;
470 std::shared_ptr<IConsumerListener> frameReplacedListener; 458 std::shared_ptr<IConsumerListener> frame_replaced_listener;
471 s32 callback_ticket{}; 459 s32 callback_ticket{};
472 BufferItem item; 460 BufferItem item;
473 461
@@ -541,12 +529,13 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
541 item.fence = fence; 529 item.fence = fence;
542 item.is_droppable = core->dequeue_buffer_cannot_block || async; 530 item.is_droppable = core->dequeue_buffer_cannot_block || async;
543 item.swap_interval = swap_interval; 531 item.swap_interval = swap_interval;
532
544 sticky_transform = sticky_transform_; 533 sticky_transform = sticky_transform_;
545 534
546 if (core->queue.empty()) { 535 if (core->queue.empty()) {
547 // When the queue is empty, we can simply queue this buffer 536 // When the queue is empty, we can simply queue this buffer
548 core->queue.push_back(item); 537 core->queue.push_back(item);
549 frameAvailableListener = core->consumer_listener; 538 frame_available_listener = core->consumer_listener;
550 } else { 539 } else {
551 // When the queue is not empty, we need to look at the front buffer 540 // When the queue is not empty, we need to look at the front buffer
552 // state to see if we need to replace it 541 // state to see if we need to replace it
@@ -563,10 +552,10 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
563 } 552 }
564 // Overwrite the droppable buffer with the incoming one 553 // Overwrite the droppable buffer with the incoming one
565 *front = item; 554 *front = item;
566 frameReplacedListener = core->consumer_listener; 555 frame_replaced_listener = core->consumer_listener;
567 } else { 556 } else {
568 core->queue.push_back(item); 557 core->queue.push_back(item);
569 frameAvailableListener = core->consumer_listener; 558 frame_available_listener = core->consumer_listener;
570 } 559 }
571 } 560 }
572 561
@@ -592,10 +581,10 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
592 callback_condition.wait(callback_mutex); 581 callback_condition.wait(callback_mutex);
593 } 582 }
594 583
595 if (frameAvailableListener != nullptr) { 584 if (frame_available_listener != nullptr) {
596 frameAvailableListener->OnFrameAvailable(item); 585 frame_available_listener->OnFrameAvailable(item);
597 } else if (frameReplacedListener != nullptr) { 586 } else if (frame_replaced_listener != nullptr) {
598 frameReplacedListener->OnFrameReplaced(item); 587 frame_replaced_listener->OnFrameReplaced(item);
599 } 588 }
600 589
601 ++current_callback_ticket; 590 ++current_callback_ticket;
@@ -669,13 +658,6 @@ Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) {
669 case NativeWindow::ConsumerUsageBits: 658 case NativeWindow::ConsumerUsageBits:
670 value = core->consumer_usage_bit; 659 value = core->consumer_usage_bit;
671 break; 660 break;
672 case NativeWindow::BufferAge:
673 if (core->buffer_age > INT32_MAX) {
674 value = 0;
675 } else {
676 value = static_cast<u32>(core->buffer_age);
677 }
678 break;
679 default: 661 default:
680 UNREACHABLE(); 662 UNREACHABLE();
681 return Status::BadValue; 663 return Status::BadValue;
@@ -737,7 +719,6 @@ Status BufferQueueProducer::Connect(const std::shared_ptr<IProducerListener>& li
737 core->buffer_has_been_queued = false; 719 core->buffer_has_been_queued = false;
738 core->dequeue_buffer_cannot_block = 720 core->dequeue_buffer_cannot_block =
739 core->consumer_controlled_by_app && producer_controlled_by_app; 721 core->consumer_controlled_by_app && producer_controlled_by_app;
740 core->allow_allocation = true;
741 722
742 return status; 723 return status;
743} 724}
@@ -770,7 +751,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
770 core->SignalDequeueCondition(); 751 core->SignalDequeueCondition();
771 buffer_wait_event->GetWritableEvent().Signal(); 752 buffer_wait_event->GetWritableEvent().Signal();
772 listener = core->consumer_listener; 753 listener = core->consumer_listener;
773 } else if (core->connected_api != NativeWindowApi::NoConnectedApi) { 754 } else {
774 LOG_ERROR(Service_NVFlinger, "still connected to another api (cur = {} req = {})", 755 LOG_ERROR(Service_NVFlinger, "still connected to another api (cur = {} req = {})",
775 core->connected_api, api); 756 core->connected_api, api);
776 status = Status::BadValue; 757 status = Status::BadValue;
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h
index 77fdcae8e..c4ca68fd3 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h
@@ -66,7 +66,7 @@ public:
66private: 66private:
67 BufferQueueProducer(const BufferQueueProducer&) = delete; 67 BufferQueueProducer(const BufferQueueProducer&) = delete;
68 68
69 Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* returnFlags) const; 69 Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags) const;
70 70
71 Kernel::KEvent* buffer_wait_event{}; 71 Kernel::KEvent* buffer_wait_event{};
72 Service::KernelHelpers::ServiceContext& service_context; 72 Service::KernelHelpers::ServiceContext& service_context;
diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvflinger/consumer_base.cpp
index be65a3f88..c2c80832c 100644
--- a/src/core/hle/service/nvflinger/consumer_base.cpp
+++ b/src/core/hle/service/nvflinger/consumer_base.cpp
@@ -36,38 +36,41 @@ void ConsumerBase::FreeBufferLocked(s32 slot_index) {
36} 36}
37 37
38void ConsumerBase::OnFrameAvailable(const BufferItem& item) { 38void ConsumerBase::OnFrameAvailable(const BufferItem& item) {
39 std::scoped_lock lock(mutex);
40 LOG_DEBUG(Service_NVFlinger, "called"); 39 LOG_DEBUG(Service_NVFlinger, "called");
41} 40}
42 41
43void ConsumerBase::OnFrameReplaced(const BufferItem& item) { 42void ConsumerBase::OnFrameReplaced(const BufferItem& item) {
44 std::scoped_lock lock(mutex);
45 LOG_DEBUG(Service_NVFlinger, "called"); 43 LOG_DEBUG(Service_NVFlinger, "called");
46} 44}
47 45
48void ConsumerBase::OnBuffersReleased() { 46void ConsumerBase::OnBuffersReleased() {
49 std::scoped_lock lock(mutex); 47 std::scoped_lock lock(mutex);
50 LOG_DEBUG(Service_NVFlinger, "called");
51}
52 48
53void ConsumerBase::OnSidebandStreamChanged() {} 49 LOG_DEBUG(Service_NVFlinger, "called");
54 50
55Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when,
56 u64 max_frame_number) {
57 if (is_abandoned) { 51 if (is_abandoned) {
58 LOG_ERROR(Service_NVFlinger, "consumer is abandoned!"); 52 // Nothing to do if we're already abandoned.
59 return Status::NoInit; 53 return;
60 } 54 }
61 55
62 Status err = consumer->AcquireBuffer(item, present_when, max_frame_number); 56 u64 mask = 0;
57 consumer->GetReleasedBuffers(&mask);
58 for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
59 if (mask & (1ULL << i)) {
60 FreeBufferLocked(i);
61 }
62 }
63}
64
65void ConsumerBase::OnSidebandStreamChanged() {}
66
67Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when) {
68 Status err = consumer->AcquireBuffer(item, present_when);
63 if (err != Status::NoError) { 69 if (err != Status::NoError) {
64 return err; 70 return err;
65 } 71 }
66 72
67 if (item->graphic_buffer != nullptr) { 73 if (item->graphic_buffer != nullptr) {
68 if (slots[item->slot].graphic_buffer != nullptr) {
69 FreeBufferLocked(item->slot);
70 }
71 slots[item->slot].graphic_buffer = item->graphic_buffer; 74 slots[item->slot].graphic_buffer = item->graphic_buffer;
72 } 75 }
73 76
diff --git a/src/core/hle/service/nvflinger/consumer_base.h b/src/core/hle/service/nvflinger/consumer_base.h
index 9ab949420..736080e3a 100644
--- a/src/core/hle/service/nvflinger/consumer_base.h
+++ b/src/core/hle/service/nvflinger/consumer_base.h
@@ -35,8 +35,7 @@ protected:
35 virtual void OnSidebandStreamChanged() override; 35 virtual void OnSidebandStreamChanged() override;
36 36
37 void FreeBufferLocked(s32 slot_index); 37 void FreeBufferLocked(s32 slot_index);
38 Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when, 38 Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when);
39 u64 max_frame_number = 0);
40 Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer); 39 Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer);
41 bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer) const; 40 bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer) const;
42 Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer, 41 Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer,
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 76ce1fbfd..6fb2cdff1 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -104,7 +104,7 @@ void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
104std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) { 104std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
105 const auto lock_guard = Lock(); 105 const auto lock_guard = Lock();
106 106
107 LOG_DEBUG(Service, "Opening \"{}\" display", name); 107 LOG_DEBUG(Service_NVFlinger, "Opening \"{}\" display", name);
108 108
109 const auto itr = 109 const auto itr =
110 std::find_if(displays.begin(), displays.end(), 110 std::find_if(displays.begin(), displays.end(),
@@ -219,7 +219,7 @@ VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) {
219 auto* layer = display->FindLayer(layer_id); 219 auto* layer = display->FindLayer(layer_id);
220 220
221 if (layer == nullptr) { 221 if (layer == nullptr) {
222 LOG_DEBUG(Service, "Layer at id {} not found. Trying to create it.", layer_id); 222 LOG_DEBUG(Service_NVFlinger, "Layer at id {} not found. Trying to create it.", layer_id);
223 CreateLayerAtId(*display, layer_id); 223 CreateLayerAtId(*display, layer_id);
224 return display->FindLayer(layer_id); 224 return display->FindLayer(layer_id);
225 } 225 }