1 // Copyright 2024 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
15 #include "GrallocEmulated.h"
16
17 #include <cutils/log.h>
18
19 #include <optional>
20
21 #include "drm_fourcc.h"
22
23 namespace gfxstream {
24 namespace {
25
26 static constexpr int numFds = 0;
27 static constexpr int numInts = 1;
28
29 #define DRM_FORMAT_R8_BLOB fourcc_code('9', '9', '9', '9')
30
GlFormatToDrmFormat(uint32_t glFormat)31 std::optional<uint32_t> GlFormatToDrmFormat(uint32_t glFormat) {
32 switch (glFormat) {
33 case kGlRGB:
34 return DRM_FORMAT_BGR888;
35 case kGlRGB565:
36 return DRM_FORMAT_BGR565;
37 case kGlRGBA:
38 return DRM_FORMAT_ABGR8888;
39 }
40 return std::nullopt;
41 }
42
AhbToDrmFormat(uint32_t ahbFormat)43 std::optional<uint32_t> AhbToDrmFormat(uint32_t ahbFormat) {
44 switch (ahbFormat) {
45 case GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM:
46 return DRM_FORMAT_ABGR8888;
47 case GFXSTREAM_AHB_FORMAT_R8G8B8X8_UNORM:
48 return DRM_FORMAT_XBGR8888;
49 case GFXSTREAM_AHB_FORMAT_R8G8B8_UNORM:
50 return DRM_FORMAT_BGR888;
51 /*
52 * Confusingly, AHARDWAREBUFFER_FORMAT_RGB_565 is defined as:
53 *
54 * "16-bit packed format that has 5-bit R, 6-bit G, and 5-bit B components, in that
55 * order, from the most-sigfinicant bits to the least-significant bits."
56 *
57 * so the order of the components is intentionally not flipped between the pixel
58 * format and the DRM format.
59 */
60 case GFXSTREAM_AHB_FORMAT_R5G6B5_UNORM:
61 return DRM_FORMAT_RGB565;
62 case GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM:
63 return DRM_FORMAT_ARGB8888;
64 case GFXSTREAM_AHB_FORMAT_BLOB:
65 return DRM_FORMAT_R8_BLOB;
66 case GFXSTREAM_AHB_FORMAT_R8_UNORM:
67 return DRM_FORMAT_R8;
68 case GFXSTREAM_AHB_FORMAT_YV12:
69 return DRM_FORMAT_YVU420;
70 case GFXSTREAM_AHB_FORMAT_R16G16B16A16_FLOAT:
71 return DRM_FORMAT_ABGR16161616F;
72 case GFXSTREAM_AHB_FORMAT_R10G10B10A2_UNORM:
73 return DRM_FORMAT_ABGR2101010;
74 }
75 return std::nullopt;
76 }
77
DrmToAhbFormat(uint32_t drmFormat)78 std::optional<uint32_t> DrmToAhbFormat(uint32_t drmFormat) {
79 switch (drmFormat) {
80 case DRM_FORMAT_ABGR8888:
81 return GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM;
82 case DRM_FORMAT_XBGR8888:
83 return GFXSTREAM_AHB_FORMAT_R8G8B8X8_UNORM;
84 case DRM_FORMAT_ARGB8888:
85 return GFXSTREAM_AHB_FORMAT_B8G8R8A8_UNORM;
86 case DRM_FORMAT_BGR888:
87 return GFXSTREAM_AHB_FORMAT_R8G8B8_UNORM;
88 case DRM_FORMAT_RGB565:
89 return GFXSTREAM_AHB_FORMAT_R5G6B5_UNORM;
90 case DRM_FORMAT_R8_BLOB:
91 return GFXSTREAM_AHB_FORMAT_BLOB;
92 case DRM_FORMAT_R8:
93 return GFXSTREAM_AHB_FORMAT_R8_UNORM;
94 case DRM_FORMAT_YVU420:
95 return GFXSTREAM_AHB_FORMAT_YV12;
96 case DRM_FORMAT_ABGR16161616F:
97 return GFXSTREAM_AHB_FORMAT_R16G16B16A16_FLOAT;
98 case DRM_FORMAT_ABGR2101010:
99 return GFXSTREAM_AHB_FORMAT_R10G10B10A2_UNORM;
100 }
101 return std::nullopt;
102 }
103
DrmToBpp(uint32_t drmFormat)104 std::optional<uint32_t> DrmToBpp(uint32_t drmFormat) {
105 switch (drmFormat) {
106 case DRM_FORMAT_ABGR8888:
107 case DRM_FORMAT_ARGB8888:
108 case DRM_FORMAT_XBGR8888:
109 return 4;
110 case DRM_FORMAT_BGR888:
111 return 3;
112 case DRM_FORMAT_RGB565:
113 return 2;
114 case DRM_FORMAT_R8_BLOB:
115 case DRM_FORMAT_R8:
116 return 1;
117 }
118 return std::nullopt;
119 }
120
DrmToVirglFormat(uint32_t drmFormat)121 std::optional<uint32_t> DrmToVirglFormat(uint32_t drmFormat) {
122 switch (drmFormat) {
123 case DRM_FORMAT_ABGR8888:
124 return VIRGL_FORMAT_R8G8B8A8_UNORM;
125 case DRM_FORMAT_ARGB8888:
126 return VIRGL_FORMAT_B8G8R8A8_UNORM;
127 case DRM_FORMAT_BGR888:
128 return VIRGL_FORMAT_R8G8B8_UNORM;
129 case DRM_FORMAT_BGR565:
130 return VIRGL_FORMAT_B5G6R5_UNORM;
131 case DRM_FORMAT_R8:
132 case DRM_FORMAT_R8_BLOB:
133 return VIRGL_FORMAT_R8_UNORM;
134 }
135 return std::nullopt;
136 }
137
138 } // namespace
139
EmulatedAHardwareBuffer(uint32_t width,uint32_t height,uint32_t drmFormat,VirtGpuResourcePtr resource)140 EmulatedAHardwareBuffer::EmulatedAHardwareBuffer(uint32_t width, uint32_t height,
141 uint32_t drmFormat, VirtGpuResourcePtr resource)
142 : mRefCount(1), mWidth(width), mHeight(height), mDrmFormat(drmFormat), mResource(resource) {}
143
~EmulatedAHardwareBuffer()144 EmulatedAHardwareBuffer::~EmulatedAHardwareBuffer() {}
145
getResourceId() const146 uint32_t EmulatedAHardwareBuffer::getResourceId() const { return mResource->getResourceHandle(); }
147
getWidth() const148 uint32_t EmulatedAHardwareBuffer::getWidth() const { return mWidth; }
149
getHeight() const150 uint32_t EmulatedAHardwareBuffer::getHeight() const { return mHeight; }
151
getAndroidFormat() const152 int EmulatedAHardwareBuffer::getAndroidFormat() const {
153 auto ahbFormat = DrmToAhbFormat(mDrmFormat);
154 if (!ahbFormat) {
155 ALOGE("Unhandled DRM format:%u", mDrmFormat);
156 return -1;
157 }
158 return *ahbFormat;
159 }
160
getDrmFormat() const161 uint32_t EmulatedAHardwareBuffer::getDrmFormat() const { return mDrmFormat; }
162
asAHardwareBuffer()163 AHardwareBuffer* EmulatedAHardwareBuffer::asAHardwareBuffer() {
164 return reinterpret_cast<AHardwareBuffer*>(this);
165 }
166
asBufferHandle()167 buffer_handle_t EmulatedAHardwareBuffer::asBufferHandle() {
168 return reinterpret_cast<buffer_handle_t>(this);
169 }
170
asEglClientBuffer()171 EGLClientBuffer EmulatedAHardwareBuffer::asEglClientBuffer() {
172 return reinterpret_cast<EGLClientBuffer>(this);
173 }
174
acquire()175 void EmulatedAHardwareBuffer::acquire() { ++mRefCount; }
176
release()177 void EmulatedAHardwareBuffer::release() {
178 --mRefCount;
179 if (mRefCount == 0) {
180 delete this;
181 }
182 }
183
lock(uint8_t ** ptr)184 int EmulatedAHardwareBuffer::lock(uint8_t** ptr) {
185 if (!mMapped) {
186 mMapped = mResource->createMapping();
187 if (!mMapped) {
188 ALOGE("Failed to lock EmulatedAHardwareBuffer: failed to create mapping.");
189 return -1;
190 }
191
192 mResource->transferFromHost(0, 0, mWidth, mHeight);
193 mResource->wait();
194 }
195
196 *ptr = (*mMapped)->asRawPtr();
197 return 0;
198 }
199
unlock()200 int EmulatedAHardwareBuffer::unlock() {
201 if (!mMapped) {
202 ALOGE("Failed to unlock EmulatedAHardwareBuffer: never locked?");
203 return -1;
204 }
205 mResource->transferToHost(0, 0, mWidth, mHeight);
206 mResource->wait();
207 mMapped.reset();
208 return 0;
209 }
210
EmulatedGralloc()211 EmulatedGralloc::EmulatedGralloc() {}
212
createColorBuffer(void *,int width,int height,uint32_t glFormat)213 uint32_t EmulatedGralloc::createColorBuffer(void*, int width, int height, uint32_t glFormat) {
214 auto drmFormat = GlFormatToDrmFormat(glFormat);
215 if (!drmFormat) {
216 ALOGE("Unhandled format");
217 }
218
219 auto ahb = allocate(width, height, *drmFormat);
220
221 EmulatedAHardwareBuffer* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
222
223 mOwned.emplace_back(rahb);
224
225 return rahb->getResourceId();
226 }
227
allocate(uint32_t width,uint32_t height,uint32_t ahbFormat,uint64_t usage,AHardwareBuffer ** outputAhb)228 int EmulatedGralloc::allocate(uint32_t width, uint32_t height, uint32_t ahbFormat, uint64_t usage,
229 AHardwareBuffer** outputAhb) {
230 (void)usage;
231
232 auto drmFormat = AhbToDrmFormat(ahbFormat);
233 if (!drmFormat) {
234 ALOGE("Unhandled AHB format:%u", ahbFormat);
235 return -1;
236 }
237
238 *outputAhb = allocate(width, height, *drmFormat);
239 if (*outputAhb == nullptr) {
240 return -1;
241 }
242
243 return 0;
244 }
245
allocate(uint32_t width,uint32_t height,uint32_t drmFormat)246 AHardwareBuffer* EmulatedGralloc::allocate(uint32_t width, uint32_t height, uint32_t drmFormat) {
247 ALOGE("Allocating AHB w:%u, h:%u, format %u", width, height, drmFormat);
248
249 auto device = VirtGpuDevice::getInstance();
250 if (!device) {
251 ALOGE("Failed to allocate: no virtio gpu device.");
252 return nullptr;
253 }
254
255 auto virglFormat = DrmToVirglFormat(drmFormat);
256 if (!virglFormat) {
257 ALOGE("Failed to allocate: Unhandled DRM format:%u to Virgl format conversion.", drmFormat);
258 return nullptr;
259 }
260
261 auto bpp = DrmToBpp(drmFormat);
262 if (!virglFormat) {
263 ALOGE("Failed to allocate: Unhandled DRM format:%u to bpp conversion.", drmFormat);
264 return nullptr;
265 }
266
267 const uint32_t bind =
268 (drmFormat == DRM_FORMAT_R8_BLOB) ? VIRGL_BIND_LINEAR : VIRGL_BIND_RENDER_TARGET;
269 const uint32_t stride = width * (*bpp);
270
271 auto resource =
272 device->createResource(width, height, stride, *virglFormat, PIPE_TEXTURE_2D, bind);
273 if (!resource) {
274 ALOGE("Failed to allocate: failed to create virtio resource.");
275 return nullptr;
276 }
277
278 resource->wait();
279
280 return reinterpret_cast<AHardwareBuffer*>(
281 new EmulatedAHardwareBuffer(width, height, drmFormat, std::move(resource)));
282 }
283
acquire(AHardwareBuffer * ahb)284 void EmulatedGralloc::acquire(AHardwareBuffer* ahb) {
285 auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
286 rahb->acquire();
287 }
288
release(AHardwareBuffer * ahb)289 void EmulatedGralloc::release(AHardwareBuffer* ahb) {
290 auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
291 rahb->release();
292 }
293
lock(AHardwareBuffer * ahb,uint8_t ** ptr)294 int EmulatedGralloc::lock(AHardwareBuffer* ahb, uint8_t** ptr) {
295 auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
296 return rahb->lock(ptr);
297 }
298
unlock(AHardwareBuffer * ahb)299 int EmulatedGralloc::unlock(AHardwareBuffer* ahb) {
300 auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
301 return rahb->unlock();
302 }
303
getHostHandle(const native_handle_t * handle)304 uint32_t EmulatedGralloc::getHostHandle(const native_handle_t* handle) {
305 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
306 return ahb->getResourceId();
307 }
308
getHostHandle(const AHardwareBuffer * handle)309 uint32_t EmulatedGralloc::getHostHandle(const AHardwareBuffer* handle) {
310 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
311 return ahb->getResourceId();
312 }
313
getNativeHandle(const AHardwareBuffer * ahb)314 const native_handle_t* EmulatedGralloc::getNativeHandle(const AHardwareBuffer* ahb) {
315 return reinterpret_cast<const native_handle_t*>(ahb);
316 }
317
getFormat(const native_handle_t * handle)318 int EmulatedGralloc::getFormat(const native_handle_t* handle) {
319 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
320 return ahb->getAndroidFormat();
321 }
322
getFormat(const AHardwareBuffer * handle)323 int EmulatedGralloc::getFormat(const AHardwareBuffer* handle) {
324 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
325 return ahb->getAndroidFormat();
326 }
327
getFormatDrmFourcc(const AHardwareBuffer * handle)328 uint32_t EmulatedGralloc::getFormatDrmFourcc(const AHardwareBuffer* handle) {
329 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
330 return ahb->getDrmFormat();
331 }
332
getWidth(const AHardwareBuffer * handle)333 uint32_t EmulatedGralloc::getWidth(const AHardwareBuffer* handle) {
334 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
335 return ahb->getWidth();
336 }
337
getHeight(const AHardwareBuffer * handle)338 uint32_t EmulatedGralloc::getHeight(const AHardwareBuffer* handle) {
339 const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
340 return ahb->getHeight();
341 }
342
getAllocatedSize(const native_handle_t *)343 size_t EmulatedGralloc::getAllocatedSize(const native_handle_t*) {
344 ALOGE("Unimplemented.");
345 return 0;
346 }
347
getAllocatedSize(const AHardwareBuffer *)348 size_t EmulatedGralloc::getAllocatedSize(const AHardwareBuffer*) {
349 ALOGE("Unimplemented.");
350 return 0;
351 }
352
getId(const AHardwareBuffer * ahb,uint64_t * id)353 int EmulatedGralloc::getId(const AHardwareBuffer* ahb, uint64_t* id) {
354 const auto* rahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(ahb);
355 *id = rahb->getResourceId();
356 return 0;
357 }
358
createPlatformGralloc(int)359 Gralloc* createPlatformGralloc(int /*deviceFd*/) {
360 return new EmulatedGralloc();
361 }
362
363 } // namespace gfxstream
364