Overwrite slots instead of queuing them, add disconnect signal
Fix for Katana Zero and Yoshi's Crafted World
This commit is contained in:
		
							parent
							
								
									ac3b4f918f
								
							
						
					
					
						commit
						8cb683f3b9
					
				| @ -25,7 +25,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) | |||||||
|     LOG_WARNING(Service, "Adding graphics buffer {}", slot); |     LOG_WARNING(Service, "Adding graphics buffer {}", slot); | ||||||
| 
 | 
 | ||||||
|     free_buffers.push_back(slot); |     free_buffers.push_back(slot); | ||||||
|     queue.push_back({ |     buffers[slot] = { | ||||||
|         .slot = slot, |         .slot = slot, | ||||||
|         .status = Buffer::Status::Free, |         .status = Buffer::Status::Free, | ||||||
|         .igbp_buffer = igbp_buffer, |         .igbp_buffer = igbp_buffer, | ||||||
| @ -33,7 +33,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) | |||||||
|         .crop_rect = {}, |         .crop_rect = {}, | ||||||
|         .swap_interval = 0, |         .swap_interval = 0, | ||||||
|         .multi_fence = {}, |         .multi_fence = {}, | ||||||
|     }); |     }; | ||||||
| 
 | 
 | ||||||
|     buffer_wait_event.writable->Signal(); |     buffer_wait_event.writable->Signal(); | ||||||
| } | } | ||||||
| @ -46,11 +46,11 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto f_itr = free_buffers.begin(); |     auto f_itr = free_buffers.begin(); | ||||||
|     auto itr = queue.end(); |     auto itr = buffers.end(); | ||||||
| 
 | 
 | ||||||
