diff options
author | bunnei <bunneidev@gmail.com> | 2021-11-12 03:36:52 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2022-03-25 02:13:32 +0100 |
commit | d13e18a8edfb6f26026acb72db426f651ab80ef2 (patch) | |
tree | dbdc99b366beae3a42792df41c288bcd58bda5d3 | |
parent | hle: nvflinger: Add android buffer queue definitions to its own header. (diff) | |
download | yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.gz yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.bz2 yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.lz yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.xz yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.zst yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.zip |
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/hle/service/nvflinger/parcel.h | 171 |
2 files changed, 172 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d9b94b480..367d44cf3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -543,6 +543,7 @@ add_library(core STATIC hle/service/nvflinger/consumer_listener.h hle/service/nvflinger/nvflinger.cpp hle/service/nvflinger/nvflinger.h + hle/service/nvflinger/parcel.h hle/service/nvflinger/pixel_format.h hle/service/nvflinger/producer_listener.h hle/service/nvflinger/status.h diff --git a/src/core/hle/service/nvflinger/parcel.h b/src/core/hle/service/nvflinger/parcel.h new file mode 100644 index 000000000..710964f5d --- /dev/null +++ b/src/core/hle/service/nvflinger/parcel.h @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright 2021 yuzu Emulator Project + +#pragma once + +#include <memory> +#include <vector> + +#include "common/alignment.h" +#include "common/assert.h" +#include "common/common_types.h" + +namespace android { + +class Parcel 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)) { + DeserializeHeader(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); + } + + 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()); + + std::memcpy(&val, buffer.data() + read_index, sizeof(T)); + read_index += sizeof(T); + read_index = Common::AlignUp(read_index, 4); + } + + template <typename T> + T Read() { + T val; + Read(val); + return val; + } + + template <typename T> + void ReadFlattened(T& val) { + const auto flattened_size = Read<s64>(); + ASSERT(sizeof(T) == flattened_size); + Read(val); + } + + template <typename T> + T ReadFlattened() { + T val; + ReadFlattened(val); + return val; + } + + 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()); + + T val; + std::memcpy(&val, buffer.data() + read_index, sizeof(T)); + read_index += sizeof(T); + return val; + } + + template <typename T> + const std::shared_ptr<T> ReadObject() { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); + + const auto is_valid{Read<bool>()}; + + if (is_valid) { + auto result = std::make_shared<T>(); + ReadFlattened(*result); + return result; + } + + return {}; + } + + std::u16string ReadInterfaceToken() { + [[maybe_unused]] const u32 unknown = Read<u32>(); + const u32 length = Read<u32>(); + + std::u16string token{}; + + for (u32 ch = 0; ch < length + 1; ++ch) { + token.push_back(ReadUnaligned<u16>()); + } + + read_index = Common::AlignUp(read_index, 4); + + return token; + } + + template <typename T> + void Write(const T& val) { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); + + 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> + void WriteObject(const T* ptr) { + static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable."); + + if (!ptr) { + Write<u32>(0); + return; + } + + Write<u32>(1); + Write<s64>(sizeof(T)); + Write(*ptr); + } + + template <typename T> + void WriteObject(const std::shared_ptr<T> ptr) { + 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); + header.objects_size = 4; + header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size); + std::memcpy(buffer.data(), &header, sizeof(Header)); + + 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); +}; + +} // namespace android |