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>
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 #define LOG_TAG "GRALLOC-GBM"
28 #include <cutils/atomic.h>
29 #include <cutils/properties.h>
34 #include <sys/types.h>
39 #include <hardware/gralloc.h>
40 #include <system/graphics.h>
44 #include "gralloc_gbm_priv.h"
45 #include <android/gralloc_handle.h>
47 #include <unordered_map>
49 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
51 #define unlikely(x) __builtin_expect(!!(x), 0)
53 static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
61 void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
63 struct bo_data_t *bo_data = (struct bo_data_t *)data;
69 static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
70 return (struct bo_data_t *)gbm_bo_get_user_data(bo);
74 static uint32_t get_gbm_format(int format)
79 case HAL_PIXEL_FORMAT_RGBA_8888:
80 fmt = GBM_FORMAT_ABGR8888;
82 case HAL_PIXEL_FORMAT_RGBX_8888:
83 fmt = GBM_FORMAT_XBGR8888;
85 case HAL_PIXEL_FORMAT_RGB_888:
86 fmt = GBM_FORMAT_RGB888;
88 case HAL_PIXEL_FORMAT_RGB_565:
89 fmt = GBM_FORMAT_RGB565;
91 case HAL_PIXEL_FORMAT_BGRA_8888:
92 fmt = GBM_FORMAT_ARGB8888;
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;
98 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
99 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
108 static int gralloc_gbm_get_bpp(int format)
113 case HAL_PIXEL_FORMAT_RGBA_8888:
114 case HAL_PIXEL_FORMAT_RGBX_8888:
115 case HAL_PIXEL_FORMAT_BGRA_8888:
118 case HAL_PIXEL_FORMAT_RGB_888:
121 case HAL_PIXEL_FORMAT_RGB_565:
122 case HAL_PIXEL_FORMAT_YCbCr_422_I:
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:
139 static unsigned int get_pipe_bind(int usage)
141 unsigned int bind = 0;
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;
157 static struct gbm_bo *gbm_import(struct gbm_device *gbm,
158 buffer_handle_t _handle)
161 struct gralloc_handle_t *handle = gralloc_handle(_handle);
162 #ifdef GBM_BO_IMPORT_FD_MODIFIER
163 struct gbm_import_fd_modifier_data data;
165 struct gbm_import_fd_data data;
168 int format = get_gbm_format(handle->format);
169 if (handle->prime_fd < 0)
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) {
179 data.height += handle->height / 2;
182 #ifdef GBM_BO_IMPORT_FD_MODIFIER
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);
189 data.fd = handle->prime_fd;
190 data.stride = handle->stride;
191 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
197 static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
198 buffer_handle_t _handle)
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);
206 width = handle->width;
207 height = handle->height;
208 if (usage & GBM_BO_USE_CURSOR) {
209 if (handle->width < 64)
211 if (handle->height < 64)
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.
219 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
221 height += handle->height / 2;
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);
228 ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
229 handle->width, handle->height, handle->format, usage);
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);
242 void gbm_free(buffer_handle_t handle)
244 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
249 gbm_bo_handle_map.erase(handle);
254 * Return the bo of a registered handle.
256 struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
258 return gbm_bo_handle_map[handle];
261 static int gbm_map(buffer_handle_t handle, int x, int y, int w, int h,
262 int enable_write, void **addr)
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);
271 if (bo_data->map_data)
274 if (gbm_handle->format == HAL_PIXEL_FORMAT_YV12) {
276 ALOGE("can't map with offset for planar %p", bo);
282 flags |= GBM_BO_TRANSFER_WRITE;
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);
289 assert(stride == gbm_bo_get_stride(bo));
294 static void gbm_unmap(struct gbm_bo *bo)
296 struct bo_data_t *bo_data = gbm_bo_data(bo);
298 gbm_bo_unmap(bo, bo_data->map_data);
299 bo_data->map_data = NULL;
302 void gbm_dev_destroy(struct gbm_device *gbm)
304 int fd = gbm_device_get_fd(gbm);
306 gbm_device_destroy(gbm);
310 struct gbm_device *gbm_dev_create(void)
312 struct gbm_device *gbm;
313 char path[PROPERTY_VALUE_MAX];
316 property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
317 fd = open(path, O_RDWR | O_CLOEXEC);
319 ALOGE("failed to open %s", path);
323 gbm = gbm_create_device(fd);
325 ALOGE("failed to create gbm device");
333 * Register a buffer handle.
335 int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
342 if (gbm_bo_handle_map.count(_handle))
345 bo = gbm_import(gbm, _handle);
349 gbm_bo_handle_map.emplace(_handle, bo);
355 * Unregister a buffer handle. It is no-op for handles created locally.
357 int gralloc_gbm_handle_unregister(buffer_handle_t handle)
367 buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
368 int width, int height, int format, int usage, int *stride)
371 native_handle_t *handle;
373 handle = gralloc_handle_create(width, height, format, usage);
377 bo = gbm_alloc(gbm, handle);
379 native_handle_delete(handle);
383 gbm_bo_handle_map.emplace(handle, bo);
386 *stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format);
392 * Lock a bo. XXX thread-safety?
394 int gralloc_gbm_bo_lock(buffer_handle_t handle,
395 int usage, int x, int y, int w, int h,
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;
405 if ((gbm_handle->usage & usage) != (uint32_t)usage) {
406 /* make FB special for testing software renderer with */
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);
417 bo_data = gbm_bo_data(bo);
419 bo_data = new struct bo_data_t();
420 gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data);
423 ALOGI("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
425 /* allow multiple locks with compatible usages */
426 if (bo_data->lock_count && (bo_data->locked_for & usage) != usage)
429 usage |= bo_data->locked_for;
432 * Some users will lock with an null crop rect.
433 * Interpret this as no-crop (full buffer WxH).
435 if (w == 0 && h == 0) {
436 w = gbm_handle->width;
437 h = gbm_handle->height;
440 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);
449 /* kernel handles the synchronization here */
452 bo_data->lock_count++;
453 bo_data->locked_for |= usage;
461 int gralloc_gbm_bo_unlock(buffer_handle_t handle)
463 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
464 struct bo_data_t *bo_data;
468 bo_data = gbm_bo_data(bo);
470 int mapped = bo_data->locked_for &
471 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
473 if (!bo_data->lock_count)
479 bo_data->lock_count--;
480 if (!bo_data->lock_count)
481 bo_data->locked_for = 0;
486 #define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
488 int 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)
492 struct gralloc_handle_t *hnd = gralloc_handle(handle);
493 int ystride, cstride;
497 ALOGD("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
499 err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr);
503 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
505 switch (hnd->format) {
506 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
507 ystride = cstride = GRALLOC_ALIGN(hnd->width, 16);
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;
515 case HAL_PIXEL_FORMAT_YV12:
516 ystride = hnd->width;
517 cstride = GRALLOC_ALIGN(ystride / 2, 16);
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;
526 ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format);