mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	nvnflinger: fix Parcel serialization
This commit is contained in:
		@@ -855,7 +855,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
 | 
				
			|||||||
        status = DequeueBuffer(&slot, &fence, is_async, width, height, pixel_format, usage);
 | 
					        status = DequeueBuffer(&slot, &fence, is_async, width, height, pixel_format, usage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        parcel_out.Write(slot);
 | 
					        parcel_out.Write(slot);
 | 
				
			||||||
        parcel_out.WriteObject(&fence);
 | 
					        parcel_out.WriteFlattenedObject(&fence);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case TransactionId::RequestBuffer: {
 | 
					    case TransactionId::RequestBuffer: {
 | 
				
			||||||
@@ -865,7 +865,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        status = RequestBuffer(slot, &buf);
 | 
					        status = RequestBuffer(slot, &buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        parcel_out.WriteObject(buf);
 | 
					        parcel_out.WriteFlattenedObject(buf);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case TransactionId::QueueBuffer: {
 | 
					    case TransactionId::QueueBuffer: {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,61 +117,67 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class OutputParcel final {
 | 
					class OutputParcel final {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    static constexpr std::size_t DefaultBufferSize = 0x40;
 | 
					    OutputParcel() = default;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    OutputParcel() : buffer(DefaultBufferSize) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    template <typename T>
 | 
					 | 
				
			||||||
    explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) {
 | 
					 | 
				
			||||||
        Write(out_data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template <typename T>
 | 
					    template <typename T>
 | 
				
			||||||
    void Write(const T& val) {
 | 
					    void Write(const T& val) {
 | 
				
			||||||
        static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
 | 
					        this->WriteImpl(val, m_data_buffer);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (buffer.size() < write_index + sizeof(T)) {
 | 
					 | 
				
			||||||
            buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::memcpy(buffer.data() + write_index, &val, sizeof(T));
 | 
					 | 
				
			||||||
        write_index += sizeof(T);
 | 
					 | 
				
			||||||
        write_index = Common::AlignUp(write_index, 4);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template <typename T>
 | 
					    template <typename T>
 | 
				
			||||||
    void WriteObject(const T* ptr) {
 | 
					    void WriteFlattenedObject(const T* ptr) {
 | 
				
			||||||
        static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!ptr) {
 | 
					        if (!ptr) {
 | 
				
			||||||
            Write<u32>(0);
 | 
					            this->Write<u32>(0);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Write<u32>(1);
 | 
					        this->Write<u32>(1);
 | 
				
			||||||
        Write<s64>(sizeof(T));
 | 
					        this->Write<s64>(sizeof(T));
 | 
				
			||||||
        Write(*ptr);
 | 
					        this->Write(*ptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template <typename T>
 | 
					    template <typename T>
 | 
				
			||||||
    void WriteObject(const std::shared_ptr<T> ptr) {
 | 
					    void WriteFlattenedObject(const std::shared_ptr<T> ptr) {
 | 
				
			||||||
        WriteObject(ptr.get());
 | 
					        this->WriteFlattenedObject(ptr.get());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <typename T>
 | 
				
			||||||
 | 
					    void WriteInterface(const T& val) {
 | 
				
			||||||
 | 
					        this->WriteImpl(val, m_data_buffer);
 | 
				
			||||||
 | 
					        this->WriteImpl(0U, m_object_buffer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<u8> Serialize() const {
 | 
					    std::vector<u8> Serialize() const {
 | 
				
			||||||
        ParcelHeader header{};
 | 
					        std::vector<u8> output_buffer(sizeof(ParcelHeader) + m_data_buffer.size() +
 | 
				
			||||||
        header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader));
 | 
					                                      m_object_buffer.size());
 | 
				
			||||||
        header.data_offset = sizeof(ParcelHeader);
 | 
					 | 
				
			||||||
        header.objects_size = 4;
 | 
					 | 
				
			||||||
        header.objects_offset = static_cast<u32>(sizeof(ParcelHeader) + header.data_size);
 | 
					 | 
				
			||||||
        std::memcpy(buffer.data(), &header, sizeof(ParcelHeader));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return buffer;
 | 
					        ParcelHeader header{};
 | 
				
			||||||
 | 
					        header.data_size = static_cast<u32>(m_data_buffer.size());
 | 
				
			||||||
 | 
					        header.data_offset = sizeof(ParcelHeader);
 | 
				
			||||||
 | 
					        header.objects_size = static_cast<u32>(m_object_buffer.size());
 | 
				
			||||||
 | 
					        header.objects_offset = header.data_offset + header.data_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::memcpy(output_buffer.data(), &header, sizeof(header));
 | 
				
			||||||
 | 
					        std::ranges::copy(m_data_buffer, output_buffer.data() + header.data_offset);
 | 
				
			||||||
 | 
					        std::ranges::copy(m_object_buffer, output_buffer.data() + header.objects_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return output_buffer;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    mutable std::vector<u8> buffer;
 | 
					    template <typename T>
 | 
				
			||||||
    std::size_t write_index = sizeof(ParcelHeader);
 | 
					        requires(std::is_trivially_copyable_v<T>)
 | 
				
			||||||
 | 
					    void WriteImpl(const T& val, std::vector<u8>& buffer) {
 | 
				
			||||||
 | 
					        const size_t aligned_size = Common::AlignUp(sizeof(T), 4);
 | 
				
			||||||
 | 
					        const size_t old_size = buffer.size();
 | 
				
			||||||
 | 
					        buffer.resize(old_size + aligned_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::memcpy(buffer.data() + old_size, &val, sizeof(T));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    std::vector<u8> m_data_buffer;
 | 
				
			||||||
 | 
					    std::vector<u8> m_object_buffer;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::android
 | 
					} // namespace Service::android
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,8 +64,8 @@ public:
 | 
				
			|||||||
private:
 | 
					private:
 | 
				
			||||||
    const u32 magic = 2;
 | 
					    const u32 magic = 2;
 | 
				
			||||||
    const u32 process_id = 1;
 | 
					    const u32 process_id = 1;
 | 
				
			||||||
    const u32 id;
 | 
					    const u64 id;
 | 
				
			||||||
    INSERT_PADDING_WORDS(3);
 | 
					    INSERT_PADDING_WORDS(2);
 | 
				
			||||||
    std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
 | 
					    std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
 | 
				
			||||||
    INSERT_PADDING_WORDS(2);
 | 
					    INSERT_PADDING_WORDS(2);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -608,7 +608,9 @@ private:
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
 | 
					        android::OutputParcel parcel;
 | 
				
			||||||
 | 
					        parcel.WriteInterface(NativeWindow{*buffer_queue_id});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
 | 
					        const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 4};
 | 
					        IPC::ResponseBuilder rb{ctx, 4};
 | 
				
			||||||
@@ -654,7 +656,9 @@ private:
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
 | 
					        android::OutputParcel parcel;
 | 
				
			||||||
 | 
					        parcel.WriteInterface(NativeWindow{*buffer_queue_id});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
 | 
					        const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 6};
 | 
					        IPC::ResponseBuilder rb{ctx, 6};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user