1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "VulkanStreamGuest.h"
15
16 #include "IOStream.h"
17 #include "ResourceTracker.h"
18
19 #include "android/base/Pool.h"
20 #include "android/base/Tracing.h"
21
22 #include <vector>
23
24 #include <log/log.h>
25 #include <inttypes.h>
26
27 namespace goldfish_vk {
28
29 class VulkanStreamGuest::Impl : public android::base::Stream {
30 public:
Impl(IOStream * stream)31 Impl(IOStream* stream) : mStream(stream) {
32 unsetHandleMapping();
33 mFeatureBits = ResourceTracker::get()->getStreamFeatures();
34 }
35
~Impl()36 ~Impl() { }
37
valid()38 bool valid() { return true; }
39
alloc(void ** ptrAddr,size_t bytes)40 void alloc(void **ptrAddr, size_t bytes) {
41 if (!bytes) {
42 *ptrAddr = nullptr;
43 return;
44 }
45
46 *ptrAddr = mPool.alloc(bytes);
47 }
48
write(const void * buffer,size_t size)49 ssize_t write(const void *buffer, size_t size) override {
50 uint8_t* streamBuf = (uint8_t*)mStream->alloc(size);
51 memcpy(streamBuf, buffer, size);
52 return size;
53 }
54
read(void * buffer,size_t size)55 ssize_t read(void *buffer, size_t size) override {
56 if (!mStream->readback(buffer, size)) {
57 ALOGE("FATAL: Could not read back %zu bytes", size);
58 abort();
59 }
60 return size;
61 }
62
clearPool()63 void clearPool() {
64 mPool.freeAll();
65 }
66
setHandleMapping(VulkanHandleMapping * mapping)67 void setHandleMapping(VulkanHandleMapping* mapping) {
68 mCurrentHandleMapping = mapping;
69 }
70
unsetHandleMapping()71 void unsetHandleMapping() {
72 mCurrentHandleMapping = &mDefaultHandleMapping;
73 }
74
handleMapping() const75 VulkanHandleMapping* handleMapping() const {
76 return mCurrentHandleMapping;
77 }
78
flush()79 void flush() {
80 commitWrite();
81 }
82
getFeatureBits() const83 uint32_t getFeatureBits() const {
84 return mFeatureBits;
85 }
86
87 private:
oustandingWriteBuffer() const88 size_t oustandingWriteBuffer() const {
89 return mWritePos;
90 }
91
remainingWriteBufferSize() const92 size_t remainingWriteBufferSize() const {
93 return mWriteBuffer.size() - mWritePos;
94 }
95
commitWrite()96 void commitWrite() {
97 AEMU_SCOPED_TRACE("VulkanStreamGuest device write");
98 mStream->flush();
99 }
100
bufferedWrite(const void * buffer,size_t size)101 ssize_t bufferedWrite(const void *buffer, size_t size) {
102 if (size > remainingWriteBufferSize()) {
103 mWriteBuffer.resize((mWritePos + size) << 1);
104 }
105 memcpy(mWriteBuffer.data() + mWritePos, buffer, size);
106 mWritePos += size;
107 return size;
108 }
109
110 android::base::Pool mPool { 8, 4096, 64 };
111
112 size_t mWritePos = 0;
113 std::vector<uint8_t> mWriteBuffer;
114 IOStream* mStream = nullptr;
115 DefaultHandleMapping mDefaultHandleMapping;
116 VulkanHandleMapping* mCurrentHandleMapping;
117 uint32_t mFeatureBits = 0;
118 };
119
VulkanStreamGuest(IOStream * stream)120 VulkanStreamGuest::VulkanStreamGuest(IOStream *stream) :
121 mImpl(new VulkanStreamGuest::Impl(stream)) { }
122
123 VulkanStreamGuest::~VulkanStreamGuest() = default;
124
valid()125 bool VulkanStreamGuest::valid() {
126 return mImpl->valid();
127 }
128
alloc(void ** ptrAddr,size_t bytes)129 void VulkanStreamGuest::alloc(void** ptrAddr, size_t bytes) {
130 mImpl->alloc(ptrAddr, bytes);
131 }
132
loadStringInPlace(char ** forOutput)133 void VulkanStreamGuest::loadStringInPlace(char** forOutput) {
134 size_t len = getBe32();
135
136 alloc((void**)forOutput, len + 1);
137
138 memset(*forOutput, 0x0, len + 1);
139
140 if (len > 0) read(*forOutput, len);
141 }
142
loadStringArrayInPlace(char *** forOutput)143 void VulkanStreamGuest::loadStringArrayInPlace(char*** forOutput) {
144 size_t count = getBe32();
145
146 if (!count) {
147 *forOutput = nullptr;
148 return;
149 }
150
151 alloc((void**)forOutput, count * sizeof(char*));
152
153 char **stringsForOutput = *forOutput;
154
155 for (size_t i = 0; i < count; i++) {
156 loadStringInPlace(stringsForOutput + i);
157 }
158 }
159
160
read(void * buffer,size_t size)161 ssize_t VulkanStreamGuest::read(void *buffer, size_t size) {
162 return mImpl->read(buffer, size);
163 }
164
write(const void * buffer,size_t size)165 ssize_t VulkanStreamGuest::write(const void *buffer, size_t size) {
166 return mImpl->write(buffer, size);
167 }
168
clearPool()169 void VulkanStreamGuest::clearPool() {
170 mImpl->clearPool();
171 }
172
setHandleMapping(VulkanHandleMapping * mapping)173 void VulkanStreamGuest::setHandleMapping(VulkanHandleMapping* mapping) {
174 mImpl->setHandleMapping(mapping);
175 }
176
unsetHandleMapping()177 void VulkanStreamGuest::unsetHandleMapping() {
178 mImpl->unsetHandleMapping();
179 }
180
handleMapping() const181 VulkanHandleMapping* VulkanStreamGuest::handleMapping() const {
182 return mImpl->handleMapping();
183 }
184
flush()185 void VulkanStreamGuest::flush() {
186 mImpl->flush();
187 }
188
getFeatureBits() const189 uint32_t VulkanStreamGuest::getFeatureBits() const {
190 return mImpl->getFeatureBits();
191 }
192
VulkanCountingStream()193 VulkanCountingStream::VulkanCountingStream() : VulkanStreamGuest(nullptr) { }
194 VulkanCountingStream::~VulkanCountingStream() = default;
195
read(void *,size_t size)196 ssize_t VulkanCountingStream::read(void*, size_t size) {
197 m_read += size;
198 return size;
199 }
200
write(const void *,size_t size)201 ssize_t VulkanCountingStream::write(const void*, size_t size) {
202 m_written += size;
203 return size;
204 }
205
rewind()206 void VulkanCountingStream::rewind() {
207 m_written = 0;
208 m_read = 0;
209 }
210
211 } // namespace goldfish_vk
212