nvflinger: Split Parcel class into InputParcel and OutputParcel
The usages of the Parcel class were already unique to either Read or Write operations. Avoids needing a vector of the input payload for the InputParcel use-case, instead it can remain as a span.
This commit is contained in:
		| @@ -815,8 +815,8 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | |||||||
|  |  | ||||||
| void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) { | void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) { | ||||||
|     Status status{Status::NoError}; |     Status status{Status::NoError}; | ||||||
|     Parcel parcel_in{ctx.ReadBuffer()}; |     InputParcel parcel_in{ctx.ReadBufferSpan()}; | ||||||
|     Parcel parcel_out{}; |     OutputParcel parcel_out{}; | ||||||
|  |  | ||||||
|     switch (code) { |     switch (code) { | ||||||
|     case TransactionId::Connect: { |     case TransactionId::Connect: { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
|  |  | ||||||
| namespace Service::android { | namespace Service::android { | ||||||
|  |  | ||||||
| QueueBufferInput::QueueBufferInput(Parcel& parcel) { | QueueBufferInput::QueueBufferInput(InputParcel& parcel) { | ||||||
|     parcel.ReadFlattened(*this); |     parcel.ReadFlattened(*this); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,11 +14,11 @@ | |||||||
|  |  | ||||||
| namespace Service::android { | namespace Service::android { | ||||||
|  |  | ||||||
| class Parcel; | class InputParcel; | ||||||
|  |  | ||||||
| #pragma pack(push, 1) | #pragma pack(push, 1) | ||||||
| struct QueueBufferInput final { | struct QueueBufferInput final { | ||||||
|     explicit QueueBufferInput(Parcel& parcel); |     explicit QueueBufferInput(InputParcel& parcel); | ||||||
|  |  | ||||||
|     void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, |     void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, | ||||||
|                  NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, |                  NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <span> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| #include "common/alignment.h" | #include "common/alignment.h" | ||||||
| @@ -12,18 +13,17 @@ | |||||||
|  |  | ||||||
| namespace Service::android { | namespace Service::android { | ||||||
|  |  | ||||||
| class Parcel final { | struct ParcelHeader { | ||||||
|  |     u32 data_size; | ||||||
|  |     u32 data_offset; | ||||||
|  |     u32 objects_size; | ||||||
|  |     u32 objects_offset; | ||||||
|  | }; | ||||||
|  | static_assert(sizeof(ParcelHeader) == 16, "ParcelHeader has wrong size"); | ||||||
|  |  | ||||||
|  | class InputParcel final { | ||||||
| public: | public: | ||||||
|     static constexpr std::size_t DefaultBufferSize = 0x40; |     explicit InputParcel(std::span<const u8> in_data) : read_buffer(std::move(in_data)) { | ||||||
|  |  | ||||||
|     Parcel() : buffer(DefaultBufferSize) {} |  | ||||||
|  |  | ||||||
|     template <typename T> |  | ||||||
|     explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) { |  | ||||||
|         Write(out_data); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) { |  | ||||||
|         DeserializeHeader(); |         DeserializeHeader(); | ||||||
|         [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); |         [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); | ||||||
|     } |     } | ||||||
| @@ -31,9 +31,9 @@ public: | |||||||
|     template <typename T> |     template <typename T> | ||||||
|     void Read(T& val) { |     void Read(T& val) { | ||||||
|         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); |         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); | ||||||
|         ASSERT(read_index + sizeof(T) <= buffer.size()); |         ASSERT(read_index + sizeof(T) <= read_buffer.size()); | ||||||
|  |  | ||||||
|         std::memcpy(&val, buffer.data() + read_index, sizeof(T)); |         std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); | ||||||
|         read_index += sizeof(T); |         read_index += sizeof(T); | ||||||
|         read_index = Common::AlignUp(read_index, 4); |         read_index = Common::AlignUp(read_index, 4); | ||||||
|     } |     } | ||||||
| @@ -62,10 +62,10 @@ public: | |||||||
|     template <typename T> |     template <typename T> | ||||||
|     T ReadUnaligned() { |     T ReadUnaligned() { | ||||||
|         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); |         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); | ||||||
|         ASSERT(read_index + sizeof(T) <= buffer.size()); |         ASSERT(read_index + sizeof(T) <= read_buffer.size()); | ||||||
|  |  | ||||||
|         T val; |         T val; | ||||||
|         std::memcpy(&val, buffer.data() + read_index, sizeof(T)); |         std::memcpy(&val, read_buffer.data() + read_index, sizeof(T)); | ||||||
|         read_index += sizeof(T); |         read_index += sizeof(T); | ||||||
|         return val; |         return val; | ||||||
|     } |     } | ||||||
| @@ -101,6 +101,31 @@ public: | |||||||
|         return token; |         return token; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void DeserializeHeader() { | ||||||
|  |         ASSERT(read_buffer.size() > sizeof(ParcelHeader)); | ||||||
|  |  | ||||||
|  |         ParcelHeader header{}; | ||||||
|  |         std::memcpy(&header, read_buffer.data(), sizeof(ParcelHeader)); | ||||||
|  |  | ||||||
|  |         read_index = header.data_offset; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     std::span<const u8> read_buffer; | ||||||
|  |     std::size_t read_index = 0; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class OutputParcel final { | ||||||
|  | public: | ||||||
|  |     static constexpr std::size_t DefaultBufferSize = 0x40; | ||||||
|  |  | ||||||
|  |     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."); |         static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); | ||||||
| @@ -133,40 +158,20 @@ public: | |||||||
|         WriteObject(ptr.get()); |         WriteObject(ptr.get()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void DeserializeHeader() { |  | ||||||
|         ASSERT(buffer.size() > sizeof(Header)); |  | ||||||
|  |  | ||||||
|         Header header{}; |  | ||||||
|         std::memcpy(&header, buffer.data(), sizeof(Header)); |  | ||||||
|  |  | ||||||
|         read_index = header.data_offset; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::vector<u8> Serialize() const { |     std::vector<u8> Serialize() const { | ||||||
|         ASSERT(read_index == 0); |         ParcelHeader header{}; | ||||||
|  |         header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader)); | ||||||
|         Header header{}; |         header.data_offset = sizeof(ParcelHeader); | ||||||
|         header.data_size = static_cast<u32>(write_index - sizeof(Header)); |  | ||||||
|         header.data_offset = sizeof(Header); |  | ||||||
|         header.objects_size = 4; |         header.objects_size = 4; | ||||||
|         header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size); |         header.objects_offset = static_cast<u32>(sizeof(ParcelHeader) + header.data_size); | ||||||
|         std::memcpy(buffer.data(), &header, sizeof(Header)); |         std::memcpy(buffer.data(), &header, sizeof(ParcelHeader)); | ||||||
|  |  | ||||||
|         return buffer; |         return buffer; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     struct Header { |  | ||||||
|         u32 data_size; |  | ||||||
|         u32 data_offset; |  | ||||||
|         u32 objects_size; |  | ||||||
|         u32 objects_offset; |  | ||||||
|     }; |  | ||||||
|     static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size"); |  | ||||||
|  |  | ||||||
|     mutable std::vector<u8> buffer; |     mutable std::vector<u8> buffer; | ||||||
|     std::size_t read_index = 0; |     std::size_t write_index = sizeof(ParcelHeader); | ||||||
|     std::size_t write_index = sizeof(Header); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Service::android | } // namespace Service::android | ||||||
|   | |||||||
| @@ -603,7 +603,7 @@ private: | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; |         const auto parcel = android::OutputParcel{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}; | ||||||
| @@ -649,7 +649,7 @@ private: | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const auto parcel = android::Parcel{NativeWindow{*buffer_queue_id}}; |         const auto parcel = android::OutputParcel{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