yuzu-emu
/
yuzu
Archived
1
0
Fork 0

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) { 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: {

View File

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

View File

@ -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_,

View File

@ -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

View File

@ -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};