|     while (f_itr != free_buffers.end()) { |     while (f_itr != free_buffers.end()) { | ||||||
|         auto slot = *f_itr; |         auto slot = *f_itr; | ||||||
|         itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) { |         itr = std::find_if(buffers.begin(), buffers.end(), [&](const Buffer& buffer) { | ||||||
|             // Only consider free buffers. Buffers become free once again after they've been
 |             // Only consider free buffers. Buffers become free once again after they've been
 | ||||||
|             // Acquired and Released by the compositor, see the NVFlinger::Compose method.
 |             // Acquired and Released by the compositor, see the NVFlinger::Compose method.
 | ||||||
|             if (buffer.status != Buffer::Status::Free) { |             if (buffer.status != Buffer::Status::Free) { | ||||||
| @ -65,14 +65,14 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue | |||||||
|             return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height; |             return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         if (itr != queue.end()) { |         if (itr != buffers.end()) { | ||||||
|             free_buffers.erase(f_itr); |             free_buffers.erase(f_itr); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         ++f_itr; |         ++f_itr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (itr == queue.end()) { |     if (itr == buffers.end()) { | ||||||
|         return std::nullopt; |         return std::nullopt; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -81,9 +81,9 @@ std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::Dequeue | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { | const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { | ||||||
|     auto itr = std::find_if(queue.begin(), queue.end(), |     auto itr = std::find_if(buffers.begin(), buffers.end(), | ||||||
|                             [&](const Buffer& buffer) { return buffer.slot == slot; }); |                             [&](const Buffer& buffer) { return buffer.slot == slot; }); | ||||||
|     ASSERT(itr != queue.end()); |     ASSERT(itr != buffers.end()); | ||||||
|     ASSERT(itr->status == Buffer::Status::Dequeued); |     ASSERT(itr->status == Buffer::Status::Dequeued); | ||||||
|     return itr->igbp_buffer; |     return itr->igbp_buffer; | ||||||
| } | } | ||||||
| @ -91,9 +91,9 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const { | |||||||
| void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, | void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, | ||||||
|                               const Common::Rectangle<int>& crop_rect, u32 swap_interval, |                               const Common::Rectangle<int>& crop_rect, u32 swap_interval, | ||||||
|                               Service::Nvidia::MultiFence& multi_fence) { |                               Service::Nvidia::MultiFence& multi_fence) { | ||||||
|     auto itr = std::find_if(queue.begin(), queue.end(), |     auto itr = std::find_if(buffers.begin(), buffers.end(), | ||||||
|                             [&](const Buffer& buffer) { return buffer.slot == slot; }); |                             [&](const Buffer& buffer) { return buffer.slot == slot; }); | ||||||
|     ASSERT(itr != queue.end()); |     ASSERT(itr != buffers.end()); | ||||||
|     ASSERT(itr->status == Buffer::Status::Dequeued); |     ASSERT(itr->status == Buffer::Status::Dequeued); | ||||||
|     itr->status = Buffer::Status::Queued; |     itr->status = Buffer::Status::Queued; | ||||||
|     itr->transform = transform; |     itr->transform = transform; | ||||||
| @ -104,9 +104,9 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) { | void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) { | ||||||
|     const auto itr = std::find_if(queue.begin(), queue.end(), |     const auto itr = std::find_if(buffers.begin(), buffers.end(), | ||||||
|                                   [slot](const Buffer& buffer) { return buffer.slot == slot; }); |                                   [slot](const Buffer& buffer) { return buffer.slot == slot; }); | ||||||
|     ASSERT(itr != queue.end()); |     ASSERT(itr != buffers.end()); | ||||||
|     ASSERT(itr->status != Buffer::Status::Free); |     ASSERT(itr->status != Buffer::Status::Free); | ||||||
|     itr->status = Buffer::Status::Free; |     itr->status = Buffer::Status::Free; | ||||||
|     itr->multi_fence = multi_fence; |     itr->multi_fence = multi_fence; | ||||||
| @ -118,16 +118,16 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { | std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { | ||||||
|     auto itr = queue.end(); |     auto itr = buffers.end(); | ||||||
|     // Iterate to find a queued buffer matching the requested slot.
 |     // Iterate to find a queued buffer matching the requested slot.
 | ||||||
|     while (itr == queue.end() && !queue_sequence.empty()) { |     while (itr == buffers.end() && !queue_sequence.empty()) { | ||||||
|         const u32 slot = queue_sequence.front(); |         const u32 slot = queue_sequence.front(); | ||||||
|         itr = std::find_if(queue.begin(), queue.end(), [&slot](const Buffer& buffer) { |         itr = std::find_if(buffers.begin(), buffers.end(), [&slot](const Buffer& buffer) { | ||||||
|             return buffer.status == Buffer::Status::Queued && buffer.slot == slot; |             return buffer.status == Buffer::Status::Queued && buffer.slot == slot; | ||||||
|         }); |         }); | ||||||
|         queue_sequence.pop_front(); |         queue_sequence.pop_front(); | ||||||
|     } |     } | ||||||
|     if (itr == queue.end()) { |     if (itr == buffers.end()) { | ||||||
|         return std::nullopt; |         return std::nullopt; | ||||||
|     } |     } | ||||||
|     itr->status = Buffer::Status::Acquired; |     itr->status = Buffer::Status::Acquired; | ||||||
| @ -135,9 +135,9 @@ std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::Ac | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void BufferQueue::ReleaseBuffer(u32 slot) { | void BufferQueue::ReleaseBuffer(u32 slot) { | ||||||
|     auto itr = std::find_if(queue.begin(), queue.end(), |     auto itr = std::find_if(buffers.begin(), buffers.end(), | ||||||
|                             [&](const Buffer& buffer) { return buffer.slot == slot; }); |                             [&](const Buffer& buffer) { return buffer.slot == slot; }); | ||||||
|     ASSERT(itr != queue.end()); |     ASSERT(itr != buffers.end()); | ||||||
|     ASSERT(itr->status == Buffer::Status::Acquired); |     ASSERT(itr->status == Buffer::Status::Acquired); | ||||||
|     itr->status = Buffer::Status::Free; |     itr->status = Buffer::Status::Free; | ||||||
|     free_buffers.push_back(slot); |     free_buffers.push_back(slot); | ||||||
| @ -146,10 +146,9 @@ void BufferQueue::ReleaseBuffer(u32 slot) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void BufferQueue::Disconnect() { | void BufferQueue::Disconnect() { | ||||||
|     queue.clear(); |     buffers.fill({}); | ||||||
|     queue_sequence.clear(); |     queue_sequence.clear(); | ||||||
|     id = 1; |     buffer_wait_event.writable->Signal(); | ||||||
|     layer_id = 1; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u32 BufferQueue::Query(QueryType type) { | u32 BufferQueue::Query(QueryType type) { | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ class KernelCore; | |||||||
| 
 | 
 | ||||||
| namespace Service::NVFlinger { | namespace Service::NVFlinger { | ||||||
| 
 | 
 | ||||||
|  | constexpr u32 buffer_slots = 0x40; | ||||||
| struct IGBPBuffer { | struct IGBPBuffer { | ||||||
|     u32_le magic; |     u32_le magic; | ||||||
|     u32_le width; |     u32_le width; | ||||||
| @ -114,7 +115,7 @@ private: | |||||||
|     u64 layer_id; |     u64 layer_id; | ||||||
| 
 | 
 | ||||||
|     std::list<u32> free_buffers; |     std::list<u32> free_buffers; | ||||||
|     std::vector<Buffer> queue; |     std::array<Buffer, buffer_slots> buffers; | ||||||
|     std::list<u32> queue_sequence; |     std::list<u32> queue_sequence; | ||||||
|     Kernel::EventPair buffer_wait_event; |     Kernel::EventPair buffer_wait_event; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -282,18 +282,24 @@ public: | |||||||
|     void DeserializeData() override { |     void DeserializeData() override { | ||||||
|         [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); |         [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); | ||||||
|         data = Read<Data>(); |         data = Read<Data>(); | ||||||
|         buffer = Read<NVFlinger::IGBPBuffer>(); |         if (data.contains_object != 0) { | ||||||
|  |             buffer_container = Read<BufferContainer>(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     struct Data { |     struct Data { | ||||||
|         u32_le slot; |         u32_le slot; | ||||||
|         INSERT_PADDING_WORDS(1); |         u32_le contains_object; | ||||||
|         u32_le graphic_buffer_length; |  | ||||||
|         INSERT_PADDING_WORDS(1); |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     Data data; |     struct BufferContainer { | ||||||
|     NVFlinger::IGBPBuffer buffer; |         u32_le graphic_buffer_length; | ||||||
|  |         INSERT_PADDING_WORDS(1); | ||||||
|  |         NVFlinger::IGBPBuffer buffer{}; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     Data data{}; | ||||||
|  |     BufferContainer buffer_container{}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class IGBPSetPreallocatedBufferResponseParcel : public Parcel { | class IGBPSetPreallocatedBufferResponseParcel : public Parcel { | ||||||
| @ -547,7 +553,7 @@ private: | |||||||
|         case TransactionId::SetPreallocatedBuffer: { |         case TransactionId::SetPreallocatedBuffer: { | ||||||
|             IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()}; |             IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()}; | ||||||
| 
 | 
 | ||||||
|             buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer); |             buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer_container.buffer); | ||||||
| 
 | 
 | ||||||
|             IGBPSetPreallocatedBufferResponseParcel response{}; |             IGBPSetPreallocatedBufferResponseParcel response{}; | ||||||
|             ctx.WriteBuffer(response.Serialize()); |             ctx.WriteBuffer(response.Serialize()); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 ameerj
						ameerj