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 <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 
52 static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
53 
54 struct bo_data_t {
55 	void *map_data;
56 	int lock_count;
57 	int locked_for;
58 };
59 
gralloc_gbm_destroy_user_data(struct gbm_bo * bo,void * data)60 void 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 
gbm_bo_data(struct gbm_bo * bo)68 static 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 
get_gbm_format(int format)73 static 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 
gralloc_gbm_get_bpp(int format)107 static 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 
get_pipe_bind(int usage)138 static 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 
gbm_import(struct gbm_device * gbm,buffer_handle_t _handle)156 static 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 
gbm_alloc(struct gbm_device * gbm,buffer_handle_t _handle)196 static 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 
gbm_free(buffer_handle_t handle)241 void 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  */
gralloc_gbm_bo_from_handle(buffer_handle_t handle)255 struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
256 {
257 	return gbm_bo_handle_map[handle];
258 }
259 
gbm_map(buffer_handle_t handle,int x,int y,int w,int h,int enable_write,void ** addr)260 static 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 
gbm_unmap(struct gbm_bo * bo)293 static 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 
gbm_dev_destroy(struct gbm_device * gbm)301 void 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 
gbm_dev_create(void)309 struct 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  */
gralloc_gbm_handle_register(buffer_handle_t _handle,struct gbm_device * gbm)334 int 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  */
gralloc_gbm_handle_unregister(buffer_handle_t handle)356 int 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  */
gralloc_gbm_bo_create(struct gbm_device * gbm,int width,int height,int format,int usage,int * stride)366 buffer_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  */
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 	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 
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;
495 	int err;
496 
497 	ALOGD("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