summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-01-08 20:28:06 -0500
committerGravatar bunnei2018-01-10 23:28:25 -0500
commite21fbd9ae5d8139d585019228e1fb1a6229f244c (patch)
tree931ddca10c9239a94ef1cacb1d86779a0adde8d2 /src
parentNV: Signal all display's vsync event 60 times per second. (diff)
downloadyuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.gz
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.tar.xz
yuzu-e21fbd9ae5d8139d585019228e1fb1a6229f244c.zip
NV: Determine what buffer to draw for each layer of each display.
Don't try to draw buffers that the guest application is using, only queued buffers are eligible for drawing. Drawing actual pixels is still not implemented.
Diffstat (limited to 'src')
-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 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/alignment.h" 5#include "common/alignment.h"
6#include "common/scope_exit.h"
6#include "core/core_timing.h" 7#include "core/core_timing.h"
7#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
8#include "core/hle/service/vi/vi.h" 9#include "core/hle/service/vi/vi.h"
@@ -721,8 +722,30 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) {
721 722
722void NVFlinger::Compose() { 723void NVFlinger::Compose() {
723 for (auto& display : displays) { 724 for (auto& display : displays) {
724 // TODO(Subv): Gather the surfaces and forward them to the GPU for drawing. 725 // Trigger vsync for this display at the end of drawing
725 display.vsync_event->Signal(); 726 SCOPE_EXIT({ display.vsync_event->Signal(); });
727
728 // Don't do anything for displays without layers.
729 if (display.layers.empty())
730 continue;
731
732 // TODO(Subv): Support more than 1 layer.
733 ASSERT_MSG(display.layers.size() == 1, "Max 1 layer per display is supported");
734
735 Layer& layer = display.layers[0];
736 auto& buffer_queue = layer.buffer_queue;
737
738 // Search for a queued buffer and acquire it
739 auto buffer = buffer_queue->AcquireBuffer();
740
741 if (buffer == boost::none) {
742 // There was no queued buffer to draw.
743 continue;
744 }
745
746 // TODO(Subv): Send the buffer to the GPU for drawing.
747
748 buffer_queue->ReleaseBuffer(buffer->slot);
726 } 749 }
727} 750}
728 751
@@ -732,7 +755,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
732 Buffer buffer{}; 755 Buffer buffer{};
733 buffer.slot = slot; 756 buffer.slot = slot;
734 buffer.igbp_buffer = igbp_buffer; 757 buffer.igbp_buffer = igbp_buffer;
735 buffer.status = Buffer::Status::Queued; 758 buffer.status = Buffer::Status::Free;
736 759
737 LOG_WARNING(Service, "Adding graphics buffer %u", slot); 760 LOG_WARNING(Service, "Adding graphics buffer %u", slot);
738 761
@@ -741,8 +764,9 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
741 764
742u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) { 765u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) {
743 auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { 766 auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
744 // Only consider enqueued buffers 767 // Only consider free buffers. Buffers become free once again after they've been Acquired
745 if (buffer.status != Buffer::Status::Queued) 768 // and Released by the compositor, see the NVFlinger::Compose method.
769 if (buffer.status != Buffer::Status::Free)
746 return false; 770 return false;
747 771
748 // Make sure that the parameters match. 772 // Make sure that the parameters match.
@@ -772,6 +796,24 @@ void BufferQueue::QueueBuffer(u32 slot) {
772 itr->status = Buffer::Status::Queued; 796 itr->status = Buffer::Status::Queued;
773} 797}
774 798
799boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() {
800 auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) {
801 return buffer.status == Buffer::Status::Queued;
802 });
803 if (itr == queue.end())
804 return boost::none;
805 itr->status = Buffer::Status::Acquired;
806 return *itr;
807}
808
809void BufferQueue::ReleaseBuffer(u32 slot) {
810 auto itr = std::find_if(queue.begin(), queue.end(),
811 [&](const Buffer& buffer) { return buffer.slot == slot; });
812 ASSERT(itr != queue.end());
813 ASSERT(itr->status == Buffer::Status::Acquired);
814 itr->status = Buffer::Status::Free;
815}
816
775Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {} 817Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {}
776 818
777Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { 819Display::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 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <boost/optional.hpp>
8#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
9#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
10 11
@@ -34,10 +35,20 @@ public:
34 BufferQueue(u32 id, u64 layer_id); 35 BufferQueue(u32 id, u64 layer_id);
35 ~BufferQueue() = default; 36 ~BufferQueue() = default;
36 37
38 struct Buffer {
39 enum class Status { Free = 0, Queued = 1, Dequeued = 2, Acquired = 3 };
40
41 u32 slot;
42 Status status = Status::Free;
43 IGBPBuffer igbp_buffer;
44 };
45
37 void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer); 46 void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
38 u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height); 47 u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height);
39 const IGBPBuffer& RequestBuffer(u32 slot) const; 48 const IGBPBuffer& RequestBuffer(u32 slot) const;
40 void QueueBuffer(u32 slot); 49 void QueueBuffer(u32 slot);
50 boost::optional<const Buffer&> AcquireBuffer();
51 void ReleaseBuffer(u32 slot);
41 52
42 u32 GetId() const { 53 u32 GetId() const {
43 return id; 54 return id;
@@ -47,14 +58,6 @@ private:
47 u32 id; 58 u32 id;
48 u64 layer_id; 59 u64 layer_id;
49 60
50 struct Buffer {
51 enum class Status { None = 0, Queued = 1, Dequeued = 2 };
52
53 u32 slot;
54 Status status = Status::None;
55 IGBPBuffer igbp_buffer;
56 };
57
58 std::vector<Buffer> queue; 61 std::vector<Buffer> queue;
59}; 62};
60 63