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