fix the potential memory corruption
[platform/adaptation/libtbm-dumb.git] / src / tbm_bufmgr_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 <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <sys/ioctl.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 #include <sys/mman.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <xf86drm.h>
47 #include <tbm_bufmgr.h>
48 #include <tbm_bufmgr_backend.h>
49 #include <pthread.h>
50 #include <tbm_surface.h>
51 #include <tbm_surface_internal.h>
52 #include <libudev.h>
53 #include <tbm_drm_helper.h>
54
55 #define DEBUG
56 #define USE_DMAIMPORT
57 #define TBM_COLOR_FORMAT_COUNT 4
58
59 #ifdef DEBUG
60 #define LOG_TAG "TBM_BACKEND"
61 #include <dlog.h>
62 static int bDebug = 0;
63
64 static char *
65 target_name()
66 {
67         FILE *f;
68         char *slash;
69         static int       initialized = 0;
70         static char app_name[128];
71
72         if (initialized)
73                 return app_name;
74
75         /* get the application name */
76         f = fopen("/proc/self/cmdline", "r");
77         if (!f)
78                 return 0;
79
80         memset(app_name, 0x00, sizeof(app_name));
81
82         if (fgets(app_name, 100, f) == NULL) {
83                 fclose(f);
84                 return 0;
85         }
86
87         fclose(f);
88
89         if ((slash = strrchr(app_name, '/')) != NULL)
90                 memmove(app_name, slash+1, strlen(slash));
91
92         initialized = 1;
93
94         return app_name;
95 }
96
97 #define TBM_DUMB_LOG(fmt, args...) LOGE("\033[31m"  "[%s]" fmt "\033[0m", target_name(), ##args)
98 #define DBG(fmt, args...)  {if (bDebug&01) LOGE(fmt, ##args); }
99 #else
100 #define TBM_DUMB_LOG(...)
101 #define DBG(...)
102 #endif
103
104 #define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
105
106 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
107 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (128)
108 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
109
110 /* check condition */
111 #define DUMB_RETURN_IF_FAIL(cond) {\
112         if (!(cond)) {\
113                 TBM_DUMB_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
114                 return;\
115         } \
116 }
117 #define DUMB_RETURN_VAL_IF_FAIL(cond, val) {\
118         if (!(cond)) {\
119                 TBM_DUMB_LOG("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
120                 return val;\
121         } \
122 }
123
124 struct dma_buf_info {
125         unsigned long   size;
126         unsigned int    fence_supported;
127         unsigned int    padding;
128 };
129
130 #define DMA_BUF_ACCESS_READ      0x1
131 #define DMA_BUF_ACCESS_WRITE    0x2
132 #define DMA_BUF_ACCESS_DMA        0x4
133 #define DMA_BUF_ACCESS_MAX        0x8
134
135 #define DMA_FENCE_LIST_MAX        5
136
137 struct dma_buf_fence {
138         unsigned long      ctx;
139         unsigned int            type;
140 };
141
142 #define DMABUF_IOCTL_BASE       'F'
143 #define DMABUF_IOWR(nr, type)   _IOWR(DMABUF_IOCTL_BASE, nr, type)
144
145 #define DMABUF_IOCTL_GET_INFO   DMABUF_IOWR(0x00, struct dma_buf_info)
146 #define DMABUF_IOCTL_GET_FENCE  DMABUF_IOWR(0x01, struct dma_buf_fence)
147 #define DMABUF_IOCTL_PUT_FENCE  DMABUF_IOWR(0x02, struct dma_buf_fence)
148
149 typedef struct _tbm_bufmgr_dumb *tbm_bufmgr_dumb;
150 typedef struct _tbm_bo_dumb *tbm_bo_dumb;
151
152 /* tbm buffor object for dumb */
153 struct _tbm_bo_dumb {
154         int fd;
155
156         unsigned int name;      /* FLINK ID */
157
158         unsigned int gem;        /* GEM Handle */
159
160         unsigned int dmabuf;  /* fd for dmabuf */
161
162         void *pBase;              /* virtual address */
163
164         unsigned int size;
165
166         unsigned int flags_dumb;
167         unsigned int flags_tbm;
168
169         pthread_mutex_t mutex;
170         struct dma_buf_fence dma_fence[DMA_FENCE_LIST_MAX];
171         int device;
172         int opt;
173 };
174
175 /* tbm bufmgr private for dumb */
176 struct _tbm_bufmgr_dumb {
177         int fd;
178         void* hashBos;
179
180         int use_dma_fence;
181
182         char *device_name;
183         void *bind_display;
184 };
185
186 char *STR_DEVICE[] = {
187         "DEF",
188         "CPU",
189         "2D",
190         "3D",
191         "MM"
192 };
193
194 char *STR_OPT[] = {
195         "NONE",
196         "RD",
197         "WR",
198         "RDWR"
199 };
200
201
202 uint32_t tbm_dumb_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
203                                                                         TBM_FORMAT_ARGB8888,
204                                                                         TBM_FORMAT_XRGB8888,
205                                                                         TBM_FORMAT_NV12,
206                                                                         TBM_FORMAT_YUV420
207                                                                         };
208
209
210 static int
211 _tbm_dumb_open_drm()
212 {
213         struct udev *udev = NULL;
214         struct udev_enumerate *e = NULL;
215         struct udev_list_entry *entry = NULL;
216         struct udev_device *device = NULL, *drm_device = NULL, *pci = NULL;
217         const char *filepath, *id;
218         struct stat s;
219         int fd = -1;
220         int ret;
221
222         udev = udev_new();
223         if (!udev) {
224                 TBM_DUMB_LOG("udev_new() failed.\n");
225                 return -1;
226         }
227
228         e = udev_enumerate_new(udev);
229         udev_enumerate_add_match_subsystem(e, "drm");
230         udev_enumerate_add_match_sysname(e, "card[0-9]*");
231         udev_enumerate_scan_devices(e);
232
233         drm_device = NULL;
234         udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
235                 filepath = udev_list_entry_get_name(entry);
236                 device = udev_device_new_from_syspath(udev, filepath);
237                 if (!device)
238                         continue;
239
240                 pci = udev_device_get_parent_with_subsystem_devtype(device, "pci", NULL);
241                 if (pci) {
242                         id = udev_device_get_sysattr_value(pci, "boot_vga");
243                         if (id && !strcmp(id, "1")) {
244                                 if (drm_device)
245                                 udev_device_unref(drm_device);
246                                 drm_device = device;
247                                 break;
248                         }
249                 }
250
251                 if (!drm_device)
252                         drm_device = device;
253                 else
254                         udev_device_unref(device);
255         }
256
257         udev_enumerate_unref(e);
258
259         /* Get device file path. */
260         filepath = udev_device_get_devnode(drm_device);
261         if (!filepath) {
262                 TBM_DUMB_LOG("udev_device_get_devnode() failed.\n");
263                 udev_device_unref(drm_device);
264                 udev_unref(udev);
265                 return -1;
266         }
267
268         /* Open DRM device file and check validity. */
269         fd = open(filepath, O_RDWR | O_CLOEXEC);
270         if (fd < 0) {
271                 TBM_DUMB_LOG("open(%s, O_RDWR | O_CLOEXEC) failed.\n");
272                 udev_device_unref(drm_device);
273                 udev_unref(udev);
274                 return -1;
275         }
276
277         ret = fstat(fd, &s);
278         if (ret) {
279                 TBM_DUMB_LOG("fstat() failed %s.\n");
280                 close(fd);
281                 udev_device_unref(drm_device);
282                 udev_unref(udev);
283                 return -1;
284         }
285
286         udev_device_unref(drm_device);
287         udev_unref(udev);
288
289         return fd;
290 }
291
292 static unsigned int
293 _get_dumb_flag_from_tbm(unsigned int ftbm)
294 {
295         unsigned int flags = 0;
296         return flags;
297 }
298
299 static unsigned int
300 _get_tbm_flag_from_dumb(unsigned int fdumb)
301 {
302         unsigned int flags = 0;
303
304         flags |= TBM_BO_SCANOUT;
305         flags |= TBM_BO_NONCACHABLE;
306
307         return flags;
308 }
309
310 static unsigned int
311 _get_name(int fd, unsigned int gem)
312 {
313         struct drm_gem_flink arg = {0,};
314
315         arg.handle = gem;
316         if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
317                 TBM_DUMB_LOG("error fail to get flink from gem:%d (DRM_IOCTL_GEM_FLINK)\n",
318                                 gem);
319                 return 0;
320         }
321
322         return (unsigned int)arg.name;
323 }
324
325 static tbm_bo_handle
326 _dumb_bo_handle(tbm_bo_dumb bo_dumb, int device)
327 {
328         tbm_bo_handle bo_handle;
329         memset(&bo_handle, 0x0, sizeof(uint64_t));
330
331         switch (device) {
332         case TBM_DEVICE_DEFAULT:
333         case TBM_DEVICE_2D:
334                 bo_handle.u32 = (uint32_t)bo_dumb->gem;
335                 break;
336         case TBM_DEVICE_CPU:
337                 if (!bo_dumb->pBase) {
338                         struct drm_mode_map_dumb arg = {0,};
339                         void *map = NULL;
340
341                         arg.handle = bo_dumb->gem;
342                         if (drmIoctl(bo_dumb->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg)) {
343                            TBM_DUMB_LOG("error Cannot map_ gem=%d\n", bo_dumb->gem);
344                            return (tbm_bo_handle) NULL;
345                         }
346
347                         map = mmap(NULL, bo_dumb->size, PROT_READ|PROT_WRITE, MAP_SHARED,
348                                                           bo_dumb->fd, arg.offset);
349                         if (map == MAP_FAILED) {
350                                 TBM_DUMB_LOG("error Cannot usrptr gem=%d\n", bo_dumb->gem);
351                                 return (tbm_bo_handle) NULL;
352                         }
353                         bo_dumb->pBase = map;
354                 }
355                 bo_handle.ptr = (void *)bo_dumb->pBase;
356                 break;
357         case TBM_DEVICE_3D:
358 #ifdef USE_DMAIMPORT
359                 if (!bo_dumb->dmabuf) {
360                         struct drm_prime_handle arg = {0, };
361
362                         arg.handle = bo_dumb->gem;
363                         if (drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
364                                 TBM_DUMB_LOG("error Cannot dmabuf=%d\n", bo_dumb->gem);
365                                 return (tbm_bo_handle) NULL;
366                         }
367                         bo_dumb->dmabuf = arg.fd;
368                 }
369
370                 bo_handle.u32 = (uint32_t)bo_dumb->dmabuf;
371 #endif
372                 break;
373         case TBM_DEVICE_MM:
374                 if (!bo_dumb->dmabuf) {
375                         struct drm_prime_handle arg = {0, };
376
377                         arg.handle = bo_dumb->gem;
378                         if (drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
379                                 TBM_DUMB_LOG("error Cannot dmabuf=%d\n", bo_dumb->gem);
380                                 return (tbm_bo_handle) NULL;
381                         }
382                         bo_dumb->dmabuf = arg.fd;
383                 }
384
385                 bo_handle.u32 = (uint32_t)bo_dumb->dmabuf;
386                 break;
387         default:
388                 TBM_DUMB_LOG("error Not supported device:%d\n", device);
389                 bo_handle.ptr = (void *) NULL;
390                 break;
391         }
392
393         return bo_handle;
394 }
395
396 #ifdef USE_CACHE
397 static int
398 _dumb_cache_flush(int fd, tbm_bo_dumb bo_dumb, int flags)
399 {
400         TBM_DUMB_LOG("warning fail to flush the cache.\n");
401         return 1;
402 }
403 #endif
404
405 static int
406 tbm_dumb_bo_size(tbm_bo bo)
407 {
408         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
409
410         tbm_bo_dumb bo_dumb;
411
412         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
413
414         return bo_dumb->size;
415 }
416
417 static void *
418 tbm_dumb_bo_alloc(tbm_bo bo, int size, int flags)
419 {
420         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
421
422         tbm_bo_dumb bo_dumb;
423         tbm_bufmgr_dumb bufmgr_dumb;
424         unsigned int dumb_flags;
425
426         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
427         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
428
429         bo_dumb = calloc(1, sizeof(struct _tbm_bo_dumb));
430         if (!bo_dumb) {
431                 TBM_DUMB_LOG("error fail to allocate the bo private\n");
432                 return 0;
433         }
434
435         dumb_flags = _get_dumb_flag_from_tbm(flags);
436
437         struct drm_mode_create_dumb arg = {0, };
438         //as we know only size for new bo set height=1 and bpp=8 and in this case
439         //width will by equal to size in bytes;
440         arg.height = 1;
441         arg.bpp = 8;
442         arg.width = size;
443         arg.flags = dumb_flags;
444         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg)) {
445                 TBM_DUMB_LOG("error Cannot create bo(flag:%x, size:%d)\n", arg.flags, (unsigned int)size);
446                 free(bo_dumb);
447                 return 0;
448         }
449
450         bo_dumb->fd = bufmgr_dumb->fd;
451         bo_dumb->gem = arg.handle;
452         bo_dumb->size = arg.size;
453         bo_dumb->flags_tbm = flags;
454         bo_dumb->flags_dumb = dumb_flags;
455         bo_dumb->name = _get_name(bo_dumb->fd, bo_dumb->gem);
456
457         pthread_mutex_init(&bo_dumb->mutex, NULL);
458
459         if (bufmgr_dumb->use_dma_fence
460                 && !bo_dumb->dmabuf) {
461                 struct drm_prime_handle arg = {0, };
462
463                 arg.handle = bo_dumb->gem;
464                 if (drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
465                         TBM_DUMB_LOG("error Cannot dmabuf=%d\n", bo_dumb->gem);
466                         free(bo_dumb);
467                         return 0;
468                 }
469                 bo_dumb->dmabuf = arg.fd;
470         }
471
472         /* add bo to hash */
473         if (drmHashInsert(bufmgr_dumb->hashBos, bo_dumb->name, (void *)bo_dumb) < 0)
474                 TBM_DUMB_LOG("error Cannot insert bo to Hash(%d)\n", bo_dumb->name);
475
476         DBG("    [%s] bo:%p, gem:%d(%d), flags:%d(%d), size:%d\n", target_name(),
477                  bo,
478                  bo_dumb->gem, bo_dumb->name,
479                  flags, dumb_flags,
480                  bo_dumb->size);
481
482         return (void *)bo_dumb;
483 }
484
485 static void
486 tbm_dumb_bo_free(tbm_bo bo)
487 {
488         tbm_bo_dumb bo_dumb, temp;
489         tbm_bufmgr_dumb bufmgr_dumb;
490
491         if (!bo)
492                 return;
493
494         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
495         DUMB_RETURN_IF_FAIL(bufmgr_dumb != NULL);
496
497         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
498         DUMB_RETURN_IF_FAIL(bo_dumb != NULL);
499
500         DBG("     [%s] bo:%p, gem:%d(%d), fd:%d, size:%d\n", target_name(),
501                  bo,
502                  bo_dumb->gem, bo_dumb->name,
503                  bo_dumb->dmabuf,
504                  bo_dumb->size);
505
506         if (bo_dumb->pBase) {
507                 if (munmap(bo_dumb->pBase, bo_dumb->size) == -1) {
508                         TBM_DUMB_LOG("error bo:%p fail to munmap(%s)\n",
509                                 bo, strerror(errno));
510                 }
511         }
512
513         /* close dmabuf */
514         if (bo_dumb->dmabuf) {
515                 close(bo_dumb->dmabuf);
516                 bo_dumb->dmabuf = 0;
517         }
518
519         /* delete bo from hash */
520         int ret;
521
522         ret = drmHashLookup(bufmgr_dumb->hashBos, bo_dumb->name, (void**)&temp);
523         if (ret == 0)
524                 drmHashDelete(bufmgr_dumb->hashBos, bo_dumb->name);
525         else
526                 TBM_DUMB_LOG("warning Cannot find bo to Hash(%d), ret =%d\n", bo_dumb->name, ret);
527
528         if (temp != bo_dumb)
529                 TBM_DUMB_LOG("hashBos probably has several BOs with same name!!!\n");
530
531         /* Free gem handle */
532         struct drm_gem_close arg = {0, };
533         memset(&arg, 0, sizeof(arg));
534         arg.handle = bo_dumb->gem;
535         if (drmIoctl(bo_dumb->fd, DRM_IOCTL_GEM_CLOSE, &arg)) {
536                 TBM_DUMB_LOG("error bo:%p fail to gem close.(%s)\n",
537                         bo, strerror(errno));
538         }
539
540         free(bo_dumb);
541 }
542
543
544 static void *
545 tbm_dumb_bo_import(tbm_bo bo, unsigned int key)
546 {
547         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
548
549         tbm_bufmgr_dumb bufmgr_dumb;
550         tbm_bo_dumb bo_dumb;
551         int ret;
552
553         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
554         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
555
556         ret = drmHashLookup(bufmgr_dumb->hashBos, key, (void **)&bo_dumb);
557         if (ret == 0)
558                 return bo_dumb;
559
560         struct drm_gem_open arg = {0, };
561
562         arg.name = key;
563         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_GEM_OPEN, &arg)) {
564                 TBM_DUMB_LOG("error Cannot open gem name=%d\n", key);
565                 return 0;
566         }
567
568         bo_dumb = calloc(1, sizeof(struct _tbm_bo_dumb));
569         if (!bo_dumb) {
570                 TBM_DUMB_LOG("error fail to allocate the bo private\n");
571                 return 0;
572         }
573
574         bo_dumb->fd = bufmgr_dumb->fd;
575         bo_dumb->gem = arg.handle;
576         bo_dumb->size = arg.size;
577         bo_dumb->flags_dumb = 0;
578         bo_dumb->name = key;
579         bo_dumb->flags_tbm = _get_tbm_flag_from_dumb(bo_dumb->flags_dumb);
580
581         if (!bo_dumb->dmabuf) {
582                 struct drm_prime_handle arg = {0, };
583
584                 arg.handle = bo_dumb->gem;
585                 if (drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
586                         TBM_DUMB_LOG("error Cannot dmabuf=%d\n", bo_dumb->gem);
587                         free(bo_dumb);
588                         return 0;
589                 }
590                 bo_dumb->dmabuf = arg.fd;
591         }
592
593         /* add bo to hash */
594         if (drmHashInsert(bufmgr_dumb->hashBos, bo_dumb->name, (void *)bo_dumb) < 0)
595                 TBM_DUMB_LOG("error Cannot insert bo to Hash(%d)\n", bo_dumb->name);
596
597         DBG("   [%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n", target_name(),
598                  bo,
599                  bo_dumb->gem, bo_dumb->name,
600                  bo_dumb->dmabuf,
601                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
602                  bo_dumb->size);
603
604         return (void *)bo_dumb;
605 }
606
607 static void *
608 tbm_dumb_bo_import_fd(tbm_bo bo, tbm_fd key)
609 {
610         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
611
612         tbm_bufmgr_dumb bufmgr_dumb;
613         tbm_bo_dumb bo_dumb;
614
615         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
616         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
617
618         int ret;
619
620         unsigned int gem = 0;
621         unsigned int name = 0;
622         unsigned int real_size = -1;
623
624         //getting handle from fd
625         struct drm_prime_handle arg = {0, };
626         struct drm_gem_open gem_open = {0, };
627
628         arg.fd = key;
629         arg.flags = 0;
630         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
631                 TBM_DUMB_LOG("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
632                                  bo, arg.fd, strerror(errno));
633                 return NULL;
634         }
635         gem = arg.handle;
636
637         /* Determine size of bo.  The fd-to-handle ioctl really should
638          * return the size, but it doesn't.  If we have kernel 3.12 or
639          * later, we can lseek on the prime fd to get the size.  Older
640          * kernels will just fail, in which case we fall back to the
641          * provided (estimated or guess size). */
642         real_size = lseek(key, 0, SEEK_END);
643
644         name = _get_name(bufmgr_dumb->fd, gem);
645         if (name == 0) {
646                 TBM_DUMB_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
647                         bo, gem, key, strerror(errno));
648                 return 0;
649         }
650
651         ret = drmHashLookup(bufmgr_dumb->hashBos, name, (void **)&bo_dumb);
652         if (ret == 0) {
653                 if (gem == bo_dumb->gem)
654                         return bo_dumb;
655         }
656
657         /* Open the same GEM object only for finding out its size */
658         gem_open.name = name;
659         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_GEM_OPEN, &gem_open)) {
660                 TBM_DUMB_LOG("error Cannot open gem name=%d\n", key);
661                 return 0;
662         }
663         /* Free gem handle to avoid a memory leak*/
664         struct drm_gem_close gem_close;
665         gem_close.handle = gem_open.handle;
666         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_GEM_CLOSE, &gem_close)) {
667                 TBM_DUMB_LOG("error bo:%p fail to gem close.(%s)\n",
668                         bo, strerror(errno));
669         }
670
671         if (real_size == -1)
672                 real_size = gem_open.size;
673
674         bo_dumb = calloc(1, sizeof(struct _tbm_bo_dumb));
675         if (!bo_dumb) {
676                 TBM_DUMB_LOG("error bo:%p fail to allocate the bo private\n", bo);
677                 return 0;
678         }
679
680         bo_dumb->fd = bufmgr_dumb->fd;
681         bo_dumb->gem = gem;
682         bo_dumb->dmabuf = 0;
683         bo_dumb->size = real_size;
684         bo_dumb->flags_dumb = 0;
685         bo_dumb->flags_tbm = _get_tbm_flag_from_dumb(bo_dumb->flags_dumb);
686         bo_dumb->name = name;
687
688         /* add bo to hash */
689         if (drmHashInsert(bufmgr_dumb->hashBos, bo_dumb->name, (void *)bo_dumb) < 0)
690                 TBM_DUMB_LOG("error Cannot insert bo to Hash(%d)\n", bo_dumb->name);
691
692         DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
693                  bo,
694                  bo_dumb->gem, bo_dumb->name,
695                  bo_dumb->dmabuf,
696                  key,
697                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
698                  bo_dumb->size);
699
700         return (void *)bo_dumb;
701 }
702
703 static unsigned int
704 tbm_dumb_bo_export(tbm_bo bo)
705 {
706         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
707
708         tbm_bo_dumb bo_dumb;
709
710         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
711         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
712
713         if (!bo_dumb->name) {
714                 bo_dumb->name = _get_name(bo_dumb->fd, bo_dumb->gem);
715                 if (!bo_dumb->name) {
716                         TBM_DUMB_LOG("error Cannot get name\n");
717                         return 0;
718                 }
719         }
720
721         DBG("   [%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n", target_name(),
722                  bo,
723                  bo_dumb->gem, bo_dumb->name,
724                  bo_dumb->dmabuf,
725                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
726                  bo_dumb->size);
727
728         return (unsigned int)bo_dumb->name;
729 }
730
731 tbm_fd
732 tbm_dumb_bo_export_fd(tbm_bo bo)
733 {
734         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, -1);
735
736         tbm_bo_dumb bo_dumb;
737         int ret;
738
739         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
740         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, -1);
741
742         struct drm_prime_handle arg = {0, };
743
744         arg.handle = bo_dumb->gem;
745         ret = drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
746         if (ret) {
747                 TBM_DUMB_LOG("error bo:%p Cannot dmabuf=%d (%s)\n",
748                         bo, bo_dumb->gem, strerror(errno));
749                 return (tbm_fd) ret;
750         }
751
752         DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
753                  bo,
754                  bo_dumb->gem, bo_dumb->name,
755                  bo_dumb->dmabuf,
756                  arg.fd,
757                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
758                  bo_dumb->size);
759
760         return (tbm_fd)arg.fd;
761 }
762
763 static tbm_bo_handle
764 tbm_dumb_bo_get_handle(tbm_bo bo, int device)
765 {
766         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
767
768         tbm_bo_handle bo_handle;
769         tbm_bo_dumb bo_dumb;
770
771         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
772         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, (tbm_bo_handle) NULL);
773
774         if (!bo_dumb->gem) {
775                 TBM_DUMB_LOG("error Cannot map gem=%d\n", bo_dumb->gem);
776                 return (tbm_bo_handle) NULL;
777         }
778
779         DBG("[%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d, %s\n", target_name(),
780                  bo,
781                  bo_dumb->gem, bo_dumb->name,
782                  bo_dumb->dmabuf,
783                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
784                  bo_dumb->size,
785                  STR_DEVICE[device]);
786
787         /*Get mapped bo_handle*/
788         bo_handle = _dumb_bo_handle(bo_dumb, device);
789         if (bo_handle.ptr == NULL) {
790                 TBM_DUMB_LOG("error Cannot get handle: gem:%d, device:%d\n", bo_dumb->gem, device);
791                 return (tbm_bo_handle) NULL;
792         }
793
794         return bo_handle;
795 }
796
797 static tbm_bo_handle
798 tbm_dumb_bo_map(tbm_bo bo, int device, int opt)
799 {
800         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
801
802         tbm_bo_handle bo_handle;
803         tbm_bo_dumb bo_dumb;
804
805         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
806         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, (tbm_bo_handle) NULL);
807
808         if (!bo_dumb->gem) {
809                 TBM_DUMB_LOG("error Cannot map gem=%d\n", bo_dumb->gem);
810                 return (tbm_bo_handle) NULL;
811         }
812
813         DBG("      [%s] bo:%p, gem:%d(%d), fd:%d, %s, %s\n", target_name(),
814                  bo,
815                  bo_dumb->gem, bo_dumb->name,
816                  bo_dumb->dmabuf,
817                  STR_DEVICE[device],
818                  STR_OPT[opt]);
819
820         /*Get mapped bo_handle*/
821         bo_handle = _dumb_bo_handle(bo_dumb, device);
822         if (bo_handle.ptr == NULL) {
823                 TBM_DUMB_LOG("error Cannot get handle: gem:%d, device:%d, opt:%d\n", bo_dumb->gem, device, opt);
824                 return (tbm_bo_handle) NULL;
825         }
826
827         return bo_handle;
828 }
829
830 static int
831 tbm_dumb_bo_unmap(tbm_bo bo)
832 {
833         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
834
835         tbm_bo_dumb bo_dumb;
836
837         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
838         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
839
840         if (!bo_dumb->gem)
841                 return 0;
842
843         DBG("    [%s] bo:%p, gem:%d(%d), fd:%d\n", target_name(),
844                   bo,
845                   bo_dumb->gem, bo_dumb->name,
846                   bo_dumb->dmabuf);
847
848         return 1;
849 }
850
851 static int
852 tbm_dumb_bo_lock(tbm_bo bo, int device, int opt)
853 {
854         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
855
856 #if USE_BACKEND_LOCK
857         tbm_bufmgr_dumb bufmgr_dumb;
858         tbm_bo_dumb bo_dumb;
859         struct dma_buf_fence fence;
860         struct flock filelock;
861         int ret = 0;
862
863         if (device != TBM_DEVICE_3D && device != TBM_DEVICE_CPU) {
864                 DBG("[libtbm-dumb:%d] %s not support device type,\n", getpid(), __FUNCTION__);
865                 return 0;
866         }
867
868         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
869         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
870
871         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
872         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
873
874         if (!bufmgr_dumb->use_dma_fence)
875            return 1;
876
877         memset(&fence, 0, sizeof(struct dma_buf_fence));
878
879         /* Check if the given type is valid or not. */
880         if (opt & TBM_OPTION_WRITE)     {
881                 if (device == TBM_DEVICE_3D)
882                         fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
883         } else if (opt & TBM_OPTION_READ)       {
884                 if (device == TBM_DEVICE_3D)
885                         fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
886         } else {
887                 TBM_DUMB_LOG("error Invalid argument\n");
888                 return 0;
889         }
890
891         /* Check if the tbm manager supports dma fence or not. */
892         if (!bufmgr_dumb->use_dma_fence) {
893                 TBM_DUMB_LOG("error Not support DMA FENCE(%s)\n", strerror(errno));
894                 return 0;
895         }
896
897         if (device == TBM_DEVICE_3D) {
898                 ret = ioctl(bo_dumb->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
899                 if (ret < 0) {
900                         TBM_DUMB_LOG("error Cannot set GET FENCE(%s)\n", strerror(errno));
901                         return 0;
902                 }
903         } else {
904                 if (opt & TBM_OPTION_WRITE)
905                         filelock.l_type = F_WRLCK;
906                 else
907                         filelock.l_type = F_RDLCK;
908
909                 filelock.l_whence = SEEK_CUR;
910                 filelock.l_start = 0;
911                 filelock.l_len = 0;
912
913                 if (-1 == fcntl(bo_dumb->dmabuf, F_SETLKW, &filelock))
914                         return 0;
915         }
916
917         pthread_mutex_lock(&bo_dumb->mutex);
918
919         if (device == TBM_DEVICE_3D) {
920                 int i;
921                 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
922                         if (bo_dumb->dma_fence[i].ctx == 0) {
923                                 bo_dumb->dma_fence[i].type = fence.type;
924                                 bo_dumb->dma_fence[i].ctx = fence.ctx;
925                                 break;
926                         }
927                 }
928
929                 if (i == DMA_FENCE_LIST_MAX) {
930                         //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
931                         TBM_DUMB_LOG("error fence list is full\n");
932                 }
933         }
934
935         pthread_mutex_unlock(&bo_dumb->mutex);
936
937         DBG("[%s] DMABUF_IOCTL_GET_FENCE! bo:%p, gem:%d(%d), fd:%ds\n", target_name(),
938                   bo,
939                   bo_dumb->gem, bo_dumb->name,
940                   bo_dumb->dmabuf);
941
942 #endif
943         return 1;
944 }
945
946 static int
947 tbm_dumb_bo_unlock(tbm_bo bo)
948 {
949         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
950
951 #if USE_BACKEND_LOCK
952         tbm_bo_dumb bo_dumb;
953         struct dma_buf_fence fence;
954         struct flock filelock;
955         unsigned int dma_type = 0;
956         int ret = 0;
957
958         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
959         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
960
961         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
962         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
963
964         if (!bufmgr_dumb->use_dma_fence)
965            return 1;
966
967         if (bo_dumb->dma_fence[0].type & DMA_BUF_ACCESS_DMA)
968                 dma_type = 1;
969
970         if (!bo_dumb->dma_fence[0].ctx && dma_type) {
971                 DBG("error FENCE not support or ignored,\n");
972                 return 0;
973         }
974
975         if (!bo_dumb->dma_fence[0].ctx && dma_type) {
976                 DBG("error device type is not 3D/CPU,\n");
977                 return 0;
978         }
979
980         pthread_mutex_lock(&bo_dumb->mutex);
981
982         if (dma_type) {
983                 fence.type = bo_dumb->dma_fence[0].type;
984                 fence.ctx = bo_dumb->dma_fence[0].ctx;
985                 int i;
986                 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
987                         bo_dumb->dma_fence[i-1].type = bo_dumb->dma_fence[i].type;
988                         bo_dumb->dma_fence[i-1].ctx = bo_dumb->dma_fence[i].ctx;
989                 }
990                 bo_dumb->dma_fence[DMA_FENCE_LIST_MAX-1].type = 0;
991                 bo_dumb->dma_fence[DMA_FENCE_LIST_MAX-1].ctx = 0;
992         }
993         pthread_mutex_unlock(&bo_dumb->mutex);
994
995         if (dma_type) {
996                 ret = ioctl(bo_dumb->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
997                 if (ret < 0) {
998                         TBM_DUMB_LOG("error Can not set PUT FENCE(%s)\n", strerror(errno));
999                         return 0;
1000                 }
1001         } else {
1002                 filelock.l_type = F_UNLCK;
1003                 filelock.l_whence = SEEK_CUR;
1004                 filelock.l_start = 0;
1005                 filelock.l_len = 0;
1006
1007                 if (-1 == fcntl(bo_dumb->dmabuf, F_SETLKW, &filelock))
1008                         return 0;
1009         }
1010
1011         DBG("[%s] DMABUF_IOCTL_PUT_FENCE! bo:%p, gem:%d(%d), fd:%ds\n", target_name(),
1012                   bo,
1013                   bo_dumb->gem, bo_dumb->name,
1014                   bo_dumb->dmabuf);
1015
1016 #endif
1017         return 1;
1018 }
1019
1020 static void
1021 tbm_dumb_bufmgr_deinit(void *priv)
1022 {
1023         DUMB_RETURN_IF_FAIL(priv != NULL);
1024
1025         tbm_bufmgr_dumb bufmgr_dumb;
1026
1027         bufmgr_dumb = (tbm_bufmgr_dumb)priv;
1028
1029         if (bufmgr_dumb->hashBos) {
1030                 unsigned long key;
1031                 void *value;
1032
1033                 while (drmHashFirst(bufmgr_dumb->hashBos, &key, &value) > 0) {
1034                         free(value);
1035                         drmHashDelete(bufmgr_dumb->hashBos, key);
1036                 }
1037
1038                 drmHashDestroy(bufmgr_dumb->hashBos);
1039                 bufmgr_dumb->hashBos = NULL;
1040         }
1041
1042         if (bufmgr_dumb->bind_display)
1043                 tbm_drm_helper_wl_auth_server_deinit();
1044
1045         if (bufmgr_dumb->device_name)
1046                 free(bufmgr_dumb->device_name);
1047
1048         if (tbm_backend_is_display_server())
1049                 tbm_drm_helper_unset_tbm_master_fd();
1050
1051         close(bufmgr_dumb->fd);
1052
1053         free(bufmgr_dumb);
1054 }
1055
1056 int
1057 tbm_dumb_surface_supported_format(uint32_t **formats, uint32_t *num)
1058 {
1059         uint32_t* color_formats = NULL;
1060
1061         color_formats = (uint32_t*)calloc(1, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1062
1063         if (color_formats == NULL)
1064                 return 0;
1065
1066         memcpy(color_formats, tbm_dumb_color_format_list , sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1067
1068         *formats = color_formats;
1069         *num = TBM_COLOR_FORMAT_COUNT;
1070
1071         return 1;
1072 }
1073
1074
1075 /**
1076  * @brief get the plane data of the surface.
1077  * @param[in] width : the width of the surface
1078  * @param[in] height : the height of the surface
1079  * @param[in] format : the format of the surface
1080  * @param[in] plane_idx : the format of the surface
1081  * @param[out] size : the size of the plane
1082  * @param[out] offset : the offset of the plane
1083  * @param[out] pitch : the pitch of the plane
1084  * @param[out] padding : the padding of the plane
1085  * @return 1 if this function succeeds, otherwise 0.
1086  */
1087 int
1088 tbm_dumb_surface_get_plane_data(int width, int height,  tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
1089 {
1090         int ret = 1;
1091         int bpp;
1092         int _offset = 0;
1093         int _pitch = 0;
1094         int _size = 0;
1095         int _bo_idx = 0;
1096
1097         switch (format) {
1098         /* 16 bpp RGB */
1099         case TBM_FORMAT_XRGB4444:
1100         case TBM_FORMAT_XBGR4444:
1101         case TBM_FORMAT_RGBX4444:
1102         case TBM_FORMAT_BGRX4444:
1103         case TBM_FORMAT_ARGB4444:
1104         case TBM_FORMAT_ABGR4444:
1105         case TBM_FORMAT_RGBA4444:
1106         case TBM_FORMAT_BGRA4444:
1107         case TBM_FORMAT_XRGB1555:
1108         case TBM_FORMAT_XBGR1555:
1109         case TBM_FORMAT_RGBX5551:
1110         case TBM_FORMAT_BGRX5551:
1111         case TBM_FORMAT_ARGB1555:
1112         case TBM_FORMAT_ABGR1555:
1113         case TBM_FORMAT_RGBA5551:
1114         case TBM_FORMAT_BGRA5551:
1115         case TBM_FORMAT_RGB565:
1116                 bpp = 16;
1117                 _offset = 0;
1118                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1119                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1120                 _bo_idx = 0;
1121                 break;
1122         /* 24 bpp RGB */
1123         case TBM_FORMAT_RGB888:
1124         case TBM_FORMAT_BGR888:
1125                 bpp = 24;
1126                 _offset = 0;
1127                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1128                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1129                 _bo_idx = 0;
1130                 break;
1131         /* 32 bpp RGB */
1132         case TBM_FORMAT_XRGB8888:
1133         case TBM_FORMAT_XBGR8888:
1134         case TBM_FORMAT_RGBX8888:
1135         case TBM_FORMAT_BGRX8888:
1136         case TBM_FORMAT_ARGB8888:
1137         case TBM_FORMAT_ABGR8888:
1138         case TBM_FORMAT_RGBA8888:
1139         case TBM_FORMAT_BGRA8888:
1140                 bpp = 32;
1141                 _offset = 0;
1142                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1143                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1144                 _bo_idx = 0;
1145                 break;
1146
1147         /* packed YCbCr */
1148         case TBM_FORMAT_YUYV:
1149         case TBM_FORMAT_YVYU:
1150         case TBM_FORMAT_UYVY:
1151         case TBM_FORMAT_VYUY:
1152         case TBM_FORMAT_AYUV:
1153                 bpp = 32;
1154                 _offset = 0;
1155                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1156                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1157                 _bo_idx = 0;
1158                 break;
1159
1160         /*
1161         * 2 plane YCbCr
1162         * index 0 = Y plane, [7:0] Y
1163         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1164         * or
1165         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1166         */
1167         case TBM_FORMAT_NV12:
1168         case TBM_FORMAT_NV21:
1169                 bpp = 12;
1170                 if (plane_idx == 0) {
1171                         _offset = 0;
1172                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1173                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1174                         _bo_idx = 0;
1175                 } else if (plane_idx == 1) {
1176                         _offset = width*height;
1177                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1178                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1179                         _bo_idx = 0;
1180                 }
1181                 break;
1182
1183         case TBM_FORMAT_NV16:
1184         case TBM_FORMAT_NV61:
1185                 bpp = 16;
1186                 //if (plane_idx == 0)
1187                 {
1188                         _offset = 0;
1189                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1190                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1191                         _bo_idx = 0;
1192                         if (plane_idx == 0)
1193                                 break;
1194                 }
1195                 //else if (plane_idx == 1)
1196                 {
1197                         _offset += _size;
1198                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1199                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1200                         _bo_idx = 0;
1201                 }
1202                 break;
1203
1204         /*
1205         * 3 plane YCbCr
1206         * index 0: Y plane, [7:0] Y
1207         * index 1: Cb plane, [7:0] Cb
1208         * index 2: Cr plane, [7:0] Cr
1209         * or
1210         * index 1: Cr plane, [7:0] Cr
1211         * index 2: Cb plane, [7:0] Cb
1212         */
1213         /*
1214         NATIVE_BUFFER_FORMAT_YV12
1215         NATIVE_BUFFER_FORMAT_I420
1216         */
1217         case TBM_FORMAT_YUV410:
1218         case TBM_FORMAT_YVU410:
1219                 bpp = 9;
1220                 break;
1221         case TBM_FORMAT_YUV411:
1222         case TBM_FORMAT_YVU411:
1223         case TBM_FORMAT_YUV420:
1224         case TBM_FORMAT_YVU420:
1225                 bpp = 12;
1226                 //if (plane_idx == 0)
1227                 {
1228                         _offset = 0;
1229                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1230                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1231                         _bo_idx = 0;
1232                         if (plane_idx == 0)
1233                                 break;
1234                 }
1235                 //else if (plane_idx == 1)
1236                 {
1237                         _offset += _size;
1238                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1239                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1240                         _bo_idx = 0;
1241                         if (plane_idx == 1)
1242                                 break;
1243                 }
1244                 //else if (plane_idx == 2)
1245                 {
1246                         _offset += _size;
1247                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1248                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1249                         _bo_idx = 0;
1250                 }
1251                 break;
1252         case TBM_FORMAT_YUV422:
1253         case TBM_FORMAT_YVU422:
1254                 bpp = 16;
1255                 //if (plane_idx == 0)
1256                 {
1257                         _offset = 0;
1258                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1259                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1260                         _bo_idx = 0;
1261                         if (plane_idx == 0)
1262                                 break;
1263                 }
1264                 //else if (plane_idx == 1)
1265                 {
1266                         _offset += _size;
1267                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1268                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1269                         _bo_idx = 0;
1270                         if (plane_idx == 1)
1271                                 break;
1272                 }
1273                 //else if (plane_idx == 2)
1274                 {
1275                         _offset += _size;
1276                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1277                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1278                         _bo_idx = 0;
1279                 }
1280                 break;
1281         case TBM_FORMAT_YUV444:
1282         case TBM_FORMAT_YVU444:
1283                 bpp = 24;
1284                 //if (plane_idx == 0)
1285                 {
1286                         _offset = 0;
1287                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1288                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1289                         _bo_idx = 0;
1290                         if (plane_idx == 0)
1291                                 break;
1292                 }
1293                 //else if (plane_idx == 1)
1294                 {
1295                         _offset += _size;
1296                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1297                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1298                         _bo_idx = 0;
1299                         if (plane_idx == 1)
1300                                 break;
1301                 }
1302                 //else if (plane_idx == 2)
1303                 {
1304                         _offset += _size;
1305                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1306                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1307                         _bo_idx = 0;
1308                 }
1309                 break;
1310         default:
1311                 bpp = 0;
1312                 break;
1313         }
1314
1315         *size = _size;
1316         *offset = _offset;
1317         *pitch = _pitch;
1318         *bo_idx = _bo_idx;
1319
1320         return ret;
1321 }
1322
1323 int
1324 tbm_dumb_bo_get_flags(tbm_bo bo)
1325 {
1326         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1327
1328         tbm_bo_dumb bo_dumb;
1329
1330         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
1331         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
1332
1333         return bo_dumb->flags_tbm;
1334 }
1335
1336 int
1337 tbm_dumb_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
1338 {
1339         tbm_bufmgr_dumb bufmgr_dumb;
1340
1341         bufmgr_dumb = tbm_backend_get_priv_from_bufmgr(bufmgr);
1342         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
1343
1344         if (!tbm_drm_helper_wl_auth_server_init(native_display, bufmgr_dumb->fd,
1345                                                                                         bufmgr_dumb->device_name, 0)) {
1346                 TBM_DUMB_LOG("error:Fail to tbm_drm_helper_wl_server_init\n");
1347                 return 0;
1348         }
1349
1350         bufmgr_dumb->bind_display = native_display;
1351
1352         return 1;
1353 }
1354
1355 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1356
1357 static TBMModuleVersionInfo DumbVersRec = {
1358         "dumb",
1359         "Samsung",
1360         TBM_ABI_VERSION,
1361 };
1362
1363 TBMModuleData tbmModuleData = { &DumbVersRec, init_tbm_bufmgr_priv};
1364
1365 int
1366 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1367 {
1368         tbm_bufmgr_dumb bufmgr_dumb;
1369         tbm_bufmgr_backend bufmgr_backend;
1370         uint64_t cap = 0;
1371         uint32_t ret;
1372         int fp;
1373         int length;
1374         char buf[1];
1375
1376         if (!bufmgr)
1377                 return 0;
1378
1379         bufmgr_dumb = calloc(1, sizeof(struct _tbm_bufmgr_dumb));
1380         if (!bufmgr_dumb) {
1381                 TBM_DUMB_LOG("error: Fail to alloc bufmgr_dumb!\n");
1382                 return 0;
1383         }
1384
1385         if (tbm_backend_is_display_server()) {
1386
1387                 bufmgr_dumb->fd = tbm_drm_helper_get_master_fd();
1388                 if (bufmgr_dumb->fd < 0)
1389                         bufmgr_dumb->fd = _tbm_dumb_open_drm();
1390
1391                 if (bufmgr_dumb->fd < 0) {
1392                         TBM_DUMB_LOG("error:Fail to create drm!\n");
1393                         goto fail_open_drm;
1394                 }
1395
1396                 tbm_drm_helper_set_tbm_master_fd(bufmgr_dumb->fd);
1397
1398                 bufmgr_dumb->device_name = drmGetDeviceNameFromFd(bufmgr_dumb->fd);
1399                 if (!bufmgr_dumb->device_name) {
1400                         TBM_DUMB_LOG("error:Fail to get device name!\n");
1401                         goto fail_get_device_name;
1402                 }
1403         } else {
1404                 if (!tbm_drm_helper_get_auth_info(&(bufmgr_dumb->fd), &(bufmgr_dumb->device_name), NULL)) {
1405                         TBM_DUMB_LOG("error:Fail to get auth drm info!\n");
1406                         goto fail_get_auth_info;
1407                 }
1408         }
1409
1410         ret = drmGetCap(bufmgr_dumb->fd, DRM_CAP_DUMB_BUFFER, &cap);
1411         if (ret || cap == 0) {
1412                 TBM_DUMB_LOG("error: drm  buffer isn't supported !\n");
1413                 goto fail_get_cap;
1414         }
1415
1416         //Create Hash Table
1417         bufmgr_dumb->hashBos = drmHashCreate();
1418
1419         //Check if the tbm manager supports dma fence or not.
1420         fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1421         if (fp != -1) {
1422                 length = read(fp, buf, 1);
1423
1424                 if (length == 1 && buf[0] == '1')
1425                         bufmgr_dumb->use_dma_fence = 1;
1426
1427                 close(fp);
1428         }
1429
1430         bufmgr_backend = tbm_backend_alloc();
1431         if (!bufmgr_backend) {
1432                 TBM_DUMB_LOG("error: Fail to create drm!\n");
1433                 goto fail_alloc_backend;
1434         }
1435
1436         bufmgr_backend->priv = (void *)bufmgr_dumb;
1437         bufmgr_backend->bufmgr_deinit = tbm_dumb_bufmgr_deinit,
1438         bufmgr_backend->bo_size = tbm_dumb_bo_size,
1439         bufmgr_backend->bo_alloc = tbm_dumb_bo_alloc,
1440         bufmgr_backend->bo_free = tbm_dumb_bo_free,
1441         bufmgr_backend->bo_import = tbm_dumb_bo_import,
1442         bufmgr_backend->bo_import_fd = tbm_dumb_bo_import_fd,
1443         bufmgr_backend->bo_export = tbm_dumb_bo_export,
1444         bufmgr_backend->bo_export_fd = tbm_dumb_bo_export_fd,
1445         bufmgr_backend->bo_get_handle = tbm_dumb_bo_get_handle,
1446         bufmgr_backend->bo_map = tbm_dumb_bo_map,
1447         bufmgr_backend->bo_unmap = tbm_dumb_bo_unmap,
1448         bufmgr_backend->surface_get_plane_data = tbm_dumb_surface_get_plane_data;
1449         bufmgr_backend->surface_supported_format = tbm_dumb_surface_supported_format;
1450         bufmgr_backend->bo_get_flags = tbm_dumb_bo_get_flags;
1451         bufmgr_backend->bo_lock = tbm_dumb_bo_lock;
1452         bufmgr_backend->bo_unlock = tbm_dumb_bo_unlock;
1453         bufmgr_backend->bufmgr_bind_native_display = tbm_dumb_bufmgr_bind_native_display;
1454
1455         if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
1456                 TBM_DUMB_LOG("error: Fail to init backend!\n");
1457                 goto fail_init_backend;
1458         }
1459
1460 #ifdef DEBUG
1461         {
1462                 char* env;
1463                 env = getenv("TBM_DUMB_DEBUG");
1464                 if (env) {
1465                         bDebug = atoi(env);
1466                         TBM_DUMB_LOG("TBM_DUMB_DEBUG=%s\n", env);
1467                 } else
1468                         bDebug = 0;
1469         }
1470 #endif
1471
1472         DBG("[%s] DMABUF FENCE is %s\n", target_name(),
1473                   bufmgr_dumb->use_dma_fence ? "supported!" : "NOT supported!");
1474
1475         DBG("[%s] drm_fd:%d\n", target_name(), bufmgr_dumb->fd);
1476
1477         return 1;
1478
1479 fail_init_backend:
1480         tbm_backend_free(bufmgr_backend);
1481 fail_alloc_backend:
1482         if (bufmgr_dumb->hashBos)
1483                 drmHashDestroy(bufmgr_dumb->hashBos);
1484         if (bufmgr_dumb->device_name)
1485                 free(bufmgr_dumb->device_name);
1486 fail_get_cap:
1487 fail_get_device_name:
1488         if (tbm_backend_is_display_server())
1489                 tbm_drm_helper_unset_tbm_master_fd();
1490         if (bufmgr_dumb->fd >= 0)
1491                 close(bufmgr_dumb->fd);
1492 fail_get_auth_info:
1493 fail_open_drm:
1494         free(bufmgr_dumb);
1495         return 0;
1496 }
1497
1498