1 // Copyright 2023 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 expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Buffer.h"
16 
17 #if GFXSTREAM_ENABLE_HOST_GLES
18 #include "gl/EmulationGl.h"
19 #endif
20 
21 #include "vulkan/BufferVk.h"
22 #include "vulkan/VkCommonOperations.h"
23 
24 namespace gfxstream {
25 
26 using android::base::ManagedDescriptor;
27 using emugl::ABORT_REASON_OTHER;
28 using emugl::FatalError;
29 
Buffer(HandleType handle,uint64_t size)30 Buffer::Buffer(HandleType handle, uint64_t size) : mHandle(handle), mSize(size) {}
31 
32 /*static*/
create(gl::EmulationGl * emulationGl,vk::VkEmulation * emulationVk,uint64_t size,HandleType handle)33 std::shared_ptr<Buffer> Buffer::create(gl::EmulationGl* emulationGl, vk::VkEmulation* emulationVk,
34                                        uint64_t size, HandleType handle) {
35     std::shared_ptr<Buffer> buffer(new Buffer(handle, size));
36 
37 #if GFXSTREAM_ENABLE_HOST_GLES
38     if (emulationGl) {
39         buffer->mBufferGl = emulationGl->createBuffer(size, handle);
40         if (!buffer->mBufferGl) {
41             ERR("Failed to initialize BufferGl.");
42             return nullptr;
43         }
44     }
45 #endif
46 
47     if (emulationVk && emulationVk->live) {
48         const bool vulkanOnly = emulationGl == nullptr;
49 
50         buffer->mBufferVk = vk::BufferVk::create(handle, size, vulkanOnly);
51         if (!buffer->mBufferVk) {
52             ERR("Failed to initialize BufferVk.");
53             return nullptr;
54         }
55 
56         if (!vulkanOnly) {
57 #if GFXSTREAM_ENABLE_HOST_GLES
58             if (!buffer->mBufferGl) {
59                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Missing BufferGl?";
60             }
61 #endif
62             // TODO: external memory sharing.
63         }
64     }
65 
66     return buffer;
67 }
68 
69 /*static*/
onLoad(gl::EmulationGl * emulationGl,vk::VkEmulation *,android::base::Stream * stream)70 std::shared_ptr<Buffer> Buffer::onLoad(gl::EmulationGl* emulationGl, vk::VkEmulation*,
71                                        android::base::Stream* stream) {
72     const auto handle = static_cast<HandleType>(stream->getBe32());
73     const auto size = static_cast<uint64_t>(stream->getBe64());
74 
75     std::shared_ptr<Buffer> buffer(new Buffer(handle, size));
76 
77 #if GFXSTREAM_ENABLE_HOST_GLES
78     if (emulationGl) {
79         buffer->mBufferGl = emulationGl->loadBuffer(stream);
80         if (!buffer->mBufferGl) {
81             ERR("Failed to load BufferGl.");
82             return nullptr;
83         }
84     }
85 #endif
86 
87     buffer->mNeedRestore = true;
88 
89     return buffer;
90 }
91 
onSave(android::base::Stream * stream)92 void Buffer::onSave(android::base::Stream* stream) {
93     stream->putBe32(mHandle);
94     stream->putBe64(mSize);
95 
96 #if GFXSTREAM_ENABLE_HOST_GLES
97     if (mBufferGl) {
98         mBufferGl->onSave(stream);
99     }
100 #endif
101 }
102 
restore()103 void Buffer::restore() {}
104 
readToBytes(uint64_t offset,uint64_t size,void * outBytes)105 void Buffer::readToBytes(uint64_t offset, uint64_t size, void* outBytes) {
106     touch();
107 
108 #if GFXSTREAM_ENABLE_HOST_GLES
109     if (mBufferGl) {
110         mBufferGl->read(offset, size, outBytes);
111         return;
112     }
113 #endif
114 
115     if (mBufferVk) {
116         mBufferVk->readToBytes(offset, size, outBytes);
117         return;
118     }
119 
120     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No Buffer impl?";
121 }
122 
updateFromBytes(uint64_t offset,uint64_t size,const void * bytes)123 bool Buffer::updateFromBytes(uint64_t offset, uint64_t size, const void* bytes) {
124     touch();
125 
126 #if GFXSTREAM_ENABLE_HOST_GLES
127     if (mBufferGl) {
128         mBufferGl->subUpdate(offset, size, bytes);
129         return true;
130     }
131 #endif
132 
133     if (mBufferVk) {
134         return mBufferVk->updateFromBytes(offset, size, bytes);
135     }
136 
137     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No Buffer impl?";
138     return false;
139 }
140 
exportBlob()141 std::optional<BlobDescriptorInfo> Buffer::exportBlob() {
142     if (!mBufferVk) {
143         return std::nullopt;
144     }
145 
146     return mBufferVk->exportBlob();
147 }
148 
149 }  // namespace gfxstream
150