1 /*
2 * Copyright 2023 Google LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <iostream>
7 #include <cutils/log.h>
8
9 #include "drm_fourcc.h"
10 #include "TestingAndroidWsi.h"
11
12 namespace gfxstream {
13
14 static constexpr int numFds = 0;
15 static constexpr int numInts = 1;
16
GlFormatToDrmFormat(uint32_t glFormat)17 std::optional<uint32_t> GlFormatToDrmFormat(uint32_t glFormat) {
18 switch (glFormat) {
19 case kGlRGB:
20 return DRM_FORMAT_BGR888;
21 case kGlRGB565:
22 return DRM_FORMAT_BGR565;
23 case kGlRGBA:
24 return DRM_FORMAT_ABGR8888;
25 }
26 return std::nullopt;
27 }
28
DrmToVirglFormat(uint32_t drmFormat)29 std::optional<uint32_t> DrmToVirglFormat(uint32_t drmFormat) {
30 switch (drmFormat) {
31 case DRM_FORMAT_ABGR8888:
32 return VIRGL_FORMAT_B8G8R8A8_UNORM;
33 case DRM_FORMAT_BGR888:
34 return VIRGL_FORMAT_R8G8B8_UNORM;
35 case DRM_FORMAT_BGR565:
36 return VIRGL_FORMAT_B5G6R5_UNORM;
37 }
38 return std::nullopt;
39 }
40
TestingAHardwareBuffer(uint32_t width,uint32_t height,VirtGpuBlobPtr resource)41 TestingAHardwareBuffer::TestingAHardwareBuffer(
42 uint32_t width,
43 uint32_t height,
44 VirtGpuBlobPtr resource)
45 : mWidth(width),
46 mHeight(height),
47 mResource(resource) {
48 mHandle = native_handle_create(numFds, numInts);
49 mHandle->data[0] = mResource->getResourceHandle();
50 }
51
~TestingAHardwareBuffer()52 TestingAHardwareBuffer::~TestingAHardwareBuffer() {
53 native_handle_close(mHandle);
54 }
55
getResourceId() const56 uint32_t TestingAHardwareBuffer::getResourceId() const {
57 return mResource->getResourceHandle();
58 }
59
getWidth() const60 uint32_t TestingAHardwareBuffer::getWidth() const {
61 return mWidth;
62 }
63
getHeight() const64 uint32_t TestingAHardwareBuffer::getHeight() const {
65 return mHeight;
66 }
67
getAndroidFormat() const68 int TestingAHardwareBuffer::getAndroidFormat() const {
69 return /*AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM=*/1;
70 }
71
getDrmFormat() const72 uint32_t TestingAHardwareBuffer::getDrmFormat() const {
73 return DRM_FORMAT_ABGR8888;
74 }
75
asAHardwareBuffer()76 AHardwareBuffer* TestingAHardwareBuffer::asAHardwareBuffer() {
77 return reinterpret_cast<AHardwareBuffer*>(this);
78 }
79
asBufferHandle()80 buffer_handle_t TestingAHardwareBuffer::asBufferHandle() {
81 return reinterpret_cast<buffer_handle_t>(mHandle);
82 }
83
asEglClientBuffer()84 EGLClientBuffer TestingAHardwareBuffer::asEglClientBuffer() {
85 return reinterpret_cast<EGLClientBuffer>(this);
86 }
87
TestingVirtGpuGralloc()88 TestingVirtGpuGralloc::TestingVirtGpuGralloc() {}
89
createColorBuffer(void *,int width,int height,uint32_t glFormat)90 uint32_t TestingVirtGpuGralloc::createColorBuffer(
91 void*,
92 int width,
93 int height,
94 uint32_t glFormat) {
95 auto drmFormat = GlFormatToDrmFormat(glFormat);
96 if (!drmFormat) {
97 ALOGE("Unhandled format");
98 }
99
100 auto ahb = allocate(width, height, *drmFormat);
101
102 uint32_t hostHandle = ahb->getResourceId();
103 mAllocatedColorBuffers.emplace(hostHandle, std::move(ahb));
104 return hostHandle;
105 }
106
allocate(uint32_t width,uint32_t height,uint32_t format,uint64_t usage,AHardwareBuffer ** outputAhb)107 int TestingVirtGpuGralloc::allocate(
108 uint32_t width,
109 uint32_t height,
110 uint32_t format,
111 uint64_t usage,
112 AHardwareBuffer** outputAhb) {
113 (void)width;
114 (void)height;
115 (void)format;
116 (void)usage;
117 (void)outputAhb;
118
119 // TODO: support export flow?
120 ALOGE("Unimplemented");
121
122 return 0;
123 }
124
allocate(uint32_t width,uint32_t height,uint32_t format)125 std::unique_ptr<TestingAHardwareBuffer> TestingVirtGpuGralloc::allocate(
126 uint32_t width,
127 uint32_t height,
128 uint32_t format) {
129 ALOGE("Allocating AHB w:%u, h:%u, format %u", width, height, format);
130
131 auto device = VirtGpuDevice::getInstance();
132 if (!device) {
133 ALOGE("Failed to allocate: no virtio gpu device.");
134 return nullptr;
135 }
136
137 auto virglFormat = DrmToVirglFormat(format);
138 if (!virglFormat) {
139 std::cout << "Unhandled DRM format:" << format;
140 return nullptr;
141 }
142
143 auto resource = device->createVirglBlob(width, height, *virglFormat);
144 if (!resource) {
145 ALOGE("Failed to allocate: failed to create virtio resource.");
146 return nullptr;
147 }
148
149 resource->wait();
150
151 return std::make_unique<TestingAHardwareBuffer>(width, height, std::move(resource));
152 }
153
acquire(AHardwareBuffer * ahb)154 void TestingVirtGpuGralloc::acquire(AHardwareBuffer* ahb) {
155 // TODO
156 }
157
release(AHardwareBuffer * ahb)158 void TestingVirtGpuGralloc::release(AHardwareBuffer* ahb) {
159 // TODO
160 }
161
getHostHandle(const native_handle_t * handle)162 uint32_t TestingVirtGpuGralloc::getHostHandle(const native_handle_t* handle) {
163 const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
164 return ahb->getResourceId();
165 }
166
getHostHandle(const AHardwareBuffer * handle)167 uint32_t TestingVirtGpuGralloc::getHostHandle(const AHardwareBuffer* handle) {
168 const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
169 return ahb->getResourceId();
170 }
171
getFormat(const native_handle_t * handle)172 int TestingVirtGpuGralloc::getFormat(const native_handle_t* handle) {
173 const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
174 return ahb->getAndroidFormat();
175 }
176
getFormat(const AHardwareBuffer * handle)177 int TestingVirtGpuGralloc::getFormat(const AHardwareBuffer* handle) {
178 const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
179 return ahb->getAndroidFormat();
180 }
181
getFormatDrmFourcc(const AHardwareBuffer * handle)182 uint32_t TestingVirtGpuGralloc::getFormatDrmFourcc(const AHardwareBuffer* handle) {
183 const auto* ahb = reinterpret_cast<const TestingAHardwareBuffer*>(handle);
184 return ahb->getDrmFormat();
185 }
186
getAllocatedSize(const native_handle_t *)187 size_t TestingVirtGpuGralloc::getAllocatedSize(const native_handle_t*) {
188 ALOGE("Unimplemented.");
189 return 0;
190 }
191
getAllocatedSize(const AHardwareBuffer *)192 size_t TestingVirtGpuGralloc::getAllocatedSize(const AHardwareBuffer*) {
193 ALOGE("Unimplemented.");
194 return 0;
195 }
196
TestingANativeWindow(uint32_t width,uint32_t height,uint32_t format,std::vector<std::unique_ptr<TestingAHardwareBuffer>> buffers)197 TestingANativeWindow::TestingANativeWindow(
198 uint32_t width,
199 uint32_t height,
200 uint32_t format,
201 std::vector<std::unique_ptr<TestingAHardwareBuffer>> buffers)
202 : mWidth(width),
203 mHeight(height),
204 mFormat(format),
205 mBuffers(std::move(buffers)) {
206 for (auto& buffer : mBuffers) {
207 mBufferQueue.push_back(QueuedAHB{
208 .ahb = buffer.get(),
209 .fence = -1,
210 });
211 }
212 }
213
asEglNativeWindowType()214 EGLNativeWindowType TestingANativeWindow::asEglNativeWindowType() {
215 return reinterpret_cast<EGLNativeWindowType>(this);
216 }
217
getWidth() const218 uint32_t TestingANativeWindow::getWidth() const {
219 return mWidth;
220 }
221
getHeight() const222 uint32_t TestingANativeWindow::getHeight() const {
223 return mHeight;
224 }
225
getFormat() const226 int TestingANativeWindow::getFormat() const {
227 return mFormat;
228 }
229
queueBuffer(EGLClientBuffer buffer,int fence)230 int TestingANativeWindow::queueBuffer(EGLClientBuffer buffer, int fence) {
231 auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
232
233 mBufferQueue.push_back(QueuedAHB{
234 .ahb = ahb,
235 .fence = fence,
236 });
237
238 return 0;
239 }
240
dequeueBuffer(EGLClientBuffer * buffer,int * fence)241 int TestingANativeWindow::dequeueBuffer(EGLClientBuffer* buffer, int* fence) {
242 auto queuedAhb = mBufferQueue.front();
243 mBufferQueue.pop_front();
244
245 *buffer = queuedAhb.ahb->asEglClientBuffer();
246 *fence = queuedAhb.fence;
247 return 0;
248 }
249
cancelBuffer(EGLClientBuffer buffer)250 int TestingANativeWindow::cancelBuffer(EGLClientBuffer buffer) {
251 auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
252
253 mBufferQueue.push_back(QueuedAHB{
254 .ahb = ahb,
255 .fence = -1,
256 });
257
258 return 0;
259 }
260
isValid(EGLNativeWindowType window)261 bool TestingVirtGpuANativeWindowHelper::isValid(EGLNativeWindowType window) {
262 // TODO: maybe a registry of valid TestingANativeWindow-s?
263 return true;
264 }
265
isValid(EGLClientBuffer buffer)266 bool TestingVirtGpuANativeWindowHelper::isValid(EGLClientBuffer buffer) {
267 // TODO: maybe a registry of valid TestingAHardwareBuffer-s?
268 return true;
269 }
270
acquire(EGLNativeWindowType window)271 void TestingVirtGpuANativeWindowHelper::acquire(EGLNativeWindowType window) {
272 // TODO: maybe a registry of valid TestingANativeWindow-s?
273 }
274
release(EGLNativeWindowType window)275 void TestingVirtGpuANativeWindowHelper::release(EGLNativeWindowType window) {
276 // TODO: maybe a registry of valid TestingANativeWindow-s?
277 }
278
acquire(EGLClientBuffer buffer)279 void TestingVirtGpuANativeWindowHelper::acquire(EGLClientBuffer buffer) {
280 // TODO: maybe a registry of valid TestingAHardwareBuffer-s?
281 }
282
release(EGLClientBuffer buffer)283 void TestingVirtGpuANativeWindowHelper::release(EGLClientBuffer buffer) {
284 // TODO: maybe a registry of valid TestingAHardwareBuffer-s?
285 }
286
getConsumerUsage(EGLNativeWindowType window,int * usage)287 int TestingVirtGpuANativeWindowHelper::getConsumerUsage(EGLNativeWindowType window, int* usage) {
288 (void)window;
289 (void)usage;
290 return 0;
291 }
setUsage(EGLNativeWindowType window,int usage)292 void TestingVirtGpuANativeWindowHelper::setUsage(EGLNativeWindowType window, int usage) {
293 (void)window;
294 (void)usage;
295 }
296
getWidth(EGLNativeWindowType window)297 int TestingVirtGpuANativeWindowHelper::getWidth(EGLNativeWindowType window) {
298 auto anw = reinterpret_cast<TestingANativeWindow*>(window);
299 return anw->getWidth();
300 }
301
getHeight(EGLNativeWindowType window)302 int TestingVirtGpuANativeWindowHelper::getHeight(EGLNativeWindowType window) {
303 auto anw = reinterpret_cast<TestingANativeWindow*>(window);
304 return anw->getHeight();
305 }
306
getWidth(EGLClientBuffer buffer)307 int TestingVirtGpuANativeWindowHelper::getWidth(EGLClientBuffer buffer) {
308 auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
309 return ahb->getWidth();
310 }
311
getHeight(EGLClientBuffer buffer)312 int TestingVirtGpuANativeWindowHelper::getHeight(EGLClientBuffer buffer) {
313 auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
314 return ahb->getHeight();
315 }
316
getFormat(EGLClientBuffer buffer,Gralloc * helper)317 int TestingVirtGpuANativeWindowHelper::getFormat(EGLClientBuffer buffer, Gralloc* helper) {
318 auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
319 return ahb->getAndroidFormat();
320 }
321
setSwapInterval(EGLNativeWindowType window,int interval)322 void TestingVirtGpuANativeWindowHelper::setSwapInterval(EGLNativeWindowType window, int interval) {
323 ALOGE("Unimplemented");
324 }
325
queueBuffer(EGLNativeWindowType window,EGLClientBuffer buffer,int fence)326 int TestingVirtGpuANativeWindowHelper::queueBuffer(EGLNativeWindowType window, EGLClientBuffer buffer, int fence) {
327 auto anw = reinterpret_cast<TestingANativeWindow*>(window);
328 return anw->queueBuffer(buffer, fence);
329 }
330
dequeueBuffer(EGLNativeWindowType window,EGLClientBuffer * buffer,int * fence)331 int TestingVirtGpuANativeWindowHelper::dequeueBuffer(EGLNativeWindowType window, EGLClientBuffer* buffer, int* fence) {
332 auto anw = reinterpret_cast<TestingANativeWindow*>(window);
333 return anw->dequeueBuffer(buffer, fence);
334 }
335
cancelBuffer(EGLNativeWindowType window,EGLClientBuffer buffer)336 int TestingVirtGpuANativeWindowHelper::cancelBuffer(EGLNativeWindowType window, EGLClientBuffer buffer) {
337 auto anw = reinterpret_cast<TestingANativeWindow*>(window);
338 return anw->cancelBuffer(buffer);
339 }
340
getHostHandle(EGLClientBuffer buffer,Gralloc *)341 int TestingVirtGpuANativeWindowHelper::getHostHandle(EGLClientBuffer buffer, Gralloc*) {
342 auto ahb = reinterpret_cast<TestingAHardwareBuffer*>(buffer);
343 return ahb->getResourceId();
344 }
345
346 } // namespace gfxstream
347