summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2021-11-11 18:36:52 -0800
committerGravatar bunnei2022-03-24 18:13:32 -0700
commitd13e18a8edfb6f26026acb72db426f651ab80ef2 (patch)
treedbdc99b366beae3a42792df41c288bcd58bda5d3 /src
parenthle: nvflinger: Add android buffer queue definitions to its own header. (diff)
downloadyuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.gz
yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.tar.xz
yuzu-d13e18a8edfb6f26026acb72db426f651ab80ef2.zip
hle: nvflinger: Move implementation for Parcel to its own header.
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/service/nvflinger/parcel.h171
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
543 hle/service/nvflinger/consumer_listener.h 543 hle/service/nvflinger/consumer_listener.h
544 hle/service/nvflinger/nvflinger.cpp 544 hle/service/nvflinger/nvflinger.cpp
545 hle/service/nvflinger/nvflinger.h 545 hle/service/nvflinger/nvflinger.h
546 hle/service/nvflinger/parcel.h
546 hle/service/nvflinger/pixel_format.h 547 hle/service/nvflinger/pixel_format.h
547 hle/service/nvflinger/producer_listener.h 548 hle/service/nvflinger/producer_listener.h
548 hle/service/nvflinger/status.h 549 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 @@
1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright 2021 yuzu Emulator Project
3
4#pragma once
5
6#include <memory>
7#include <vector>
8
9#include "common/alignment.h"
10#include "common/assert.h"
11#include "common/common_types.h"
12
13namespace android {
14
15class Parcel final {
16public:
17 static constexpr std::size_t DefaultBufferSize = 0x40;
18
19 Parcel() : buffer(DefaultBufferSize) {}
20
21 template <typename T>
22 explicit Parcel(const T& out_data) : buffer(DefaultBufferSize) {
23 Write(out_data);
24 }
25
26 explicit Parcel(std::vector<u8> in_data) : buffer(std::move(in_data)) {
27 DeserializeHeader();
28 [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
29 }
30
31 template <typename T>
32 void Read(T& val) {
33 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
34 ASSERT(read_index + sizeof(T) <= buffer.size());
35
36 std::memcpy(&val, buffer.data() + read_index, sizeof(T));
37 read_index += sizeof(T);
38 read_index = Common::AlignUp(read_index, 4);
39 }
40
41 template <typename T>
42 T Read() {
43 T val;
44 Read(val);
45 return val;
46 }
47
48 template <typename T>
49 void ReadFlattened(T& val) {
50 const auto flattened_size = Read<s64>();
51 ASSERT(sizeof(T) == flattened_size);
52 Read(val);
53 }
54
55 template <typename T>
56 T ReadFlattened() {
57 T val;
58 ReadFlattened(val);
59 return val;
60 }
61
62 template <typename T>
63 T ReadUnaligned() {
64 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
65 ASSERT(read_index + sizeof(T) <= buffer.size());
66
67 T val;
68 std::memcpy(&val, buffer.data() + read_index, sizeof(T));
69 read_index += sizeof(T);
70 return val;
71 }
72
73 template <typename T>
74 const std::shared_ptr<T> ReadObject() {
75 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
76
77 const auto is_valid{Read<bool>()};
78
79 if (is_valid) {
80 auto result = std::make_shared<T>();
81 ReadFlattened(*result);
82 return result;
83 }
84
85 return {};
86 }
87
88 std::u16string ReadInterfaceToken() {
89 [[maybe_unused]] const u32 unknown = Read<u32>();
90 const u32 length = Read<u32>();
91
92 std::u16string token{};
93
94 for (u32 ch = 0; ch < length + 1; ++ch) {
95 token.push_back(ReadUnaligned<u16>());
96 }
97
98 read_index = Common::AlignUp(read_index, 4);
99
100 return token;
101 }
102
103 template <typename T>
104 void Write(const T& val) {
105 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
106
107 if (buffer.size() < write_index + sizeof(T)) {
108 buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
109 }
110
111 std::memcpy(buffer.data() + write_index, &val, sizeof(T));
112 write_index += sizeof(T);
113 write_index = Common::AlignUp(write_index, 4);
114 }
115
116 template <typename T>
117 void WriteObject(const T* ptr) {
118 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
119
120 if (!ptr) {
121 Write<u32>(0);
122 return;
123 }
124
125 Write<u32>(1);
126 Write<s64>(sizeof(T));
127 Write(*ptr);
128 }
129
130 template <typename T>
131 void WriteObject(const std::shared_ptr<T> ptr) {
132 WriteObject(ptr.get());
133 }
134
135 void DeserializeHeader() {
136 ASSERT(buffer.size() > sizeof(Header));
137
138 Header header{};
139 std::memcpy(&header, buffer.data(), sizeof(Header));
140
141 read_index = header.data_offset;
142 }
143
144 std::vector<u8> Serialize() const {
145 ASSERT(read_index == 0);
146
147 Header header{};
148 header.data_size = static_cast<u32>(write_index - sizeof(Header));
149 header.data_offset = sizeof(Header);
150 header.objects_size = 4;
151 header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
152 std::memcpy(buffer.data(), &header, sizeof(Header));
153
154 return buffer;
155 }
156
157private:
158 struct Header {
159 u32 data_size;
160 u32 data_offset;
161 u32 objects_size;
162 u32 objects_offset;
163 };
164 static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
165
166 mutable std::vector<u8> buffer;
167 std::size_t read_index = 0;
168 std::size_t write_index = sizeof(Header);
169};
170
171} // namespace android