vi: Remove DequeueBuffer and wait until next available buffer.
This commit is contained in:
parent
c86af6939c
commit
c1c92c30f9
|
@ -26,24 +26,30 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
|
||||||
LOG_WARNING(Service, "Adding graphics buffer %u", slot);
|
LOG_WARNING(Service, "Adding graphics buffer %u", slot);
|
||||||
|
|
||||||
queue.emplace_back(buffer);
|
queue.emplace_back(buffer);
|
||||||
|
|
||||||
|
if (buffer_wait_event) {
|
||||||
|
buffer_wait_event->Signal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) {
|
boost::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
|
||||||
auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
|
auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
|
||||||
// Only consider free buffers. Buffers become free once again after they've been Acquired
|
// Only consider free buffers. Buffers become free once again after they've been Acquired
|
||||||
// and Released by the compositor, see the NVFlinger::Compose method.
|
// and Released by the compositor, see the NVFlinger::Compose method.
|
||||||
if (buffer.status != Buffer::Status::Free)
|
if (buffer.status != Buffer::Status::Free) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the parameters match.
|
// Make sure that the parameters match.
|
||||||
return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
|
return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (itr == queue.end()) {
|
if (itr == queue.end()) {
|
||||||
LOG_CRITICAL(Service_NVDRV, "no free buffers for pixel_format=%d, width=%d, height=%d",
|
return boost::none;
|
||||||
pixel_format, width, height);
|
|
||||||
itr = queue.begin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer_wait_event = nullptr;
|
||||||
|
|
||||||
itr->status = Buffer::Status::Dequeued;
|
itr->status = Buffer::Status::Dequeued;
|
||||||
return itr->slot;
|
return itr->slot;
|
||||||
}
|
}
|
||||||
|
@ -81,6 +87,10 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
|
||||||
ASSERT(itr != queue.end());
|
ASSERT(itr != queue.end());
|
||||||
ASSERT(itr->status == Buffer::Status::Acquired);
|
ASSERT(itr->status == Buffer::Status::Acquired);
|
||||||
itr->status = Buffer::Status::Free;
|
itr->status = Buffer::Status::Free;
|
||||||
|
|
||||||
|
if (buffer_wait_event) {
|
||||||
|
buffer_wait_event->Signal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 BufferQueue::Query(QueryType type) {
|
u32 BufferQueue::Query(QueryType type) {
|
||||||
|
@ -96,5 +106,10 @@ u32 BufferQueue::Query(QueryType type) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_event) {
|
||||||
|
ASSERT_MSG(!buffer_wait_event, "buffer_wait_event only supports a single waiting thread!");
|
||||||
|
buffer_wait_event = std::move(wait_event);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace NVFlinger
|
} // namespace NVFlinger
|
||||||
} // namespace Service
|
} // namespace Service
|
||||||
|
|
|
@ -69,12 +69,13 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
|
void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
|
||||||
u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height);
|
boost::optional<u32> DequeueBuffer(u32 width, u32 height);
|
||||||
const IGBPBuffer& RequestBuffer(u32 slot) const;
|
const IGBPBuffer& RequestBuffer(u32 slot) const;
|
||||||
void QueueBuffer(u32 slot, BufferTransformFlags transform);
|
void QueueBuffer(u32 slot, BufferTransformFlags transform);
|
||||||
boost::optional<const Buffer&> AcquireBuffer();
|
boost::optional<const Buffer&> AcquireBuffer();
|
||||||
void ReleaseBuffer(u32 slot);
|
void ReleaseBuffer(u32 slot);
|
||||||
u32 Query(QueryType type);
|
u32 Query(QueryType type);
|
||||||
|
void SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_event);
|
||||||
|
|
||||||
u32 GetId() const {
|
u32 GetId() const {
|
||||||
return id;
|
return id;
|
||||||
|
@ -90,6 +91,9 @@ private:
|
||||||
|
|
||||||
std::vector<Buffer> queue;
|
std::vector<Buffer> queue;
|
||||||
Kernel::SharedPtr<Kernel::Event> native_handle;
|
Kernel::SharedPtr<Kernel::Event> native_handle;
|
||||||
|
|
||||||
|
/// Used to signal waiting thread when no buffers are available
|
||||||
|
Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace NVFlinger
|
} // namespace NVFlinger
|
||||||
|
|
|
@ -486,12 +486,30 @@ private:
|
||||||
ctx.WriteBuffer(response.Serialize());
|
ctx.WriteBuffer(response.Serialize());
|
||||||
} else if (transaction == TransactionId::DequeueBuffer) {
|
} else if (transaction == TransactionId::DequeueBuffer) {
|
||||||
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
|
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
|
||||||
|
const u32 width{request.data.width};
|
||||||
|
const u32 height{request.data.height};
|
||||||
|
boost::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
|
||||||
|
|
||||||
u32 slot = buffer_queue->DequeueBuffer(request.data.pixel_format, request.data.width,
|
if (slot != boost::none) {
|
||||||
request.data.height);
|
// Buffer is available
|
||||||
|
IGBPDequeueBufferResponseParcel response{*slot};
|
||||||
IGBPDequeueBufferResponseParcel response{slot};
|
ctx.WriteBuffer(response.Serialize());
|
||||||
ctx.WriteBuffer(response.Serialize());
|
} else {
|
||||||
|
// Wait the current thread until a buffer becomes available
|
||||||
|
auto wait_event = ctx.SleepClientThread(
|
||||||
|
Kernel::GetCurrentThread(), "IHOSBinderDriver::DequeueBuffer", -1,
|
||||||
|
[=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||||
|
ThreadWakeupReason reason) {
|
||||||
|
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
||||||
|
auto buffer_queue = nv_flinger->GetBufferQueue(id);
|
||||||
|
boost::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
|
||||||
|
IGBPDequeueBufferResponseParcel response{*slot};
|
||||||
|
ctx.WriteBuffer(response.Serialize());
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
});
|
||||||
|
buffer_queue->SetBufferWaitEvent(std::move(wait_event));
|
||||||
|
}
|
||||||
} else if (transaction == TransactionId::RequestBuffer) {
|
} else if (transaction == TransactionId::RequestBuffer) {
|
||||||
IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
|
IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
|
||||||
|
|
||||||
|
|
Reference in New Issue