summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp41
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h3
-rw-r--r--src/core/hle/service/vi/vi.cpp16
3 files changed, 33 insertions, 27 deletions
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 191286ce9..101b00492 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -25,7 +25,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
25 LOG_WARNING(Service, "Adding graphics buffer {}", slot); 25 LOG_WARNING(Service, "Adding graphics buffer {}", slot);
26 26
27 free_buffers.push_back(slot); 27 free_buffers.push_back(slot);
28 queue.push_back({ 28 buffers[slot] = {
29 .slot = slot, 29 .slot = slot,
30 .status = Buffer::Status::Free, 30 .status = Buffer::Status::Free,
31 .igbp_buffer = igbp_buffer, 31 .igbp_buffer = igbp_buffer,
@@ -33,7 +33,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
33 .crop_rect = {}, 33 .crop_rect = {},
34 .swap_interval = 0, 34 .swap_interval = 0,
35 .multi_fence = {}, 35 .multi_fence = {},
36 }); 36 };
37 37
38 buffer_wait_event.writable->Signal(); 38 buffer_wait_event.writable->Signal();
39} 39}
@@ -46,11 +46,11 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue
46 } 46 }
47 47
48 auto f_itr = free_buffers.begin(); 48 auto f_itr = free_buffers.begin();
49 auto itr = queue.end(); 49 auto itr = buffers.end();
50 50
51 while (f_itr != free_buffers.end()) { 51 while (f_itr != free_buffers.end()) {
52 auto slot = *f_itr; 52 auto slot = *f_itr;
53 itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { 53 itr = std::find_if(buffers.begin(), buffers.end(), [&](const Buffer& buffer) {
54 // Only consider free buffers. Buffers become free once again after they've been 54 // Only consider free buffers. Buffers become free once again after they've been
55 // Acquired and Released by the compositor, see the NVFlinger::Compose method. 55 // Acquired and Released by the compositor, see the NVFlinger::Compose method.
56 if (buffer.status != Buffer::Status::Free) { 56 if (buffer.status != Buffer::Status::Free) {
@@ -65,14 +65,14 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue
65 return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height; 65 return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
66 }); 66 });
67 67
68 if (itr != queue.end()) { 68 if (itr != buffers.end()) {
69 free_buffers.erase(f_itr); 69 free_buffers.erase(f_itr);
70 break; 70 break;
71 } 71 }
72 ++f_itr; 72 ++f_itr;
73 } 73 }
74 74
75 if (itr == queue.end()) { 75 if (itr == buffers.end()) {
76 return std::nullopt; 76 return std::nullopt;
77 } 77 }
78 78
@@ -81,9 +81,9 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue
81} 81}
82 82
83const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { 83const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
84 auto itr = std::find_if(queue.begin(), queue.end(), 84 auto itr = std::find_if(buffers.begin(), buffers.end(),
85 [&](const Buffer& buffer) { return buffer.slot == slot; }); 85 [&](const Buffer& buffer) { return buffer.slot == slot; });
86 ASSERT(itr != queue.end()); 86 ASSERT(itr != buffers.end());
87 ASSERT(itr->status == Buffer::Status::Dequeued); 87 ASSERT(itr->status == Buffer::Status::Dequeued);
88 return itr->igbp_buffer; 88 return itr->igbp_buffer;
89} 89}
@@ -91,9 +91,9 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
91void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, 91void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
92 const Common::Rectangle<int>& crop_rect, u32 swap_interval, 92 const Common::Rectangle<int>& crop_rect, u32 swap_interval,
93 Service::Nvidia::MultiFence& multi_fence) { 93 Service::Nvidia::MultiFence& multi_fence) {
94 auto itr = std::find_if(queue.begin(), queue.end(), 94 auto itr = std::find_if(buffers.begin(), buffers.end(),
95 [&](const Buffer& buffer) { return buffer.slot == slot; }); 95 [&](const Buffer& buffer) { return buffer.slot == slot; });
96 ASSERT(itr != queue.end()); 96 ASSERT(itr != buffers.end());
97 ASSERT(itr->status == Buffer::Status::Dequeued); 97 ASSERT(itr->status == Buffer::Status::Dequeued);
98 itr->status = Buffer::Status::Queued; 98 itr->status = Buffer::Status::Queued;
99 itr->transform = transform; 99 itr->transform = transform;
@@ -104,9 +104,9 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
104} 104}
105 105
106void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) { 106void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) {
107 const auto itr = std::find_if(queue.begin(), queue.end(), 107 const auto itr = std::find_if(buffers.begin(), buffers.end(),
108 [slot](const Buffer& buffer) { return buffer.slot == slot; }); 108 [slot](const Buffer& buffer) { return buffer.slot == slot; });
109 ASSERT(itr != queue.end()); 109 ASSERT(itr != buffers.end());
110 ASSERT(itr->status != Buffer::Status::Free); 110 ASSERT(itr->status != Buffer::Status::Free);
111 itr->status = Buffer::Status::Free; 111 itr->status = Buffer::Status::Free;
112 itr->multi_fence = multi_fence; 112 itr->multi_fence = multi_fence;
@@ -118,16 +118,16 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
118} 118}
119 119
120std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { 120std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
121 auto itr = queue.end(); 121 auto itr = buffers.end();
122 // Iterate to find a queued buffer matching the requested slot. 122 // Iterate to find a queued buffer matching the requested slot.
123 while (itr == queue.end() && !queue_sequence.empty()) { 123 while (itr == buffers.end() && !queue_sequence.empty()) {
124 const u32 slot = queue_sequence.front(); 124 const u32 slot = queue_sequence.front();
125 itr = std::find_if(queue.begin(), queue.end(), [&slot](const Buffer& buffer) { 125 itr = std::find_if(buffers.begin(), buffers.end(), [&slot](const Buffer& buffer) {
126 return buffer.status == Buffer::Status::Queued && buffer.slot == slot; 126 return buffer.status == Buffer::Status::Queued && buffer.slot == slot;
127 }); 127 });
128 queue_sequence.pop_front(); 128 queue_sequence.pop_front();
129 } 129 }
130 if (itr == queue.end()) { 130 if (itr == buffers.end()) {
131 return std::nullopt; 131 return std::nullopt;
132 } 132 }
133 itr->status = Buffer::Status::Acquired; 133 itr->status = Buffer::Status::Acquired;
@@ -135,9 +135,9 @@ std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::Ac
135} 135}
136 136
137void BufferQueue::ReleaseBuffer(u32 slot) { 137void BufferQueue::ReleaseBuffer(u32 slot) {
138 auto itr = std::find_if(queue.begin(), queue.end(), 138 auto itr = std::find_if(buffers.begin(), buffers.end(),
139 [&](const Buffer& buffer) { return buffer.slot == slot; }); 139 [&](const Buffer& buffer) { return buffer.slot == slot; });
140 ASSERT(itr != queue.end()); 140 ASSERT(itr != buffers.end());
141 ASSERT(itr->status == Buffer::Status::Acquired); 141 ASSERT(itr->status == Buffer::Status::Acquired);
142 itr->status = Buffer::Status::Free; 142 itr->status = Buffer::Status::Free;
143 free_buffers.push_back(slot); 143 free_buffers.push_back(slot);
@@ -146,10 +146,9 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
146} 146}
147 147
148void BufferQueue::Disconnect() { 148void BufferQueue::Disconnect() {
149 queue.clear(); 149 buffers.fill({});
150 queue_sequence.clear(); 150 queue_sequence.clear();
151 id = 1; 151 buffer_wait_event.writable->Signal();
152 layer_id = 1;
153} 152}
154 153
155u32 BufferQueue::Query(QueryType type) { 154u32 BufferQueue::Query(QueryType type) {
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index e7517c7e1..e610923cb 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -21,6 +21,7 @@ class KernelCore;
21 21
22namespace Service::NVFlinger { 22namespace Service::NVFlinger {
23 23
24constexpr u32 buffer_slots = 0x40;
24struct IGBPBuffer { 25struct IGBPBuffer {
25 u32_le magic; 26 u32_le magic;
26 u32_le width; 27 u32_le width;
@@ -114,7 +115,7 @@ private:
114 u64 layer_id; 115 u64 layer_id;
115 116
116 std::list<u32> free_buffers; 117 std::list<u32> free_buffers;
117 std::vector<Buffer> queue; 118 std::array<Buffer, buffer_slots> buffers;
118 std::list<u32> queue_sequence; 119 std::list<u32> queue_sequence;
119 Kernel::EventPair buffer_wait_event; 120 Kernel::EventPair buffer_wait_event;
120}; 121};
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 5d8841ae8..45cfffe06 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -282,18 +282,24 @@ public:
282 void DeserializeData() override { 282 void DeserializeData() override {
283 [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); 283 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
284 data = Read<Data>(); 284 data = Read<Data>();
285 buffer = Read<NVFlinger::IGBPBuffer>(); 285 if (data.contains_object != 0) {
286 buffer_container = Read<BufferContainer>();
287 }
286 } 288 }
287 289
288 struct Data { 290 struct Data {
289 u32_le slot; 291 u32_le slot;
290 INSERT_PADDING_WORDS(1); 292 u32_le contains_object;
293 };
294
295 struct BufferContainer {
291 u32_le graphic_buffer_length; 296 u32_le graphic_buffer_length;
292 INSERT_PADDING_WORDS(1); 297 INSERT_PADDING_WORDS(1);
298 NVFlinger::IGBPBuffer buffer{};
293 }; 299 };
294 300
295 Data data; 301 Data data{};
296 NVFlinger::IGBPBuffer buffer; 302 BufferContainer buffer_container{};
297}; 303};
298 304
299class IGBPSetPreallocatedBufferResponseParcel : public Parcel { 305class IGBPSetPreallocatedBufferResponseParcel : public Parcel {
@@ -547,7 +553,7 @@ private:
547 case TransactionId::SetPreallocatedBuffer: { 553 case TransactionId::SetPreallocatedBuffer: {
548 IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()}; 554 IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()};
549 555
550 buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer); 556 buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer_container.buffer);
551 557
552 IGBPSetPreallocatedBufferResponseParcel response{}; 558 IGBPSetPreallocatedBufferResponseParcel response{};
553 ctx.WriteBuffer(response.Serialize()); 559 ctx.WriteBuffer(response.Serialize());