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
18 #include "android/base/Pool.h"
19 #include "android/base/Tracing.h"
20
21 #include <vector>
22
23 #include <log/log.h>
24 #include <inttypes.h>
25
26 namespace goldfish_vk {
27
28 class VulkanStreamGuest::Impl : public android::base::Stream {
29 public:
Impl(IOStream * stream)30 Impl(IOStream* stream) : mStream(stream) { unsetHandleMapping(); }
31
~Impl()32 ~Impl() { }
33
valid()34 bool valid() { return true; }
35
alloc(void ** ptrAddr,size_t bytes)36 void alloc(void **ptrAddr, size_t bytes) {
37 if (!bytes) {
38 *ptrAddr = nullptr;
39 return;
40 }
41
42 *ptrAddr = mPool.alloc(bytes);
43 }
44
write(const void * buffer,size_t size)45 ssize_t write(const void *buffer, size_t size) override {
46 uint8_t* streamBuf = (uint8_t*)mStream->alloc(size);
47 memcpy(streamBuf, buffer, size);
48 return size;
49 }
50
read(void * buffer,size_t size)51 ssize_t read(void *buffer, size_t size) override {
52 commitWrite();
53 if (!mStream->readFully(buffer, size)) {
54 ALOGE("FATAL: Could not read back %zu bytes", size);
55 abort();
56 }
57 return size;
58 }
59
clearPool()60 void clearPool() {
61 mPool.freeAll();
62 }
63
setHandleMapping(VulkanHandleMapping * mapping)64 void setHandleMapping(VulkanHandleMapping* mapping) {
65 mCurrentHandleMapping = mapping;
66 }
67
unsetHandleMapping()68 void unsetHandleMapping() {
69 mCurrentHandleMapping = &mDefaultHandleMapping;
70 }
71
handleMapping() const72 VulkanHandleMapping* handleMapping() const {
73 return mCurrentHandleMapping;
74 }
75
flush()76 void flush() {
77 commitWrite();
78 }
79
80 private:
oustandingWriteBuffer() const81 size_t oustandingWriteBuffer() const {
82 return mWritePos;
83 }
84
remainingWriteBufferSize() const85 size_t remainingWriteBufferSize() const {
86 return mWriteBuffer.size() - mWritePos;
87 }
88
commitWrite()89 void commitWrite() {
90 AEMU_SCOPED_TRACE("VulkanStreamGuest device write");
91 mStream->flush();
92 }
93
bufferedWrite(const void * buffer,size_t size)94 ssize_t bufferedWrite(const void *buffer, size_t size) {
95 if (size > remainingWriteBufferSize()) {
96 mWriteBuffer.resize((mWritePos + size) << 1);
97 }
98 memcpy(mWriteBuffer.data() + mWritePos, buffer, size);
99 mWritePos += size;
100 return size;
101 }
102
103 android::base::Pool mPool { 8, 4096, 64 };
104
105 size_t mWritePos = 0;
106 std::vector<uint8_t> mWriteBuffer;
107 IOStream* mStream = nullptr;
108 DefaultHandleMapping mDefaultHandleMapping;
109 VulkanHandleMapping* mCurrentHandleMapping;
110 };
111
VulkanStreamGuest(IOStream * stream)112 VulkanStreamGuest::VulkanStreamGuest(IOStream *stream) :
113 mImpl(new VulkanStreamGuest::Impl(stream)) { }
114
115 VulkanStreamGuest::~VulkanStreamGuest() = default;
116
valid()117 bool VulkanStreamGuest::valid() {
118 return mImpl->valid();
119 }
120
alloc(void ** ptrAddr,size_t bytes)121 void VulkanStreamGuest::alloc(void** ptrAddr, size_t bytes) {
122 mImpl->alloc(ptrAddr, bytes);
123 }
124
loadStringInPlace(char ** forOutput)125 void VulkanStreamGuest::loadStringInPlace(char** forOutput) {
126 size_t len = getBe32();
127
128 alloc((void**)forOutput, len + 1);
129
130 memset(*forOutput, 0x0, len + 1);
131
132 if (len > 0) read(*forOutput, len);
133 }
134
loadStringArrayInPlace(char *** forOutput)135 void VulkanStreamGuest::loadStringArrayInPlace(char*** forOutput) {
136 size_t count = getBe32();
137
138 if (!count) {
139 *forOutput = nullptr;
140 return;
141 }
142
143 alloc((void**)forOutput, count * sizeof(char*));
144
145 char **stringsForOutput = *forOutput;
146
147 for (size_t i = 0; i < count; i++) {
148 loadStringInPlace(stringsForOutput + i);
149 }
150 }
151
152
read(void * buffer,size_t size)153 ssize_t VulkanStreamGuest::read(void *buffer, size_t size) {
154 return mImpl->read(buffer, size);
155 }
156
write(const void * buffer,size_t size)157 ssize_t VulkanStreamGuest::write(const void *buffer, size_t size) {
158 return mImpl->write(buffer, size);
159 }
160
clearPool()161 void VulkanStreamGuest::clearPool() {
162 mImpl->clearPool();
163 }
164
setHandleMapping(VulkanHandleMapping * mapping)165 void VulkanStreamGuest::setHandleMapping(VulkanHandleMapping* mapping) {
166 mImpl->setHandleMapping(mapping);
167 }
168
unsetHandleMapping()169 void VulkanStreamGuest::unsetHandleMapping() {
170 mImpl->unsetHandleMapping();
171 }
172
handleMapping() const173 VulkanHandleMapping* VulkanStreamGuest::handleMapping() const {
174 return mImpl->handleMapping();
175 }
176
flush()177 void VulkanStreamGuest::flush() {
178 mImpl->flush();
179 }
180
VulkanCountingStream()181 VulkanCountingStream::VulkanCountingStream() : VulkanStreamGuest(nullptr) { }
182 VulkanCountingStream::~VulkanCountingStream() = default;
183
read(void *,size_t size)184 ssize_t VulkanCountingStream::read(void*, size_t size) {
185 m_read += size;
186 return size;
187 }
188
write(const void *,size_t size)189 ssize_t VulkanCountingStream::write(const void*, size_t size) {
190 m_written += size;
191 return size;
192 }
193
rewind()194 void VulkanCountingStream::rewind() {
195 m_written = 0;
196 m_read = 0;
197 }
198
199 } // namespace goldfish_vk
200