01705b120aaf2b18a5ad1733a40e4a47f0241d02
[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;
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**)&bo_dumb);
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         /* Free gem handle */
529         struct drm_gem_close arg = {0, };
530         memset(&arg, 0, sizeof(arg));
531         arg.handle = bo_dumb->gem;
532         if (drmIoctl(bo_dumb->fd, DRM_IOCTL_GEM_CLOSE, &arg)) {
533                 TBM_DUMB_LOG("error bo:%p fail to gem close.(%s)\n",
534                         bo, strerror(errno));
535         }
536
537         free(bo_dumb);
538 }
539
540
541 static void *
542 tbm_dumb_bo_import(tbm_bo bo, unsigned int key)
543 {
544         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
545
546         tbm_bufmgr_dumb bufmgr_dumb;
547         tbm_bo_dumb bo_dumb;
548         int ret;
549
550         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
551         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
552
553         ret = drmHashLookup(bufmgr_dumb->hashBos, key, (void **)&bo_dumb);
554         if (ret == 0)
555                 return bo_dumb;
556
557         struct drm_gem_open arg = {0, };
558
559         arg.name = key;
560         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_GEM_OPEN, &arg)) {
561                 TBM_DUMB_LOG("error Cannot open gem name=%d\n", key);
562                 return 0;
563         }
564
565         bo_dumb = calloc(1, sizeof(struct _tbm_bo_dumb));
566         if (!bo_dumb) {
567                 TBM_DUMB_LOG("error fail to allocate the bo private\n");
568                 return 0;
569         }
570
571         bo_dumb->fd = bufmgr_dumb->fd;
572         bo_dumb->gem = arg.handle;
573         bo_dumb->size = arg.size;
574         bo_dumb->flags_dumb = 0;
575         bo_dumb->name = key;
576         bo_dumb->flags_tbm = _get_tbm_flag_from_dumb(bo_dumb->flags_dumb);
577
578         if (!bo_dumb->dmabuf) {
579                 struct drm_prime_handle arg = {0, };
580
581                 arg.handle = bo_dumb->gem;
582                 if (drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg)) {
583                         TBM_DUMB_LOG("error Cannot dmabuf=%d\n", bo_dumb->gem);
584                         free(bo_dumb);
585                         return 0;
586                 }
587                 bo_dumb->dmabuf = arg.fd;
588         }
589
590         /* add bo to hash */
591         if (drmHashInsert(bufmgr_dumb->hashBos, bo_dumb->name, (void *)bo_dumb) < 0)
592                 TBM_DUMB_LOG("error Cannot insert bo to Hash(%d)\n", bo_dumb->name);
593
594         DBG("   [%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n", target_name(),
595                  bo,
596                  bo_dumb->gem, bo_dumb->name,
597                  bo_dumb->dmabuf,
598                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
599                  bo_dumb->size);
600
601         return (void *)bo_dumb;
602 }
603
604 static void *
605 tbm_dumb_bo_import_fd(tbm_bo bo, tbm_fd key)
606 {
607         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
608
609         tbm_bufmgr_dumb bufmgr_dumb;
610         tbm_bo_dumb bo_dumb;
611
612         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
613         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
614
615         int ret;
616
617         unsigned int gem = 0;
618         unsigned int name = 0;
619         unsigned int real_size = -1;
620
621         //getting handle from fd
622         struct drm_prime_handle arg = {0, };
623         struct drm_gem_open gem_open = {0, };
624
625         arg.fd = key;
626         arg.flags = 0;
627         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
628                 TBM_DUMB_LOG("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
629                                  bo, arg.fd, strerror(errno));
630                 return NULL;
631         }
632         gem = arg.handle;
633
634         /* Determine size of bo.  The fd-to-handle ioctl really should
635          * return the size, but it doesn't.  If we have kernel 3.12 or
636          * later, we can lseek on the prime fd to get the size.  Older
637          * kernels will just fail, in which case we fall back to the
638          * provided (estimated or guess size). */
639         real_size = lseek(key, 0, SEEK_END);
640
641         name = _get_name(bufmgr_dumb->fd, gem);
642         if (name == 0) {
643                 TBM_DUMB_LOG("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
644                         bo, gem, key, strerror(errno));
645                 return 0;
646         }
647
648         ret = drmHashLookup(bufmgr_dumb->hashBos, name, (void **)&bo_dumb);
649         if (ret == 0) {
650                 if (gem == bo_dumb->gem)
651                         return bo_dumb;
652         }
653
654         /* Open the same GEM object only for finding out its size */
655         gem_open.name = name;
656         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_GEM_OPEN, &gem_open)) {
657                 TBM_DUMB_LOG("error Cannot open gem name=%d\n", key);
658                 return 0;
659         }
660         /* Free gem handle to avoid a memory leak*/
661         struct drm_gem_close gem_close;
662         gem_close.handle = gem_open.handle;
663         if (drmIoctl(bufmgr_dumb->fd, DRM_IOCTL_GEM_CLOSE, &gem_close)) {
664                 TBM_DUMB_LOG("error bo:%p fail to gem close.(%s)\n",
665                         bo, strerror(errno));
666         }
667
668         if (real_size == -1)
669                 real_size = gem_open.size;
670
671         bo_dumb = calloc(1, sizeof(struct _tbm_bo_dumb));
672         if (!bo_dumb) {
673                 TBM_DUMB_LOG("error bo:%p fail to allocate the bo private\n", bo);
674                 return 0;
675         }
676
677         bo_dumb->fd = bufmgr_dumb->fd;
678         bo_dumb->gem = gem;
679         bo_dumb->dmabuf = 0;
680         bo_dumb->size = real_size;
681         bo_dumb->flags_dumb = 0;
682         bo_dumb->flags_tbm = _get_tbm_flag_from_dumb(bo_dumb->flags_dumb);
683         bo_dumb->name = name;
684
685         /* add bo to hash */
686         if (drmHashInsert(bufmgr_dumb->hashBos, bo_dumb->name, (void *)bo_dumb) < 0)
687                 TBM_DUMB_LOG("error Cannot insert bo to Hash(%d)\n", bo_dumb->name);
688
689         DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
690                  bo,
691                  bo_dumb->gem, bo_dumb->name,
692                  bo_dumb->dmabuf,
693                  key,
694                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
695                  bo_dumb->size);
696
697         return (void *)bo_dumb;
698 }
699
700 static unsigned int
701 tbm_dumb_bo_export(tbm_bo bo)
702 {
703         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
704
705         tbm_bo_dumb bo_dumb;
706
707         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
708         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
709
710         if (!bo_dumb->name) {
711                 bo_dumb->name = _get_name(bo_dumb->fd, bo_dumb->gem);
712                 if (!bo_dumb->name) {
713                         TBM_DUMB_LOG("error Cannot get name\n");
714                         return 0;
715                 }
716         }
717
718         DBG("   [%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n", target_name(),
719                  bo,
720                  bo_dumb->gem, bo_dumb->name,
721                  bo_dumb->dmabuf,
722                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
723                  bo_dumb->size);
724
725         return (unsigned int)bo_dumb->name;
726 }
727
728 tbm_fd
729 tbm_dumb_bo_export_fd(tbm_bo bo)
730 {
731         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, -1);
732
733         tbm_bo_dumb bo_dumb;
734         int ret;
735
736         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
737         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, -1);
738
739         struct drm_prime_handle arg = {0, };
740
741         arg.handle = bo_dumb->gem;
742         ret = drmIoctl(bo_dumb->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
743         if (ret) {
744                 TBM_DUMB_LOG("error bo:%p Cannot dmabuf=%d (%s)\n",
745                         bo, bo_dumb->gem, strerror(errno));
746                 return (tbm_fd) ret;
747         }
748
749         DBG(" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
750                  bo,
751                  bo_dumb->gem, bo_dumb->name,
752                  bo_dumb->dmabuf,
753                  arg.fd,
754                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
755                  bo_dumb->size);
756
757         return (tbm_fd)arg.fd;
758 }
759
760 static tbm_bo_handle
761 tbm_dumb_bo_get_handle(tbm_bo bo, int device)
762 {
763         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
764
765         tbm_bo_handle bo_handle;
766         tbm_bo_dumb bo_dumb;
767
768         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
769         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, (tbm_bo_handle) NULL);
770
771         if (!bo_dumb->gem) {
772                 TBM_DUMB_LOG("error Cannot map gem=%d\n", bo_dumb->gem);
773                 return (tbm_bo_handle) NULL;
774         }
775
776         DBG("[%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d, %s\n", target_name(),
777                  bo,
778                  bo_dumb->gem, bo_dumb->name,
779                  bo_dumb->dmabuf,
780                  bo_dumb->flags_tbm, bo_dumb->flags_dumb,
781                  bo_dumb->size,
782                  STR_DEVICE[device]);
783
784         /*Get mapped bo_handle*/
785         bo_handle = _dumb_bo_handle(bo_dumb, device);
786         if (bo_handle.ptr == NULL) {
787                 TBM_DUMB_LOG("error Cannot get handle: gem:%d, device:%d\n", bo_dumb->gem, device);
788                 return (tbm_bo_handle) NULL;
789         }
790
791         return bo_handle;
792 }
793
794 static tbm_bo_handle
795 tbm_dumb_bo_map(tbm_bo bo, int device, int opt)
796 {
797         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, (tbm_bo_handle) NULL);
798
799         tbm_bo_handle bo_handle;
800         tbm_bo_dumb bo_dumb;
801
802         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
803         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, (tbm_bo_handle) NULL);
804
805         if (!bo_dumb->gem) {
806                 TBM_DUMB_LOG("error Cannot map gem=%d\n", bo_dumb->gem);
807                 return (tbm_bo_handle) NULL;
808         }
809
810         DBG("      [%s] bo:%p, gem:%d(%d), fd:%d, %s, %s\n", target_name(),
811                  bo,
812                  bo_dumb->gem, bo_dumb->name,
813                  bo_dumb->dmabuf,
814                  STR_DEVICE[device],
815                  STR_OPT[opt]);
816
817         /*Get mapped bo_handle*/
818         bo_handle = _dumb_bo_handle(bo_dumb, device);
819         if (bo_handle.ptr == NULL) {
820                 TBM_DUMB_LOG("error Cannot get handle: gem:%d, device:%d, opt:%d\n", bo_dumb->gem, device, opt);
821                 return (tbm_bo_handle) NULL;
822         }
823
824         return bo_handle;
825 }
826
827 static int
828 tbm_dumb_bo_unmap(tbm_bo bo)
829 {
830         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
831
832         tbm_bo_dumb bo_dumb;
833
834         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
835         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
836
837         if (!bo_dumb->gem)
838                 return 0;
839
840         DBG("    [%s] bo:%p, gem:%d(%d), fd:%d\n", target_name(),
841                   bo,
842                   bo_dumb->gem, bo_dumb->name,
843                   bo_dumb->dmabuf);
844
845         return 1;
846 }
847
848 static int
849 tbm_dumb_bo_lock(tbm_bo bo, int device, int opt)
850 {
851         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
852
853 #if USE_BACKEND_LOCK
854         tbm_bufmgr_dumb bufmgr_dumb;
855         tbm_bo_dumb bo_dumb;
856         struct dma_buf_fence fence;
857         struct flock filelock;
858         int ret = 0;
859
860         if (device != TBM_DEVICE_3D && device != TBM_DEVICE_CPU) {
861                 DBG("[libtbm-dumb:%d] %s not support device type,\n", getpid(), __FUNCTION__);
862                 return 0;
863         }
864
865         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
866         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
867
868         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
869         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
870
871         if (!bufmgr_dumb->use_dma_fence)
872            return 1;
873
874         memset(&fence, 0, sizeof(struct dma_buf_fence));
875
876         /* Check if the given type is valid or not. */
877         if (opt & TBM_OPTION_WRITE)     {
878                 if (device == TBM_DEVICE_3D)
879                         fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
880         } else if (opt & TBM_OPTION_READ)       {
881                 if (device == TBM_DEVICE_3D)
882                         fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
883         } else {
884                 TBM_DUMB_LOG("error Invalid argument\n");
885                 return 0;
886         }
887
888         /* Check if the tbm manager supports dma fence or not. */
889         if (!bufmgr_dumb->use_dma_fence) {
890                 TBM_DUMB_LOG("error Not support DMA FENCE(%s)\n", strerror(errno));
891                 return 0;
892         }
893
894         if (device == TBM_DEVICE_3D) {
895                 ret = ioctl(bo_dumb->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
896                 if (ret < 0) {
897                         TBM_DUMB_LOG("error Cannot set GET FENCE(%s)\n", strerror(errno));
898                         return 0;
899                 }
900         } else {
901                 if (opt & TBM_OPTION_WRITE)
902                         filelock.l_type = F_WRLCK;
903                 else
904                         filelock.l_type = F_RDLCK;
905
906                 filelock.l_whence = SEEK_CUR;
907                 filelock.l_start = 0;
908                 filelock.l_len = 0;
909
910                 if (-1 == fcntl(bo_dumb->dmabuf, F_SETLKW, &filelock))
911                         return 0;
912         }
913
914         pthread_mutex_lock(&bo_dumb->mutex);
915
916         if (device == TBM_DEVICE_3D) {
917                 int i;
918                 for (i = 0; i < DMA_FENCE_LIST_MAX; i++) {
919                         if (bo_dumb->dma_fence[i].ctx == 0) {
920                                 bo_dumb->dma_fence[i].type = fence.type;
921                                 bo_dumb->dma_fence[i].ctx = fence.ctx;
922                                 break;
923                         }
924                 }
925
926                 if (i == DMA_FENCE_LIST_MAX) {
927                         //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
928                         TBM_DUMB_LOG("error fence list is full\n");
929                 }
930         }
931
932         pthread_mutex_unlock(&bo_dumb->mutex);
933
934         DBG("[%s] DMABUF_IOCTL_GET_FENCE! bo:%p, gem:%d(%d), fd:%ds\n", target_name(),
935                   bo,
936                   bo_dumb->gem, bo_dumb->name,
937                   bo_dumb->dmabuf);
938
939 #endif
940         return 1;
941 }
942
943 static int
944 tbm_dumb_bo_unlock(tbm_bo bo)
945 {
946         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
947
948 #if USE_BACKEND_LOCK
949         tbm_bo_dumb bo_dumb;
950         struct dma_buf_fence fence;
951         struct flock filelock;
952         unsigned int dma_type = 0;
953         int ret = 0;
954
955         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
956         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
957
958         bufmgr_dumb = (tbm_bufmgr_dumb)tbm_backend_get_bufmgr_priv(bo);
959         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
960
961         if (!bufmgr_dumb->use_dma_fence)
962            return 1;
963
964         if (bo_dumb->dma_fence[0].type & DMA_BUF_ACCESS_DMA)
965                 dma_type = 1;
966
967         if (!bo_dumb->dma_fence[0].ctx && dma_type) {
968                 DBG("error FENCE not support or ignored,\n");
969                 return 0;
970         }
971
972         if (!bo_dumb->dma_fence[0].ctx && dma_type) {
973                 DBG("error device type is not 3D/CPU,\n");
974                 return 0;
975         }
976
977         pthread_mutex_lock(&bo_dumb->mutex);
978
979         if (dma_type) {
980                 fence.type = bo_dumb->dma_fence[0].type;
981                 fence.ctx = bo_dumb->dma_fence[0].ctx;
982                 int i;
983                 for (i = 1; i < DMA_FENCE_LIST_MAX; i++) {
984                         bo_dumb->dma_fence[i-1].type = bo_dumb->dma_fence[i].type;
985                         bo_dumb->dma_fence[i-1].ctx = bo_dumb->dma_fence[i].ctx;
986                 }
987                 bo_dumb->dma_fence[DMA_FENCE_LIST_MAX-1].type = 0;
988                 bo_dumb->dma_fence[DMA_FENCE_LIST_MAX-1].ctx = 0;
989         }
990         pthread_mutex_unlock(&bo_dumb->mutex);
991
992         if (dma_type) {
993                 ret = ioctl(bo_dumb->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
994                 if (ret < 0) {
995                         TBM_DUMB_LOG("error Can not set PUT FENCE(%s)\n", strerror(errno));
996                         return 0;
997                 }
998         } else {
999                 filelock.l_type = F_UNLCK;
1000                 filelock.l_whence = SEEK_CUR;
1001                 filelock.l_start = 0;
1002                 filelock.l_len = 0;
1003
1004                 if (-1 == fcntl(bo_dumb->dmabuf, F_SETLKW, &filelock))
1005                         return 0;
1006         }
1007
1008         DBG("[%s] DMABUF_IOCTL_PUT_FENCE! bo:%p, gem:%d(%d), fd:%ds\n", target_name(),
1009                   bo,
1010                   bo_dumb->gem, bo_dumb->name,
1011                   bo_dumb->dmabuf);
1012
1013 #endif
1014         return 1;
1015 }
1016
1017 static void
1018 tbm_dumb_bufmgr_deinit(void *priv)
1019 {
1020         DUMB_RETURN_IF_FAIL(priv != NULL);
1021
1022         tbm_bufmgr_dumb bufmgr_dumb;
1023
1024         bufmgr_dumb = (tbm_bufmgr_dumb)priv;
1025
1026         if (bufmgr_dumb->hashBos) {
1027                 unsigned long key;
1028                 void *value;
1029
1030                 while (drmHashFirst(bufmgr_dumb->hashBos, &key, &value) > 0) {
1031                         free(value);
1032                         drmHashDelete(bufmgr_dumb->hashBos, key);
1033                 }
1034
1035                 drmHashDestroy(bufmgr_dumb->hashBos);
1036                 bufmgr_dumb->hashBos = NULL;
1037         }
1038
1039         if (bufmgr_dumb->bind_display)
1040                 tbm_drm_helper_wl_auth_server_deinit();
1041
1042         if (bufmgr_dumb->device_name)
1043                 free(bufmgr_dumb->device_name);
1044
1045         if (tbm_backend_is_display_server())
1046                 tbm_drm_helper_unset_tbm_master_fd();
1047
1048         close(bufmgr_dumb->fd);
1049
1050         free(bufmgr_dumb);
1051 }
1052
1053 int
1054 tbm_dumb_surface_supported_format(uint32_t **formats, uint32_t *num)
1055 {
1056         uint32_t* color_formats = NULL;
1057
1058         color_formats = (uint32_t*)calloc(1, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1059
1060         if (color_formats == NULL)
1061                 return 0;
1062
1063         memcpy(color_formats, tbm_dumb_color_format_list , sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
1064
1065         *formats = color_formats;
1066         *num = TBM_COLOR_FORMAT_COUNT;
1067
1068         return 1;
1069 }
1070
1071
1072 /**
1073  * @brief get the plane data of the surface.
1074  * @param[in] width : the width of the surface
1075  * @param[in] height : the height of the surface
1076  * @param[in] format : the format of the surface
1077  * @param[in] plane_idx : the format of the surface
1078  * @param[out] size : the size of the plane
1079  * @param[out] offset : the offset of the plane
1080  * @param[out] pitch : the pitch of the plane
1081  * @param[out] padding : the padding of the plane
1082  * @return 1 if this function succeeds, otherwise 0.
1083  */
1084 int
1085 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)
1086 {
1087         int ret = 1;
1088         int bpp;
1089         int _offset = 0;
1090         int _pitch = 0;
1091         int _size = 0;
1092         int _bo_idx = 0;
1093
1094         switch (format) {
1095         /* 16 bpp RGB */
1096         case TBM_FORMAT_XRGB4444:
1097         case TBM_FORMAT_XBGR4444:
1098         case TBM_FORMAT_RGBX4444:
1099         case TBM_FORMAT_BGRX4444:
1100         case TBM_FORMAT_ARGB4444:
1101         case TBM_FORMAT_ABGR4444:
1102         case TBM_FORMAT_RGBA4444:
1103         case TBM_FORMAT_BGRA4444:
1104         case TBM_FORMAT_XRGB1555:
1105         case TBM_FORMAT_XBGR1555:
1106         case TBM_FORMAT_RGBX5551:
1107         case TBM_FORMAT_BGRX5551:
1108         case TBM_FORMAT_ARGB1555:
1109         case TBM_FORMAT_ABGR1555:
1110         case TBM_FORMAT_RGBA5551:
1111         case TBM_FORMAT_BGRA5551:
1112         case TBM_FORMAT_RGB565:
1113                 bpp = 16;
1114                 _offset = 0;
1115                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1116                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1117                 _bo_idx = 0;
1118                 break;
1119         /* 24 bpp RGB */
1120         case TBM_FORMAT_RGB888:
1121         case TBM_FORMAT_BGR888:
1122                 bpp = 24;
1123                 _offset = 0;
1124                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1125                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1126                 _bo_idx = 0;
1127                 break;
1128         /* 32 bpp RGB */
1129         case TBM_FORMAT_XRGB8888:
1130         case TBM_FORMAT_XBGR8888:
1131         case TBM_FORMAT_RGBX8888:
1132         case TBM_FORMAT_BGRX8888:
1133         case TBM_FORMAT_ARGB8888:
1134         case TBM_FORMAT_ABGR8888:
1135         case TBM_FORMAT_RGBA8888:
1136         case TBM_FORMAT_BGRA8888:
1137                 bpp = 32;
1138                 _offset = 0;
1139                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1140                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1141                 _bo_idx = 0;
1142                 break;
1143
1144         /* packed YCbCr */
1145         case TBM_FORMAT_YUYV:
1146         case TBM_FORMAT_YVYU:
1147         case TBM_FORMAT_UYVY:
1148         case TBM_FORMAT_VYUY:
1149         case TBM_FORMAT_AYUV:
1150                 bpp = 32;
1151                 _offset = 0;
1152                 _pitch = SIZE_ALIGN((width * bpp)>>3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1153                 _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1154                 _bo_idx = 0;
1155                 break;
1156
1157         /*
1158         * 2 plane YCbCr
1159         * index 0 = Y plane, [7:0] Y
1160         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1161         * or
1162         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1163         */
1164         case TBM_FORMAT_NV12:
1165         case TBM_FORMAT_NV21:
1166                 bpp = 12;
1167                 if (plane_idx == 0) {
1168                         _offset = 0;
1169                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1170                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1171                         _bo_idx = 0;
1172                 } else if (plane_idx == 1) {
1173                         _offset = width*height;
1174                         _pitch = SIZE_ALIGN(width , TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1175                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1176                         _bo_idx = 0;
1177                 }
1178                 break;
1179
1180         case TBM_FORMAT_NV16:
1181         case TBM_FORMAT_NV61:
1182                 bpp = 16;
1183                 //if (plane_idx == 0)
1184                 {
1185                         _offset = 0;
1186                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1187                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1188                         _bo_idx = 0;
1189                         if (plane_idx == 0)
1190                                 break;
1191                 }
1192                 //else if (plane_idx == 1)
1193                 {
1194                         _offset += _size;
1195                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1196                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1197                         _bo_idx = 0;
1198                 }
1199                 break;
1200
1201         /*
1202         * 3 plane YCbCr
1203         * index 0: Y plane, [7:0] Y
1204         * index 1: Cb plane, [7:0] Cb
1205         * index 2: Cr plane, [7:0] Cr
1206         * or
1207         * index 1: Cr plane, [7:0] Cr
1208         * index 2: Cb plane, [7:0] Cb
1209         */
1210         /*
1211         NATIVE_BUFFER_FORMAT_YV12
1212         NATIVE_BUFFER_FORMAT_I420
1213         */
1214         case TBM_FORMAT_YUV410:
1215         case TBM_FORMAT_YVU410:
1216                 bpp = 9;
1217                 break;
1218         case TBM_FORMAT_YUV411:
1219         case TBM_FORMAT_YVU411:
1220         case TBM_FORMAT_YUV420:
1221         case TBM_FORMAT_YVU420:
1222                 bpp = 12;
1223                 //if (plane_idx == 0)
1224                 {
1225                         _offset = 0;
1226                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1227                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1228                         _bo_idx = 0;
1229                         if (plane_idx == 0)
1230                                 break;
1231                 }
1232                 //else if (plane_idx == 1)
1233                 {
1234                         _offset += _size;
1235                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1236                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1237                         _bo_idx = 0;
1238                         if (plane_idx == 1)
1239                                 break;
1240                 }
1241                 //else if (plane_idx == 2)
1242                 {
1243                         _offset += _size;
1244                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1245                         _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
1246                         _bo_idx = 0;
1247                 }
1248                 break;
1249         case TBM_FORMAT_YUV422:
1250         case TBM_FORMAT_YVU422:
1251                 bpp = 16;
1252                 //if (plane_idx == 0)
1253                 {
1254                         _offset = 0;
1255                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1256                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1257                         _bo_idx = 0;
1258                         if (plane_idx == 0)
1259                                 break;
1260                 }
1261                 //else if (plane_idx == 1)
1262                 {
1263                         _offset += _size;
1264                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1265                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1266                         _bo_idx = 0;
1267                         if (plane_idx == 1)
1268                                 break;
1269                 }
1270                 //else if (plane_idx == 2)
1271                 {
1272                         _offset += _size;
1273                         _pitch = SIZE_ALIGN(width/2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1274                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1275                         _bo_idx = 0;
1276                 }
1277                 break;
1278         case TBM_FORMAT_YUV444:
1279         case TBM_FORMAT_YVU444:
1280                 bpp = 24;
1281                 //if (plane_idx == 0)
1282                 {
1283                         _offset = 0;
1284                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1285                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1286                         _bo_idx = 0;
1287                         if (plane_idx == 0)
1288                                 break;
1289                 }
1290                 //else if (plane_idx == 1)
1291                 {
1292                         _offset += _size;
1293                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1294                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1295                         _bo_idx = 0;
1296                         if (plane_idx == 1)
1297                                 break;
1298                 }
1299                 //else if (plane_idx == 2)
1300                 {
1301                         _offset += _size;
1302                         _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1303                         _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
1304                         _bo_idx = 0;
1305                 }
1306                 break;
1307         default:
1308                 bpp = 0;
1309                 break;
1310         }
1311
1312         *size = _size;
1313         *offset = _offset;
1314         *pitch = _pitch;
1315         *bo_idx = _bo_idx;
1316
1317         return ret;
1318 }
1319
1320 int
1321 tbm_dumb_bo_get_flags(tbm_bo bo)
1322 {
1323         DUMB_RETURN_VAL_IF_FAIL(bo != NULL, 0);
1324
1325         tbm_bo_dumb bo_dumb;
1326
1327         bo_dumb = (tbm_bo_dumb)tbm_backend_get_bo_priv(bo);
1328         DUMB_RETURN_VAL_IF_FAIL(bo_dumb != NULL, 0);
1329
1330         return bo_dumb->flags_tbm;
1331 }
1332
1333 int
1334 tbm_dumb_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
1335 {
1336         tbm_bufmgr_dumb bufmgr_dumb;
1337
1338         bufmgr_dumb = tbm_backend_get_priv_from_bufmgr(bufmgr);
1339         DUMB_RETURN_VAL_IF_FAIL(bufmgr_dumb != NULL, 0);
1340
1341         if (!tbm_drm_helper_wl_auth_server_init(native_display, bufmgr_dumb->fd,
1342                                                                                         bufmgr_dumb->device_name, 0)) {
1343                 TBM_DUMB_LOG("error:Fail to tbm_drm_helper_wl_server_init\n");
1344                 return 0;
1345         }
1346
1347         bufmgr_dumb->bind_display = native_display;
1348
1349         return 1;
1350 }
1351
1352 MODULEINITPPROTO(init_tbm_bufmgr_priv);
1353
1354 static TBMModuleVersionInfo DumbVersRec = {
1355         "dumb",
1356         "Samsung",
1357         TBM_ABI_VERSION,
1358 };
1359
1360 TBMModuleData tbmModuleData = { &DumbVersRec, init_tbm_bufmgr_priv};
1361
1362 int
1363 init_tbm_bufmgr_priv(tbm_bufmgr bufmgr, int fd)
1364 {
1365         tbm_bufmgr_dumb bufmgr_dumb;
1366         tbm_bufmgr_backend bufmgr_backend;
1367         uint64_t cap = 0;
1368         uint32_t ret;
1369         int fp;
1370         int length;
1371         char buf[1];
1372
1373         if (!bufmgr)
1374                 return 0;
1375
1376         bufmgr_dumb = calloc(1, sizeof(struct _tbm_bufmgr_dumb));
1377         if (!bufmgr_dumb) {
1378                 TBM_DUMB_LOG("error: Fail to alloc bufmgr_dumb!\n");
1379                 return 0;
1380         }
1381
1382         if (tbm_backend_is_display_server()) {
1383
1384                 bufmgr_dumb->fd = tbm_drm_helper_get_master_fd();
1385                 if (bufmgr_dumb->fd < 0)
1386                         bufmgr_dumb->fd = _tbm_dumb_open_drm();
1387
1388                 if (bufmgr_dumb->fd < 0) {
1389                         TBM_DUMB_LOG("error:Fail to create drm!\n");
1390                         goto fail_open_drm;
1391                 }
1392
1393                 tbm_drm_helper_set_tbm_master_fd(bufmgr_dumb->fd);
1394
1395                 bufmgr_dumb->device_name = drmGetDeviceNameFromFd(bufmgr_dumb->fd);
1396                 if (!bufmgr_dumb->device_name) {
1397                         TBM_DUMB_LOG("error:Fail to get device name!\n");
1398                         goto fail_get_device_name;
1399                 }
1400         } else {
1401                 if (!tbm_drm_helper_get_auth_info(&(bufmgr_dumb->fd), &(bufmgr_dumb->device_name), NULL)) {
1402                         TBM_DUMB_LOG("error:Fail to get auth drm info!\n");
1403                         goto fail_get_auth_info;
1404                 }
1405         }
1406
1407         ret = drmGetCap(bufmgr_dumb->fd, DRM_CAP_DUMB_BUFFER, &cap);
1408         if (ret || cap == 0) {
1409                 TBM_DUMB_LOG("error: drm  buffer isn't supported !\n");
1410                 goto fail_get_cap;
1411         }
1412
1413         //Create Hash Table
1414         bufmgr_dumb->hashBos = drmHashCreate();
1415
1416         //Check if the tbm manager supports dma fence or not.
1417         fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1418         if (fp != -1) {
1419                 length = read(fp, buf, 1);
1420
1421                 if (length == 1 && buf[0] == '1')
1422                         bufmgr_dumb->use_dma_fence = 1;
1423
1424                 close(fp);
1425         }
1426
1427         bufmgr_backend = tbm_backend_alloc();
1428         if (!bufmgr_backend) {
1429                 TBM_DUMB_LOG("error: Fail to create drm!\n");
1430                 goto fail_alloc_backend;
1431         }
1432
1433         bufmgr_backend->priv = (void *)bufmgr_dumb;
1434         bufmgr_backend->bufmgr_deinit = tbm_dumb_bufmgr_deinit,
1435         bufmgr_backend->bo_size = tbm_dumb_bo_size,
1436         bufmgr_backend->bo_alloc = tbm_dumb_bo_alloc,
1437         bufmgr_backend->bo_free = tbm_dumb_bo_free,
1438         bufmgr_backend->bo_import = tbm_dumb_bo_import,
1439         bufmgr_backend->bo_import_fd = tbm_dumb_bo_import_fd,
1440         bufmgr_backend->bo_export = tbm_dumb_bo_export,
1441         bufmgr_backend->bo_export_fd = tbm_dumb_bo_export_fd,
1442         bufmgr_backend->bo_get_handle = tbm_dumb_bo_get_handle,
1443         bufmgr_backend->bo_map = tbm_dumb_bo_map,
1444         bufmgr_backend->bo_unmap = tbm_dumb_bo_unmap,
1445         bufmgr_backend->surface_get_plane_data = tbm_dumb_surface_get_plane_data;
1446         bufmgr_backend->surface_supported_format = tbm_dumb_surface_supported_format;
1447         bufmgr_backend->bo_get_flags = tbm_dumb_bo_get_flags;
1448         bufmgr_backend->bo_lock = tbm_dumb_bo_lock;
1449         bufmgr_backend->bo_unlock = tbm_dumb_bo_unlock;
1450         bufmgr_backend->bufmgr_bind_native_display = tbm_dumb_bufmgr_bind_native_display;
1451
1452         if (!tbm_backend_init(bufmgr, bufmgr_backend)) {
1453                 TBM_DUMB_LOG("error: Fail to init backend!\n");
1454                 goto fail_init_backend;
1455         }
1456
1457 #ifdef DEBUG
1458         {
1459                 char* env;
1460                 env = getenv("TBM_DUMB_DEBUG");
1461                 if (env) {
1462                         bDebug = atoi(env);
1463                         TBM_DUMB_LOG("TBM_DUMB_DEBUG=%s\n", env);
1464                 } else
1465                         bDebug = 0;
1466         }
1467 #endif
1468
1469         DBG("[%s] DMABUF FENCE is %s\n", target_name(),
1470                   bufmgr_dumb->use_dma_fence ? "supported!" : "NOT supported!");
1471
1472         DBG("[%s] drm_fd:%d\n", target_name(), bufmgr_dumb->fd);
1473
1474         return 1;
1475
1476 fail_init_backend:
1477         tbm_backend_free(bufmgr_backend);
1478 fail_alloc_backend:
1479         if (bufmgr_dumb->hashBos)
1480                 drmHashDestroy(bufmgr_dumb->hashBos);
1481         if (bufmgr_dumb->device_name)
1482                 free(bufmgr_dumb->device_name);
1483 fail_get_cap:
1484 fail_get_device_name:
1485         if (tbm_backend_is_display_server())
1486                 tbm_drm_helper_unset_tbm_master_fd();
1487         if (bufmgr_dumb->fd >= 0)
1488                 close(bufmgr_dumb->fd);
1489 fail_get_auth_info:
1490 fail_open_drm:
1491         free(bufmgr_dumb);
1492         return 0;
1493 }
1494
1495