summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp105
1 files changed, 46 insertions, 59 deletions
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 101b00492..377f47e8e 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -22,6 +22,7 @@ BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
22BufferQueue::~BufferQueue() = default; 22BufferQueue::~BufferQueue() = default;
23 23
24void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) { 24void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
25 ASSERT(slot < buffer_slots);
25 LOG_WARNING(Service, "Adding graphics buffer {}", slot); 26 LOG_WARNING(Service, "Adding graphics buffer {}", slot);
26 27
27 free_buffers.push_back(slot); 28 free_buffers.push_back(slot);
@@ -44,73 +45,57 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue
44 if (free_buffers.empty()) { 45 if (free_buffers.empty()) {
45 return std::nullopt; 46 return std::nullopt;
46 } 47 }
47
48 auto f_itr = free_buffers.begin(); 48 auto f_itr = free_buffers.begin();
49 auto itr = buffers.end(); 49 auto slot = buffers.size();
50 50
51 while (f_itr != free_buffers.end()) { 51 while (f_itr != free_buffers.end()) {
52 auto slot = *f_itr; 52 const Buffer& buffer = buffers[*f_itr];
53 itr = std::find_if(buffers.begin(), buffers.end(), [&](const Buffer& buffer) { 53 if (buffer.status == Buffer::Status::Free && buffer.igbp_buffer.width == width &&
54 // Only consider free buffers. Buffers become free once again after they've been 54 buffer.igbp_buffer.height == height) {
55 // Acquired and Released by the compositor, see the NVFlinger::Compose method. 55 slot = *f_itr;
56 if (buffer.status != Buffer::Status::Free) {
57 return false;
58 }
59
60 if (buffer.slot != slot) {
61 return false;
62 }
63
64 // Make sure that the parameters match.
65 return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
66 });
67
68 if (itr != buffers.end()) {
69 free_buffers.erase(f_itr); 56 free_buffers.erase(f_itr);
70 break; 57 break;
71 } 58 }
72 ++f_itr; 59 ++f_itr;
73 } 60 }
74 61 if (slot == buffers.size()) {
75 if (itr == buffers.end()) {
76 return std::nullopt; 62 return std::nullopt;
77 } 63 }
78 64 buffers[slot].status = Buffer::Status::Dequeued;
79 itr->status = Buffer::Status::Dequeued; 65 return {{buffers[slot].slot, &buffers[slot].multi_fence}};
80 return {{itr->slot, &itr->multi_fence}};
81} 66}
82 67
83const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { 68const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
84 auto itr = std::find_if(buffers.begin(), buffers.end(), 69 ASSERT(slot < buffers.size());
85 [&](const Buffer& buffer) { return buffer.slot == slot; }); 70 ASSERT(buffers[slot].status == Buffer::Status::Dequeued);
86 ASSERT(itr != buffers.end()); 71 ASSERT(buffers[slot].slot == slot);
87 ASSERT(itr->status == Buffer::Status::Dequeued); 72
88 return itr->igbp_buffer; 73 return buffers[slot].igbp_buffer;
89} 74}
90 75
91void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, 76void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
92 const Common::Rectangle<int>& crop_rect, u32 swap_interval, 77 const Common::Rectangle<int>& crop_rect, u32 swap_interval,
93 Service::Nvidia::MultiFence& multi_fence) { 78 Service::Nvidia::MultiFence& multi_fence) {
94 auto itr = std::find_if(buffers.begin(), buffers.end(), 79 ASSERT(slot < buffers.size());
95 [&](const Buffer& buffer) { return buffer.slot == slot; }); 80 ASSERT(buffers[slot].status == Buffer::Status::Dequeued);
96 ASSERT(itr != buffers.end()); 81 ASSERT(buffers[slot].slot == slot);
97 ASSERT(itr->status == Buffer::Status::Dequeued); 82
98 itr->status = Buffer::Status::Queued; 83 buffers[slot].status = Buffer::Status::Queued;
99 itr->transform = transform; 84 buffers[slot].transform = transform;
100 itr->crop_rect = crop_rect; 85 buffers[slot].crop_rect = crop_rect;
101 itr->swap_interval = swap_interval; 86 buffers[slot].swap_interval = swap_interval;
102 itr->multi_fence = multi_fence; 87 buffers[slot].multi_fence = multi_fence;
103 queue_sequence.push_back(slot); 88 queue_sequence.push_back(slot);
104} 89}
105 90
106void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) { 91void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) {
107 const auto itr = std::find_if(buffers.begin(), buffers.end(), 92 ASSERT(slot < buffers.size());
108 [slot](const Buffer& buffer) { return buffer.slot == slot; }); 93 ASSERT(buffers[slot].status != Buffer::Status::Free);
109 ASSERT(itr != buffers.end()); 94 ASSERT(buffers[slot].slot == slot);
110 ASSERT(itr->status != Buffer::Status::Free); 95
111 itr->status = Buffer::Status::Free; 96 buffers[slot].status = Buffer::Status::Free;
112 itr->multi_fence = multi_fence; 97 buffers[slot].multi_fence = multi_fence;
113 itr->swap_interval = 0; 98 buffers[slot].swap_interval = 0;
114 99
115 free_buffers.push_back(slot); 100 free_buffers.push_back(slot);
116 101
@@ -118,28 +103,30 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
118} 103}
119 104
120std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { 105std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
121 auto itr = buffers.end(); 106 std::size_t buffer_slot = buffers.size();
122 // Iterate to find a queued buffer matching the requested slot. 107 // Iterate to find a queued buffer matching the requested slot.
123 while (itr == buffers.end() && !queue_sequence.empty()) { 108 while (buffer_slot == buffers.size() && !queue_sequence.empty()) {
124 const u32 slot = queue_sequence.front(); 109 const auto slot = static_cast<std::size_t>(queue_sequence.front());
125 itr = std::find_if(buffers.begin(), buffers.end(), [&slot](const Buffer& buffer) { 110 ASSERT(slot < buffers.size());
126 return buffer.status == Buffer::Status::Queued && buffer.slot == slot; 111 if (buffers[slot].status == Buffer::Status::Queued) {
127 }); 112 ASSERT(buffers[slot].slot == slot);
113 buffer_slot = slot;
114 }
128 queue_sequence.pop_front(); 115 queue_sequence.pop_front();
129 } 116 }
130 if (itr == buffers.end()) { 117 if (buffer_slot == buffers.size()) {
131 return std::nullopt; 118 return std::nullopt;
132 } 119 }
133 itr->status = Buffer::Status::Acquired; 120 buffers[buffer_slot].status = Buffer::Status::Acquired;
134 return *itr; 121 return {{buffers[buffer_slot]}};
135} 122}
136 123
137void BufferQueue::ReleaseBuffer(u32 slot) { 124void BufferQueue::ReleaseBuffer(u32 slot) {
138 auto itr = std::find_if(buffers.begin(), buffers.end(), 125 ASSERT(slot < buffers.size());
139 [&](const Buffer& buffer) { return buffer.slot == slot; }); 126 ASSERT(buffers[slot].status == Buffer::Status::Acquired);
140 ASSERT(itr != buffers.end()); 127 ASSERT(buffers[slot].slot == slot);
141 ASSERT(itr->status == Buffer::Status::Acquired); 128
142 itr->status = Buffer::Status::Free; 129 buffers[slot].status = Buffer::Status::Free;
143 free_buffers.push_back(slot); 130 free_buffers.push_back(slot);
144 131
145 buffer_wait_event.writable->Signal(); 132 buffer_wait_event.writable->Signal();