diff options
Diffstat (limited to 'src/core/hle/service/vi/vi.cpp')
-rw-r--r-- | src/core/hle/service/vi/vi.cpp | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index fab7a12e4..67d82c2bf 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/alignment.h" +#include "common/scope_exit.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/vi/vi.h" @@ -721,8 +722,30 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) { void NVFlinger::Compose() { for (auto& display : displays) { - // TODO(Subv): Gather the surfaces and forward them to the GPU for drawing. - display.vsync_event->Signal(); + // Trigger vsync for this display at the end of drawing + SCOPE_EXIT({ display.vsync_event->Signal(); }); + + // Don't do anything for displays without layers. + if (display.layers.empty()) + continue; + + // TODO(Subv): Support more than 1 layer. + ASSERT_MSG(display.layers.size() == 1, "Max 1 layer per display is supported"); + + Layer& layer = display.layers[0]; + auto& buffer_queue = layer.buffer_queue; + + // Search for a queued buffer and acquire it + auto buffer = buffer_queue->AcquireBuffer(); + + if (buffer == boost::none) { + // There was no queued buffer to draw. + continue; + } + + // TODO(Subv): Send the buffer to the GPU for drawing. + + buffer_queue->ReleaseBuffer(buffer->slot); } } @@ -732,7 +755,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { Buffer buffer{}; buffer.slot = slot; buffer.igbp_buffer = igbp_buffer; - buffer.status = Buffer::Status::Queued; + buffer.status = Buffer::Status::Free; LOG_WARNING(Service, "Adding graphics buffer %u", slot); @@ -741,8 +764,9 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) { auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { - // Only consider enqueued buffers - if (buffer.status != Buffer::Status::Queued) + // 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; // Make sure that the parameters match. @@ -772,6 +796,24 @@ void BufferQueue::QueueBuffer(u32 slot) { itr->status = Buffer::Status::Queued; } +boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() { + auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) { + return buffer.status == Buffer::Status::Queued; + }); + if (itr == queue.end()) + return boost::none; + itr->status = Buffer::Status::Acquired; + return *itr; +} + +void BufferQueue::ReleaseBuffer(u32 slot) { + auto itr = std::find_if(queue.begin(), queue.end(), + [&](const Buffer& buffer) { return buffer.slot == slot; }); + ASSERT(itr != queue.end()); + ASSERT(itr->status == Buffer::Status::Acquired); + itr->status = Buffer::Status::Free; +} + Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {} Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { |