• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <log/log.h>
28 #include <cutils/atomic.h>
29 #include <cutils/properties.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #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 
53 static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
54 
55 struct bo_data_t {
56 	void *map_data;
57 	int lock_count;
58 	int locked_for;
59 };
60 
gralloc_gbm_destroy_user_data(struct gbm_bo * bo,void * data)61 void 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 
gbm_bo_data(struct gbm_bo * bo)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);
71 }
72 
73 
get_gbm_format(int format)74 static 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 
gralloc_gbm_get_bpp(int format)108 static 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 
get_pipe_bind(int usage)139 static 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 
gbm_import(struct gbm_device * gbm,buffer_handle_t _handle)157 static 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 
gbm_alloc(struct gbm_device * gbm,buffer_handle_t _handle)197 static 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 
gbm_free(buffer_handle_t handle)242 void 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  */
gralloc_gbm_bo_from_handle(buffer_handle_t handle)256 struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
257 {
258 	return gbm_bo_handle_map[handle];
259 }
260 
gbm_map(buffer_handle_t handle,int x,int y,int w,int h,int enable_write,void ** addr)261 static 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 
gbm_unmap(struct gbm_bo * bo)294 static 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 
gbm_dev_destroy(struct gbm_device * gbm)302 void 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 
gbm_dev_create(void)310 struct 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  */
gralloc_gbm_handle_register(buffer_handle_t _handle,struct gbm_device * gbm)335 int 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  */
gralloc_gbm_handle_unregister(buffer_handle_t handle)357 int 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  */
gralloc_gbm_bo_create(struct gbm_device * gbm,int width,int height,int format,int usage,int * stride)367 buffer_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 */
386 	*stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format);
387 
388 	return handle;
389 }
390 
391 /*
392  * Lock a bo.  XXX thread-safety?
393  */
gralloc_gbm_bo_lock(buffer_handle_t handle,int usage,int x,int y,int w,int h,void ** addr)394 int 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 	ALOGV("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 
431 	/*
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 
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);
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  */
gralloc_gbm_bo_unlock(buffer_handle_t handle)461 int 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 }
485 
486 #define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
487 
gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle,int usage,int x,int y,int w,int h,struct android_ycbcr * ycbcr)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)
491 {
492 	struct gralloc_handle_t *hnd = gralloc_handle(handle);
493 	int ystride, cstride;
494 	void *addr = 0;
495 	int err;
496 
497 	ALOGV("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
498 
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 }
532