diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 52 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.h | 19 |
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 | ||
| 722 | void NVFlinger::Compose() { | 723 | void 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 | ||
| 742 | u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) { | 765 | u32 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 | ||
| 799 | boost::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 | |||
| 809 | void 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 | |||
| 775 | Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {} | 817 | Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {} |
| 776 | 818 | ||
| 777 | Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { | 819 | 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 @@ | |||
| 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 | ||