ad38ca90a4ffd6c5aa26321785ddca9c7e4edd93
[platform/adaptation/libtbm-dumb.git] / src / tbm_backend_dumb.c
1 /**************************************************************************
2
3 libtbm_dumb
4
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8
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:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
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.
28
29 **************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <libudev.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <string.h>
41 #include <sys/ioctl.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44 #include <sys/mman.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <errno.h>
48 #include <xf86drm.h>
49 #include <xf86drmMode.h>
50 #include <pthread.h>
51 #include <hal-common.h>
52 #include <hal-tbm-types.h>
53 #include <hal-tbm-interface.h>
54 #include "tbm_backend_log.h"
55
56 #ifdef HAVE_DMA_BUF
57 #include <linux/dma-buf.h>
58 #endif
59
60 #define TBM_COLOR_FORMAT_COUNT 4
61
62 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
63
64 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
65 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (128)
66 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
67
68 typedef struct _tbm_dumb_bufmgr tbm_dumb_bufmgr;
69 typedef struct _tbm_dumb_bo tbm_dumb_bo;
70
71 /* tbm buffor object for dumb */
72 struct _tbm_dumb_bo {
73         int fd;
74
75         unsigned int name;    /* FLINK ID */
76
77         unsigned int gem;     /* GEM Handle */
78
79         int dmabuf;           /* fd for dmabuf */
80
81         void *pBase;          /* virtual address */
82
83         unsigned int size;
84
85         unsigned int flags_dumb;
86         unsigned int flags_tbm;
87
88         pthread_mutex_t mutex;
89         int device;
90         int opt;
91
92         tbm_dumb_bufmgr *bufmgr_data;
93 };
94
95 /* tbm bufmgr private for dumb */
96 struct _tbm_dumb_bufmgr {
97         int fd;
98         void *hashBos;
99 };
100
101 static char *STR_DEVICE[] = {
102         "DEF",
103         "CPU",
104         "2D",
105         "3D",
106         "MM"
107 };
108
109 static char *STR_OPT[] = {
110         "NONE",
111         "RD",
112         "WR",
113         "RDWR"
114 };
115
116 static uint32_t tbm_dumb_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
117                                                                         HAL_TBM_FORMAT_ARGB8888,
118                                                                         HAL_TBM_FORMAT_XRGB8888,
119                                                                         HAL_TBM_FORMAT_NV12,
120                                                                         HAL_TBM_FORMAT_YUV420
121 };
122
123 static int
124 _tbm_dumb_is_kms(struct udev_device *device)
125 {
126         drmModeRes *res;
127         int fd = -1, id = -1;
128         const char *file_name;
129         const char *sys_num;
130
131         file_name = udev_device_get_devnode(device);
132         if (!file_name) return 0;
133
134         TBM_BACKEND_INFO("check kms device:%s", file_name);
135
136         sys_num = udev_device_get_sysnum(device);
137         if (!sys_num) return 0;
138
139         id = atoi(sys_num);
140         if (id < 0) return 0;
141
142         fd = open(file_name, O_RDWR | O_CLOEXEC);
143         if (fd < 0) {
144                 TBM_BACKEND_ERR("fail to open drm device:%s", file_name);
145                 return 0;
146         }
147
148         res = drmModeGetResources(fd);
149         if (!res) goto fail;
150
151         if ((res->count_crtcs <= 0) || (res->count_connectors <= 0) ||
152                 (res->count_encoders <= 0))
153                 goto fail;
154
155         close(fd);
156         drmModeFreeResources(res);
157
158         return 1;
159
160 fail:
161         if (fd >= 0) close(fd);
162         if (res) drmModeFreeResources(res);
163
164         return 0;
165 }
166
167 static struct udev_device *
168 _tbm_dumb_find_primary_gpu(void)
169 {
170         struct udev *udev;
171         struct udev_enumerate *e;
172         struct udev_list_entry *entry;
173         const char *path, *id;
174         struct udev_device *device, *drm_device, *pci;
175
176         udev = udev_new();
177         if (!udev) {
178                 TBM_BACKEND_ERR("fail to initialize udev context");
179                 return NULL;
180         }
181
182         e = udev_enumerate_new(udev);
183         udev_enumerate_add_match_subsystem(e, "drm");
184         udev_enumerate_add_match_sysname(e, "card[0-9]*");
185
186         udev_enumerate_scan_devices(e);
187         drm_device = NULL;
188         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
189                 int is_boot_vga;
190
191                 path = udev_list_entry_get_name(entry);
192                 device = udev_device_new_from_syspath(udev, path);
193                 if (!device)
194                         continue;
195
196                 pci = udev_device_get_parent_with_subsystem_devtype(device,
197                                                 "pci", NULL);
198                 if (pci) {
199                         id = udev_device_get_sysattr_value(pci, "boot_vga");
200                         if (id && !strcmp(id, "1"))
201                                 is_boot_vga = 1;
202                 }
203
204                 if (!is_boot_vga && drm_device) {
205                         udev_device_unref(device);
206                         continue;
207                 }
208
209                 if (!_tbm_dumb_is_kms(device)) {
210                         udev_device_unref(device);
211                         continue;
212                 }
213
214                 if (is_boot_vga) {
215                         if (drm_device)
216                                 udev_device_unref(drm_device);
217                         drm_device = device;
218                         break;
219                 }
220
221                 drm_device = device;
222         }
223
224         udev_enumerate_unref(e);
225
226         return drm_device;
227 }
228
229 static int
230 _tbm_dumb_open_drm(void)
231 {
232         int fd = -1;
233         struct udev_device *drm_device = NULL;
234         const char *file_name;
235
236         drm_device = _tbm_dumb_find_primary_gpu();
237         if (!drm_device) {
238                 TBM_BACKEND_ERR("fail to find drm device");
239                 goto ret;
240         }
241
242         file_name = udev_device_get_devnode(drm_device);
243         if (!file_name) {
244                 TBM_BACKEND_ERR("fail to get devnode");
245                 goto ret;
246         }
247
248         fd = open(file_name, O_RDWR | O_CLOEXEC);
249         if (fd < 0) {
250                 TBM_BACKEND_ERR("fail to open drm device:%s", file_name);
251                 goto ret;
252         }
253
254         TBM_BACKEND_INFO("open drm device (name:%s fd:%d)", file_name, fd);
255 ret:
256         if (drm_device) udev_device_unref(drm_device);
257
258         return fd;
259 }
260
261 static unsigned int
262 _get_dumb_flag_from_tbm(unsigned int ftbm)
263 {
264         unsigned int flags = 0;
265         return flags;
266 }
267
268 static unsigned int
269 _get_tbm_flag_from_dumb(unsigned int fdumb)
270 {
271         unsigned int flags = 0;
272
273         flags |= HAL_TBM_BO_SCANOUT;
274         flags |= HAL_TBM_BO_NONCACHABLE;
275
276         return flags;
277 }
278
279 static unsigned int
280 _get_name(int fd, unsigned int gem)
281 {
282         struct drm_gem_flink arg = {0,};
283
284         arg.handle = gem;
285         if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
286                 TBM_BACKEND_ERR("fail to DRM_IOCTL_GEM_FLINK gem:%d", gem);
287                 return 0;
288         }
289
290         return (unsigned int)arg.name;
291 }
292
293 static hal_tbm_bo_handle
294 _dumb_bo_handle(tbm_dumb_bo *bo_data, int device)
295 {
296         hal_tbm_bo_handle bo_handle;
297         struct drm_mode_map_dumb map_dumb_arg = {0, };
298         void *map = NULL;
299
300         memset(&bo_handle, 0x0, sizeof(uint64_t));
301
302         switch (device) {
303         case HAL_TBM_DEVICE_DEFAULT:
304         case HAL_TBM_DEVICE_2D:
305                 bo_handle.u32 = (uint32_t)bo_data->gem;
306                 break;
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;
314                         }
315
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;
321                         }
322                         bo_data->pBase = map;
323                 }
324                 bo_handle.ptr = (void *)bo_data->pBase;
325                 break;
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;
331                 }
332
333                 bo_handle.s32 = (int32_t)bo_data->dmabuf;
334                 break;
335         default:
336                 TBM_BACKEND_ERR("Not supported device:%d", device);
337                 bo_handle.ptr = (void *) NULL;
338                 break;
339         }
340
341         return bo_handle;
342 }
343
344 static hal_tbm_bufmgr_capability
345 tbm_dumb_bufmgr_get_capabilities(hal_tbm_bufmgr *bufmgr, hal_tbm_error *error)
346 {
347         hal_tbm_bufmgr_capability capabilities = HAL_TBM_BUFMGR_CAPABILITY_NONE;
348
349         capabilities = HAL_TBM_BUFMGR_CAPABILITY_SHARE_KEY | HAL_TBM_BUFMGR_CAPABILITY_SHARE_FD;
350
351         if (error)
352                 *error = HAL_TBM_ERROR_NONE;
353
354         return capabilities;
355 }
356
357 static hal_tbm_error
358 tbm_dumb_bufmgr_get_supported_formats(hal_tbm_bufmgr *bufmgr,
359                                                         uint32_t **formats, uint32_t *num)
360 {
361         tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
362         uint32_t *color_formats;
363
364         TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
365
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;
369
370         memcpy(color_formats, tbm_dumb_color_format_list, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
371
372         *formats = color_formats;
373         *num = TBM_COLOR_FORMAT_COUNT;
374
375         TBM_BACKEND_DBG("supported format count = %d", *num);
376
377         return HAL_TBM_ERROR_NONE;
378 }
379
380 static hal_tbm_error
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)
385 {
386         tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
387         int bpp;
388         int _offset = 0;
389         int _pitch = 0;
390         int _size = 0;
391         int _bo_idx = 0;
392
393         TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
394
395         switch (format) {
396         /* 16 bpp RGB */
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:
414                 bpp = 16;
415                 _offset = 0;
416                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
417                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
418                 _bo_idx = 0;
419                 break;
420         /* 24 bpp RGB */
421         case HAL_TBM_FORMAT_RGB888:
422         case HAL_TBM_FORMAT_BGR888:
423                 bpp = 24;
424                 _offset = 0;
425                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
426                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
427                 _bo_idx = 0;
428                 break;
429         /* 32 bpp RGB */
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:
438                 bpp = 32;
439                 _offset = 0;
440                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
441                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
442                 _bo_idx = 0;
443                 break;
444
445         /* packed YCbCr */
446         case HAL_TBM_FORMAT_YUYV:
447         case HAL_TBM_FORMAT_YVYU:
448         case HAL_TBM_FORMAT_UYVY:
449         case HAL_TBM_FORMAT_VYUY:
450                 bpp = 16;
451                 _offset = 0;
452                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
453                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
454                 _bo_idx = 0;
455                 break;
456         case HAL_TBM_FORMAT_AYUV:
457                 bpp = 32;
458                 _offset = 0;
459                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
460                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
461                 _bo_idx = 0;
462                 break;
463
464         /*
465         * 2 plane YCbCr
466         * index 0 = Y plane, [7:0] Y
467         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
468         * or
469         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
470         */
471         case HAL_TBM_FORMAT_NV12:
472         case HAL_TBM_FORMAT_NV21:
473                 bpp = 12;
474                 //if (plane_idx == 0)
475                 {
476                         _offset = 0;
477                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
478                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
479                         _bo_idx = 0;
480                         if (plane_idx == 0)
481                                 break;
482                 }
483                 //else if (plane_idx == 1)
484                 {
485                         _offset += _size;
486                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
487                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
488                         _bo_idx = 0;
489                 }
490                 break;
491         case HAL_TBM_FORMAT_NV16:
492         case HAL_TBM_FORMAT_NV61:
493                 bpp = 16;
494                 //if (plane_idx == 0)
495                 {
496                         _offset = 0;
497                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
498                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
499                         _bo_idx = 0;
500                         if (plane_idx == 0)
501                                 break;
502                 }
503                 //else if (plane_idx == 1)
504                 {
505                         _offset += _size;
506                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
507                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
508                         _bo_idx = 0;
509                 }
510                 break;
511
512         /*
513         * 3 plane YCbCr
514         * index 0: Y plane, [7:0] Y
515         * index 1: Cb plane, [7:0] Cb
516         * index 2: Cr plane, [7:0] Cr
517         * or
518         * index 1: Cr plane, [7:0] Cr
519         * index 2: Cb plane, [7:0] Cb
520         */
521         /*
522         NATIVE_BUFFER_FORMAT_YV12
523         NATIVE_BUFFER_FORMAT_I420
524         */
525         case HAL_TBM_FORMAT_YUV410:
526         case HAL_TBM_FORMAT_YVU410:
527                 bpp = 9;
528                 break;
529         case HAL_TBM_FORMAT_YUV411:
530         case HAL_TBM_FORMAT_YVU411:
531         case HAL_TBM_FORMAT_YUV420:
532         case HAL_TBM_FORMAT_YVU420:
533                 bpp = 12;
534                 //if (plane_idx == 0)
535                 {
536                         _offset = 0;
537                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
538                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
539                         _bo_idx = 0;
540                         if (plane_idx == 0)
541                                 break;
542                 }
543                 //else if (plane_idx == 1)
544                 {
545                         _offset += _size;
546                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
547                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
548                         _bo_idx = 0;
549                         if (plane_idx == 1)
550                                 break;
551                 }
552                 //else if (plane_idx == 2)
553                 {
554                         _offset += _size;
555                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
556                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
557                         _bo_idx = 0;
558                 }
559                 break;
560         case HAL_TBM_FORMAT_YUV422:
561         case HAL_TBM_FORMAT_YVU422:
562                 bpp = 16;
563                 //if (plane_idx == 0)
564                 {
565                         _offset = 0;
566                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
567                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
568                         _bo_idx = 0;
569                         if (plane_idx == 0)
570                                 break;
571                 }
572                 //else if (plane_idx == 1)
573                 {
574                         _offset += _size;
575                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
576                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
577                         _bo_idx = 0;
578                         if (plane_idx == 1)
579                                 break;
580                 }
581                 //else if (plane_idx == 2)
582                 {
583                         _offset += _size;
584                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
585                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
586                         _bo_idx = 0;
587                 }
588                 break;
589         case HAL_TBM_FORMAT_YUV444:
590         case HAL_TBM_FORMAT_YVU444:
591                 bpp = 24;
592                 //if (plane_idx == 0)
593                 {
594                         _offset = 0;
595                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
596                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
597                         _bo_idx = 0;
598                         if (plane_idx == 0)
599                                 break;
600                 }
601                 //else if (plane_idx == 1)
602                 {
603                         _offset += _size;
604                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
605                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
606                         _bo_idx = 0;
607                         if (plane_idx == 1)
608                                 break;
609                 }
610                 //else if (plane_idx == 2)
611                 {
612                         _offset += _size;
613                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
614                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
615                         _bo_idx = 0;
616                 }
617                 break;
618         default:
619                 bpp = 0;
620                 break;
621         }
622
623         *size = _size;
624         *offset = _offset;
625         *pitch = _pitch;
626         *bo_idx = _bo_idx;
627
628         return HAL_TBM_ERROR_NONE;
629 }
630
631 static hal_tbm_bo *
632 tbm_dumb_bufmgr_alloc_bo(hal_tbm_bufmgr *bufmgr, unsigned int size,
633                                         hal_tbm_bo_memory_type flags, hal_tbm_error *error)
634 {
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, };
641
642         if (bufmgr_data == NULL) {
643                 TBM_BACKEND_ERR("bufmgr_data is null");
644                 if (error)
645                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
646                 return NULL;
647         }
648
649         dumb_flags = _get_dumb_flag_from_tbm(flags);
650
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);
660                 if (error)
661                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
662                 return NULL;
663         }
664
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);
671
672                 if (error)
673                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
674                 return NULL;
675         }
676
677         bo_data = calloc(1, sizeof(struct _tbm_dumb_bo));
678         if (!bo_data) {
679                 TBM_BACKEND_ERR("fail to allocate the bo_data private");
680                 if (error)
681                         *error = HAL_TBM_ERROR_OUT_OF_MEMORY;
682                 return NULL;
683         }
684
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);
693
694         pthread_mutex_init(&bo_data->mutex, NULL);
695
696         /* add bo to hash */
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);
700
701         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d flags:%d size:%d",
702                         bo_data,
703                         bo_data->gem,
704                         bo_data->name,
705                         bo_data->flags_tbm,
706                         bo_data->size);
707
708         if (error)
709                 *error = HAL_TBM_ERROR_NONE;
710
711         return (hal_tbm_bo *)bo_data;
712 }
713
714 static hal_tbm_bo *
715 tbm_dumb_bufmgr_import_fd(hal_tbm_bufmgr *bufmgr, hal_tbm_fd key, hal_tbm_error *error)
716 {
717         tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)bufmgr;
718         tbm_dumb_bo *bo_data;
719         unsigned int gem = 0;
720         unsigned int name;
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;
725         int ret;
726
727         if (bufmgr_data == NULL) {
728                 TBM_BACKEND_ERR("bufmgr_data is null");
729                 if (error)
730                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
731                 return NULL;
732         }
733
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);
739                 if (error)
740                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
741                 return NULL;
742         }
743         gem = prime_handle_arg.handle;
744
745         name = _get_name(bufmgr_data->fd, gem);
746         if (name == 0) {
747                 TBM_BACKEND_ERR("fail to get name gem:%d (%m)", gem);
748                 if (error)
749                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
750                 return NULL;
751         }
752
753         ret = drmHashLookup(bufmgr_data->hashBos, name, (void **)&bo_data);
754         if (ret == 0) {
755                 if (gem == bo_data->gem) {
756                         if (error)
757                                 *error = HAL_TBM_ERROR_NONE;
758                         return bo_data;
759                 }
760         }
761
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)",
773                                         gem, name);
774                         if (error)
775                                 *error = HAL_TBM_ERROR_INVALID_OPERATION;
776                         return NULL;
777                 }
778
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);
783                         if (error)
784                                 *error = HAL_TBM_ERROR_INVALID_OPERATION;
785                         return NULL;
786                 }
787
788                 real_size = open_arg.size;
789         }
790
791         bo_data = calloc(1, sizeof(struct _tbm_dumb_bo));
792         if (!bo_data) {
793                 TBM_BACKEND_ERR("fail to allocate the bo_data private");
794                 if (error)
795                         *error = HAL_TBM_ERROR_OUT_OF_MEMORY;
796                 return NULL;
797         }
798
799         bo_data->bufmgr_data = bufmgr_data;
800         bo_data->fd = bufmgr_data->fd;
801         bo_data->gem = gem;
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;
807
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);
812
813         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d key_fd:%d flags:%d size:%d",
814                         bo_data,
815                         bo_data->gem,
816                         bo_data->name,
817                         key,
818                         bo_data->flags_tbm,
819                         bo_data->size);
820
821         if (error)
822                 *error = HAL_TBM_ERROR_NONE;
823
824         return (hal_tbm_bo *)bo_data;
825 }
826
827 static hal_tbm_bo *
828 tbm_dumb_bufmgr_import_key(hal_tbm_bufmgr *bufmgr, hal_tbm_key key, hal_tbm_error *error)
829 {
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, };
835         int ret;
836
837         if (bufmgr_data == NULL) {
838                 TBM_BACKEND_ERR("bufmgr_data is null");
839                 if (error)
840                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
841                 return NULL;
842         }
843
844         ret = drmHashLookup(bufmgr_data->hashBos, key, (void **)&bo_data);
845         if (ret == 0) {
846                 if (error)
847                         *error = HAL_TBM_ERROR_NONE;
848                 return (hal_tbm_bo *)bo_data;
849         }
850
851         open_arg.name = key;
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);
854                 if (error)
855                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
856                 return NULL;
857         }
858
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",
862                                 open_arg.handle);
863                 close_arg.handle = open_arg.handle;
864                 drmIoctl(bufmgr_data->fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
865
866                 if (error)
867                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
868                 return NULL;
869         }
870
871         bo_data = calloc(1, sizeof(struct _tbm_dumb_bo));
872         if (!bo_data) {
873                 TBM_BACKEND_ERR("fail to allocate the bo_data private");
874                 if (error)
875                         *error = HAL_TBM_ERROR_OUT_OF_MEMORY;
876                 return NULL;
877         }
878
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;
885         bo_data->name = key;
886         bo_data->flags_tbm = _get_tbm_flag_from_dumb(bo_data->flags_dumb);
887
888         /* add bo to hash */
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);
891
892         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d flags:%d size:%d",
893                         bo_data,
894                         bo_data->gem,
895                         bo_data->name,
896                         bo_data->flags_tbm,
897                         bo_data->size);
898
899         if (error)
900                 *error = HAL_TBM_ERROR_NONE;
901
902         return (hal_tbm_bo *)bo_data;
903 }
904
905 static void
906 tbm_dumb_bo_free(hal_tbm_bo *bo)
907 {
908         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
909         tbm_dumb_bo *temp;
910         tbm_dumb_bufmgr *bufmgr_data;
911         struct drm_gem_close close_arg = {0, };
912         int ret;
913
914         if (!bo_data)
915                 return;
916
917         bufmgr_data = bo_data->bufmgr_data;
918         if (!bufmgr_data)
919                 return;
920
921         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d size:%d",
922                         bo_data,
923                         bo_data->gem,
924                         bo_data->name,
925                         bo_data->dmabuf,
926                         bo_data->size);
927
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)",
931                                         bo_data);
932                 }
933         }
934
935         /* close dmabuf */
936         if (bo_data->dmabuf >= 0) {
937                 close(bo_data->dmabuf);
938                 bo_data->dmabuf = -1;
939         }
940
941         /* delete bo from hash */
942         ret = drmHashLookup(bufmgr_data->hashBos, bo_data->name, (void**)&temp);
943         if (ret == 0)
944                 drmHashDelete(bufmgr_data->hashBos, bo_data->name);
945         else
946                 TBM_BACKEND_ERR("fail to find bo_data to Hash:%d, ret:%d", bo_data->name, ret);
947
948         if (temp != bo_data)
949                 TBM_BACKEND_ERR("hashBos probably has several BOs with same name!!!");
950
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);
956
957         free(bo_data);
958 }
959
960 static int
961 tbm_dumb_bo_get_size(hal_tbm_bo *bo, hal_tbm_error *error)
962 {
963         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
964
965         if (!bo_data) {
966                 if (error)
967                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
968                 return 0;
969         }
970
971         if (error)
972                 *error = HAL_TBM_ERROR_NONE;
973
974         return bo_data->size;
975 }
976
977 static hal_tbm_bo_memory_type
978 tbm_dumb_bo_get_memory_type(hal_tbm_bo *bo, hal_tbm_error *error)
979 {
980         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
981
982         if (!bo_data) {
983                 if (error)
984                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
985                 return HAL_TBM_BO_DEFAULT;
986         }
987
988         if (error)
989                 *error = HAL_TBM_ERROR_NONE;
990
991         return bo_data->flags_tbm;
992 }
993
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)
996 {
997         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
998         hal_tbm_bo_handle bo_handle;
999
1000         if (!bo_data) {
1001                 if (error)
1002                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1003                 return (hal_tbm_bo_handle) NULL;
1004         }
1005
1006         if (!bo_data->gem) {
1007                 TBM_BACKEND_ERR("invalid gem bo_data:%p", bo_data);
1008                 if (error)
1009                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1010                 return (hal_tbm_bo_handle) NULL;
1011         }
1012
1013         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d flags:%d size:%d %s",
1014                         bo_data,
1015                         bo_data->gem,
1016                         bo_data->name,
1017                         bo_data->dmabuf,
1018                         bo_data->flags_tbm,
1019                         bo_data->size,
1020                         STR_DEVICE[device]);
1021
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);
1027                 if (error)
1028                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
1029                 return (hal_tbm_bo_handle) NULL;
1030         }
1031
1032         if (error)
1033                 *error = HAL_TBM_ERROR_NONE;
1034
1035         return bo_handle;
1036 }
1037
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)
1041 {
1042         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1043         hal_tbm_bo_handle bo_handle;
1044         tbm_dumb_bufmgr *bufmgr_data;
1045
1046         if (!bo_data) {
1047                 if (error)
1048                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1049                 return (hal_tbm_bo_handle) NULL;
1050         }
1051
1052         bufmgr_data = bo_data->bufmgr_data;
1053         if (!bufmgr_data) {
1054                 if (error)
1055                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1056                 return (hal_tbm_bo_handle) NULL;
1057         }
1058
1059         if (!bo_data->gem) {
1060                 TBM_BACKEND_ERR("invalid gem bo_data:%p", bo_data);
1061                 if (error)
1062                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1063                 return (hal_tbm_bo_handle) NULL;
1064         }
1065
1066         TBM_BACKEND_DBG("bo_data:%p, gem:%d name:%d fd:%d %s %s",
1067                         bo_data,
1068                         bo_data->gem,
1069                         bo_data->name,
1070                         bo_data->dmabuf,
1071                         STR_DEVICE[device],
1072                         STR_OPT[opt]);
1073
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);
1079                 if (error)
1080                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1081                 return (hal_tbm_bo_handle) NULL;
1082         }
1083
1084 #ifdef HAVE_DMA_BUF
1085         struct dma_buf_sync sync = {0, };
1086
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;
1093
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)",
1096                                         bo_data);
1097                 }
1098         }
1099 #endif
1100
1101         bo_data->device = device;
1102         bo_data->opt = opt;
1103
1104         if (error)
1105                 *error = HAL_TBM_ERROR_NONE;
1106
1107         return bo_handle;
1108 }
1109
1110 static hal_tbm_error
1111 tbm_dumb_bo_unmap(hal_tbm_bo *bo)
1112 {
1113         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1114         tbm_dumb_bufmgr *bufmgr_data;
1115
1116         if (!bo_data)
1117                 return HAL_TBM_ERROR_INVALID_PARAMETER;
1118
1119         bufmgr_data = bo_data->bufmgr_data;
1120         if (!bufmgr_data)
1121                 return HAL_TBM_ERROR_INVALID_PARAMETER;
1122
1123         if (!bo_data->gem)
1124                 return HAL_TBM_ERROR_INVALID_PARAMETER;
1125
1126 #ifdef HAVE_DMA_BUF
1127         struct dma_buf_sync sync = {0, };
1128
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;
1135
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)",
1138                                         bo_data);
1139                 }
1140         }
1141 #endif
1142
1143         bo_data->device = 0;
1144         bo_data->opt = 0;
1145
1146         TBM_BACKEND_DBG("bo_data:%p, gem:%d name:%d fd:%d",
1147                         bo_data,
1148                         bo_data->gem,
1149                         bo_data->name,
1150                         bo_data->dmabuf);
1151
1152         return HAL_TBM_ERROR_NONE;
1153 }
1154
1155 hal_tbm_fd
1156 tbm_dumb_bo_export_fd(hal_tbm_bo *bo, hal_tbm_error *error)
1157 {
1158         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1159         struct drm_prime_handle prime_handle_arg = {0, };
1160         int ret;
1161
1162         if (!bo_data) {
1163                 if (error)
1164                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1165                 return -1;
1166         }
1167
1168         prime_handle_arg.handle = bo_data->gem;
1169         ret = drmIoctl(bo_data->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle_arg);
1170         if (ret) {
1171                 TBM_BACKEND_ERR("fail to DRM_IOCTL_PRIME_HANDLE_TO_FD bo_data:%p gem:%d (%m)",
1172                                 bo_data, bo_data->gem);
1173                 if (error)
1174                         *error = HAL_TBM_ERROR_INVALID_OPERATION;
1175                 return (hal_tbm_fd)ret;
1176         }
1177
1178         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d key_fd:%d flags:%d size:%d",
1179                         bo_data,
1180                         bo_data->gem,
1181                         bo_data->name,
1182                         bo_data->dmabuf,
1183                         prime_handle_arg.fd,
1184                         bo_data->flags_tbm,
1185                         bo_data->size);
1186
1187         if (error)
1188                 *error = HAL_TBM_ERROR_NONE;
1189
1190         return (hal_tbm_fd)prime_handle_arg.fd;
1191 }
1192
1193 static hal_tbm_key
1194 tbm_dumb_bo_export_key(hal_tbm_bo *bo, hal_tbm_error *error)
1195 {
1196         tbm_dumb_bo *bo_data = (tbm_dumb_bo *)bo;
1197
1198         if (!bo_data) {
1199                 if (error)
1200                         *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1201                 return 0;
1202         }
1203
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);
1208                         if (error)
1209                                 *error = HAL_TBM_ERROR_INVALID_PARAMETER;
1210                         return 0;
1211                 }
1212         }
1213
1214         TBM_BACKEND_DBG("bo_data:%p gem:%d name:%d fd:%d flags:%d size:%d",
1215                         bo_data,
1216                         bo_data->gem,
1217                         bo_data->name,
1218                         bo_data->dmabuf,
1219                         bo_data->flags_tbm,
1220                         bo_data->size);
1221
1222         if (error)
1223                 *error = HAL_TBM_ERROR_NONE;
1224
1225         return (hal_tbm_key)bo_data->name;
1226 }
1227
1228 static hal_tbm_error
1229 _tbm_dumb_authenticated_drm_fd_handler(hal_tbm_fd auth_fd, void *user_data)
1230 {
1231         tbm_dumb_bufmgr *bufmgr_data = (tbm_dumb_bufmgr *)user_data;
1232
1233         TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
1234
1235         bufmgr_data->fd = auth_fd;
1236         TBM_BACKEND_INFO("Get the authenticated drm_fd(%d)!", bufmgr_data->fd);
1237
1238         return HAL_TBM_ERROR_NONE;
1239 }
1240
1241 static int
1242 hal_backend_tbm_dumb_exit(void *data)
1243 {
1244         hal_tbm_backend_data *backend_data = (hal_tbm_backend_data *)data;
1245         tbm_dumb_bufmgr *bufmgr_data;
1246         unsigned long key;
1247         void *value;
1248
1249         TBM_BACKEND_RETURN_VAL_IF_FAIL(backend_data != NULL, -1);
1250
1251         bufmgr_data = (tbm_dumb_bufmgr *)backend_data->bufmgr;
1252         TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, -1);
1253
1254         if (backend_data->bufmgr_funcs)
1255                 free(backend_data->bufmgr_funcs);
1256         if (backend_data->bo_funcs)
1257                 free(backend_data->bo_funcs);
1258
1259         if (bufmgr_data->hashBos) {
1260                 while (drmHashFirst(bufmgr_data->hashBos, &key, &value) > 0) {
1261                         free(value);
1262                         drmHashDelete(bufmgr_data->hashBos, key);
1263                 }
1264
1265                 drmHashDestroy(bufmgr_data->hashBos);
1266                 bufmgr_data->hashBos = NULL;
1267         }
1268
1269         close(bufmgr_data->fd);
1270
1271         free(backend_data->bufmgr);
1272         free(backend_data);
1273
1274         return HAL_TBM_ERROR_NONE;
1275 }
1276
1277 static int
1278 hal_backend_tbm_dumb_init(void **data)
1279 {
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;
1284         int drm_fd = -1;
1285         uint64_t cap = 0;
1286         uint32_t ret;
1287
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!");
1292                 *data = NULL;
1293                 return -1;
1294         }
1295         *data = backend_data;
1296
1297         /* allocate a hal_tbm_bufmgr */
1298         bufmgr_data = calloc(1, sizeof(struct _tbm_dumb_bufmgr));
1299         if (!bufmgr_data) {
1300                 TBM_BACKEND_ERR("fail to alloc bufmgr_data!");
1301                 goto fail_alloc_bufmgr_data;
1302         }
1303         backend_data->bufmgr = (hal_tbm_bufmgr *)bufmgr_data;
1304
1305         // open drm_fd
1306         drm_fd = _tbm_dumb_open_drm();
1307         if (drm_fd < 0) {
1308                 TBM_BACKEND_ERR("fail to open drm!");
1309                 goto fail_open_drm;
1310         }
1311
1312         // set true when backend has a drm_device.
1313         backend_data->has_drm_device = 1;
1314
1315         ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap);
1316         if (ret || cap == 0) {
1317                 TBM_BACKEND_ERR("drm buffer isn't supported !");
1318                 goto fail_get_cap;
1319         }
1320
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;
1326
1327                 bufmgr_data->fd = drm_fd;
1328                 TBM_BACKEND_INFO("Get the master drm_fd(%d)!", bufmgr_data->fd);
1329         } else {
1330                 // drm_fd is not a master_drm_fd.
1331                 // request authenticated fd
1332                 close(drm_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;
1337
1338                 TBM_BACKEND_INFO("A backend requests an authenticated drm_fd.");
1339         }
1340
1341         /*Create Hash Table*/
1342         bufmgr_data->hashBos = drmHashCreate();
1343
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;
1349         }
1350         backend_data->bufmgr_funcs = bufmgr_funcs;
1351
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;
1359
1360         /* alloc and register bo_funcs */
1361         bo_funcs = calloc(1, sizeof(struct _hal_tbm_bo_funcs));
1362         if (!bo_funcs) {
1363                 TBM_BACKEND_ERR("fail to alloc bo_funcs!");
1364                 goto fail_alloc_bo_funcs;
1365         }
1366         backend_data->bo_funcs = bo_funcs;
1367
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;
1378
1379         TBM_BACKEND_DBG("drm_fd:%d", bufmgr_data->fd);
1380
1381         return HAL_TBM_ERROR_NONE;
1382
1383 fail_alloc_bo_funcs:
1384         free(bufmgr_funcs);
1385 fail_alloc_bufmgr_funcs:
1386         if (bufmgr_data->hashBos)
1387                 drmHashDestroy(bufmgr_data->hashBos);
1388 fail_get_cap:
1389         if (backend_data->drm_info.is_master)
1390                 close(bufmgr_data->fd);
1391         else
1392                 close(drm_fd);
1393 fail_open_drm:
1394         free(bufmgr_data);
1395 fail_alloc_bufmgr_data:
1396         free(backend_data);
1397
1398         *data = NULL;
1399
1400         return -1;
1401 }
1402
1403 hal_backend hal_backend_tbm_data = {
1404         "dumb",
1405         "Samsung",
1406         HAL_ABI_VERSION_TIZEN_6_5,
1407         hal_backend_tbm_dumb_init,
1408         hal_backend_tbm_dumb_exit
1409 };