2
1
Fork 0
mirror of https://github.com/yuzu-emu/yuzu.git synced 2024-07-04 23:31:19 +01:00

nvnflinger: fix Parcel serialization

This commit is contained in:
Liam 2023-05-11 17:09:19 -04:00
parent 6e10a0c130
commit bb94beed15
3 changed files with 51 additions and 41 deletions

View file

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

View file

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

View file

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