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>
40 #include <hardware/gralloc.h>
41 #include <system/graphics.h>
45 #include "gralloc_gbm_priv.h"
46 #include <android/gralloc_handle.h>
48 #include <unordered_map>
50 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
52 #define unlikely(x) __builtin_expect(!!(x), 0)
54 static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
62 void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
64 struct bo_data_t *bo_data = (struct bo_data_t *)data;
70 static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
71 return (struct bo_data_t *)gbm_bo_get_user_data(bo);
75 static uint32_t get_gbm_format(int format)
80 case HAL_PIXEL_FORMAT_RGBA_8888:
81 fmt = GBM_FORMAT_ABGR8888;
83 case HAL_PIXEL_FORMAT_RGBX_8888:
84 fmt = GBM_FORMAT_XBGR8888;
86 case HAL_PIXEL_FORMAT_RGB_888:
87 fmt = GBM_FORMAT_RGB888;
89 case HAL_PIXEL_FORMAT_RGB_565:
90 fmt = GBM_FORMAT_RGB565;
92 case HAL_PIXEL_FORMAT_BGRA_8888:
93 fmt = GBM_FORMAT_ARGB8888;
95 case HAL_PIXEL_FORMAT_YV12:
96 /* YV12 is planar, but must be a single buffer so ask for GR88 */
97 fmt = GBM_FORMAT_GR88;
99 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
100 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
109 static int gralloc_gbm_get_bpp(int format)
114 case HAL_PIXEL_FORMAT_RGBA_8888:
115 case HAL_PIXEL_FORMAT_RGBX_8888:
116 case HAL_PIXEL_FORMAT_BGRA_8888:
119 case HAL_PIXEL_FORMAT_RGB_888:
122 case HAL_PIXEL_FORMAT_RGB_565:
123 case HAL_PIXEL_FORMAT_YCbCr_422_I:
126 /* planar; only Y is considered */
127 case HAL_PIXEL_FORMAT_YV12:
128 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
129 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
140 static unsigned int get_pipe_bind(int usage)
142 unsigned int bind = 0;
144 if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
145 bind |= GBM_BO_USE_LINEAR;
146 if (usage & GRALLOC_USAGE_CURSOR)
147 ;//bind |= GBM_BO_USE_CURSOR;
148 if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
149 bind |= GBM_BO_USE_RENDERING;
150 if (usage & GRALLOC_USAGE_HW_FB)
151 bind |= GBM_BO_USE_SCANOUT;
152 if (usage & GRALLOC_USAGE_HW_COMPOSER)
153 bind |= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
158 static struct gbm_bo *gbm_import(struct gbm_device *gbm,
159 buffer_handle_t _handle)
162 struct gralloc_handle_t *handle = gralloc_handle(_handle);
163 #ifdef GBM_BO_IMPORT_FD_MODIFIER
164 struct gbm_import_fd_modifier_data data;
166 struct gbm_import_fd_data data;
169 int format = get_gbm_format(handle->format);
170 if (handle->prime_fd < 0)
173 memset(&data, 0, sizeof(data));
174 data.width = handle->width;
175 data.height = handle->height;
176 data.format = format;
177 /* Adjust the width and height for a GBM GR88 buffer */
178 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
180 data.height += handle->height / 2;
183 #ifdef GBM_BO_IMPORT_FD_MODIFIER
185 data.fds[0] = handle->prime_fd;
186 data.strides[0] = handle->stride;
187 data.modifier = handle->modifier;
188 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
190 data.fd = handle->prime_fd;
191 data.stride = handle->stride;
192 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
198 static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
199 buffer_handle_t _handle)
202 struct gralloc_handle_t *handle = gralloc_handle(_handle);
203 int format = get_gbm_format(handle->format);
204 int usage = get_pipe_bind(handle->usage);
207 width = handle->width;
208 height = handle->height;
209 if (usage & GBM_BO_USE_CURSOR) {
210 if (handle->width < 64)
212 if (handle->height < 64)
217 * For YV12, we request GR88, so halve the width since we're getting
218 * 16bpp. Then increase the height by 1.5 for the U and V planes.
220 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
222 height += handle->height / 2;
225 ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x",
226 handle->width, handle->height, handle->format, usage);
227 bo = gbm_bo_create(gbm, width, height, format, usage);
229 ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
230 handle->width, handle->height, handle->format, usage);
234 handle->prime_fd = gbm_bo_get_fd(bo);
235 handle->stride = gbm_bo_get_stride(bo);
236 #ifdef GBM_BO_IMPORT_FD_MODIFIER
237 handle->modifier = gbm_bo_get_modifier(bo);
243 int gbm_free(buffer_handle_t handle)
245 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
250 gbm_bo_handle_map.erase(handle);
256 * Return the bo of a registered handle.
258 struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
260 return gbm_bo_handle_map[handle];
263 static int gbm_map(buffer_handle_t handle, int enable_write, void **addr)
266 int flags = GBM_BO_TRANSFER_READ;
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)
275 flags |= GBM_BO_TRANSFER_WRITE;
277 *addr = gbm_bo_map(bo, 0, 0, gbm_bo_get_width(bo), gbm_bo_get_height(bo),
278 flags, &stride, &bo_data->map_data);
279 ALOGV("mapped bo %p at %p", bo, *addr);
283 assert(stride == gbm_bo_get_stride(bo));
288 static void gbm_unmap(struct gbm_bo *bo)
290 struct bo_data_t *bo_data = gbm_bo_data(bo);
292 gbm_bo_unmap(bo, bo_data->map_data);
293 bo_data->map_data = NULL;
296 void gbm_dev_destroy(struct gbm_device *gbm)
298 int fd = gbm_device_get_fd(gbm);
300 gbm_device_destroy(gbm);
304 struct gbm_device *gbm_dev_create(bool master)
306 struct gbm_device *gbm;
307 char path[PROPERTY_VALUE_MAX];
310 if (property_get("gralloc.gbm.device", path, NULL) > 0)
311 fd = open(path, O_RDWR | O_CLOEXEC);
313 fd = drmOpenByFB(0, master ? DRM_NODE_PRIMARY : DRM_NODE_RENDER);
316 ALOGE("failed to open %s", path);
320 gbm = gbm_create_device(fd);
322 ALOGE("failed to create gbm device");
330 * Register a buffer handle.
332 int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
339 if (gbm_bo_handle_map.count(_handle))
342 bo = gbm_import(gbm, _handle);
346 gbm_bo_handle_map.emplace(_handle, bo);
352 * Unregister a buffer handle. It is no-op for handles created locally.
354 int gralloc_gbm_handle_unregister(buffer_handle_t handle)
356 return gbm_free(handle);
362 buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
363 int width, int height, int format, int usage, int *stride)
366 native_handle_t *handle;
368 handle = gralloc_handle_create(width, height, format, usage);
372 bo = gbm_alloc(gbm, handle);
374 native_handle_delete(handle);
378 gbm_bo_handle_map.emplace(handle, bo);
381 *stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format);
387 * Lock a bo. XXX thread-safety?
389 int gralloc_gbm_bo_lock(buffer_handle_t handle,
390 int usage, int /*x*/, int /*y*/, int /*w*/, int /*h*/,
393 struct gralloc_handle_t *gbm_handle = gralloc_handle(handle);
394 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
395 struct bo_data_t *bo_data;
400 if ((gbm_handle->usage & usage) != (uint32_t)usage) {
401 /* make FB special for testing software renderer with */
403 if (!(gbm_handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
404 !(gbm_handle->usage & GRALLOC_USAGE_HW_FB) &&
405 !(gbm_handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
406 ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
407 gbm_handle->usage, usage);
412 bo_data = gbm_bo_data(bo);
414 bo_data = new struct bo_data_t();
415 gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data);
418 ALOGV("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
420 /* allow multiple locks with compatible usages */
421 if (bo_data->lock_count && (bo_data->locked_for & usage) != usage)
424 usage |= bo_data->locked_for;
426 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
427 GRALLOC_USAGE_SW_READ_MASK)) {
428 /* the driver is supposed to wait for the bo */
429 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
430 int err = gbm_map(handle, write, addr);
435 /* kernel handles the synchronization here */
438 bo_data->lock_count++;
439 bo_data->locked_for |= usage;
447 int gralloc_gbm_bo_unlock(buffer_handle_t handle)
449 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
450 struct bo_data_t *bo_data;
454 bo_data = gbm_bo_data(bo);
456 int mapped = bo_data->locked_for &
457 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
459 if (!bo_data->lock_count)
465 bo_data->lock_count--;
466 if (!bo_data->lock_count)
467 bo_data->locked_for = 0;
472 #define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
474 int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle,
475 int usage, int x, int y, int w, int h,
476 struct android_ycbcr *ycbcr)
478 struct gralloc_handle_t *hnd = gralloc_handle(handle);
479 int ystride, cstride;
483 ALOGV("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
485 err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr);
489 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
491 switch (hnd->format) {
492 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
493 ystride = cstride = GRALLOC_ALIGN(hnd->width, 16);
495 ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
496 ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + 1;
497 ycbcr->ystride = ystride;
498 ycbcr->cstride = cstride;
499 ycbcr->chroma_step = 2;
501 case HAL_PIXEL_FORMAT_YV12:
502 ystride = hnd->width;
503 cstride = GRALLOC_ALIGN(ystride / 2, 16);
505 ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
506 ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + cstride * hnd->height / 2;
507 ycbcr->ystride = ystride;
508 ycbcr->cstride = cstride;
509 ycbcr->chroma_step = 1;
512 ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format);