summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-03-18 20:27:15 -0400
committerGravatar bunnei2018-03-18 20:56:35 -0400
commitc1c92c30f9951e41a2091770cc5bf1354fba7794 (patch)
tree2304ea66a7dbca1f1848c316976a24203c24a5c6 /src
parenthle_ipc: Add SleepClientThread to block current thread within HLE routines. (diff)
downloadyuzu-c1c92c30f9951e41a2091770cc5bf1354fba7794.tar.gz
yuzu-c1c92c30f9951e41a2091770cc5bf1354fba7794.tar.xz
yuzu-c1c92c30f9951e41a2091770cc5bf1354fba7794.zip
vi: Remove DequeueBuffer and wait until next available buffer.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp25
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h6
-rw-r--r--src/core/hle/service/vi/vi.cpp30
3 files changed, 49 insertions, 12 deletions
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index e2c25048b..e4ff2e267 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -26,24 +26,30 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
26 LOG_WARNING(Service, "Adding graphics buffer %u", slot); 26 LOG_WARNING(Service, "Adding graphics buffer %u", slot);
27 27
28 queue.emplace_back(buffer); 28 queue.emplace_back(buffer);
29
30 if (buffer_wait_event) {
31 buffer_wait_event->Signal();
32 }
29} 33}
30 34
31u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) { 35boost::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
32 auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { 36 auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
33 // Only consider free buffers. Buffers become free once again after they've been Acquired 37 // Only consider free buffers. Buffers become free once again after they've been Acquired
34 // and Released by the compositor, see the NVFlinger::Compose method. 38 // and Released by the compositor, see the NVFlinger::Compose method.
35 if (buffer.status != Buffer::Status::Free) 39 if (buffer.status != Buffer::Status::Free) {
36 return false; 40 return false;
41 }
37 42
38 // Make sure that the parameters match. 43 // Make sure that the parameters match.
39 return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height; 44 return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
40 }); 45 });
46
41 if (itr == queue.end()) { 47 if (itr == queue.end()) {
42 LOG_CRITICAL(Service_NVDRV, "no free buffers for pixel_format=%d, width=%d, height=%d", 48 return boost::none;
43 pixel_format, width, height);
44 itr = queue.begin();
45 } 49 }
46 50
51 buffer_wait_event = nullptr;
52
47 itr->status = Buffer::Status::Dequeued; 53 itr->status = Buffer::Status::Dequeued;
48 return itr->slot; 54 return itr->slot;
49} 55}
@@ -81,6 +87,10 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
81 ASSERT(itr != queue.end()); 87 ASSERT(itr != queue.end());
82 ASSERT(itr->status == Buffer::Status::Acquired); 88 ASSERT(itr->status == Buffer::Status::Acquired);
83 itr->status = Buffer::Status::Free; 89 itr->status = Buffer::Status::Free;
90
91 if (buffer_wait_event) {
92 buffer_wait_event->Signal();
93 }
84} 94}
85 95
86u32 BufferQueue::Query(QueryType type) { 96u32 BufferQueue::Query(QueryType type) {
@@ -96,5 +106,10 @@ u32 BufferQueue::Query(QueryType type) {
96 return 0; 106 return 0;
97} 107}
98 108
109void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_event) {
110 ASSERT_MSG(!buffer_wait_event, "buffer_wait_event only supports a single waiting thread!");
111 buffer_wait_event = std::move(wait_event);
112}
113
99} // namespace NVFlinger 114} // namespace NVFlinger
100} // namespace Service 115} // namespace Service
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index ef9732769..686eadca7 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -69,12 +69,13 @@ public:
69 }; 69 };
70 70
71 void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer); 71 void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
72 u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height); 72 boost::optional<u32> DequeueBuffer(u32 width, u32 height);
73 const IGBPBuffer& RequestBuffer(u32 slot) const; 73 const IGBPBuffer& RequestBuffer(u32 slot) const;
74 void QueueBuffer(u32 slot, BufferTransformFlags transform); 74 void QueueBuffer(u32 slot, BufferTransformFlags transform);
75 boost::optional<const Buffer&> AcquireBuffer(); 75 boost::optional<const Buffer&> AcquireBuffer();
76 void ReleaseBuffer(u32 slot); 76 void ReleaseBuffer(u32 slot);
77 u32 Query(QueryType type); 77 u32 Query(QueryType type);
78 void SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_event);
78 79
79 u32 GetId() const { 80 u32 GetId() const {
80 return id; 81 return id;
@@ -90,6 +91,9 @@ private:
90 91
91 std::vector<Buffer> queue; 92 std::vector<Buffer> queue;
92 Kernel::SharedPtr<Kernel::Event> native_handle; 93 Kernel::SharedPtr<Kernel::Event> native_handle;
94
95 /// Used to signal waiting thread when no buffers are available
96 Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
93}; 97};
94 98
95} // namespace NVFlinger 99} // namespace NVFlinger
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 0aa621dfe..7b6453447 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -486,12 +486,30 @@ private:
486 ctx.WriteBuffer(response.Serialize()); 486 ctx.WriteBuffer(response.Serialize());
487 } else if (transaction == TransactionId::DequeueBuffer) { 487 } else if (transaction == TransactionId::DequeueBuffer) {
488 IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; 488 IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
489 489 const u32 width{request.data.width};
490 u32 slot = buffer_queue->DequeueBuffer(request.data.pixel_format, request.data.width, 490 const u32 height{request.data.height};
491 request.data.height); 491 boost::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
492 492
493 IGBPDequeueBufferResponseParcel response{slot}; 493 if (slot != boost::none) {
494 ctx.WriteBuffer(response.Serialize()); 494 // Buffer is available
495 IGBPDequeueBufferResponseParcel response{*slot};
496 ctx.WriteBuffer(response.Serialize());
497 } else {
498 // Wait the current thread until a buffer becomes available
499 auto wait_event = ctx.SleepClientThread(
500 Kernel::GetCurrentThread(), "IHOSBinderDriver::DequeueBuffer", -1,
501 [=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
502 ThreadWakeupReason reason) {
503 // Repeat TransactParcel DequeueBuffer when a buffer is available
504 auto buffer_queue = nv_flinger->GetBufferQueue(id);
505 boost::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
506 IGBPDequeueBufferResponseParcel response{*slot};
507 ctx.WriteBuffer(response.Serialize());
508 IPC::ResponseBuilder rb{ctx, 2};
509 rb.Push(RESULT_SUCCESS);
510 });
511 buffer_queue->SetBufferWaitEvent(std::move(wait_event));
512 }
495 } else if (transaction == TransactionId::RequestBuffer) { 513 } else if (transaction == TransactionId::RequestBuffer) {
496 IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()}; 514 IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
497 515