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:
ameerj 2022-12-25 13:57:16 -05:00
parent 7ffd624248
commit 32d01a39b0
5 changed files with 53 additions and 48 deletions

View File

@ -815,8 +815,8 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
void BufferQueueProducer::Transact(Kernel::HLERequestContext& ctx, TransactionId code, u32 flags) {
Status status{Status::NoError};
Parcel parcel_in{ctx.ReadBuffer()};
Parcel parcel_out{};
InputParcel parcel_in{ctx.ReadBufferSpan()};
OutputParcel parcel_out{};
switch (code) {
case TransactionId::Connect: {

View File

@ -9,7 +9,7 @@
namespace Service::android {
QueueBufferInput::QueueBufferInput(Parcel& parcel) {
QueueBufferInput::QueueBufferInput(InputParcel& parcel) {
parcel.ReadFlattened(*this);
}

View File

@ -14,11 +14,11 @@
namespace Service::android {
class Parcel;
class InputParcel;
#pragma pack(push, 1)
struct QueueBufferInput final {
explicit QueueBufferInput(Parcel& parcel);
explicit QueueBufferInput(InputParcel& parcel);
void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_,
NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_,

View File

@ -4,6 +4,7 @@
#pragma once
#include <memory>
#include <span>
#include <vector>
#include "common/alignment.h"
@ -12,18 +13,17 @@
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:
static constexpr std::size_t DefaultBufferSize = 0x40;
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)) {
explicit InputParcel(std::span<const u8> in_data) : read_buffer(std::move(in_data)) {
DeserializeHeader();
[[maybe_unused]] const std::u16string token = ReadInterfaceToken();
}
@ -31,9 +31,9 @@ public:
template <typename T>
void Read(T& val) {
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 = Common::AlignUp(read_index, 4);
}
@ -62,10 +62,10 @@ public:
template <typename T>
T ReadUnaligned() {
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;
std::memcpy(&val, buffer.data() + read_index, sizeof(T));
std::memcpy(&val, read_buffer.data() + read_index, sizeof(T));
read_index += sizeof(T);
return val;
}
@ -101,6 +101,31 @@ public:
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>
void Write(const T& val) {
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
@ -133,40 +158,20 @@ public:
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 {
ASSERT(read_index == 0);
Header header{};
header.data_size = static_cast<u32>(write_index - sizeof(Header));
header.data_offset = sizeof(Header);
ParcelHeader header{};
header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader));
header.data_offset = sizeof(ParcelHeader);
header.objects_size = 4;
header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
std::memcpy(buffer.data(), &header, sizeof(Header));
header.objects_offset = static_cast<u32>(sizeof(ParcelHeader) + header.data_size);
std::memcpy(buffer.data(), &header, sizeof(ParcelHeader));
return buffer;
}
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;
std::size_t read_index = 0;
std::size_t write_index = sizeof(Header);
std::size_t write_index = sizeof(ParcelHeader);
};
} // namespace Service::android

View File

@ -603,7 +603,7 @@ private:
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());
IPC::ResponseBuilder rb{ctx, 4};
@ -649,7 +649,7 @@ private:
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());
IPC::ResponseBuilder rb{ctx, 6};