blob: 29d11cdff84b8b2daced27cf5ae1c25976442430 [file] [log] [blame]
Amit Pundirc738b812019-06-19 16:13:49 +05301/*
2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3 * Copyright (C) 2010-2011 LunarG Inc.
4 * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#define LOG_TAG "GRALLOC-GBM"
26
John Stultzb6d45bd2020-09-17 06:06:26 +000027#include <log/log.h>
Amit Pundirc738b812019-06-19 16:13:49 +053028#include <cutils/atomic.h>
29#include <cutils/properties.h>
30#include <stdlib.h>
31#include <string.h>
John Stultzb6d45bd2020-09-17 06:06:26 +000032#include <unistd.h>
Amit Pundirc738b812019-06-19 16:13:49 +053033#include <errno.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <assert.h>
38
39#include <hardware/gralloc.h>
40#include <system/graphics.h>
41
42#include <gbm.h>
43
44#include "gralloc_gbm_priv.h"
45#include <android/gralloc_handle.h>
46
47#include <unordered_map>
48
49#define MAX(a, b) (((a) > (b)) ? (a) : (b))
50
51#define unlikely(x) __builtin_expect(!!(x), 0)
52
53static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
54
55struct bo_data_t {
56 void *map_data;
57 int lock_count;
58 int locked_for;
59};
60
61void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
62{
63 struct bo_data_t *bo_data = (struct bo_data_t *)data;
64 delete bo_data;
65
66 (void)bo;
67}
68
69static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
70 return (struct bo_data_t *)gbm_bo_get_user_data(bo);
71}
72
73
74static uint32_t get_gbm_format(int format)
75{
76 uint32_t fmt;
77
78 switch (format) {
79 case HAL_PIXEL_FORMAT_RGBA_8888:
80 fmt = GBM_FORMAT_ABGR8888;
81 break;
82 case HAL_PIXEL_FORMAT_RGBX_8888:
83 fmt = GBM_FORMAT_XBGR8888;
84 break;
85 case HAL_PIXEL_FORMAT_RGB_888:
86 fmt = GBM_FORMAT_RGB888;
87 break;
88 case HAL_PIXEL_FORMAT_RGB_565:
89 fmt = GBM_FORMAT_RGB565;
90 break;
91 case HAL_PIXEL_FORMAT_BGRA_8888:
92 fmt = GBM_FORMAT_ARGB8888;
93 break;
94 case HAL_PIXEL_FORMAT_YV12:
95 /* YV12 is planar, but must be a single buffer so ask for GR88 */
96 fmt = GBM_FORMAT_GR88;
97 break;
98 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
99 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
100 default:
101 fmt = 0;
102 break;
103 }
104
105 return fmt;
106}
107
108static int gralloc_gbm_get_bpp(int format)
109{
110 int bpp;
111
112 switch (format) {
113 case HAL_PIXEL_FORMAT_RGBA_8888:
114 case HAL_PIXEL_FORMAT_RGBX_8888:
115 case HAL_PIXEL_FORMAT_BGRA_8888:
116 bpp = 4;
117 break;
118 case HAL_PIXEL_FORMAT_RGB_888:
119 bpp = 3;
120 break;
121 case HAL_PIXEL_FORMAT_RGB_565:
122 case HAL_PIXEL_FORMAT_YCbCr_422_I:
123 bpp = 2;
124 break;
125 /* planar; only Y is considered */
126 case HAL_PIXEL_FORMAT_YV12:
127 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
128 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
129 bpp = 1;
130 break;
131 default:
132 bpp = 0;
133 break;
134 }
135
136 return bpp;
137}
138
139static unsigned int get_pipe_bind(int usage)
140{
141 unsigned int bind = 0;
142
143 if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
144 bind |= GBM_BO_USE_LINEAR;
145 if (usage & GRALLOC_USAGE_CURSOR)
146 ;//bind |= GBM_BO_USE_CURSOR;
147 if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
148 bind |= GBM_BO_USE_RENDERING;
149 if (usage & GRALLOC_USAGE_HW_FB)
150 bind |= GBM_BO_USE_SCANOUT;
151 if (usage & GRALLOC_USAGE_HW_COMPOSER)
152 bind |= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
153
154 return bind;
155}
156
157static struct gbm_bo *gbm_import(struct gbm_device *gbm,
158 buffer_handle_t _handle)
159{
160 struct gbm_bo *bo;
161 struct gralloc_handle_t *handle = gralloc_handle(_handle);
162 #ifdef GBM_BO_IMPORT_FD_MODIFIER
163 struct gbm_import_fd_modifier_data data;
164 #else
165 struct gbm_import_fd_data data;
166 #endif
167
168 int format = get_gbm_format(handle->format);
169 if (handle->prime_fd < 0)
170 return NULL;
171
172 memset(&data, 0, sizeof(data));
173 data.width = handle->width;
174 data.height = handle->height;
175 data.format = format;
176 /* Adjust the width and height for a GBM GR88 buffer */
177 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
178 data.width /= 2;
179 data.height += handle->height / 2;
180 }
181
182 #ifdef GBM_BO_IMPORT_FD_MODIFIER
183 data.num_fds = 1;
184 data.fds[0] = handle->prime_fd;
185 data.strides[0] = handle->stride;
186 data.modifier = handle->modifier;
187 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
188 #else
189 data.fd = handle->prime_fd;
190 data.stride = handle->stride;
191 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
192 #endif
193
194 return bo;
195}
196
197static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
198 buffer_handle_t _handle)
199{
200 struct gbm_bo *bo;
201 struct gralloc_handle_t *handle = gralloc_handle(_handle);
202 int format = get_gbm_format(handle->format);
203 int usage = get_pipe_bind(handle->usage);
204 int width, height;
205
206 width = handle->width;
207 height = handle->height;
208 if (usage & GBM_BO_USE_CURSOR) {
209 if (handle->width < 64)
210 width = 64;
211 if (handle->height < 64)
212 height = 64;
213 }
214
215 /*
216 * For YV12, we request GR88, so halve the width since we're getting
217 * 16bpp. Then increase the height by 1.5 for the U and V planes.
218 */
219 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
220 width /= 2;
221 height += handle->height / 2;
222 }
223
224 ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x",
225 handle->width, handle->height, handle->format, usage);
226 bo = gbm_bo_create(gbm, width, height, format, usage);
227 if (!bo) {
228 ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
229 handle->width, handle->height, handle->format, usage);
230 return NULL;
231 }
232
233 handle->prime_fd = gbm_bo_get_fd(bo);
234 handle->stride = gbm_bo_get_stride(bo);
235 #ifdef GBM_BO_IMPORT_FD_MODIFIER
236 handle->modifier = gbm_bo_get_modifier(bo);
237 #endif
238
239 return bo;
240}
241
242void gbm_free(buffer_handle_t handle)
243{
244 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
245
246 if (!bo)
247 return;
248
249 gbm_bo_handle_map.erase(handle);
250 gbm_bo_destroy(bo);
251}
252
253/*
254 * Return the bo of a registered handle.
255 */
256struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
257{
258 return gbm_bo_handle_map[handle];
259}
260
261static int gbm_map(buffer_handle_t handle, int x, int y, int w, int h,
262 int enable_write, void **addr)
263{
264 int err = 0;
265 int flags = GBM_BO_TRANSFER_READ;
266 struct gralloc_gbm_handle_t *gbm_handle = gralloc_handle(handle);
267 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
268 struct bo_data_t *bo_data = gbm_bo_data(bo);
269 uint32_t stride;
270
271 if (bo_data->map_data)
272 return -EINVAL;
273
274 if (gbm_handle->format == HAL_PIXEL_FORMAT_YV12) {
275 if (x || y)
276 ALOGE("can't map with offset for planar %p", bo);
277 w /= 2;
278 h += h / 2;
279 }
280
281 if (enable_write)
282 flags |= GBM_BO_TRANSFER_WRITE;
283
284 *addr = gbm_bo_map(bo, 0, 0, x + w, y + h, flags, &stride, &bo_data->map_data);
285 ALOGV("mapped bo %p (%d, %d)-(%d, %d) at %p", bo, x, y, w, h, *addr);
286 if (*addr == NULL)
287 return -ENOMEM;
288
289 assert(stride == gbm_bo_get_stride(bo));
290
291 return err;
292}
293
294static void gbm_unmap(struct gbm_bo *bo)
295{
296 struct bo_data_t *bo_data = gbm_bo_data(bo);
297
298 gbm_bo_unmap(bo, bo_data->map_data);
299 bo_data->map_data = NULL;
300}
301
302void gbm_dev_destroy(struct gbm_device *gbm)
303{
304 int fd = gbm_device_get_fd(gbm);
305
306 gbm_device_destroy(gbm);
307 close(fd);
308}
309
310struct gbm_device *gbm_dev_create(void)
311{
312 struct gbm_device *gbm;
313 char path[PROPERTY_VALUE_MAX];
314 int fd;
315
316 property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
317 fd = open(path, O_RDWR | O_CLOEXEC);
318 if (fd < 0) {
319 ALOGE("failed to open %s", path);
320 return NULL;
321 }
322
323 gbm = gbm_create_device(fd);
324 if (!gbm) {
325 ALOGE("failed to create gbm device");
326 close(fd);
327 }
328
329 return gbm;
330}
331
332/*
333 * Register a buffer handle.
334 */
335int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
336{
337 struct gbm_bo *bo;
338
339 if (!_handle)
340 return -EINVAL;
341
342 if (gbm_bo_handle_map.count(_handle))
343 return -EINVAL;
344
345 bo = gbm_import(gbm, _handle);
346 if (!bo)
347 return -EINVAL;
348
349 gbm_bo_handle_map.emplace(_handle, bo);
350
351 return 0;
352}
353
354/*
355 * Unregister a buffer handle. It is no-op for handles created locally.
356 */
357int gralloc_gbm_handle_unregister(buffer_handle_t handle)
358{
359 gbm_free(handle);
360
361 return 0;
362}
363
364/*
365 * Create a bo.
366 */
367buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
368 int width, int height, int format, int usage, int *stride)
369{
370 struct gbm_bo *bo;
371 native_handle_t *handle;
372
373 handle = gralloc_handle_create(width, height, format, usage);
374 if (!handle)
375 return NULL;
376
377 bo = gbm_alloc(gbm, handle);
378 if (!bo) {
379 native_handle_delete(handle);
380 return NULL;
381 }
382
383 gbm_bo_handle_map.emplace(handle, bo);
384
385 /* in pixels */
John Stultzb6d45bd2020-09-17 06:06:26 +0000386 *stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format);
Amit Pundirc738b812019-06-19 16:13:49 +0530387
388 return handle;
389}
390
391/*
392 * Lock a bo. XXX thread-safety?
393 */
394int gralloc_gbm_bo_lock(buffer_handle_t handle,
395 int usage, int x, int y, int w, int h,
396 void **addr)
397{
398 struct gralloc_handle_t *gbm_handle = gralloc_handle(handle);
399 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
400 struct bo_data_t *bo_data;
401
402 if (!bo)
403 return -EINVAL;
404
405 if ((gbm_handle->usage & usage) != (uint32_t)usage) {
406 /* make FB special for testing software renderer with */
407
408 if (!(gbm_handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
409 !(gbm_handle->usage & GRALLOC_USAGE_HW_FB) &&
410 !(gbm_handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
411 ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
412 gbm_handle->usage, usage);
413 return -EINVAL;
414 }
415 }
416
417 bo_data = gbm_bo_data(bo);
418 if (!bo_data) {
419 bo_data = new struct bo_data_t();
420 gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data);
421 }
422
John Stultzb6d45bd2020-09-17 06:06:26 +0000423 ALOGV("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
Amit Pundirc738b812019-06-19 16:13:49 +0530424
425 /* allow multiple locks with compatible usages */
426 if (bo_data->lock_count && (bo_data->locked_for & usage) != usage)
427 return -EINVAL;
428
429 usage |= bo_data->locked_for;
430
John Stultz080cc302020-03-03 06:00:32 +0000431 /*
432 * Some users will lock with an null crop rect.
433 * Interpret this as no-crop (full buffer WxH).
434 */
435 if (w == 0 && h == 0) {
436 w = gbm_handle->width;
437 h = gbm_handle->height;
438 }
439
Amit Pundirc738b812019-06-19 16:13:49 +0530440 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
441 GRALLOC_USAGE_SW_READ_MASK)) {
442 /* the driver is supposed to wait for the bo */
443 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
444 int err = gbm_map(handle, x, y, w, h, write, addr);
445 if (err)
446 return err;
447 }
448 else {
449 /* kernel handles the synchronization here */
450 }
451
452 bo_data->lock_count++;
453 bo_data->locked_for |= usage;
454
455 return 0;
456}
457
458/*
459 * Unlock a bo.
460 */
461int gralloc_gbm_bo_unlock(buffer_handle_t handle)
462{
463 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
464 struct bo_data_t *bo_data;
465 if (!bo)
466 return -EINVAL;
467
468 bo_data = gbm_bo_data(bo);
469
470 int mapped = bo_data->locked_for &
471 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
472
473 if (!bo_data->lock_count)
474 return 0;
475
476 if (mapped)
477 gbm_unmap(bo);
478
479 bo_data->lock_count--;
480 if (!bo_data->lock_count)
481 bo_data->locked_for = 0;
482
483 return 0;
484}
Shawn Guo968b4662020-06-09 21:33:13 +0800485
486#define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
487
488int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle,
489 int usage, int x, int y, int w, int h,
490 struct android_ycbcr *ycbcr)
491{
492 struct gralloc_handle_t *hnd = gralloc_handle(handle);
493 int ystride, cstride;
John Stultzb6d45bd2020-09-17 06:06:26 +0000494 void *addr = 0;
Shawn Guo968b4662020-06-09 21:33:13 +0800495 int err;
496
John Stultzb6d45bd2020-09-17 06:06:26 +0000497 ALOGV("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
Shawn Guo968b4662020-06-09 21:33:13 +0800498
499 err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr);
500 if (err)
501 return err;
502
503 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
504
505 switch (hnd->format) {
506 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
507 ystride = cstride = GRALLOC_ALIGN(hnd->width, 16);
508 ycbcr->y = addr;
509 ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
510 ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + 1;
511 ycbcr->ystride = ystride;
512 ycbcr->cstride = cstride;
513 ycbcr->chroma_step = 2;
514 break;
515 case HAL_PIXEL_FORMAT_YV12:
516 ystride = hnd->width;
517 cstride = GRALLOC_ALIGN(ystride / 2, 16);
518 ycbcr->y = addr;
519 ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
520 ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + cstride * hnd->height / 2;
521 ycbcr->ystride = ystride;
522 ycbcr->cstride = cstride;
523 ycbcr->chroma_step = 1;
524 break;
525 default:
526 ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format);
527 return -EINVAL;
528 }
529
530 return 0;
531}