Change DRM_EXYNOS_GEM_MAP to DRM_IOCTL_MODE_MAP_DUMB and mmap
[archive/platform/adaptation/samsung_exynos/libtbm-exynos4412.git] / src / tbm_bufmgr_exynos4412.c
1 /**************************************************************************
2
3 libtbm_exynos4412
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 <exynos_drm.h>
50 #include <pthread.h>
51 #include <tbm_surface.h>
52 #include <tbm_surface_internal.h>
53
54 #define DEBUG
55 #define USE_DMAIMPORT
56 #define TBM_COLOR_FORMAT_COUNT 8
57
58 #ifdef DEBUG
59 #define LOG_TAG "TBM_BACKEND"
60 #include <dlog.h>
61 static int bDebug=0;
62
63 char* target_name()
64 {
65     FILE *f;
66     char *slash;
67     static int  initialized = 0;
68     static char app_name[128];
69
70     if ( initialized )
71         return app_name;
72
73     /* get the application name */
74     f = fopen("/proc/self/cmdline", "r");
75
76     if ( !f )
77     {
78         return 0;
79     }
80
81     memset(app_name, 0x00, sizeof(app_name));
82
83     if ( fgets(app_name, 100, f) == NULL )
84     {
85         fclose(f);
86         return 0;
87     }
88
89     fclose(f);
90
91     if ( (slash=strrchr(app_name, '/')) != NULL )
92     {
93         memmove(app_name, slash+1, strlen(slash));
94     }
95
96     initialized = 1;
97
98     return app_name;
99 }
100 #define TBM_EXYNOS4412_LOG(fmt, args...)                LOGE("\033[31m"  "[%s]" fmt "\033[0m", target_name(), ##args)
101 #define DBG(fmt, args...)               if(bDebug&01) LOGE("[%s]" fmt, target_name(), ##args)
102 #else
103 #define TBM_EXYNOS4412_LOG(...)
104 #define DBG(...)
105 #endif
106
107 #define SIZE_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
108
109 #define TBM_SURFACE_ALIGNMENT_PLANE (64)
110 #define TBM_SURFACE_ALIGNMENT_PITCH_RGB (64)
111 #define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
112
113
114 /* check condition */
115 #define EXYNOS4412_RETURN_IF_FAIL(cond) {\
116     if (!(cond)) {\
117         TBM_EXYNOS4412_LOG ("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
118         return;\
119     }\
120 }
121 #define EXYNOS4412_RETURN_VAL_IF_FAIL(cond, val) {\
122     if (!(cond)) {\
123         TBM_EXYNOS4412_LOG ("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
124         return val;\
125     }\
126 }
127
128 struct dma_buf_info {
129         unsigned long   size;
130         unsigned int    fence_supported;
131         unsigned int    padding;
132 };
133
134 #define DMA_BUF_ACCESS_READ             0x1
135 #define DMA_BUF_ACCESS_WRITE            0x2
136 #define DMA_BUF_ACCESS_DMA              0x4
137 #define DMA_BUF_ACCESS_MAX              0x8
138
139 #define DMA_FENCE_LIST_MAX              5
140
141 struct dma_buf_fence {
142         unsigned long           ctx;
143         unsigned int            type;
144 };
145
146 #define DMABUF_IOCTL_BASE       'F'
147 #define DMABUF_IOWR(nr, type)   _IOWR(DMABUF_IOCTL_BASE, nr, type)
148
149 #define DMABUF_IOCTL_GET_INFO   DMABUF_IOWR(0x00, struct dma_buf_info)
150 #define DMABUF_IOCTL_GET_FENCE  DMABUF_IOWR(0x01, struct dma_buf_fence)
151 #define DMABUF_IOCTL_PUT_FENCE  DMABUF_IOWR(0x02, struct dma_buf_fence)
152
153 typedef struct _tbm_bufmgr_exynos4412 *tbm_bufmgr_exynos4412;
154 typedef struct _tbm_bo_exynos4412 *tbm_bo_exynos4412;
155
156 typedef struct _exynos4412_private
157 {
158     int ref_count;
159 } PrivGem;
160
161 /* tbm buffor object for exynos4412 */
162 struct _tbm_bo_exynos4412
163 {
164     int fd;
165
166     unsigned int name;    /* FLINK ID */
167
168     unsigned int gem;     /* GEM Handle */
169
170     unsigned int dmabuf;  /* fd for dmabuf */
171
172     void *pBase;          /* virtual address */
173
174     unsigned int size;
175
176     unsigned int flags_exynos;
177     unsigned int flags_tbm;
178
179     PrivGem* private;
180
181     pthread_mutex_t mutex;
182     struct dma_buf_fence dma_fence[DMA_FENCE_LIST_MAX];
183     int device;
184     int opt;
185 };
186
187 /* tbm bufmgr private for exynos4412 */
188 struct _tbm_bufmgr_exynos4412
189 {
190     int fd;
191     int isLocal;
192     void* hashBos;
193
194     int use_dma_fence;
195 };
196
197 char *STR_DEVICE[]=
198 {
199     "DEF",
200     "CPU",
201     "2D",
202     "3D",
203     "MM"
204 };
205
206 char *STR_OPT[]=
207 {
208     "NONE",
209     "RD",
210     "WR",
211     "RDWR"
212 };
213
214
215 uint32_t tbm_exynos4412_color_format_list[TBM_COLOR_FORMAT_COUNT] = {   TBM_FORMAT_RGBA8888,
216                                                                                                                                                 TBM_FORMAT_BGRA8888,
217                                                                                                                                                 TBM_FORMAT_RGBX8888,
218                                                                                                                                                 TBM_FORMAT_RGB888,
219                                                                                                                                                 TBM_FORMAT_NV12,
220                                                                                                                                                 TBM_FORMAT_NV21,
221                                                                                                                                                 TBM_FORMAT_YUV420,
222                                                                                                                                                 TBM_FORMAT_YVU420 };
223
224
225 static unsigned int
226 _get_exynos_flag_from_tbm (unsigned int ftbm)
227 {
228     unsigned int flags = 0;
229
230     if (ftbm & TBM_BO_SCANOUT)
231         flags |= EXYNOS_BO_CONTIG;
232     else
233         flags |= EXYNOS_BO_NONCONTIG;
234
235     if (ftbm & TBM_BO_WC)
236         flags |= EXYNOS_BO_WC;
237     else if (ftbm & TBM_BO_NONCACHABLE)
238         flags |= EXYNOS_BO_NONCACHABLE;
239     else
240         flags |= EXYNOS_BO_CACHABLE;
241
242     return flags;
243 }
244
245 static unsigned int
246 _get_tbm_flag_from_exynos (unsigned int fexynos)
247 {
248     unsigned int flags = 0;
249
250     if (fexynos & EXYNOS_BO_NONCONTIG)
251         flags |= TBM_BO_DEFAULT;
252     else
253         flags |= TBM_BO_SCANOUT;
254
255     if (fexynos & EXYNOS_BO_WC)
256         flags |= TBM_BO_WC;
257     else if (fexynos & EXYNOS_BO_CACHABLE)
258         flags |= TBM_BO_DEFAULT;
259     else
260         flags |= TBM_BO_NONCACHABLE;
261
262     return flags;
263 }
264
265 static unsigned int
266 _get_name (int fd, unsigned int gem)
267 {
268     struct drm_gem_flink arg = {0,};
269
270     arg.handle = gem;
271     if (drmIoctl (fd, DRM_IOCTL_GEM_FLINK, &arg))
272     {
273         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
274                  "error %s:%d fail to get flink gem=%d\n",
275                  getpid(), __FUNCTION__, __LINE__, gem);
276         return 0;
277     }
278
279     return (unsigned int)arg.name;
280 }
281
282 static tbm_bo_handle
283 _exynos4412_bo_handle (tbm_bo_exynos4412 bo_exynos4412, int device)
284 {
285     tbm_bo_handle bo_handle;
286     memset (&bo_handle, 0x0, sizeof (uint64_t));
287
288     switch(device)
289     {
290     case TBM_DEVICE_DEFAULT:
291     case TBM_DEVICE_2D:
292         bo_handle.u32 = (uint32_t)bo_exynos4412->gem;
293         break;
294     case TBM_DEVICE_CPU:
295         if (!bo_exynos4412->pBase)
296         {
297             struct drm_mode_map_dumb arg = {0,};
298             void *map = NULL;
299
300             arg.handle = bo_exynos4412->gem;
301             if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg))
302             {
303                 TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
304                          "error %s:%d Cannot map_dumb gem=%d\n",
305                          getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
306                 return (tbm_bo_handle) NULL;
307             }
308
309             map = mmap (NULL, bo_exynos4412->size, PROT_READ|PROT_WRITE, MAP_SHARED,
310                               bo_exynos4412->fd, arg.offset);
311             if (map == MAP_FAILED)
312             {
313                 TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
314                          "error %s:%d Cannot usrptr gem=%d\n",
315                          getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
316                 return (tbm_bo_handle) NULL;
317             }
318             bo_exynos4412->pBase = map;
319         }
320
321         bo_handle.ptr = (void *)bo_exynos4412->pBase;
322         break;
323     case TBM_DEVICE_3D:
324 #ifdef USE_DMAIMPORT
325         if (bo_exynos4412->dmabuf)
326         {
327             bo_handle.u32 = (uint32_t)bo_exynos4412->dmabuf;
328             break;
329         }
330
331         if (!bo_exynos4412->dmabuf)
332         {
333             struct drm_prime_handle arg = {0, };
334
335             arg.handle = bo_exynos4412->gem;
336             if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
337             {
338                 TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
339                          "error %s:%d Cannot dmabuf=%d\n",
340                          getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
341                 return (tbm_bo_handle) NULL;
342             }
343             bo_exynos4412->dmabuf = arg.fd;
344         }
345
346         bo_handle.u32 = (uint32_t)bo_exynos4412->dmabuf;
347 #endif
348         break;
349     case TBM_DEVICE_MM:
350         if (!bo_exynos4412->dmabuf)
351         {
352             struct drm_prime_handle arg = {0, };
353
354             arg.handle = bo_exynos4412->gem;
355             if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
356             {
357                 TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
358                          "error %s:%d Cannot dmabuf=%d\n",
359                          getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
360                 return (tbm_bo_handle) NULL;
361             }
362             bo_exynos4412->dmabuf = arg.fd;
363         }
364
365         bo_handle.u32 = (uint32_t)bo_exynos4412->dmabuf;
366         break;
367     default:
368         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
369                  "error %s:%d Not supported device:%d\n",
370                  getpid(), __FUNCTION__, __LINE__, device);
371         bo_handle.ptr = (void *) NULL;
372         break;
373     }
374
375     return bo_handle;
376 }
377
378 static int
379 _exynos4412_cache_flush (int fd, tbm_bo_exynos4412 bo_exynos4412, int flags)
380 {
381 #ifdef ENABLE_CACHECRTL
382     struct drm_exynos_gem_cache_op cache_op = {0, };
383     int ret;
384
385     /* if bo_exynos4412 is null, do cache_flush_all */
386     if(bo_exynos4412)
387     {
388         cache_op.flags = 0;
389         cache_op.usr_addr = (uint64_t)((uint32_t)bo_exynos4412->pBase);
390         cache_op.size = bo_exynos4412->size;
391     }
392     else
393     {
394         flags = TBM_CACHE_FLUSH_ALL;
395         cache_op.flags = 0;
396         cache_op.usr_addr = 0;
397         cache_op.size = 0;
398     }
399
400     if (flags & TBM_CACHE_INV)
401     {
402         if(flags & TBM_CACHE_ALL)
403             cache_op.flags |= EXYNOS_DRM_CACHE_INV_ALL;
404         else
405             cache_op.flags |= EXYNOS_DRM_CACHE_INV_RANGE;
406     }
407
408     if (flags & TBM_CACHE_CLN)
409     {
410         if(flags & TBM_CACHE_ALL)
411             cache_op.flags |= EXYNOS_DRM_CACHE_CLN_ALL;
412         else
413             cache_op.flags |= EXYNOS_DRM_CACHE_CLN_RANGE;
414     }
415
416     if(flags & TBM_CACHE_ALL)
417         cache_op.flags |= EXYNOS_DRM_ALL_CACHES_CORES;
418
419     ret = drmCommandWriteRead (fd, DRM_EXYNOS_GEM_CACHE_OP, &cache_op, sizeof(cache_op));
420     if (ret)
421     {
422         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
423                  "error %s:%d fail to flush the cache.\n",
424                  getpid(), __FUNCTION__, __LINE__);
425         return 0;
426     }
427 #else
428     TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
429              "warning %s:%d fail to enable the cache flush.\n",
430              getpid(), __FUNCTION__, __LINE__);
431 #endif
432     return 1;
433 }
434
435 static int
436 tbm_exynos4412_bo_size (tbm_bo bo)
437 {
438     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
439
440     tbm_bo_exynos4412 bo_exynos4412;
441
442     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
443
444     return bo_exynos4412->size;
445 }
446
447 static void *
448 tbm_exynos4412_bo_alloc (tbm_bo bo, int size, int flags)
449 {
450     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
451
452     tbm_bo_exynos4412 bo_exynos4412;
453     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
454     unsigned int exynos_flags;
455
456     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
457     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
458
459     bo_exynos4412 = calloc (1, sizeof(struct _tbm_bo_exynos4412));
460     if (!bo_exynos4412)
461     {
462         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
463                  "error %s:%d fail to allocate the bo private\n",
464                  getpid(), __FUNCTION__, __LINE__);
465         return 0;
466     }
467
468     exynos_flags = _get_exynos_flag_from_tbm (flags);
469     if((flags & TBM_BO_SCANOUT) &&
470         size <= 4*1024)
471     {
472         exynos_flags |= EXYNOS_BO_NONCONTIG;
473     }
474
475     struct drm_exynos_gem_create arg = {0, };
476     arg.size = size;
477     arg.flags = exynos_flags;
478     if (drmCommandWriteRead(bufmgr_exynos4412->fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg)))
479     {
480         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
481                  "error %s:%d Cannot create bo(flag:%x, size:%d)\n",
482                  getpid(), __FUNCTION__, __LINE__, arg.flags, (unsigned int)arg.size);
483         free (bo_exynos4412);
484         return 0;
485     }
486
487     bo_exynos4412->fd = bufmgr_exynos4412->fd;
488     bo_exynos4412->gem = arg.handle;
489     bo_exynos4412->size = size;
490     bo_exynos4412->flags_tbm = flags;
491     bo_exynos4412->flags_exynos = exynos_flags;
492     bo_exynos4412->name = _get_name (bo_exynos4412->fd, bo_exynos4412->gem);
493
494     pthread_mutex_init(&bo_exynos4412->mutex, NULL);
495
496     if (bufmgr_exynos4412->use_dma_fence
497         && !bo_exynos4412->dmabuf)
498     {
499         struct drm_prime_handle arg = {0, };
500
501         arg.handle = bo_exynos4412->gem;
502         if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
503         {
504             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
505                     "error %s:%d Cannot dmabuf=%d\n",
506                     getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
507             free (bo_exynos4412);
508             return 0;
509         }
510         bo_exynos4412->dmabuf = arg.fd;
511     }
512
513     /* add bo to hash */
514     PrivGem* privGem = calloc (1, sizeof(PrivGem));
515     privGem->ref_count = 1;
516     if (drmHashInsert(bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void *)privGem) < 0)
517     {
518         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
519                  "error %s:%d Cannot insert bo to Hash(%d)\n",
520                  getpid(), __FUNCTION__, __LINE__, bo_exynos4412->name);
521     }
522
523     DBG ("[libtbm-exynos4412:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
524          __FUNCTION__, bo_exynos4412->size,
525          bo_exynos4412->gem, bo_exynos4412->name,
526          flags, exynos_flags);
527
528     return (void *)bo_exynos4412;
529 }
530
531 static void
532 tbm_exynos4412_bo_free(tbm_bo bo)
533 {
534     tbm_bo_exynos4412 bo_exynos4412;
535     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
536
537     if (!bo)
538         return;
539
540     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
541     EXYNOS4412_RETURN_IF_FAIL (bufmgr_exynos4412!=NULL);
542
543     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
544     EXYNOS4412_RETURN_IF_FAIL (bo_exynos4412!=NULL);
545
546     DBG ("[libtbm-exynos4412:%d] %s size:%d, gem:%d(%d)\n",
547          getpid(), __FUNCTION__, bo_exynos4412->size, bo_exynos4412->gem, bo_exynos4412->name);
548
549     if (bo_exynos4412->pBase)
550     {
551         if (munmap(bo_exynos4412->pBase, bo_exynos4412->size) == -1)
552         {
553             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
554                      "error %s:%d\n",
555                      getpid(), __FUNCTION__, __LINE__);
556         }
557     }
558
559     /* close dmabuf */
560     if (bo_exynos4412->dmabuf)
561     {
562         close (bo_exynos4412->dmabuf);
563         bo_exynos4412->dmabuf = 0;
564     }
565
566     /* delete bo from hash */
567     PrivGem *privGem = NULL;
568     int ret;
569
570     ret = drmHashLookup (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void**)&privGem);
571     if (ret == 0)
572     {
573         privGem->ref_count--;
574         if (privGem->ref_count == 0)
575         {
576             drmHashDelete (bufmgr_exynos4412->hashBos, bo_exynos4412->name);
577             free (privGem);
578             privGem = NULL;
579         }
580     }
581     else
582     {
583         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
584                  "warning %s:%d Cannot find bo to Hash(%d), ret=%d\n",
585                  getpid(), __FUNCTION__, __LINE__, bo_exynos4412->name, ret);
586     }
587
588     /* Free gem handle */
589     struct drm_gem_close arg = {0, };
590     memset (&arg, 0, sizeof(arg));
591     arg.handle = bo_exynos4412->gem;
592     if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_GEM_CLOSE, &arg))
593     {
594         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
595                  "error %s:%d\n",
596                  getpid(), __FUNCTION__, __LINE__);
597     }
598
599     free (bo_exynos4412);
600 }
601
602
603 static void *
604 tbm_exynos4412_bo_import (tbm_bo bo, unsigned int key)
605 {
606     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
607
608     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
609     tbm_bo_exynos4412 bo_exynos4412;
610
611     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
612     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
613
614     struct drm_gem_open arg = {0, };
615     struct drm_exynos_gem_info info = {0, };
616
617     arg.name = key;
618     if (drmIoctl(bufmgr_exynos4412->fd, DRM_IOCTL_GEM_OPEN, &arg))
619     {
620         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
621                 "error %s:%d Cannot open gem name=%d\n",
622                 getpid(), __FUNCTION__, __LINE__, key);
623         return 0;
624     }
625
626     info.handle = arg.handle;
627     if (drmCommandWriteRead(bufmgr_exynos4412->fd,
628                            DRM_EXYNOS_GEM_GET,
629                            &info,
630                            sizeof(struct drm_exynos_gem_info)))
631     {
632         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
633                 "error %s:%d Cannot get gem info=%d\n",
634                 getpid(), __FUNCTION__, __LINE__, key);
635         return 0;
636     }
637
638     bo_exynos4412 = calloc (1, sizeof(struct _tbm_bo_exynos4412));
639     if (!bo_exynos4412)
640     {
641         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
642                 "error %s:%d fail to allocate the bo private\n",
643                 getpid(), __FUNCTION__, __LINE__);
644         return 0;
645     }
646
647     bo_exynos4412->fd = bufmgr_exynos4412->fd;
648     bo_exynos4412->gem = arg.handle;
649     bo_exynos4412->size = arg.size;
650     bo_exynos4412->flags_exynos = info.flags;
651     bo_exynos4412->name = key;
652     bo_exynos4412->flags_tbm = _get_tbm_flag_from_exynos (bo_exynos4412->flags_exynos);
653
654     if (!bo_exynos4412->dmabuf)
655     {
656         struct drm_prime_handle arg = {0, };
657
658         arg.handle = bo_exynos4412->gem;
659         if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
660         {
661             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
662                     "error %s:%d Cannot dmabuf=%d\n",
663                     getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
664             free (bo_exynos4412);
665             return 0;
666         }
667         bo_exynos4412->dmabuf = arg.fd;
668     }
669
670     /* add bo to hash */
671     PrivGem *privGem = NULL;
672     int ret;
673
674     ret = drmHashLookup (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void**)&privGem);
675     if (ret == 0)
676     {
677         privGem->ref_count++;
678     }
679     else if (ret == 1)
680     {
681         privGem = calloc (1, sizeof(PrivGem));
682         privGem->ref_count = 1;
683         if (drmHashInsert (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void *)privGem) < 0)
684         {
685             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
686                     "error %s:%d Cannot insert bo to Hash(%d)\n",
687                     getpid(), __FUNCTION__, __LINE__, bo_exynos4412->name);
688         }
689     }
690     else
691     {
692         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
693                 "error %s:%d Cannot insert bo to Hash(%d)\n",
694                 getpid(), __FUNCTION__, __LINE__, bo_exynos4412->name);
695     }
696
697     DBG ("[libtbm-exynos4412:%d] %s size:%d, gem:%d(%d, %d), flags:%d(%d)\n", getpid(),
698          __FUNCTION__, bo_exynos4412->size,
699          bo_exynos4412->gem, bo_exynos4412->name, bo_exynos4412->dmabuf,
700          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos);
701
702     return (void *)bo_exynos4412;
703 }
704
705 static void *
706 tbm_exynos4412_bo_import_fd (tbm_bo bo, tbm_fd key)
707 {
708     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
709
710     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
711     tbm_bo_exynos4412 bo_exynos4412;
712
713     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
714     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
715
716     unsigned int gem = 0;
717     unsigned int real_size = -1;
718     struct drm_exynos_gem_info info = {0, };
719
720         //getting handle from fd
721     struct drm_prime_handle arg = {0, };
722
723         arg.fd = key;
724         arg.flags = 0;
725     if (drmIoctl (bufmgr_exynos4412->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg))
726     {
727         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
728                  "error %s:%d Cannot getting gem from prime fd=%d\n",
729                  getpid(), __FUNCTION__, __LINE__, arg.fd);
730         return NULL;
731     }
732     gem = arg.handle;
733
734         /* Determine size of bo.  The fd-to-handle ioctl really should
735          * return the size, but it doesn't.  If we have kernel 3.12 or
736          * later, we can lseek on the prime fd to get the size.  Older
737          * kernels will just fail, in which case we fall back to the
738          * provided (estimated or guess size). */
739         real_size = lseek(key, 0, SEEK_END);
740
741     info.handle = gem;
742     if (drmCommandWriteRead(bufmgr_exynos4412->fd,
743                            DRM_EXYNOS_GEM_GET,
744                            &info,
745                            sizeof(struct drm_exynos_gem_info)))
746     {
747         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
748                 "error %s:%d Cannot get gem info=%d\n",
749                 getpid(), __FUNCTION__, __LINE__, key);
750         return 0;
751     }
752
753     if (real_size == -1)
754         real_size = info.size;
755
756     bo_exynos4412 = calloc (1, sizeof(struct _tbm_bo_exynos4412));
757     if (!bo_exynos4412)
758     {
759         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
760                 "error %s:%d fail to allocate the bo private\n",
761                 getpid(), __FUNCTION__, __LINE__);
762         return 0;
763     }
764
765     bo_exynos4412->fd = bufmgr_exynos4412->fd;
766     bo_exynos4412->gem = gem;
767     bo_exynos4412->size = real_size;
768     bo_exynos4412->flags_exynos = info.flags;
769     bo_exynos4412->flags_tbm = _get_tbm_flag_from_exynos (bo_exynos4412->flags_exynos);
770
771     bo_exynos4412->name = _get_name(bo_exynos4412->fd, bo_exynos4412->gem);
772     if (!bo_exynos4412->name)
773     {
774         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
775                 "error %s:%d Cannot get name\n",
776                 getpid(), __FUNCTION__, __LINE__);
777         return 0;
778     }
779
780         bo_exynos4412->dmabuf = (unsigned int)key;
781
782     /* add bo to hash */
783     PrivGem *privGem = NULL;
784     int ret;
785
786     ret = drmHashLookup (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void**)&privGem);
787     if (ret == 0)
788     {
789         privGem->ref_count++;
790     }
791     else if (ret == 1)
792     {
793         privGem = calloc (1, sizeof(PrivGem));
794         privGem->ref_count = 1;
795         if (drmHashInsert (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void *)privGem) < 0)
796         {
797             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
798                     "error %s:%d Cannot insert bo to Hash(%d)\n",
799                     getpid(), __FUNCTION__, __LINE__, bo_exynos4412->name);
800         }
801     }
802     else
803     {
804         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
805                 "error %s:%d Cannot insert bo to Hash(%d)\n",
806                 getpid(), __FUNCTION__, __LINE__, bo_exynos4412->name);
807     }
808
809     DBG ("[libtbm-exynos4412:%d] %s size:%d, gem:%d(%d,%d), flags:%d(%d)\n", getpid(),
810          __FUNCTION__, bo_exynos4412->size,
811          bo_exynos4412->gem, bo_exynos4412->name, bo_exynos4412->dmabuf,
812          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos);
813
814     return (void *)bo_exynos4412;
815 }
816
817 static unsigned int
818 tbm_exynos4412_bo_export (tbm_bo bo)
819 {
820     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
821
822     tbm_bo_exynos4412 bo_exynos4412;
823
824     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
825     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
826
827     if (!bo_exynos4412->name)
828     {
829         bo_exynos4412->name = _get_name(bo_exynos4412->fd, bo_exynos4412->gem);
830         if (!bo_exynos4412->name)
831         {
832             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
833                     "error %s:%d Cannot get name\n",
834                     getpid(), __FUNCTION__, __LINE__);
835             return 0;
836         }
837     }
838
839     DBG ("[libtbm-exynos4412:%d] %s size:%d, gem:%d(%d), flags:%d(%d)\n", getpid(),
840          __FUNCTION__, bo_exynos4412->size,
841          bo_exynos4412->gem, bo_exynos4412->name,
842          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos);
843
844     return (unsigned int)bo_exynos4412->name;
845 }
846
847 tbm_fd
848 tbm_exynos4412_bo_export_fd (tbm_bo bo)
849 {
850     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
851
852     tbm_bo_exynos4412 bo_exynos4412;
853
854     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
855     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
856
857     if (!bo_exynos4412->dmabuf)
858     {
859         struct drm_prime_handle arg = {0, };
860
861         arg.handle = bo_exynos4412->gem;
862         if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
863         {
864             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
865                      "error %s:%d Cannot dmabuf=%d\n",
866                      getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
867             return (tbm_fd) 0;
868         }
869         bo_exynos4412->dmabuf = arg.fd;
870     }
871
872     DBG ("[libtbm-exynos4412:%d] %s size:%d, gem:%d(%d, %d), flags:%d(%d)\n", getpid(),
873          __FUNCTION__, bo_exynos4412->size,
874          bo_exynos4412->gem, bo_exynos4412->name, bo_exynos4412->dmabuf,
875          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos);
876
877     return (tbm_fd)bo_exynos4412->dmabuf;
878 }
879
880 static tbm_bo_handle
881 tbm_exynos4412_bo_get_handle (tbm_bo bo, int device)
882 {
883     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, (tbm_bo_handle) NULL);
884
885     tbm_bo_handle bo_handle;
886     tbm_bo_exynos4412 bo_exynos4412;
887
888     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
889     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, (tbm_bo_handle) NULL);
890
891     if (!bo_exynos4412->gem)
892     {
893         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
894                 "error %s:%d Cannot map gem=%d\n",
895                 getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
896         return (tbm_bo_handle) NULL;
897     }
898
899     DBG ("[libtbm-exynos4412:%d] %s gem:%d(%d), %s\n", getpid(),
900          __FUNCTION__, bo_exynos4412->gem, bo_exynos4412->name, STR_DEVICE[device]);
901
902     /*Get mapped bo_handle*/
903     bo_handle = _exynos4412_bo_handle (bo_exynos4412, device);
904     if (bo_handle.ptr == NULL)
905     {
906         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
907                 "error %s:%d Cannot get handle: gem:%d, device:%d\n",
908                 getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem, device);
909         return (tbm_bo_handle) NULL;
910     }
911
912     return bo_handle;
913 }
914
915 static tbm_bo_handle
916 tbm_exynos4412_bo_map (tbm_bo bo, int device, int opt)
917 {
918     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, (tbm_bo_handle) NULL);
919
920     tbm_bo_handle bo_handle;
921     tbm_bo_exynos4412 bo_exynos4412;
922
923     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
924     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, (tbm_bo_handle) NULL);
925
926     if (!bo_exynos4412->gem)
927     {
928         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
929                 "error %s:%d Cannot map gem=%d\n",
930                 getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem);
931         return (tbm_bo_handle) NULL;
932     }
933
934     DBG ("[libtbm-exynos4412:%d] %s gem:%d(%d), %s, %s\n", getpid(),
935          __FUNCTION__, bo_exynos4412->gem, bo_exynos4412->name, STR_DEVICE[device], STR_OPT[opt]);
936
937     /*Get mapped bo_handle*/
938     bo_handle = _exynos4412_bo_handle (bo_exynos4412, device);
939     if (bo_handle.ptr == NULL)
940     {
941         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
942                 "error %s:%d Cannot get handle: gem:%d, device:%d, opt:%d\n",
943                 getpid(), __FUNCTION__, __LINE__, bo_exynos4412->gem, device, opt);
944         return (tbm_bo_handle) NULL;
945     }
946
947     return bo_handle;
948 }
949
950 static int
951 tbm_exynos4412_bo_unmap (tbm_bo bo)
952 {
953     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
954
955     tbm_bo_exynos4412 bo_exynos4412;
956
957     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
958     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
959
960     if (!bo_exynos4412->gem)
961         return 0;
962
963     DBG ("[libtbm-exynos4412:%d] %s gem:%d(%d) \n", getpid(),
964          __FUNCTION__, bo_exynos4412->gem, bo_exynos4412->name);
965
966     return 1;
967 }
968
969 static int
970 tbm_exynos4412_bo_cache_flush (tbm_bo bo, int flags)
971 {
972     tbm_bufmgr_exynos4412 bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
973     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
974
975     /* cache flush is managed by kernel side when using dma-fence. */
976     if (bufmgr_exynos4412->use_dma_fence)
977        return 1;
978
979     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
980
981     tbm_bo_exynos4412 bo_exynos4412;
982
983     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
984     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
985
986     if (!_exynos4412_cache_flush(bo_exynos4412->fd, bo_exynos4412, flags))
987         return 0;
988
989     return 1;
990 }
991
992 static int
993 tbm_exynos4412_bo_get_global_key (tbm_bo bo)
994 {
995     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
996
997     tbm_bo_exynos4412 bo_exynos4412;
998
999     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
1000     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
1001
1002     if (!bo_exynos4412->name)
1003     {
1004         if (!bo_exynos4412->gem)
1005             return 0;
1006
1007         bo_exynos4412->name = _get_name(bo_exynos4412->fd, bo_exynos4412->gem);
1008     }
1009
1010     return bo_exynos4412->name;
1011 }
1012
1013 static int
1014 tbm_exynos4412_bo_lock(tbm_bo bo, int device, int opt)
1015 {
1016     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
1017
1018     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
1019     tbm_bo_exynos4412 bo_exynos4412;
1020     struct dma_buf_fence fence;
1021     struct flock filelock;
1022     int ret=0;
1023
1024     if (device != TBM_DEVICE_3D && device != TBM_DEVICE_CPU)
1025     {
1026         DBG ("[libtbm-exynos4412:%d] %s not support device type,\n", getpid(), __FUNCTION__);
1027             return 0;
1028     }
1029
1030     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
1031     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
1032
1033     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
1034     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
1035
1036     memset(&fence, 0, sizeof(struct dma_buf_fence));
1037
1038     /* Check if the given type is valid or not. */
1039     if (opt & TBM_OPTION_WRITE)
1040     {
1041         if (device == TBM_DEVICE_3D)
1042             fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1043     }
1044     else if (opt & TBM_OPTION_READ)
1045     {
1046         if (device == TBM_DEVICE_3D)
1047             fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1048     }
1049     else
1050     {
1051         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] error %s:%d Invalid argument\n", getpid(), __FUNCTION__, __LINE__);
1052         return 0;
1053     }
1054
1055     /* Check if the tbm manager supports dma fence or not. */
1056     if (!bufmgr_exynos4412->use_dma_fence)
1057     {
1058         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
1059                 "error %s:%d  Not support DMA FENCE(%s)\n",
1060                 getpid(), __FUNCTION__, __LINE__, strerror(errno) );
1061         return 0;
1062
1063     }
1064
1065     if (device == TBM_DEVICE_3D)
1066     {
1067         ret = ioctl(bo_exynos4412->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1068         if (ret < 0)
1069         {
1070             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
1071                     "error %s:%d  Can not set GET FENCE(%s)\n",
1072                     getpid(), __FUNCTION__, __LINE__, strerror(errno) );
1073             return 0;
1074         }
1075     } else
1076     {
1077         if (opt & TBM_OPTION_WRITE)
1078             filelock.l_type = F_WRLCK;
1079         else
1080             filelock.l_type = F_RDLCK;
1081
1082         filelock.l_whence = SEEK_CUR;
1083         filelock.l_start = 0;
1084         filelock.l_len = 0;
1085
1086         if (-1 == fcntl(bo_exynos4412->dmabuf, F_SETLKW, &filelock))
1087         {
1088             return 0;
1089         }
1090     }
1091
1092     pthread_mutex_lock(&bo_exynos4412->mutex);
1093
1094     if (device == TBM_DEVICE_3D)
1095     {
1096         int i;
1097         for (i = 0; i < DMA_FENCE_LIST_MAX; i++)
1098         {
1099             if (bo_exynos4412->dma_fence[i].ctx == 0)
1100             {
1101                 bo_exynos4412->dma_fence[i].type = fence.type;
1102                 bo_exynos4412->dma_fence[i].ctx = fence.ctx;
1103                 break;
1104             }
1105         }
1106
1107         if (i == DMA_FENCE_LIST_MAX)
1108         {
1109             //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1110             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
1111                     "error %s:%d  fence list is full\n",
1112                     getpid(), __FUNCTION__, __LINE__);
1113         }
1114     }
1115
1116     pthread_mutex_unlock(&bo_exynos4412->mutex);
1117
1118     DBG ("[libtbm-exynos4412:%d] %s DMABUF_IOCTL_GET_FENCE! flink_id=%d dmabuf=%d\n", getpid(),
1119             __FUNCTION__, bo_exynos4412->name, bo_exynos4412->dmabuf);
1120
1121     return 1;
1122 }
1123
1124 static int
1125 tbm_exynos4412_bo_unlock(tbm_bo bo)
1126 {
1127     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
1128
1129     tbm_bo_exynos4412 bo_exynos4412;
1130     struct dma_buf_fence fence;
1131     struct flock filelock;
1132     unsigned int dma_type = 0;
1133     int ret=0;
1134
1135     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
1136     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
1137
1138     if (bo_exynos4412->dma_fence[0].type & DMA_BUF_ACCESS_DMA)
1139             dma_type = 1;
1140
1141     if (!bo_exynos4412->dma_fence[0].ctx && dma_type)
1142     {
1143         DBG ("[libtbm-exynos4412:%d] %s FENCE not support or ignored,\n", getpid(), __FUNCTION__);
1144         return 0;
1145     }
1146
1147     if (!bo_exynos4412->dma_fence[0].ctx && dma_type)
1148     {
1149         DBG ("[libtbm-exynos4412:%d] %s device type is not 3D/CPU,\n", getpid(), __FUNCTION__);
1150         return 0;
1151     }
1152
1153     pthread_mutex_lock(&bo_exynos4412->mutex);
1154
1155     if (dma_type)
1156     {
1157         fence.type = bo_exynos4412->dma_fence[0].type;
1158         fence.ctx = bo_exynos4412->dma_fence[0].ctx;
1159         int i;
1160         for (i = 1; i < DMA_FENCE_LIST_MAX; i++)
1161         {
1162             bo_exynos4412->dma_fence[i-1].type = bo_exynos4412->dma_fence[i].type;
1163             bo_exynos4412->dma_fence[i-1].ctx = bo_exynos4412->dma_fence[i].ctx;
1164         }
1165         bo_exynos4412->dma_fence[DMA_FENCE_LIST_MAX-1].type = 0;
1166         bo_exynos4412->dma_fence[DMA_FENCE_LIST_MAX-1].ctx = 0;
1167     }
1168     pthread_mutex_unlock(&bo_exynos4412->mutex);
1169
1170     if (dma_type)
1171     {
1172         ret = ioctl(bo_exynos4412->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1173         if (ret < 0)
1174         {
1175             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
1176                     "error %s:%d  Can not set PUT FENCE(%s)\n",
1177                     getpid(), __FUNCTION__, __LINE__, strerror(errno) );
1178             return 0;
1179         }
1180     } else
1181     {
1182         filelock.l_type = F_UNLCK;
1183         filelock.l_whence = SEEK_CUR;
1184         filelock.l_start = 0;
1185         filelock.l_len = 0;
1186
1187         if (-1 == fcntl(bo_exynos4412->dmabuf, F_SETLKW, &filelock))
1188         {
1189             return 0;
1190         }
1191     }
1192
1193     DBG ("[libtbm-exynos4412:%d] %s DMABUF_IOCTL_PUT_FENCE! flink_id=%d dmabuf=%d\n", getpid(),
1194             __FUNCTION__, bo_exynos4412->name, bo_exynos4412->dmabuf);
1195
1196     return 1;
1197 }
1198
1199 static void
1200 tbm_exynos4412_bufmgr_deinit (void *priv)
1201 {
1202     EXYNOS4412_RETURN_IF_FAIL (priv!=NULL);
1203
1204     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
1205
1206     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)priv;
1207
1208     if (bufmgr_exynos4412->hashBos)
1209     {
1210         unsigned long key;
1211         void *value;
1212
1213         while (drmHashFirst(bufmgr_exynos4412->hashBos, &key, &value) > 0)
1214         {
1215             free (value);
1216             drmHashDelete (bufmgr_exynos4412->hashBos, key);
1217         }
1218
1219         drmHashDestroy (bufmgr_exynos4412->hashBos);
1220         bufmgr_exynos4412->hashBos = NULL;
1221     }
1222
1223     free (bufmgr_exynos4412);
1224 }
1225
1226 int
1227 tbm_exynos4412_surface_supported_format(uint32_t **formats, uint32_t *num)
1228 {
1229     uint32_t* color_formats=NULL;
1230
1231     color_formats = (uint32_t*)calloc (1,sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1232
1233     if( color_formats == NULL )
1234     {
1235         return 0;
1236     }
1237     memcpy( color_formats, tbm_exynos4412_color_format_list , sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT );
1238
1239
1240     *formats = color_formats;
1241     *num = TBM_COLOR_FORMAT_COUNT;
1242
1243     fprintf (stderr, "tbm_exynos4412_surface_supported_format  count = %d \n",*num);
1244
1245     return 1;
1246 }
1247
1248
1249 /**
1250  * @brief get the plane data of the surface.
1251  * @param[in] surface : the surface
1252  * @param[in] width : the width of the surface
1253  * @param[in] height : the height of the surface
1254  * @param[in] format : the format of the surface
1255  * @param[in] plane_idx : the format of the surface
1256  * @param[out] size : the size of the plane
1257  * @param[out] offset : the offset of the plane
1258  * @param[out] pitch : the pitch of the plane
1259  * @param[out] padding : the padding of the plane
1260  * @return 1 if this function succeeds, otherwise 0.
1261  */
1262 int
1263 tbm_exynos4412_surface_get_plane_data(tbm_surface_h surface, int width, int height, tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
1264 {
1265     int ret = 1;
1266     int bpp;
1267     int _offset =0;
1268     int _pitch =0;
1269     int _size =0;
1270
1271
1272     switch(format)
1273     {
1274         /* 16 bpp RGB */
1275         case TBM_FORMAT_XRGB4444:
1276         case TBM_FORMAT_XBGR4444:
1277         case TBM_FORMAT_RGBX4444:
1278         case TBM_FORMAT_BGRX4444:
1279         case TBM_FORMAT_ARGB4444:
1280         case TBM_FORMAT_ABGR4444:
1281         case TBM_FORMAT_RGBA4444:
1282         case TBM_FORMAT_BGRA4444:
1283         case TBM_FORMAT_XRGB1555:
1284         case TBM_FORMAT_XBGR1555:
1285         case TBM_FORMAT_RGBX5551:
1286         case TBM_FORMAT_BGRX5551:
1287         case TBM_FORMAT_ARGB1555:
1288         case TBM_FORMAT_ABGR1555:
1289         case TBM_FORMAT_RGBA5551:
1290         case TBM_FORMAT_BGRA5551:
1291         case TBM_FORMAT_RGB565:
1292             bpp = 16;
1293             _offset = 0;
1294                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1295             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1296             break;
1297         /* 24 bpp RGB */
1298         case TBM_FORMAT_RGB888:
1299         case TBM_FORMAT_BGR888:
1300             bpp = 24;
1301             _offset = 0;
1302                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1303             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1304             break;
1305         /* 32 bpp RGB */
1306         case TBM_FORMAT_XRGB8888:
1307         case TBM_FORMAT_XBGR8888:
1308         case TBM_FORMAT_RGBX8888:
1309         case TBM_FORMAT_BGRX8888:
1310         case TBM_FORMAT_ARGB8888:
1311         case TBM_FORMAT_ABGR8888:
1312         case TBM_FORMAT_RGBA8888:
1313         case TBM_FORMAT_BGRA8888:
1314             bpp = 32;
1315             _offset = 0;
1316                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1317             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1318             break;
1319
1320         /* packed YCbCr */
1321         case TBM_FORMAT_YUYV:
1322         case TBM_FORMAT_YVYU:
1323         case TBM_FORMAT_UYVY:
1324         case TBM_FORMAT_VYUY:
1325         case TBM_FORMAT_AYUV:
1326             bpp = 32;
1327             _offset = 0;
1328                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1329             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1330             break;
1331
1332         /*
1333         * 2 plane YCbCr
1334         * index 0 = Y plane, [7:0] Y
1335         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1336         * or
1337         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1338         */
1339         case TBM_FORMAT_NV12:
1340         case TBM_FORMAT_NV21:
1341             bpp = 12;
1342             if(plane_idx == 0)
1343             {
1344                 _offset = 0;
1345                                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1346                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1347             }
1348             else if( plane_idx ==1 )
1349             {
1350                 _offset = width*height;
1351                                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1352                                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1353             }
1354             break;
1355
1356         case TBM_FORMAT_NV16:
1357         case TBM_FORMAT_NV61:
1358                         bpp = 16;
1359             //if(plane_idx == 0)
1360             {
1361                 _offset = 0;
1362                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1363                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1364                 if(plane_idx == 0)
1365                         break;
1366             }
1367             //else if( plane_idx ==1 )
1368             {
1369                 _offset += _size;
1370                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1371                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1372             }
1373             break;
1374
1375         /*
1376         * 3 plane YCbCr
1377         * index 0: Y plane, [7:0] Y
1378         * index 1: Cb plane, [7:0] Cb
1379         * index 2: Cr plane, [7:0] Cr
1380         * or
1381         * index 1: Cr plane, [7:0] Cr
1382         * index 2: Cb plane, [7:0] Cb
1383         */
1384         /*
1385         NATIVE_BUFFER_FORMAT_YV12
1386         NATIVE_BUFFER_FORMAT_I420
1387         */
1388         case TBM_FORMAT_YUV410:
1389         case TBM_FORMAT_YVU410:
1390             bpp = 9;
1391             break;
1392         case TBM_FORMAT_YUV411:
1393         case TBM_FORMAT_YVU411:
1394         case TBM_FORMAT_YUV420:
1395         case TBM_FORMAT_YVU420:
1396             bpp = 12;
1397             //if(plane_idx == 0)
1398             {
1399                 _offset = 0;
1400                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1401                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1402                         if(plane_idx == 0)
1403                                 break;
1404             }
1405             //else if( plane_idx == 1 )
1406             {
1407                 _offset += _size;
1408                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1409                         _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1410                         if(plane_idx == 1)
1411                                 break;
1412             }
1413             //else if (plane_idx == 2 )
1414             {
1415                 _offset += _size;
1416                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1417                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1418             }
1419             break;
1420         case TBM_FORMAT_YUV422:
1421         case TBM_FORMAT_YVU422:
1422             bpp = 16;
1423             //if(plane_idx == 0)
1424             {
1425                 _offset = 0;
1426                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1427                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1428                         if(plane_idx == 0)
1429                                 break;
1430             }
1431             //else if( plane_idx == 1 )
1432             {
1433                 _offset += _size;
1434                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1435                         _size = SIZE_ALIGN(_pitch*(height),TBM_SURFACE_ALIGNMENT_PLANE);
1436                         if(plane_idx == 1)
1437                                 break;
1438             }
1439             //else if (plane_idx == 2 )
1440             {
1441                 _offset += _size;
1442                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1443                 _size = SIZE_ALIGN(_pitch*(height),TBM_SURFACE_ALIGNMENT_PLANE);
1444             }
1445             break;
1446         case TBM_FORMAT_YUV444:
1447         case TBM_FORMAT_YVU444:
1448             bpp = 24;
1449             //if(plane_idx == 0)
1450             {
1451                 _offset = 0;
1452                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1453                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1454                         if(plane_idx == 0)
1455                                 break;
1456             }
1457             //else if( plane_idx == 1 )
1458             {
1459                 _offset += _size;
1460                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1461                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1462                         if(plane_idx == 1)
1463                                 break;
1464             }
1465             //else if (plane_idx == 2 )
1466             {
1467                 _offset += _size;
1468                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1469                _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1470             }
1471             break;
1472         default:
1473             bpp = 0;
1474             break;
1475     }
1476
1477     *size = _size;
1478     *offset = _offset;
1479     *pitch = _pitch;
1480
1481     return ret;
1482 }
1483 /**
1484 * @brief get the size of the surface with a format.
1485 * @param[in] surface : the surface
1486 * @param[in] width : the width of the surface
1487 * @param[in] height : the height of the surface
1488 * @param[in] format : the format of the surface
1489 * @return size of the surface if this function succeeds, otherwise 0.
1490 */
1491
1492 int
1493 tbm_exynos4412_surface_get_size(tbm_surface_h surface, int width, int height, tbm_format format)
1494 {
1495         int ret = 0;
1496         int bpp = 0;
1497         int _pitch =0;
1498         int _size =0;
1499         int align =TBM_SURFACE_ALIGNMENT_PLANE;
1500
1501     switch(format)
1502     {
1503         /* 16 bpp RGB */
1504         case TBM_FORMAT_XRGB4444:
1505         case TBM_FORMAT_XBGR4444:
1506         case TBM_FORMAT_RGBX4444:
1507         case TBM_FORMAT_BGRX4444:
1508         case TBM_FORMAT_ARGB4444:
1509         case TBM_FORMAT_ABGR4444:
1510         case TBM_FORMAT_RGBA4444:
1511         case TBM_FORMAT_BGRA4444:
1512         case TBM_FORMAT_XRGB1555:
1513         case TBM_FORMAT_XBGR1555:
1514         case TBM_FORMAT_RGBX5551:
1515         case TBM_FORMAT_BGRX5551:
1516         case TBM_FORMAT_ARGB1555:
1517         case TBM_FORMAT_ABGR1555:
1518         case TBM_FORMAT_RGBA5551:
1519         case TBM_FORMAT_BGRA5551:
1520         case TBM_FORMAT_RGB565:
1521             bpp = 16;
1522                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1523             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1524             break;
1525         /* 24 bpp RGB */
1526         case TBM_FORMAT_RGB888:
1527         case TBM_FORMAT_BGR888:
1528             bpp = 24;
1529                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1530             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1531             break;
1532         /* 32 bpp RGB */
1533         case TBM_FORMAT_XRGB8888:
1534         case TBM_FORMAT_XBGR8888:
1535         case TBM_FORMAT_RGBX8888:
1536         case TBM_FORMAT_BGRX8888:
1537         case TBM_FORMAT_ARGB8888:
1538         case TBM_FORMAT_ABGR8888:
1539         case TBM_FORMAT_RGBA8888:
1540         case TBM_FORMAT_BGRA8888:
1541             bpp = 32;
1542                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1543             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1544             break;
1545         /* packed YCbCr */
1546         case TBM_FORMAT_YUYV:
1547         case TBM_FORMAT_YVYU:
1548         case TBM_FORMAT_UYVY:
1549         case TBM_FORMAT_VYUY:
1550         case TBM_FORMAT_AYUV:
1551             bpp = 32;
1552                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1553             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1554             break;
1555         /*
1556         * 2 plane YCbCr
1557         * index 0 = Y plane, [7:0] Y
1558         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1559         * or
1560         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1561         */
1562         case TBM_FORMAT_NV12:
1563         case TBM_FORMAT_NV21:
1564                         bpp = 12;
1565                          //plane_idx == 0
1566                          {
1567                                  _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1568                                  _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1569                          }
1570                          //plane_idx ==1
1571                          {
1572                                  _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1573                                  _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1574                          }
1575                          break;
1576
1577             break;
1578         case TBM_FORMAT_NV16:
1579         case TBM_FORMAT_NV61:
1580             bpp = 16;
1581             //plane_idx == 0
1582             {
1583                                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1584                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1585             }
1586             //plane_idx ==1
1587             {
1588                             _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1589                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1590             }
1591
1592             break;
1593         /*
1594         * 3 plane YCbCr
1595         * index 0: Y plane, [7:0] Y
1596         * index 1: Cb plane, [7:0] Cb
1597         * index 2: Cr plane, [7:0] Cr
1598         * or
1599         * index 1: Cr plane, [7:0] Cr
1600         * index 2: Cb plane, [7:0] Cb
1601         */
1602         case TBM_FORMAT_YUV410:
1603         case TBM_FORMAT_YVU410:
1604             bpp = 9;
1605             align = TBM_SURFACE_ALIGNMENT_PITCH_YUV;
1606             break;
1607         case TBM_FORMAT_YUV411:
1608         case TBM_FORMAT_YVU411:
1609         case TBM_FORMAT_YUV420:
1610         case TBM_FORMAT_YVU420:
1611             bpp = 12;
1612             //plane_idx == 0
1613             {
1614                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1615                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1616             }
1617             //plane_idx == 1
1618             {
1619                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1620                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1621             }
1622             //plane_idx == 2
1623             {
1624                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1625                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1626             }
1627
1628             break;
1629         case TBM_FORMAT_YUV422:
1630         case TBM_FORMAT_YVU422:
1631             bpp = 16;
1632             //plane_idx == 0
1633             {
1634                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1635                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1636             }
1637             //plane_idx == 1
1638             {
1639                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1640                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1641             }
1642             //plane_idx == 2
1643             {
1644                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1645                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1646             }
1647             break;
1648         case TBM_FORMAT_YUV444:
1649         case TBM_FORMAT_YVU444:
1650             bpp = 24;
1651             align = TBM_SURFACE_ALIGNMENT_PITCH_YUV;
1652             break;
1653
1654         default:
1655             bpp = 0;
1656             break;
1657     }
1658
1659         if(_size > 0)
1660                 ret = _size;
1661         else
1662             ret =  SIZE_ALIGN( (width * height * bpp) >> 3, align);
1663
1664     return ret;
1665
1666 }
1667
1668 MODULEINITPPROTO (init_tbm_bufmgr_priv);
1669
1670 static TBMModuleVersionInfo Exynos4412VersRec =
1671 {
1672     "exynos4412",
1673     "Samsung",
1674     TBM_ABI_VERSION,
1675 };
1676
1677 TBMModuleData tbmModuleData = { &Exynos4412VersRec, init_tbm_bufmgr_priv};
1678
1679 int
1680 init_tbm_bufmgr_priv (tbm_bufmgr bufmgr, int fd)
1681 {
1682     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
1683     tbm_bufmgr_backend bufmgr_backend;
1684
1685     if (!bufmgr)
1686         return 0;
1687
1688     bufmgr_exynos4412 = calloc (1, sizeof(struct _tbm_bufmgr_exynos4412));
1689     if (!bufmgr_exynos4412)
1690     {
1691         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] error: Fail to alloc bufmgr_exynos4412!\n", getpid());
1692         return 0;
1693     }
1694
1695     bufmgr_exynos4412->fd = fd;
1696     if (bufmgr_exynos4412->fd < 0)
1697     {
1698         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] error: Fail to create drm!\n", getpid());
1699         free (bufmgr_exynos4412);
1700         return 0;
1701     }
1702
1703     //Create Hash Table
1704     bufmgr_exynos4412->hashBos = drmHashCreate ();
1705
1706     //Check if the tbm manager supports dma fence or not.
1707     int fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1708     int length;
1709     char buf[1];
1710     if (fp != -1)
1711     {
1712         length = read(fp, buf, 1);
1713
1714         if (length == 1 && buf[0] == '1')
1715             bufmgr_exynos4412->use_dma_fence = 1;
1716
1717         close(fp);
1718     }
1719
1720     bufmgr_backend = tbm_backend_alloc();
1721     if (!bufmgr_backend)
1722     {
1723         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] error: Fail to create drm!\n", getpid());
1724         free (bufmgr_exynos4412);
1725         return 0;
1726     }
1727
1728     bufmgr_backend->priv = (void *)bufmgr_exynos4412;
1729     bufmgr_backend->bufmgr_deinit = tbm_exynos4412_bufmgr_deinit,
1730     bufmgr_backend->bo_size = tbm_exynos4412_bo_size,
1731     bufmgr_backend->bo_alloc = tbm_exynos4412_bo_alloc,
1732     bufmgr_backend->bo_free = tbm_exynos4412_bo_free,
1733     bufmgr_backend->bo_import = tbm_exynos4412_bo_import,
1734     bufmgr_backend->bo_import_fd = tbm_exynos4412_bo_import_fd,
1735     bufmgr_backend->bo_export = tbm_exynos4412_bo_export,
1736     bufmgr_backend->bo_export_fd = tbm_exynos4412_bo_export_fd,
1737     bufmgr_backend->bo_get_handle = tbm_exynos4412_bo_get_handle,
1738     bufmgr_backend->bo_map = tbm_exynos4412_bo_map,
1739     bufmgr_backend->bo_unmap = tbm_exynos4412_bo_unmap,
1740     bufmgr_backend->bo_cache_flush = tbm_exynos4412_bo_cache_flush,
1741     bufmgr_backend->bo_get_global_key = tbm_exynos4412_bo_get_global_key;
1742     bufmgr_backend->surface_get_plane_data = tbm_exynos4412_surface_get_plane_data;
1743     bufmgr_backend->surface_get_size = tbm_exynos4412_surface_get_size;
1744     bufmgr_backend->surface_supported_format = tbm_exynos4412_surface_supported_format;
1745
1746     if (bufmgr_exynos4412->use_dma_fence)
1747     {
1748         bufmgr_backend->flags = (TBM_LOCK_CTRL_BACKEND | TBM_CACHE_CTRL_BACKEND);
1749         bufmgr_backend->bo_lock = NULL;
1750         bufmgr_backend->bo_lock2 = tbm_exynos4412_bo_lock;
1751         bufmgr_backend->bo_unlock = tbm_exynos4412_bo_unlock;
1752     }
1753     else
1754     {
1755         bufmgr_backend->flags = 0;
1756         bufmgr_backend->bo_lock = NULL;
1757         bufmgr_backend->bo_unlock = NULL;
1758     }
1759
1760     if (!tbm_backend_init (bufmgr, bufmgr_backend))
1761     {
1762         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] error: Fail to init backend!\n", getpid());
1763         tbm_backend_free (bufmgr_backend);
1764         free (bufmgr_exynos4412);
1765         return 0;
1766     }
1767
1768 #ifdef DEBUG
1769     {
1770         char* env;
1771         env = getenv ("TBM_EXYNOS4412_DEBUG");
1772         if (env)
1773         {
1774             bDebug = atoi (env);
1775             TBM_EXYNOS4412_LOG ("TBM_EXYNOS4412_DEBUG=%s\n", env);
1776         }
1777         else
1778         {
1779             bDebug = 0;
1780         }
1781     }
1782 #endif
1783
1784     DBG ("[libtbm-exynos4412:%d] %s DMABUF FENCE is %s\n", getpid(),
1785          __FUNCTION__, bufmgr_exynos4412->use_dma_fence ? "supported!" : "NOT supported!");
1786
1787     DBG ("[libtbm-exynos4412:%d] %s fd:%d\n", getpid(),
1788          __FUNCTION__, bufmgr_exynos4412->fd);
1789
1790     return 1;
1791 }
1792
1793