1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
41 #include <sys/ioctl.h>
42 #include <sys/types.h>
49 #include <xf86drmMode.h>
51 #include <hal-common.h>
52 #include <hal-tbm-types.h>
53 #include <hal-tbm-interface.h>
54 #include "tbm_backend_log.h"
57 #include <linux/dma-buf.h>
60 #define TBM_COLOR_FORMAT_COUNT 4
62 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
64 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
65 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (128)
66 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
68 typedef struct _tbm_dumb_bufmgr tbm_dumb_bufmgr;
69 typedef struct _tbm_dumb_bo tbm_dumb_bo;
71 /* tbm buffor object for dumb */
75 unsigned int name; /* FLINK ID */
77 unsigned int gem; /* GEM Handle */
79 int dmabuf; /* fd for dmabuf */
81 void *pBase; /* virtual address */
85 unsigned int flags_dumb;
86 unsigned int flags_tbm;
88 pthread_mutex_t mutex;
92 tbm_dumb_bufmgr *bufmgr_data;
95 /* tbm bufmgr private for dumb */
96 struct _tbm_dumb_bufmgr {
101 static char *STR_DEVICE[] = {
109 static char *STR_OPT[] = {
116 static uint32_t tbm_dumb_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
117 HAL_TBM_FORMAT_ARGB8888,
118 HAL_TBM_FORMAT_XRGB8888,
120 HAL_TBM_FORMAT_YUV420
124 _tbm_dumb_is_kms(struct udev_device *device)
127 int fd = -1, id = -1;
128 const char *file_name;
131 file_name = udev_device_get_devnode(device);
132 if (!file_name) return 0;
134 TBM_BACKEND_INFO("check kms device:%s", file_name);
136 sys_num = udev_device_get_sysnum(device);
137 if (!sys_num) return 0;
140 if (id < 0) return 0;
142 fd = open(file_name, O_RDWR | O_CLOEXEC);
144 TBM_BACKEND_ERR("fail to open drm device:%s", file_name);
148 res = drmModeGetResources(fd);
151 if ((res->count_crtcs <= 0) || (res->count_connectors <= 0) ||
152 (res->count_encoders <= 0))
156 drmModeFreeResources(res);
161 if (fd >= 0) close(fd);
162 if (res) drmModeFreeResources(res);
167 static struct udev_device *
168 _tbm_dumb_find_primary_gpu(void)
171 struct udev_enumerate *e;
172 struct udev_list_entry *entry;
173 const char *path, *id;
174 struct udev_device *device, *drm_device, *pci;
178 TBM_BACKEND_ERR("fail to initialize udev context");
182 e = udev_enumerate_new(udev);
183 udev_enumerate_add_match_subsystem(e, "drm");
184 udev_enumerate_add_match_sysname(e, "card[0-9]*");
186 udev_enumerate_scan_devices(e);
188 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
191 path = udev_list_entry_get_name(entry);
192 device = udev_device_new_from_syspath(udev, path);
196 pci = udev_device_get_parent_with_subsystem_devtype(device,
199 id = udev_device_get_sysattr_value(pci, "boot_vga");
200 if (id && !strcmp(id, "1"))
204 if (!is_boot_vga && drm_device) {
205 udev_device_unref(device);
209 if (!_tbm_dumb_is_kms(device)) {
210 udev_device_unref(device);
216 udev_device_unref(drm_device);
224 udev_enumerate_unref(e);
230 _tbm_dumb_open_drm(void)
233 struct udev_device *drm_device = NULL;
234 const char *file_name;
236 drm_device = _tbm_dumb_find_primary_gpu();
238 TBM_BACKEND_ERR("fail to find drm device");
242 file_name = udev_device_get_devnode(drm_device);
244 TBM_BACKEND_ERR("fail to get devnode");
248 fd = open(file_name, O_RDWR | O_CLOEXEC);
250 TBM_BACKEND_ERR("fail to open drm device:%s", file_name);
254 TBM_BACKEND_INFO("open drm device (name:%s fd:%d)", file_name, fd);
256 if (drm_device) udev_device_unref(drm_device);
262 _get_dumb_flag_from_tbm(unsigned int ftbm)
264 unsigned int flags = 0;
269 _get_tbm_flag_from_dumb(unsigned int fdumb)
271 unsigned int flags = 0;
273 flags |= HAL_TBM_BO_SCANOUT;
274 flags |= HAL_TBM_BO_NONCACHABLE;
280 _get_name(int fd, unsigned int gem)
282 struct drm_gem_flink arg = {0,};
285 if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
286 TBM_BACKEND_ERR("fail to DRM_IOCTL_GEM_FLINK gem:%d", gem);
290 return (unsigned int)arg.name;
293 static hal_tbm_bo_handle
294 _dumb_bo_handle(tbm_dumb_bo *bo_data, int device)
296 hal_tbm_bo_handle bo_handle;
297 struct drm_mode_map_dumb map_dumb_arg = {0, };
300 memset(&bo_handle, 0x0, sizeof(uint64_t));
303 case HAL_TBM_DEVICE_DEFAULT:
304 case HAL_TBM_DEVICE_2D:
305 bo_handle.u32 = (uint32_t)bo_data->gem;
307 case HAL_TBM_DEVICE_CPU:
308 if (!bo_data->pBase) {
309 map_dumb_arg.handle = bo_data->gem;
310 if (drmIoctl(bo_data->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb_arg)) {
311 TBM_BACKEND_ERR("fail to DRM_IOCTL_MODE_MAP_DUMB bo_data:%p gem:%d",
312 bo_data, bo_data->gem);
313 return (hal_tbm_bo_handle) NULL;
316 map = mmap(NULL, bo_data->size, PROT_READ | PROT_WRITE, MAP_SHARED,
317 bo_data->fd, map_dumb_arg.offset);
318 if (map == MAP_FAILED) {
319 TBM_BACKEND_ERR("fail to mmap bo_data:%p gem:%d", bo_data, bo_data->gem);
320 return (hal_tbm_bo_handle) NULL;
322 bo_data->pBase = map;
324 bo_handle.ptr = (void *)bo_data->pBase;
326 case HAL_TBM_DEVICE_3D:
327 case HAL_TBM_DEVICE_MM:
328 if (bo_data->dmabuf < 0) {
329 TBM_BACKEND_ERR("invalid dmabuf bo_data:%p", bo_data);
330 return (hal_tbm_bo_handle) NULL;
333 bo_handle.s32 = (int32_t)bo_data->dmabuf;
336 TBM_BACKEND_ERR("Not supported device:%d", device);
337 bo_handle.ptr = (void *) NULL;
344 static hal_tbm_bufmgr_capability
345 tbm_dumb_bufmgr_get_capabilities(hal_tbm_bufmgr *bufmgr, hal_tbm_error *error)
347 hal_tbm_bufmgr_capability capabilities = HAL_TBM_BUFMGR_CAPABILITY_NONE;
349 capabilities = HAL_TBM_BUFMGR_CAPABILITY_SHARE_KEY | HAL_TBM_BUFMGR_CAPABILITY_SHARE_FD;
352 *error = HAL_TBM_ERROR_NONE;
358 tbm_dumb_bufmgr_get_supported_formats(hal_tbm_bufmgr *bufmgr,
359 uint32_t **formats, uint32_t *num)
361 tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
362 uint32_t *color_formats;
364 TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
366 color_formats = (uint32_t *)calloc(1, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
367 if (color_formats == NULL)
368 return HAL_TBM_ERROR_OUT_OF_MEMORY;
370 memcpy(color_formats, tbm_dumb_color_format_list, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
372 *formats = color_formats;
373 *num = TBM_COLOR_FORMAT_COUNT;
375 TBM_BACKEND_DBG("supported format count = %d", *num);
377 return HAL_TBM_ERROR_NONE;
381 tbm_dumb_bufmgr_get_plane_data(hal_tbm_bufmgr *bufmgr,
382 hal_tbm_format format, int plane_idx, int width,
383 int height, uint32_t *size, uint32_t *offset,
384 uint32_t *pitch, int *bo_idx)
386 tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
393 TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
397 case HAL_TBM_FORMAT_XRGB4444:
398 case HAL_TBM_FORMAT_XBGR4444:
399 case HAL_TBM_FORMAT_RGBX4444:
400 case HAL_TBM_FORMAT_BGRX4444:
401 case HAL_TBM_FORMAT_ARGB4444:
402 case HAL_TBM_FORMAT_ABGR4444:
403 case HAL_TBM_FORMAT_RGBA4444:
404 case HAL_TBM_FORMAT_BGRA4444:
405 case HAL_TBM_FORMAT_XRGB1555:
406 case HAL_TBM_FORMAT_XBGR1555:
407 case HAL_TBM_FORMAT_RGBX5551:
408 case HAL_TBM_FORMAT_BGRX5551:
409 case HAL_TBM_FORMAT_ARGB1555:
410 case HAL_TBM_FORMAT_ABGR1555:
411 case HAL_TBM_FORMAT_RGBA5551:
412 case HAL_TBM_FORMAT_BGRA5551:
413 case HAL_TBM_FORMAT_RGB565:
416 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
417 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
421 case HAL_TBM_FORMAT_RGB888:
422 case HAL_TBM_FORMAT_BGR888:
425 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
426 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
430 case HAL_TBM_FORMAT_XRGB8888:
431 case HAL_TBM_FORMAT_XBGR8888:
432 case HAL_TBM_FORMAT_RGBX8888:
433 case HAL_TBM_FORMAT_BGRX8888:
434 case HAL_TBM_FORMAT_ARGB8888:
435 case HAL_TBM_FORMAT_ABGR8888:
436 case HAL_TBM_FORMAT_RGBA8888:
437 case HAL_TBM_FORMAT_BGRA8888:
440 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
441 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
446 case HAL_TBM_FORMAT_YUYV:
447 case HAL_TBM_FORMAT_YVYU:
448 case HAL_TBM_FORMAT_UYVY:
449 case HAL_TBM_FORMAT_VYUY:
452 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
453 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
456 case HAL_TBM_FORMAT_AYUV:
459 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
460 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
466 * index 0 = Y plane, [7:0] Y
467 * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
469 * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
471 case HAL_TBM_FORMAT_NV12:
472 case HAL_TBM_FORMAT_NV21:
474 //if (plane_idx == 0)
477 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
478 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
483 //else if (plane_idx == 1)
486 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
487 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
491 case HAL_TBM_FORMAT_NV16:
492 case HAL_TBM_FORMAT_NV61:
494 //if (plane_idx == 0)
497 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
498 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
503 //else if (plane_idx == 1)
506 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
507 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
514 * index 0: Y plane, [7:0] Y
515 * index 1: Cb plane, [7:0] Cb
516 * index 2: Cr plane, [7:0] Cr
518 * index 1: Cr plane, [7:0] Cr
519 * index 2: Cb plane, [7:0] Cb
522 NATIVE_BUFFER_FORMAT_YV12
523 NATIVE_BUFFER_FORMAT_I420
525 case HAL_TBM_FORMAT_YUV410:
526 case HAL_TBM_FORMAT_YVU410:
529 case HAL_TBM_FORMAT_YUV411:
530 case HAL_TBM_FORMAT_YVU411:
531 case HAL_TBM_FORMAT_YUV420:
532 case HAL_TBM_FORMAT_YVU420:
534 //if (plane_idx == 0)
537 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
538 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
543 //else if (plane_idx == 1)
546 _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
547 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
552 //else if (plane_idx == 2)
555 _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
556 _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
560 case HAL_TBM_FORMAT_YUV422:
561 case HAL_TBM_FORMAT_YVU422:
563 //if (plane_idx == 0)
566 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
567 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
572 //else if (plane_idx == 1)
575 _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
576 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
581 //else if (plane_idx == 2)
584 _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
585 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
589 case HAL_TBM_FORMAT_YUV444:
590 case HAL_TBM_FORMAT_YVU444:
592 //if (plane_idx == 0)
595 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
596 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
601 //else if (plane_idx == 1)
604 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
605 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
610 //else if (plane_idx == 2)
613 _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
614 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
628 return HAL_TBM_ERROR_NONE;
632 tbm_dumb_bufmgr_alloc_bo(hal_tbm_bufmgr *bufmgr, unsigned int size,
633 hal_tbm_bo_memory_type flags, hal_tbm_error *error)
635 tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
636 tbm_dumb_bo *bo_data;
637 unsigned int dumb_flags;
638 struct drm_mode_create_dumb create_dumb_arg = {0, };
639 struct drm_prime_handle prime_handle_arg = {0, };
640 struct drm_gem_close close_arg = {0, };
642 if (bufmgr_data == NULL) {
643 TBM_BACKEND_ERR("bufmgr_data is null");
645 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
649 dumb_flags = _get_dumb_flag_from_tbm(flags);
651 //as we know only size for new bo set height=1 and bpp=8 and in this case
652 //width will by equal to size in bytes;
653 create_dumb_arg.height = 1;
654 create_dumb_arg.bpp = 8;
655 create_dumb_arg.width = size;
656 create_dumb_arg.flags = dumb_flags;
657 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb_arg)) {
658 TBM_BACKEND_ERR("fail to DRM_IOCTL_MODE_CREATE_DUMB flag:%x size:%d",
659 create_dumb_arg.flags, (unsigned int)size);
661 *error = HAL_TBM_ERROR_INVALID_OPERATION;
665 prime_handle_arg.handle = create_dumb_arg.handle;
666 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle_arg)) {
667 TBM_BACKEND_ERR("fail to DRM_IOCTL_PRIME_HANDLE_TO_FD gem:%d",
668 create_dumb_arg.handle);
669 close_arg.handle = create_dumb_arg.handle;
670 drmIoctl(bufmgr_data->fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
673 *error = HAL_TBM_ERROR_INVALID_OPERATION;
677 bo_data = calloc(1, sizeof(struct _tbm_dumb_bo));
679 TBM_BACKEND_ERR("fail to allocate the bo_data private");
681 *error = HAL_TBM_ERROR_OUT_OF_MEMORY;
685 bo_data->bufmgr_data = bufmgr_data;
686 bo_data->fd = bufmgr_data->fd;
687 bo_data->gem = create_dumb_arg.handle;
688 bo_data->size = create_dumb_arg.size;
689 bo_data->dmabuf = prime_handle_arg.fd;
690 bo_data->flags_tbm = flags;
691 bo_data->flags_dumb = dumb_flags;
692 bo_data->name = _get_name(bo_data->fd, bo_data->gem);
694 pthread_mutex_init(&bo_data->mutex, NULL);
697 if (drmHashInsert(bufmgr_data->hashBos, bo_data->name, (void *)bo_data) < 0)
698 TBM_BACKEND_ERR("fail to insert bo_data to Hash:%d bo_data:%p gem:%d",
699 bo_data->name, bo_data, bo_data->gem);
701 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d flags:%d size:%d",
709 *error = HAL_TBM_ERROR_NONE;
711 return (hal_tbm_bo *)bo_data;
715 tbm_dumb_bufmgr_import_fd(hal_tbm_bufmgr *bufmgr, hal_tbm_fd key, hal_tbm_error *error)
717 tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
718 tbm_dumb_bo *bo_data;
719 unsigned int gem = 0;
721 struct drm_prime_handle prime_handle_arg = {0, };
722 struct drm_gem_open open_arg = {0, };
723 struct drm_gem_close close_arg = {0, };
724 unsigned int real_size = -1;
727 if (bufmgr_data == NULL) {
728 TBM_BACKEND_ERR("bufmgr_data is null");
730 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
734 prime_handle_arg.fd = key;
735 prime_handle_arg.flags = 0;
736 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle_arg)) {
737 TBM_BACKEND_ERR("fail to DRM_IOCTL_PRIME_FD_TO_HANDLE key:%d (%m)",
738 prime_handle_arg.fd);
740 *error = HAL_TBM_ERROR_INVALID_OPERATION;
743 gem = prime_handle_arg.handle;
745 name = _get_name(bufmgr_data->fd, gem);
747 TBM_BACKEND_ERR("fail to get name gem:%d (%m)", gem);
749 *error = HAL_TBM_ERROR_INVALID_OPERATION;
753 ret = drmHashLookup(bufmgr_data->hashBos, name, (void **)&bo_data);
755 if (gem == bo_data->gem) {
757 *error = HAL_TBM_ERROR_NONE;
762 /* Determine size of bo. The fd-to-handle ioctl really should
763 * return the size, but it doesn't. If we have kernel 3.12 or
764 * later, we can lseek on the prime fd to get the size. Older
765 * kernels will just fail, in which case we fall back to the
766 * provided (estimated or guess size). */
767 real_size = lseek(key, 0, SEEK_END);
768 if (real_size == -1) {
769 /* Open the same GEM object only for finding out its size */
770 open_arg.name = name;
771 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) {
772 TBM_BACKEND_ERR("fail to DRM_IOCTL_GEM_OPEN gem:%d name:%d (%m)",
775 *error = HAL_TBM_ERROR_INVALID_OPERATION;
779 /* Free gem handle to avoid a memory leak*/
780 close_arg.handle = open_arg.handle;
781 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
782 TBM_BACKEND_ERR("fail to DRM_IOCTL_GEM_CLOSE gem:%d (%m)", open_arg.handle);
784 *error = HAL_TBM_ERROR_INVALID_OPERATION;
788 real_size = open_arg.size;
791 bo_data = calloc(1, sizeof(struct _tbm_dumb_bo));
793 TBM_BACKEND_ERR("fail to allocate the bo_data private");
795 *error = HAL_TBM_ERROR_OUT_OF_MEMORY;
799 bo_data->bufmgr_data = bufmgr_data;
800 bo_data->fd = bufmgr_data->fd;
802 bo_data->size = real_size;
803 bo_data->dmabuf = dup(key);
804 bo_data->flags_dumb = 0;
805 bo_data->flags_tbm = _get_tbm_flag_from_dumb(bo_data->flags_dumb);
806 bo_data->name = name;
808 /* add bo_data to hash */
809 if (drmHashInsert(bufmgr_data->hashBos, bo_data->name, (void *)bo_data) < 0)
810 TBM_BACKEND_ERR("fail to insert bo_data to Hash:%d bo_data:%p gem:%d fd:%d",
811 bo_data->name, bo_data, gem, key);
813 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d key_fd:%d flags:%d size:%d",
822 *error = HAL_TBM_ERROR_NONE;
824 return (hal_tbm_bo *)bo_data;
828 tbm_dumb_bufmgr_import_key(hal_tbm_bufmgr *bufmgr, hal_tbm_key key, hal_tbm_error *error)
830 tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
831 tbm_dumb_bo *bo_data;
832 struct drm_gem_open open_arg = {0, };
833 struct drm_prime_handle prime_handle_arg = {0, };
834 struct drm_gem_close close_arg = {0, };
837 if (bufmgr_data == NULL) {
838 TBM_BACKEND_ERR("bufmgr_data is null");
840 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
844 ret = drmHashLookup(bufmgr_data->hashBos, key, (void **)&bo_data);
847 *error = HAL_TBM_ERROR_NONE;
848 return (hal_tbm_bo *)bo_data;
852 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) {
853 TBM_BACKEND_ERR("fail to DRM_IOCTL_GEM_OPEN name:%d", key);
855 *error = HAL_TBM_ERROR_INVALID_OPERATION;
859 prime_handle_arg.handle = open_arg.handle;
860 if (drmIoctl(bufmgr_data->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle_arg)) {
861 TBM_BACKEND_ERR("fail to DRM_IOCTL_PRIME_HANDLE_TO_FD gem:%d",
863 close_arg.handle = open_arg.handle;
864 drmIoctl(bufmgr_data->fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
867 *error = HAL_TBM_ERROR_INVALID_OPERATION;
871 bo_data = calloc(1, sizeof(struct _tbm_dumb_bo));
873 TBM_BACKEND_ERR("fail to allocate the bo_data private");
875 *error = HAL_TBM_ERROR_OUT_OF_MEMORY;
879 bo_data->bufmgr_data = bufmgr_data;
880 bo_data->fd = bufmgr_data->fd;
881 bo_data->gem = open_arg.handle;
882 bo_data->size = open_arg.size;
883 bo_data->dmabuf = prime_handle_arg.fd;
884 bo_data->flags_dumb = 0;
886 bo_data->flags_tbm = _get_tbm_flag_from_dumb(bo_data->flags_dumb);
889 if (drmHashInsert(bufmgr_data->hashBos, bo_data->name, (void *)bo_data) < 0)
890 TBM_BACKEND_ERR("fail to insert bo_data:%p to Hash:%d", bo_data, bo_data->name);
892 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d flags:%d size:%d",
900 *error = HAL_TBM_ERROR_NONE;
902 return (hal_tbm_bo *)bo_data;
906 tbm_dumb_bo_free(hal_tbm_bo *bo)
908 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
910 tbm_dumb_bufmgr *bufmgr_data;
911 struct drm_gem_close close_arg = {0, };
917 bufmgr_data = bo_data->bufmgr_data;
921 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d size:%d",
928 if (bo_data->pBase) {
929 if (munmap(bo_data->pBase, bo_data->size) == -1) {
930 TBM_BACKEND_ERR("fail to munmap bo_data:%p (%m)",
936 if (bo_data->dmabuf >= 0) {
937 close(bo_data->dmabuf);
938 bo_data->dmabuf = -1;
941 /* delete bo from hash */
942 ret = drmHashLookup(bufmgr_data->hashBos, bo_data->name, (void**)&temp);
944 drmHashDelete(bufmgr_data->hashBos, bo_data->name);
946 TBM_BACKEND_ERR("fail to find bo_data to Hash:%d, ret:%d", bo_data->name, ret);
949 TBM_BACKEND_ERR("hashBos probably has several BOs with same name!!!");
951 /* Free gem handle */
952 close_arg.handle = bo_data->gem;
953 if (drmIoctl(bo_data->fd, DRM_IOCTL_GEM_CLOSE, &close_arg))
954 TBM_BACKEND_ERR("fail to gem close bo_data:%p gem:%d (%m)",
955 bo_data, bo_data->gem);
961 tbm_dumb_bo_get_size(hal_tbm_bo *bo, hal_tbm_error *error)
963 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
967 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
972 *error = HAL_TBM_ERROR_NONE;
974 return bo_data->size;
977 static hal_tbm_bo_memory_type
978 tbm_dumb_bo_get_memory_type(hal_tbm_bo *bo, hal_tbm_error *error)
980 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
984 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
985 return HAL_TBM_BO_DEFAULT;
989 *error = HAL_TBM_ERROR_NONE;
991 return bo_data->flags_tbm;
994 static hal_tbm_bo_handle
995 tbm_dumb_bo_get_handle(hal_tbm_bo *bo, hal_tbm_bo_device_type device, hal_tbm_error *error)
997 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
998 hal_tbm_bo_handle bo_handle;
1002 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1003 return (hal_tbm_bo_handle) NULL;
1006 if (!bo_data->gem) {
1007 TBM_BACKEND_ERR("invalid gem bo_data:%p", bo_data);
1009 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1010 return (hal_tbm_bo_handle) NULL;
1013 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d flags:%d size:%d %s",
1020 STR_DEVICE[device]);
1022 /*Get mapped bo_handle*/
1023 bo_handle = _dumb_bo_handle(bo_data, device);
1024 if (bo_handle.ptr == NULL) {
1025 TBM_BACKEND_ERR("fail to get handle bo_data:%p gem:%d device:%d",
1026 bo_data, bo_data->gem, device);
1028 *error = HAL_TBM_ERROR_INVALID_OPERATION;
1029 return (hal_tbm_bo_handle) NULL;
1033 *error = HAL_TBM_ERROR_NONE;
1038 static hal_tbm_bo_handle
1039 tbm_dumb_bo_map(hal_tbm_bo *bo, hal_tbm_bo_device_type device,
1040 hal_tbm_bo_access_option opt, hal_tbm_error *error)
1042 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1043 hal_tbm_bo_handle bo_handle;
1044 tbm_dumb_bufmgr *bufmgr_data;
1048 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1049 return (hal_tbm_bo_handle) NULL;
1052 bufmgr_data = bo_data->bufmgr_data;
1055 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1056 return (hal_tbm_bo_handle) NULL;
1059 if (!bo_data->gem) {
1060 TBM_BACKEND_ERR("invalid gem bo_data:%p", bo_data);
1062 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1063 return (hal_tbm_bo_handle) NULL;
1066 TBM_BACKEND_DBG("bo_data:%p, gem:%d name:%d fd:%d %s %s",
1074 /*Get mapped bo_handle*/
1075 bo_handle = _dumb_bo_handle(bo_data, device);
1076 if (bo_handle.ptr == NULL) {
1077 TBM_BACKEND_ERR("fail to get handle gem:%d device:%d opt:%d",
1078 bo_data->gem, device, opt);
1080 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1081 return (hal_tbm_bo_handle) NULL;
1085 struct dma_buf_sync sync = {0, };
1087 if (device == HAL_TBM_DEVICE_CPU) {
1088 sync.flags |= DMA_BUF_SYNC_START;
1089 if (opt & HAL_TBM_OPTION_READ)
1090 sync.flags |= DMA_BUF_SYNC_READ;
1091 else if (opt & HAL_TBM_OPTION_WRITE)
1092 sync.flags |= DMA_BUF_SYNC_WRITE;
1094 if (drmIoctl(bo_data->dmabuf, DMA_BUF_IOCTL_SYNC, &sync)) {
1095 TBM_BACKEND_WRN("fail to DMA_BUF_IOCTL_SYNC bo_data:%p (%m)",
1101 bo_data->device = device;
1105 *error = HAL_TBM_ERROR_NONE;
1110 static hal_tbm_error
1111 tbm_dumb_bo_unmap(hal_tbm_bo *bo)
1113 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1114 tbm_dumb_bufmgr *bufmgr_data;
1117 return HAL_TBM_ERROR_INVALID_PARAMETER;
1119 bufmgr_data = bo_data->bufmgr_data;
1121 return HAL_TBM_ERROR_INVALID_PARAMETER;
1124 return HAL_TBM_ERROR_INVALID_PARAMETER;
1127 struct dma_buf_sync sync = {0, };
1129 if (bo_data->device == HAL_TBM_DEVICE_CPU) {
1130 sync.flags |= DMA_BUF_SYNC_END;
1131 if (bo_data->opt & HAL_TBM_OPTION_READ)
1132 sync.flags |= DMA_BUF_SYNC_READ;
1133 else if (bo_data->opt & HAL_TBM_OPTION_WRITE)
1134 sync.flags |= DMA_BUF_SYNC_WRITE;
1136 if (drmIoctl(bo_data->dmabuf, DMA_BUF_IOCTL_SYNC, &sync)) {
1137 TBM_BACKEND_WRN("fail to DMA_BUF_IOCTL_SYNC bo_data:%p (%m)",
1143 bo_data->device = 0;
1146 TBM_BACKEND_DBG("bo_data:%p, gem:%d name:%d fd:%d",
1152 return HAL_TBM_ERROR_NONE;
1156 tbm_dumb_bo_export_fd(hal_tbm_bo *bo, hal_tbm_error *error)
1158 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1159 struct drm_prime_handle prime_handle_arg = {0, };
1164 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1168 prime_handle_arg.handle = bo_data->gem;
1169 ret = drmIoctl(bo_data->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle_arg);
1171 TBM_BACKEND_ERR("fail to DRM_IOCTL_PRIME_HANDLE_TO_FD bo_data:%p gem:%d (%m)",
1172 bo_data, bo_data->gem);
1174 *error = HAL_TBM_ERROR_INVALID_OPERATION;
1175 return (hal_tbm_fd)ret;
1178 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d key_fd:%d flags:%d size:%d",
1183 prime_handle_arg.fd,
1188 *error = HAL_TBM_ERROR_NONE;
1190 return (hal_tbm_fd)prime_handle_arg.fd;
1194 tbm_dumb_bo_export_key(hal_tbm_bo *bo, hal_tbm_error *error)
1196 tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1200 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1204 if (!bo_data->name) {
1205 bo_data->name = _get_name(bo_data->fd, bo_data->gem);
1206 if (!bo_data->name) {
1207 TBM_BACKEND_ERR("fail to get name bo_data:%p", bo_data);
1209 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1214 TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d flags:%d size:%d",
1223 *error = HAL_TBM_ERROR_NONE;
1225 return (hal_tbm_key)bo_data->name;
1228 static hal_tbm_error
1229 _tbm_dumb_authenticated_drm_fd_handler(hal_tbm_fd auth_fd, void *user_data)
1231 tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)user_data;
1233 TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
1235 bufmgr_data->fd = auth_fd;
1236 TBM_BACKEND_INFO("Get the authenticated drm_fd(%d)!", bufmgr_data->fd);
1238 return HAL_TBM_ERROR_NONE;
1242 hal_backend_tbm_dumb_exit(void *data)
1244 hal_tbm_backend_data *backend_data = (hal_tbm_backend_data *)data;
1245 tbm_dumb_bufmgr *bufmgr_data;
1249 TBM_BACKEND_RETURN_VAL_IF_FAIL(backend_data != NULL, -1);
1251 bufmgr_data = (tbm_dumb_bufmgr *)backend_data->bufmgr;
1252 TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, -1);
1254 if (backend_data->bufmgr_funcs)
1255 free(backend_data->bufmgr_funcs);
1256 if (backend_data->bo_funcs)
1257 free(backend_data->bo_funcs);
1259 if (bufmgr_data->hashBos) {
1260 while (drmHashFirst(bufmgr_data->hashBos, &key, &value) > 0) {
1262 drmHashDelete(bufmgr_data->hashBos, key);
1265 drmHashDestroy(bufmgr_data->hashBos);
1266 bufmgr_data->hashBos = NULL;
1269 close(bufmgr_data->fd);
1271 free(backend_data->bufmgr);
1274 return HAL_TBM_ERROR_NONE;
1278 hal_backend_tbm_dumb_init(void **data)
1280 hal_tbm_backend_data *backend_data = NULL;
1281 hal_tbm_bufmgr_funcs *bufmgr_funcs = NULL;
1282 hal_tbm_bo_funcs *bo_funcs = NULL;
1283 tbm_dumb_bufmgr *bufmgr_data = NULL;
1288 /* allocate a hal_tbm_backend_data */
1289 backend_data = calloc(1, sizeof(struct _hal_tbm_backend_data));
1290 if (!backend_data) {
1291 TBM_BACKEND_ERR("fail to alloc backend_data!");
1295 *data = backend_data;
1297 /* allocate a hal_tbm_bufmgr */
1298 bufmgr_data = calloc(1, sizeof(struct _tbm_dumb_bufmgr));
1300 TBM_BACKEND_ERR("fail to alloc bufmgr_data!");
1301 goto fail_alloc_bufmgr_data;
1303 backend_data->bufmgr = (hal_tbm_bufmgr *)bufmgr_data;
1306 drm_fd = _tbm_dumb_open_drm();
1308 TBM_BACKEND_ERR("fail to open drm!");
1312 // set true when backend has a drm_device.
1313 backend_data->has_drm_device = 1;
1315 ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap);
1316 if (ret || cap == 0) {
1317 TBM_BACKEND_ERR("drm buffer isn't supported !");
1321 // check if drm_fd is master_drm_fd.
1322 if (drmIsMaster(drm_fd)) {
1323 // drm_fd is a master_drm_fd.
1324 backend_data->drm_info.drm_fd = drm_fd;
1325 backend_data->drm_info.is_master = 1;
1327 bufmgr_data->fd = drm_fd;
1328 TBM_BACKEND_INFO("Get the master drm_fd(%d)!", bufmgr_data->fd);
1330 // drm_fd is not a master_drm_fd.
1331 // request authenticated fd
1333 backend_data->drm_info.drm_fd = -1;
1334 backend_data->drm_info.is_master = 0;
1335 backend_data->drm_info.auth_drm_fd_func = _tbm_dumb_authenticated_drm_fd_handler;
1336 backend_data->drm_info.user_data = bufmgr_data;
1338 TBM_BACKEND_INFO("A backend requests an authenticated drm_fd.");
1341 /*Create Hash Table*/
1342 bufmgr_data->hashBos = drmHashCreate();
1344 /* alloc and register bufmgr_funcs */
1345 bufmgr_funcs = calloc(1, sizeof(struct _hal_tbm_bufmgr_funcs));
1346 if (!bufmgr_funcs) {
1347 TBM_BACKEND_ERR("fail to alloc bufmgr_funcs!");
1348 goto fail_alloc_bufmgr_funcs;
1350 backend_data->bufmgr_funcs = bufmgr_funcs;
1352 bufmgr_funcs->bufmgr_get_capabilities = tbm_dumb_bufmgr_get_capabilities;
1353 bufmgr_funcs->bufmgr_get_supported_formats = tbm_dumb_bufmgr_get_supported_formats;
1354 bufmgr_funcs->bufmgr_get_plane_data = tbm_dumb_bufmgr_get_plane_data;
1355 bufmgr_funcs->bufmgr_alloc_bo = tbm_dumb_bufmgr_alloc_bo;
1356 bufmgr_funcs->bufmgr_alloc_bo_with_format = NULL;
1357 bufmgr_funcs->bufmgr_import_fd = tbm_dumb_bufmgr_import_fd;
1358 bufmgr_funcs->bufmgr_import_key = tbm_dumb_bufmgr_import_key;
1360 /* alloc and register bo_funcs */
1361 bo_funcs = calloc(1, sizeof(struct _hal_tbm_bo_funcs));
1363 TBM_BACKEND_ERR("fail to alloc bo_funcs!");
1364 goto fail_alloc_bo_funcs;
1366 backend_data->bo_funcs = bo_funcs;
1368 bo_funcs->bo_free = tbm_dumb_bo_free;
1369 bo_funcs->bo_get_size = tbm_dumb_bo_get_size;
1370 bo_funcs->bo_get_memory_types = tbm_dumb_bo_get_memory_type;
1371 bo_funcs->bo_get_handle = tbm_dumb_bo_get_handle;
1372 bo_funcs->bo_map = tbm_dumb_bo_map;
1373 bo_funcs->bo_unmap = tbm_dumb_bo_unmap;
1374 bo_funcs->bo_lock = NULL;
1375 bo_funcs->bo_unlock = NULL;
1376 bo_funcs->bo_export_fd = tbm_dumb_bo_export_fd;
1377 bo_funcs->bo_export_key = tbm_dumb_bo_export_key;
1379 TBM_BACKEND_DBG("drm_fd:%d", bufmgr_data->fd);
1381 return HAL_TBM_ERROR_NONE;
1383 fail_alloc_bo_funcs:
1385 fail_alloc_bufmgr_funcs:
1386 if (bufmgr_data->hashBos)
1387 drmHashDestroy(bufmgr_data->hashBos);
1389 if (backend_data->drm_info.is_master)
1390 close(bufmgr_data->fd);
1395 fail_alloc_bufmgr_data:
1403 hal_backend hal_backend_tbm_data = {
1406 HAL_ABI_VERSION_TIZEN_6_5,
1407 hal_backend_tbm_dumb_init,
1408 hal_backend_tbm_dumb_exit