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