summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/vi
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2018-01-09 02:28:06 +0100
committerbunnei <bunneidev@gmail.com>2018-01-11 05:28:25 +0100
commite21fbd9ae5d8139d585019228e1fb1a6229f244c (patch)
tree931ddca10c9239a94ef1cacb1d86779a0adde8d2 /src/core/hle/service/vi
parentNV: Signal all display's vsync event 60 times per second. (diff)
downloadyuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.gz
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.bz2
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.lz
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.xz
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.zst
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.zip
Diffstat (limited to 'src/core/hle/service/vi')
-rw-r--r--src/core/hle/service/vi/vi.cpp52
-rw-r--r--src/core/hle/service/vi/vi.h19
2 files changed, 58 insertions, 13 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)) {
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 1bd8f7472..576c4ce32 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -5,6 +5,7 @@
#pragma once
#include <memory>
+#include <boost/optional.hpp>
#include "core/hle/kernel/event.h"
#include "core/hle/service/service.h"
@@ -34,10 +35,20 @@ public:
BufferQueue(u32 id, u64 layer_id);
~BufferQueue() = default;
+ struct Buffer {
+ enum class Status { Free = 0, Queued = 1, Dequeued = 2, Acquired = 3 };
+
+ u32 slot;
+ Status status = Status::Free;
+ IGBPBuffer igbp_buffer;
+ };
+
void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height);
const IGBPBuffer& RequestBuffer(u32 slot) const;
void QueueBuffer(u32 slot);
+ boost::optional<const Buffer&> AcquireBuffer();
+ void ReleaseBuffer(u32 slot);
u32 GetId() const {
return id;
@@ -47,14 +58,6 @@ private:
u32 id;
u64 layer_id;
- struct Buffer {
- enum class Status { None = 0, Queued = 1, Dequeued = 2 };
-
- u32 slot;
- Status status = Status::None;
- IGBPBuffer igbp_buffer;
- };
-
std::vector<Buffer> queue;
};