blob: 43907e5fbf56f24afb3c859355a500343e615569 [file] [log] [blame]
Amit Pundir4e375822019-04-18 16:46:10 +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
27#include <cutils/log.h>
28#include <cutils/atomic.h>
29#include <cutils/properties.h>
30#include <stdlib.h>
31#include <string.h>
32#include <errno.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <assert.h>
37
38#include <hardware/gralloc.h>
39#include <system/graphics.h>
40
41#include <gbm.h>
42
43#include "gralloc_gbm_priv.h"
44#include <android/gralloc_handle.h>
45
46#include <unordered_map>
47
48#define MAX(a, b) (((a) > (b)) ? (a) : (b))
49
50#define unlikely(x) __builtin_expect(!!(x), 0)
51
52static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
53
54struct bo_data_t {
55 void *map_data;
56 int lock_count;
57 int locked_for;
58};
59
60void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
61{
62 struct bo_data_t *bo_data = (struct bo_data_t *)data;
63 delete bo_data;
64
65 (void)bo;
66}
67
68static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
69 return (struct bo_data_t *)gbm_bo_get_user_data(bo);
70}
71
72
73static uint32_t get_gbm_format(int format)
74{
75 uint32_t fmt;
76
77 switch (format) {
78 case HAL_PIXEL_FORMAT_RGBA_8888:
79 fmt = GBM_FORMAT_ABGR8888;
80 break;
81 case HAL_PIXEL_FORMAT_RGBX_8888:
82 fmt = GBM_FORMAT_XBGR8888;
83 break;
84 case HAL_PIXEL_FORMAT_RGB_888:
85 fmt = GBM_FORMAT_RGB888;
86 break;
87 case HAL_PIXEL_FORMAT_RGB_565:
88 fmt = GBM_FORMAT_RGB565;
89 break;
90 case HAL_PIXEL_FORMAT_BGRA_8888:
91 fmt = GBM_FORMAT_ARGB8888;
92 break;
93 case HAL_PIXEL_FORMAT_YV12:
94 /* YV12 is planar, but must be a single buffer so ask for GR88 */
95 fmt = GBM_FORMAT_GR88;
96 break;
97 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
98 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
99 default:
100 fmt = 0;
101 break;
102 }
103
104 return fmt;
105}
106
107static int gralloc_gbm_get_bpp(int format)
108{
109 int bpp;
110
111 switch (format) {
112 case HAL_PIXEL_FORMAT_RGBA_8888:
113 case HAL_PIXEL_FORMAT_RGBX_8888:
114 case HAL_PIXEL_FORMAT_BGRA_8888:
115 bpp = 4;
116 break;
117 case HAL_PIXEL_FORMAT_RGB_888:
118 bpp = 3;
119 break;
120 case HAL_PIXEL_FORMAT_RGB_565:
121 case HAL_PIXEL_FORMAT_YCbCr_422_I:
122 bpp = 2;
123 break;
124 /* planar; only Y is considered */
125 case HAL_PIXEL_FORMAT_YV12:
126 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
127 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
128 bpp = 1;
129 break;
130 default:
131 bpp = 0;
132 break;
133 }
134
135 return bpp;
136}
137
138static unsigned int get_pipe_bind(int usage)
139{
140 unsigned int bind = 0;
141
142 if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
143 bind |= GBM_BO_USE_LINEAR;
144 if (usage & GRALLOC_USAGE_CURSOR)
145 ;//bind |= GBM_BO_USE_CURSOR;
146 if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
147 bind |= GBM_BO_USE_RENDERING;
148 if (usage & GRALLOC_USAGE_HW_FB)
149 bind |= GBM_BO_USE_SCANOUT;
150 if (usage & GRALLOC_USAGE_HW_COMPOSER)
151 bind |= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
152
153 return bind;
154}
155
156static struct gbm_bo *gbm_import(struct gbm_device *gbm,
157 buffer_handle_t _handle)
158{
159 struct gbm_bo *bo;
160 struct gralloc_handle_t *handle = gralloc_handle(_handle);
161 #ifdef GBM_BO_IMPORT_FD_MODIFIER
162 struct gbm_import_fd_modifier_data data;
163 #else
164 struct gbm_import_fd_data data;
165 #endif
166
167 int format = get_gbm_format(handle->format);
168 if (handle->prime_fd < 0)
169 return NULL;
170
171 memset(&data, 0, sizeof(data));
172 data.width = handle->width;
173 data.height = handle->height;
174 data.format = format;
175 /* Adjust the width and height for a GBM GR88 buffer */
176 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
177 data.width /= 2;
178 data.height += handle->height / 2;
179 }
180
181 #ifdef GBM_BO_IMPORT_FD_MODIFIER
182 data.num_fds = 1;
183 data.fds[0] = handle->prime_fd;
184 data.strides[0] = handle->stride;
185 data.modifier = handle->modifier;
186 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
187 #else
188 data.fd = handle->prime_fd;
189 data.stride = handle->stride;
190 bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
191 #endif
192
193 return bo;
194}
195
196static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
197 buffer_handle_t _handle)
198{
199 struct gbm_bo *bo;
200 struct gralloc_handle_t *handle = gralloc_handle(_handle);
201 int format = get_gbm_format(handle->format);
202 int usage = get_pipe_bind(handle->usage);
203 int width, height;
204
205 width = handle->width;
206 height = handle->height;
207 if (usage & GBM_BO_USE_CURSOR) {
208 if (handle->width < 64)
209 width = 64;
210 if (handle->height < 64)
211 height = 64;
212 }
213
214 /*
215 * For YV12, we request GR88, so halve the width since we're getting
216 * 16bpp. Then increase the height by 1.5 for the U and V planes.
217 */
218 if (handle->format == HAL_PIXEL_FORMAT_YV12) {
219 width /= 2;
220 height += handle->height / 2;
221 }
222
223 ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x",
224 handle->width, handle->height, handle->format, usage);
225 bo = gbm_bo_create(gbm, width, height, format, usage);
226 if (!bo) {
227 ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
228 handle->width, handle->height, handle->format, usage);
229 return NULL;
230 }
231
232 handle->prime_fd = gbm_bo_get_fd(bo);
233 handle->stride = gbm_bo_get_stride(bo);
234 #ifdef GBM_BO_IMPORT_FD_MODIFIER
235 handle->modifier = gbm_bo_get_modifier(bo);
236 #endif
237
238 return bo;
239}
240
241void gbm_free(buffer_handle_t handle)
242{
243 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
244
245 if (!bo)
246 return;
247
248 gbm_bo_handle_map.erase(handle);
249 gbm_bo_destroy(bo);
250}
251
252/*
253 * Return the bo of a registered handle.
254 */
255struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
256{
257 return gbm_bo_handle_map[handle];
258}
259
260static int gbm_map(buffer_handle_t handle, int x, int y, int w, int h,
261 int enable_write, void **addr)
262{
263 int err = 0;
264 int flags = GBM_BO_TRANSFER_READ;
265 struct gralloc_gbm_handle_t *gbm_handle = gralloc_handle(handle);
266 struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
267 struct bo_data_t *bo_data = gbm_bo_data(bo);
268 uint32_t stride;
269
270 if (bo_data->map_data)
271 return -EINVAL;
272
273 if (gbm_handle->format == HAL_PIXEL_FORMAT_YV12) {
274 if (x || y)
275 ALOGE("can't map with offset for planar %p", bo);
276 w /= 2;
277 h += h / 2;
278 }
279
280 if (enable_write)
281 flags |= GBM_BO_TRANSFER_WRITE;
282
283 *addr = gbm_bo_map(bo, 0, 0, x + w, y + h, flags, &stride, &bo_data->map_data);
284 ALOGV("mapped bo %p (%d, %d)-(%d, %d) at %p", bo, x, y, w, h, *addr);
285 if (*addr == NULL)
286 return -ENOMEM;
287
288 assert(stride == gbm_bo_get_stride(bo));
289
290 return err;
291}
292
293static void gbm_unmap(struct gbm_bo *bo)
294{
295 struct bo_data_t *bo_data = gbm_bo_data(bo);
296
297 gbm_bo_unmap(bo, bo_data->map_data);
298 bo_data->map_data = NULL;
299}
300
301void gbm_dev_destroy(struct gbm_device *gbm)
302{
303 int fd = gbm_device_get_fd(gbm);
304
305 gbm_device_destroy(gbm);
306 close(fd);
307}
308
309struct gbm_device *gbm_dev_create(void)
310{
311 struct gbm_device *gbm;
312 char path[PROPERTY_VALUE_MAX];
313 int fd;
314
315 property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
316 fd = open(path, O_RDWR | O_CLOEXEC);
317 if (fd < 0) {
318 ALOGE("failed to open %s", path);
319 return NULL;
320 }
321
322 gbm = gbm_create_device(fd);
323 if (!gbm) {
324 ALOGE("failed to create gbm device");
325 close(fd);
326 }
327
328 return gbm;
329}
330
331/*
332 * Register a buffer handle.
333 */
334int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
335{
336 struct gbm_bo *bo;
337
338 if (!_handle)
339 return -EINVAL;
340
341 if (gbm_bo_handle_map.count(_handle))
342 return -EINVAL;
343
344 bo = gbm_import(gbm, _handle);
345 if (!bo)
346 return -EINVAL;
347
348 gbm_bo_handle_map.emplace(_handle, bo);
349
350 return 0;
351}
352
353/*
354 * Unregister a buffer handle. It is no-op for handles created locally.
355 */
356int gralloc_gbm_handle_unregister(buffer_handle_t handle)
357{
358 gbm_free(handle);
359
360 return 0;
361}
362
363/*
364 * Create a bo.
365 */
366buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
367 int width, int height, int format, int usage, int *stride)
368{
369 struct gbm_bo *bo;
370 native_handle_t *handle;
371
372 handle = gralloc_handle_create(width, height, format, usage);
373 if (!handle)
374 return NULL;
375
376 bo = gbm_alloc(gbm, handle);
377 if (!bo) {
378 native_handle_delete(handle);
379 return NULL;
380 }
381
382 gbm_bo_handle_map.emplace(handle, bo);
383
384 /* in pixels */
385 struct gralloc_handle_t *ghandle = gralloc_handle(handle);
386 *stride = ghandle->stride / gralloc_gbm_get_bpp(format);
387
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
423 ALOGI("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
424
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 Stultz2ae5f4a2020-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 Pundir4e375822019-04-18 16:46:10 +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}