export_fd returns negative value if fail
[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(fmt, ##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 ("error fail to get flink from gem:%d (DRM_IOCTL_GEM_FLINK)\n",
274                 gem);
275         return 0;
276     }
277
278     return (unsigned int)arg.name;
279 }
280
281 static tbm_bo_handle
282 _exynos4412_bo_handle (tbm_bo_exynos4412 bo_exynos4412, int device)
283 {
284     tbm_bo_handle bo_handle;
285     memset (&bo_handle, 0x0, sizeof (uint64_t));
286
287     switch(device)
288     {
289     case TBM_DEVICE_DEFAULT:
290     case TBM_DEVICE_2D:
291         bo_handle.u32 = (uint32_t)bo_exynos4412->gem;
292         break;
293     case TBM_DEVICE_CPU:
294         if (!bo_exynos4412->pBase)
295         {
296             struct drm_mode_map_dumb arg = {0,};
297             void *map = NULL;
298
299             arg.handle = bo_exynos4412->gem;
300             if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg))
301             {
302                TBM_EXYNOS4412_LOG ("error Cannot map_dumb gem=%d\n", bo_exynos4412->gem);
303                return (tbm_bo_handle) NULL;
304             }
305
306             map = mmap (NULL, bo_exynos4412->size, PROT_READ|PROT_WRITE, MAP_SHARED,
307                               bo_exynos4412->fd, arg.offset);
308             if (map == MAP_FAILED)
309             {
310                 TBM_EXYNOS4412_LOG ("error Cannot usrptr gem=%d\n", bo_exynos4412->gem);
311                 return (tbm_bo_handle) NULL;
312             }
313             bo_exynos4412->pBase = map;
314         }
315         bo_handle.ptr = (void *)bo_exynos4412->pBase;
316         break;
317     case TBM_DEVICE_3D:
318 #ifdef USE_DMAIMPORT
319         if (bo_exynos4412->dmabuf)
320         {
321             bo_handle.u32 = (uint32_t)bo_exynos4412->dmabuf;
322             break;
323         }
324
325         if (!bo_exynos4412->dmabuf)
326         {
327             struct drm_prime_handle arg = {0, };
328
329             arg.handle = bo_exynos4412->gem;
330             if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
331             {
332                 TBM_EXYNOS4412_LOG ("error Cannot dmabuf=%d\n", bo_exynos4412->gem);
333                 return (tbm_bo_handle) NULL;
334             }
335             bo_exynos4412->dmabuf = arg.fd;
336         }
337
338         bo_handle.u32 = (uint32_t)bo_exynos4412->dmabuf;
339 #endif
340         break;
341     case TBM_DEVICE_MM:
342         if (!bo_exynos4412->dmabuf)
343         {
344             struct drm_prime_handle arg = {0, };
345
346             arg.handle = bo_exynos4412->gem;
347             if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
348             {
349                 TBM_EXYNOS4412_LOG ("error Cannot dmabuf=%d\n", bo_exynos4412->gem);
350                 return (tbm_bo_handle) NULL;
351             }
352             bo_exynos4412->dmabuf = arg.fd;
353         }
354
355         bo_handle.u32 = (uint32_t)bo_exynos4412->dmabuf;
356         break;
357     default:
358         TBM_EXYNOS4412_LOG ("error Not supported device:%d\n", device);
359         bo_handle.ptr = (void *) NULL;
360         break;
361     }
362
363     return bo_handle;
364 }
365
366 static int
367 _exynos4412_cache_flush (int fd, tbm_bo_exynos4412 bo_exynos4412, int flags)
368 {
369 #ifdef ENABLE_CACHECRTL
370     struct drm_exynos_gem_cache_op cache_op = {0, };
371     int ret;
372
373     /* if bo_exynos4412 is null, do cache_flush_all */
374     if(bo_exynos4412)
375     {
376         cache_op.flags = 0;
377         cache_op.usr_addr = (uint64_t)((uint32_t)bo_exynos4412->pBase);
378         cache_op.size = bo_exynos4412->size;
379     }
380     else
381     {
382         flags = TBM_CACHE_FLUSH_ALL;
383         cache_op.flags = 0;
384         cache_op.usr_addr = 0;
385         cache_op.size = 0;
386     }
387
388     if (flags & TBM_CACHE_INV)
389     {
390         if(flags & TBM_CACHE_ALL)
391             cache_op.flags |= EXYNOS_DRM_CACHE_INV_ALL;
392         else
393             cache_op.flags |= EXYNOS_DRM_CACHE_INV_RANGE;
394     }
395
396     if (flags & TBM_CACHE_CLN)
397     {
398         if(flags & TBM_CACHE_ALL)
399             cache_op.flags |= EXYNOS_DRM_CACHE_CLN_ALL;
400         else
401             cache_op.flags |= EXYNOS_DRM_CACHE_CLN_RANGE;
402     }
403
404     if(flags & TBM_CACHE_ALL)
405         cache_op.flags |= EXYNOS_DRM_ALL_CACHES_CORES;
406
407     ret = drmCommandWriteRead (fd, DRM_EXYNOS_GEM_CACHE_OP, &cache_op, sizeof(cache_op));
408     if (ret)
409     {
410         TBM_EXYNOS4412_LOG ("error fail to flush the cache.\n");
411         return 0;
412     }
413 #else
414     TBM_EXYNOS4412_LOG ("warning fail to enable the cache flush.\n");
415 #endif
416     return 1;
417 }
418
419 static int
420 tbm_exynos4412_bo_size (tbm_bo bo)
421 {
422     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
423
424     tbm_bo_exynos4412 bo_exynos4412;
425
426     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
427
428     return bo_exynos4412->size;
429 }
430
431 static void *
432 tbm_exynos4412_bo_alloc (tbm_bo bo, int size, int flags)
433 {
434     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
435
436     tbm_bo_exynos4412 bo_exynos4412;
437     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
438     unsigned int exynos_flags;
439
440     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
441     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
442
443     bo_exynos4412 = calloc (1, sizeof(struct _tbm_bo_exynos4412));
444     if (!bo_exynos4412)
445     {
446         TBM_EXYNOS4412_LOG ("error fail to allocate the bo private\n");
447         return 0;
448     }
449
450     exynos_flags = _get_exynos_flag_from_tbm (flags);
451     if((flags & TBM_BO_SCANOUT) &&
452         size <= 4*1024)
453     {
454         exynos_flags |= EXYNOS_BO_NONCONTIG;
455     }
456
457     struct drm_exynos_gem_create arg = {0, };
458     arg.size = size;
459     arg.flags = exynos_flags;
460     if (drmCommandWriteRead(bufmgr_exynos4412->fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg)))
461     {
462         TBM_EXYNOS4412_LOG ("error Cannot create bo(flag:%x, size:%d)\n", arg.flags, (unsigned int)arg.size);
463         free (bo_exynos4412);
464         return 0;
465     }
466
467     bo_exynos4412->fd = bufmgr_exynos4412->fd;
468     bo_exynos4412->gem = arg.handle;
469     bo_exynos4412->size = size;
470     bo_exynos4412->flags_tbm = flags;
471     bo_exynos4412->flags_exynos = exynos_flags;
472     bo_exynos4412->name = _get_name (bo_exynos4412->fd, bo_exynos4412->gem);
473
474     pthread_mutex_init(&bo_exynos4412->mutex, NULL);
475
476     if (bufmgr_exynos4412->use_dma_fence
477         && !bo_exynos4412->dmabuf)
478     {
479         struct drm_prime_handle arg = {0, };
480
481         arg.handle = bo_exynos4412->gem;
482         if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
483         {
484             TBM_EXYNOS4412_LOG ("error Cannot dmabuf=%d\n", bo_exynos4412->gem);
485             free (bo_exynos4412);
486             return 0;
487         }
488         bo_exynos4412->dmabuf = arg.fd;
489     }
490
491     /* add bo to hash */
492     PrivGem* privGem = calloc (1, sizeof(PrivGem));
493     if (!privGem)
494     {
495         TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
496                 "error %s:%d Fail to calloc privGem\n",
497                 getpid(), __FUNCTION__, __LINE__);
498         free (bo_exynos4412);
499         return 0;
500     }
501
502     privGem->ref_count = 1;
503     if (drmHashInsert(bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void *)privGem) < 0)
504     {
505         TBM_EXYNOS4412_LOG ("error Cannot insert bo to Hash(%d)\n", bo_exynos4412->name);
506     }
507
508     DBG ("     [%s] bo:%p, gem:%d(%d), flags:%d(%d), size:%d\n", target_name(),
509          bo,
510          bo_exynos4412->gem, bo_exynos4412->name,
511          flags, exynos_flags,
512          bo_exynos4412->size);
513
514     return (void *)bo_exynos4412;
515 }
516
517 static void
518 tbm_exynos4412_bo_free(tbm_bo bo)
519 {
520     tbm_bo_exynos4412 bo_exynos4412;
521     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
522
523     if (!bo)
524         return;
525
526     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
527     EXYNOS4412_RETURN_IF_FAIL (bufmgr_exynos4412!=NULL);
528
529     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
530     EXYNOS4412_RETURN_IF_FAIL (bo_exynos4412!=NULL);
531
532     DBG ("      [%s] bo:%p, gem:%d(%d), fd:%d, size:%d\n",target_name(),
533          bo,
534          bo_exynos4412->gem, bo_exynos4412->name,
535          bo_exynos4412->dmabuf,
536          bo_exynos4412->size);
537
538     if (bo_exynos4412->pBase)
539     {
540         if (munmap(bo_exynos4412->pBase, bo_exynos4412->size) == -1)
541         {
542             TBM_EXYNOS4412_LOG ("error bo:%p fail to munmap(%s)\n",
543                 bo, strerror(errno));
544         }
545     }
546
547     /* close dmabuf */
548     if (bo_exynos4412->dmabuf)
549     {
550         close (bo_exynos4412->dmabuf);
551         bo_exynos4412->dmabuf = 0;
552     }
553
554     /* delete bo from hash */
555     PrivGem *privGem = NULL;
556     int ret;
557
558     ret = drmHashLookup (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void**)&privGem);
559     if (ret == 0)
560     {
561         privGem->ref_count--;
562         if (privGem->ref_count == 0)
563         {
564             drmHashDelete (bufmgr_exynos4412->hashBos, bo_exynos4412->name);
565             free (privGem);
566             privGem = NULL;
567         }
568     }
569     else
570     {
571         TBM_EXYNOS4412_LOG ("warning Cannot find bo to Hash(%d), ret=%d\n", bo_exynos4412->name, ret);
572     }
573
574     /* Free gem handle */
575     struct drm_gem_close arg = {0, };
576     memset (&arg, 0, sizeof(arg));
577     arg.handle = bo_exynos4412->gem;
578     if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_GEM_CLOSE, &arg))
579     {
580         TBM_EXYNOS4412_LOG ("error bo:%p fail to gem close.(%s)\n",
581             bo, strerror(errno));
582     }
583
584     free (bo_exynos4412);
585 }
586
587
588 static void *
589 tbm_exynos4412_bo_import (tbm_bo bo, unsigned int key)
590 {
591     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
592
593     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
594     tbm_bo_exynos4412 bo_exynos4412;
595
596     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
597     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
598
599     struct drm_gem_open arg = {0, };
600     struct drm_exynos_gem_info info = {0, };
601
602     arg.name = key;
603     if (drmIoctl(bufmgr_exynos4412->fd, DRM_IOCTL_GEM_OPEN, &arg))
604     {
605         TBM_EXYNOS4412_LOG ("error Cannot open gem name=%d\n", key);
606         return 0;
607     }
608
609     info.handle = arg.handle;
610     if (drmCommandWriteRead(bufmgr_exynos4412->fd,
611                            DRM_EXYNOS_GEM_GET,
612                            &info,
613                            sizeof(struct drm_exynos_gem_info)))
614     {
615         TBM_EXYNOS4412_LOG ("error Cannot get gem info=%d\n", key);
616         return 0;
617     }
618
619     bo_exynos4412 = calloc (1, sizeof(struct _tbm_bo_exynos4412));
620     if (!bo_exynos4412)
621     {
622         TBM_EXYNOS4412_LOG ("error fail to allocate the bo private\n");
623         return 0;
624     }
625
626     bo_exynos4412->fd = bufmgr_exynos4412->fd;
627     bo_exynos4412->gem = arg.handle;
628     bo_exynos4412->size = arg.size;
629     bo_exynos4412->flags_exynos = info.flags;
630     bo_exynos4412->name = key;
631     bo_exynos4412->flags_tbm = _get_tbm_flag_from_exynos (bo_exynos4412->flags_exynos);
632
633     if (!bo_exynos4412->dmabuf)
634     {
635         struct drm_prime_handle arg = {0, };
636
637         arg.handle = bo_exynos4412->gem;
638         if (drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg))
639         {
640             TBM_EXYNOS4412_LOG ("error Cannot dmabuf=%d\n", bo_exynos4412->gem);
641             free (bo_exynos4412);
642             return 0;
643         }
644         bo_exynos4412->dmabuf = arg.fd;
645     }
646
647     /* add bo to hash */
648     PrivGem *privGem = NULL;
649     int ret;
650
651     ret = drmHashLookup (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void**)&privGem);
652     if (ret == 0)
653     {
654         privGem->ref_count++;
655     }
656     else if (ret == 1)
657     {
658         privGem = calloc (1, sizeof(PrivGem));
659         if (!privGem)
660         {
661             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
662                     "error %s:%d Fail to calloc privGem\n",
663                     getpid(), __FUNCTION__, __LINE__);
664             free (bo_exynos4412);
665             return 0;
666         }
667
668         privGem->ref_count = 1;
669         if (drmHashInsert (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void *)privGem) < 0)
670         {
671             TBM_EXYNOS4412_LOG ("error Cannot insert bo to Hash(%d)\n", bo_exynos4412->name);
672         }
673     }
674     else
675     {
676         TBM_EXYNOS4412_LOG ("error Cannot insert bo to Hash(%d)\n", bo_exynos4412->name);
677     }
678
679     DBG ("    [%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n", target_name(),
680          bo,
681          bo_exynos4412->gem, bo_exynos4412->name,
682          bo_exynos4412->dmabuf,
683          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos,
684          bo_exynos4412->size);
685
686     return (void *)bo_exynos4412;
687 }
688
689 static void *
690 tbm_exynos4412_bo_import_fd (tbm_bo bo, tbm_fd key)
691 {
692     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
693
694     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
695     tbm_bo_exynos4412 bo_exynos4412;
696
697     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
698     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
699
700     unsigned int gem = 0;
701     unsigned int real_size = -1;
702     struct drm_exynos_gem_info info = {0, };
703
704         //getting handle from fd
705     struct drm_prime_handle arg = {0, };
706
707         arg.fd = key;
708         arg.flags = 0;
709     if (drmIoctl (bufmgr_exynos4412->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg))
710     {
711         TBM_EXYNOS4412_LOG ("error bo:%p Cannot get gem handle from fd:%d (%s)\n",
712                  bo, arg.fd, strerror(errno));
713         return NULL;
714     }
715     gem = arg.handle;
716
717         /* Determine size of bo.  The fd-to-handle ioctl really should
718          * return the size, but it doesn't.  If we have kernel 3.12 or
719          * later, we can lseek on the prime fd to get the size.  Older
720          * kernels will just fail, in which case we fall back to the
721          * provided (estimated or guess size). */
722         real_size = lseek(key, 0, SEEK_END);
723
724     info.handle = gem;
725     if (drmCommandWriteRead(bufmgr_exynos4412->fd,
726                            DRM_EXYNOS_GEM_GET,
727                            &info,
728                            sizeof(struct drm_exynos_gem_info)))
729     {
730         TBM_EXYNOS4412_LOG ("error bo:%p Cannot get gem info from gem:%d, fd:%d (%s)\n",
731                 bo, gem, key, strerror(errno));
732         return 0;
733     }
734
735     if (real_size == -1)
736         real_size = info.size;
737
738     bo_exynos4412 = calloc (1, sizeof(struct _tbm_bo_exynos4412));
739     if (!bo_exynos4412)
740     {
741         TBM_EXYNOS4412_LOG ("error bo:%p fail to allocate the bo private\n", bo);
742         return 0;
743     }
744
745     bo_exynos4412->fd = bufmgr_exynos4412->fd;
746     bo_exynos4412->gem = gem;
747     bo_exynos4412->size = real_size;
748     bo_exynos4412->flags_exynos = info.flags;
749     bo_exynos4412->flags_tbm = _get_tbm_flag_from_exynos (bo_exynos4412->flags_exynos);
750
751     bo_exynos4412->name = _get_name(bo_exynos4412->fd, bo_exynos4412->gem);
752     if (!bo_exynos4412->name)
753     {
754         TBM_EXYNOS4412_LOG ("error bo:%p Cannot get name from gem:%d, fd:%d (%s)\n",
755             bo, gem, key, strerror(errno));
756         free (bo_exynos4412);
757         return 0;
758     }
759
760     /* add bo to hash */
761     PrivGem *privGem = NULL;
762     int ret;
763
764     ret = drmHashLookup (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void**)&privGem);
765     if (ret == 0)
766     {
767         privGem->ref_count++;
768     }
769     else if (ret == 1)
770     {
771         privGem = calloc (1, sizeof(PrivGem));
772         if (!privGem)
773         {
774             TBM_EXYNOS4412_LOG ("[libtbm-exynos4412:%d] "
775                     "error %s:%d Fail to calloc privGem\n",
776                     getpid(), __FUNCTION__, __LINE__);
777             free (bo_exynos4412);
778             return 0;
779         }
780
781         privGem->ref_count = 1;
782         if (drmHashInsert (bufmgr_exynos4412->hashBos, bo_exynos4412->name, (void *)privGem) < 0)
783         {
784             TBM_EXYNOS4412_LOG ("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
785                 bo, bo_exynos4412->name, gem, key);
786         }
787     }
788     else
789     {
790         TBM_EXYNOS4412_LOG ("error bo:%p Cannot insert bo to Hash(%d) from gem:%d, fd:%d\n",
791                 bo, bo_exynos4412->name, gem, key);
792     }
793
794     DBG (" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
795          bo,
796          bo_exynos4412->gem, bo_exynos4412->name,
797          bo_exynos4412->dmabuf,
798          key,
799          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos,
800          bo_exynos4412->size);
801
802     return (void *)bo_exynos4412;
803 }
804
805 static unsigned int
806 tbm_exynos4412_bo_export (tbm_bo bo)
807 {
808     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
809
810     tbm_bo_exynos4412 bo_exynos4412;
811
812     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
813     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
814
815     if (!bo_exynos4412->name)
816     {
817         bo_exynos4412->name = _get_name(bo_exynos4412->fd, bo_exynos4412->gem);
818         if (!bo_exynos4412->name)
819         {
820             TBM_EXYNOS4412_LOG ("error Cannot get name\n");
821             return 0;
822         }
823     }
824
825     DBG ("    [%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d\n", target_name(),
826          bo,
827          bo_exynos4412->gem, bo_exynos4412->name,
828          bo_exynos4412->dmabuf,
829          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos,
830          bo_exynos4412->size);
831
832     return (unsigned int)bo_exynos4412->name;
833 }
834
835 tbm_fd
836 tbm_exynos4412_bo_export_fd (tbm_bo bo)
837 {
838     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, -1);
839
840     tbm_bo_exynos4412 bo_exynos4412;
841     int ret;
842
843     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
844     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, -1);
845
846     struct drm_prime_handle arg = {0, };
847
848     arg.handle = bo_exynos4412->gem;
849     ret = drmIoctl (bo_exynos4412->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
850     if (ret)
851     {
852         TBM_EXYNOS4412_LOG ("error bo:%p Cannot dmabuf=%d (%s)\n",
853             bo, bo_exynos4412->gem, strerror(errno));
854         return (tbm_fd) ret;
855     }
856
857     DBG (" [%s] bo:%p, gem:%d(%d), fd:%d, key_fd:%d, flags:%d(%d), size:%d\n", target_name(),
858          bo,
859          bo_exynos4412->gem, bo_exynos4412->name,
860          bo_exynos4412->dmabuf,
861          arg.fd,
862          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos,
863          bo_exynos4412->size);
864
865     return (tbm_fd)arg.fd;
866 }
867
868 static tbm_bo_handle
869 tbm_exynos4412_bo_get_handle (tbm_bo bo, int device)
870 {
871     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, (tbm_bo_handle) NULL);
872
873     tbm_bo_handle bo_handle;
874     tbm_bo_exynos4412 bo_exynos4412;
875
876     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
877     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, (tbm_bo_handle) NULL);
878
879     if (!bo_exynos4412->gem)
880     {
881         TBM_EXYNOS4412_LOG ("error Cannot map gem=%d\n", bo_exynos4412->gem);
882         return (tbm_bo_handle) NULL;
883     }
884
885     DBG ("[%s] bo:%p, gem:%d(%d), fd:%d, flags:%d(%d), size:%d, %s\n", target_name(),
886          bo,
887          bo_exynos4412->gem, bo_exynos4412->name,
888          bo_exynos4412->dmabuf,
889          bo_exynos4412->flags_tbm, bo_exynos4412->flags_exynos,
890          bo_exynos4412->size,
891          STR_DEVICE[device]);
892
893     /*Get mapped bo_handle*/
894     bo_handle = _exynos4412_bo_handle (bo_exynos4412, device);
895     if (bo_handle.ptr == NULL)
896     {
897         TBM_EXYNOS4412_LOG ("error Cannot get handle: gem:%d, device:%d\n", bo_exynos4412->gem, device);
898         return (tbm_bo_handle) NULL;
899     }
900
901     return bo_handle;
902 }
903
904 static tbm_bo_handle
905 tbm_exynos4412_bo_map (tbm_bo bo, int device, int opt)
906 {
907     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, (tbm_bo_handle) NULL);
908
909     tbm_bo_handle bo_handle;
910     tbm_bo_exynos4412 bo_exynos4412;
911
912     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
913     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, (tbm_bo_handle) NULL);
914
915     if (!bo_exynos4412->gem)
916     {
917         TBM_EXYNOS4412_LOG ("error Cannot map gem=%d\n", bo_exynos4412->gem);
918         return (tbm_bo_handle) NULL;
919     }
920
921     DBG ("       [%s] bo:%p, gem:%d(%d), fd:%d, %s, %s\n", target_name(),
922          bo,
923          bo_exynos4412->gem, bo_exynos4412->name,
924          bo_exynos4412->dmabuf,
925          STR_DEVICE[device],
926          STR_OPT[opt]);
927
928     /*Get mapped bo_handle*/
929     bo_handle = _exynos4412_bo_handle (bo_exynos4412, device);
930     if (bo_handle.ptr == NULL)
931     {
932         TBM_EXYNOS4412_LOG ("error Cannot get handle: gem:%d, device:%d, opt:%d\n", bo_exynos4412->gem, device, opt);
933         return (tbm_bo_handle) NULL;
934     }
935
936     return bo_handle;
937 }
938
939 static int
940 tbm_exynos4412_bo_unmap (tbm_bo bo)
941 {
942     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
943
944     tbm_bo_exynos4412 bo_exynos4412;
945
946     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
947     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
948
949     if (!bo_exynos4412->gem)
950         return 0;
951
952     DBG ("     [%s] bo:%p, gem:%d(%d), fd:%d\n", target_name(),
953           bo,
954           bo_exynos4412->gem, bo_exynos4412->name,
955           bo_exynos4412->dmabuf);
956
957     return 1;
958 }
959
960 static int
961 tbm_exynos4412_bo_cache_flush (tbm_bo bo, int flags)
962 {
963     tbm_bufmgr_exynos4412 bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
964     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
965
966     /* cache flush is managed by kernel side when using dma-fence. */
967     if (bufmgr_exynos4412->use_dma_fence)
968        return 1;
969
970     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
971
972     tbm_bo_exynos4412 bo_exynos4412;
973
974     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
975     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
976
977     if (!_exynos4412_cache_flush(bo_exynos4412->fd, bo_exynos4412, flags))
978         return 0;
979
980     return 1;
981 }
982
983 static int
984 tbm_exynos4412_bo_get_global_key (tbm_bo bo)
985 {
986     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
987
988     tbm_bo_exynos4412 bo_exynos4412;
989
990     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
991     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
992
993     if (!bo_exynos4412->name)
994     {
995         if (!bo_exynos4412->gem)
996             return 0;
997
998         bo_exynos4412->name = _get_name(bo_exynos4412->fd, bo_exynos4412->gem);
999     }
1000
1001     return bo_exynos4412->name;
1002 }
1003
1004 static int
1005 tbm_exynos4412_bo_lock(tbm_bo bo, int device, int opt)
1006 {
1007     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
1008
1009     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
1010     tbm_bo_exynos4412 bo_exynos4412;
1011     struct dma_buf_fence fence;
1012     struct flock filelock;
1013     int ret=0;
1014
1015     if (device != TBM_DEVICE_3D && device != TBM_DEVICE_CPU)
1016     {
1017         DBG ("[libtbm-exynos4412:%d] %s not support device type,\n", getpid(), __FUNCTION__);
1018             return 0;
1019     }
1020
1021     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
1022     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
1023
1024     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_bufmgr_priv(bo);
1025     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr_exynos4412!=NULL, 0);
1026
1027     memset(&fence, 0, sizeof(struct dma_buf_fence));
1028
1029     /* Check if the given type is valid or not. */
1030     if (opt & TBM_OPTION_WRITE)
1031     {
1032         if (device == TBM_DEVICE_3D)
1033             fence.type = DMA_BUF_ACCESS_WRITE | DMA_BUF_ACCESS_DMA;
1034     }
1035     else if (opt & TBM_OPTION_READ)
1036     {
1037         if (device == TBM_DEVICE_3D)
1038             fence.type = DMA_BUF_ACCESS_READ | DMA_BUF_ACCESS_DMA;
1039     }
1040     else
1041     {
1042         TBM_EXYNOS4412_LOG ("error Invalid argument\n");
1043         return 0;
1044     }
1045
1046     /* Check if the tbm manager supports dma fence or not. */
1047     if (!bufmgr_exynos4412->use_dma_fence)
1048     {
1049         TBM_EXYNOS4412_LOG ("error Not support DMA FENCE(%s)\n", strerror(errno) );
1050         return 0;
1051
1052     }
1053
1054     if (device == TBM_DEVICE_3D)
1055     {
1056         ret = ioctl(bo_exynos4412->dmabuf, DMABUF_IOCTL_GET_FENCE, &fence);
1057         if (ret < 0)
1058         {
1059             TBM_EXYNOS4412_LOG ("error Cannot set GET FENCE(%s)\n", strerror(errno) );
1060             return 0;
1061         }
1062     } else
1063     {
1064         if (opt & TBM_OPTION_WRITE)
1065             filelock.l_type = F_WRLCK;
1066         else
1067             filelock.l_type = F_RDLCK;
1068
1069         filelock.l_whence = SEEK_CUR;
1070         filelock.l_start = 0;
1071         filelock.l_len = 0;
1072
1073         if (-1 == fcntl(bo_exynos4412->dmabuf, F_SETLKW, &filelock))
1074         {
1075             return 0;
1076         }
1077     }
1078
1079     pthread_mutex_lock(&bo_exynos4412->mutex);
1080
1081     if (device == TBM_DEVICE_3D)
1082     {
1083         int i;
1084         for (i = 0; i < DMA_FENCE_LIST_MAX; i++)
1085         {
1086             if (bo_exynos4412->dma_fence[i].ctx == 0)
1087             {
1088                 bo_exynos4412->dma_fence[i].type = fence.type;
1089                 bo_exynos4412->dma_fence[i].ctx = fence.ctx;
1090                 break;
1091             }
1092         }
1093
1094         if (i == DMA_FENCE_LIST_MAX)
1095         {
1096             //TODO: if dma_fence list is full, it needs realloc. I will fix this. by minseok3.kim
1097             TBM_EXYNOS4412_LOG ("error fence list is full\n");
1098         }
1099     }
1100
1101     pthread_mutex_unlock(&bo_exynos4412->mutex);
1102
1103     DBG ("[%s] DMABUF_IOCTL_GET_FENCE! bo:%p, gem:%d(%d), fd:%ds\n", target_name(),
1104           bo,
1105           bo_exynos4412->gem, bo_exynos4412->name,
1106           bo_exynos4412->dmabuf);
1107
1108     return 1;
1109 }
1110
1111 static int
1112 tbm_exynos4412_bo_unlock(tbm_bo bo)
1113 {
1114     EXYNOS4412_RETURN_VAL_IF_FAIL (bo!=NULL, 0);
1115
1116     tbm_bo_exynos4412 bo_exynos4412;
1117     struct dma_buf_fence fence;
1118     struct flock filelock;
1119     unsigned int dma_type = 0;
1120     int ret=0;
1121
1122     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
1123     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412!=NULL, 0);
1124
1125     if (bo_exynos4412->dma_fence[0].type & DMA_BUF_ACCESS_DMA)
1126             dma_type = 1;
1127
1128     if (!bo_exynos4412->dma_fence[0].ctx && dma_type)
1129     {
1130         DBG ("[libtbm-exynos4412:%d] %s FENCE not support or ignored,\n", getpid(), __FUNCTION__);
1131         return 0;
1132     }
1133
1134     if (!bo_exynos4412->dma_fence[0].ctx && dma_type)
1135     {
1136         DBG ("[libtbm-exynos4412:%d] %s device type is not 3D/CPU,\n", getpid(), __FUNCTION__);
1137         return 0;
1138     }
1139
1140     pthread_mutex_lock(&bo_exynos4412->mutex);
1141
1142     if (dma_type)
1143     {
1144         fence.type = bo_exynos4412->dma_fence[0].type;
1145         fence.ctx = bo_exynos4412->dma_fence[0].ctx;
1146         int i;
1147         for (i = 1; i < DMA_FENCE_LIST_MAX; i++)
1148         {
1149             bo_exynos4412->dma_fence[i-1].type = bo_exynos4412->dma_fence[i].type;
1150             bo_exynos4412->dma_fence[i-1].ctx = bo_exynos4412->dma_fence[i].ctx;
1151         }
1152         bo_exynos4412->dma_fence[DMA_FENCE_LIST_MAX-1].type = 0;
1153         bo_exynos4412->dma_fence[DMA_FENCE_LIST_MAX-1].ctx = 0;
1154     }
1155     pthread_mutex_unlock(&bo_exynos4412->mutex);
1156
1157     if (dma_type)
1158     {
1159         ret = ioctl(bo_exynos4412->dmabuf, DMABUF_IOCTL_PUT_FENCE, &fence);
1160         if (ret < 0)
1161         {
1162             TBM_EXYNOS4412_LOG ("error Can not set PUT FENCE(%s)\n", strerror(errno));
1163             return 0;
1164         }
1165     } else
1166     {
1167         filelock.l_type = F_UNLCK;
1168         filelock.l_whence = SEEK_CUR;
1169         filelock.l_start = 0;
1170         filelock.l_len = 0;
1171
1172         if (-1 == fcntl(bo_exynos4412->dmabuf, F_SETLKW, &filelock))
1173         {
1174             return 0;
1175         }
1176     }
1177
1178     DBG ("[%s] DMABUF_IOCTL_PUT_FENCE! bo:%p, gem:%d(%d), fd:%ds\n", target_name(),
1179           bo,
1180           bo_exynos4412->gem, bo_exynos4412->name,
1181           bo_exynos4412->dmabuf);
1182
1183     return 1;
1184 }
1185
1186 static void
1187 tbm_exynos4412_bufmgr_deinit (void *priv)
1188 {
1189     EXYNOS4412_RETURN_IF_FAIL (priv!=NULL);
1190
1191     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
1192
1193     bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)priv;
1194
1195     if (bufmgr_exynos4412->hashBos)
1196     {
1197         unsigned long key;
1198         void *value;
1199
1200         while (drmHashFirst(bufmgr_exynos4412->hashBos, &key, &value) > 0)
1201         {
1202             free (value);
1203             drmHashDelete (bufmgr_exynos4412->hashBos, key);
1204         }
1205
1206         drmHashDestroy (bufmgr_exynos4412->hashBos);
1207         bufmgr_exynos4412->hashBos = NULL;
1208     }
1209
1210     free (bufmgr_exynos4412);
1211 }
1212
1213 int
1214 tbm_exynos4412_surface_supported_format(uint32_t **formats, uint32_t *num)
1215 {
1216     uint32_t* color_formats=NULL;
1217
1218     color_formats = (uint32_t*)calloc (1,sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT);
1219
1220     if( color_formats == NULL )
1221     {
1222         return 0;
1223     }
1224     memcpy( color_formats, tbm_exynos4412_color_format_list , sizeof(uint32_t)*TBM_COLOR_FORMAT_COUNT );
1225
1226
1227     *formats = color_formats;
1228     *num = TBM_COLOR_FORMAT_COUNT;
1229
1230     fprintf (stderr, "tbm_exynos4412_surface_supported_format  count = %d \n",*num);
1231
1232     return 1;
1233 }
1234
1235
1236 /**
1237  * @brief get the plane data of the surface.
1238  * @param[in] surface : the surface
1239  * @param[in] width : the width of the surface
1240  * @param[in] height : the height of the surface
1241  * @param[in] format : the format of the surface
1242  * @param[in] plane_idx : the format of the surface
1243  * @param[out] size : the size of the plane
1244  * @param[out] offset : the offset of the plane
1245  * @param[out] pitch : the pitch of the plane
1246  * @param[out] padding : the padding of the plane
1247  * @return 1 if this function succeeds, otherwise 0.
1248  */
1249 int
1250 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, int *bo_idx)
1251 {
1252     int ret = 1;
1253     int bpp;
1254     int _offset =0;
1255     int _pitch =0;
1256     int _size =0;
1257     int _bo_idx = 0;
1258
1259     switch(format)
1260     {
1261         /* 16 bpp RGB */
1262         case TBM_FORMAT_XRGB4444:
1263         case TBM_FORMAT_XBGR4444:
1264         case TBM_FORMAT_RGBX4444:
1265         case TBM_FORMAT_BGRX4444:
1266         case TBM_FORMAT_ARGB4444:
1267         case TBM_FORMAT_ABGR4444:
1268         case TBM_FORMAT_RGBA4444:
1269         case TBM_FORMAT_BGRA4444:
1270         case TBM_FORMAT_XRGB1555:
1271         case TBM_FORMAT_XBGR1555:
1272         case TBM_FORMAT_RGBX5551:
1273         case TBM_FORMAT_BGRX5551:
1274         case TBM_FORMAT_ARGB1555:
1275         case TBM_FORMAT_ABGR1555:
1276         case TBM_FORMAT_RGBA5551:
1277         case TBM_FORMAT_BGRA5551:
1278         case TBM_FORMAT_RGB565:
1279             bpp = 16;
1280             _offset = 0;
1281                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1282             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1283             _bo_idx = 0;
1284             break;
1285         /* 24 bpp RGB */
1286         case TBM_FORMAT_RGB888:
1287         case TBM_FORMAT_BGR888:
1288             bpp = 24;
1289             _offset = 0;
1290                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1291             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1292             _bo_idx = 0;
1293             break;
1294         /* 32 bpp RGB */
1295         case TBM_FORMAT_XRGB8888:
1296         case TBM_FORMAT_XBGR8888:
1297         case TBM_FORMAT_RGBX8888:
1298         case TBM_FORMAT_BGRX8888:
1299         case TBM_FORMAT_ARGB8888:
1300         case TBM_FORMAT_ABGR8888:
1301         case TBM_FORMAT_RGBA8888:
1302         case TBM_FORMAT_BGRA8888:
1303             bpp = 32;
1304             _offset = 0;
1305                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1306             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1307             _bo_idx = 0;
1308             break;
1309
1310         /* packed YCbCr */
1311         case TBM_FORMAT_YUYV:
1312         case TBM_FORMAT_YVYU:
1313         case TBM_FORMAT_UYVY:
1314         case TBM_FORMAT_VYUY:
1315         case TBM_FORMAT_AYUV:
1316             bpp = 32;
1317             _offset = 0;
1318                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1319             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1320             _bo_idx = 0;
1321             break;
1322
1323         /*
1324         * 2 plane YCbCr
1325         * index 0 = Y plane, [7:0] Y
1326         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1327         * or
1328         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1329         */
1330         case TBM_FORMAT_NV12:
1331             bpp = 12;
1332             if(plane_idx == 0)
1333             {
1334                 _offset = 0;
1335                                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1336                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1337                 _bo_idx = 0;
1338             }
1339             else if( plane_idx ==1 )
1340             {
1341                 _offset = 0;
1342                                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1343                                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1344                 _bo_idx = 1;
1345             }
1346             break;
1347         case TBM_FORMAT_NV21:
1348             bpp = 12;
1349             if(plane_idx == 0)
1350             {
1351                 _offset = 0;
1352                                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1353                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1354                 _bo_idx = 0;
1355             }
1356             else if( plane_idx ==1 )
1357             {
1358                 _offset = width*height;
1359                                 _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1360                                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1361                 _bo_idx = 0;
1362             }
1363             break;
1364
1365         case TBM_FORMAT_NV16:
1366         case TBM_FORMAT_NV61:
1367                         bpp = 16;
1368             //if(plane_idx == 0)
1369             {
1370                 _offset = 0;
1371                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1372                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1373                 _bo_idx = 0;
1374                 if(plane_idx == 0)
1375                         break;
1376             }
1377             //else if( plane_idx ==1 )
1378             {
1379                 _offset += _size;
1380                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1381                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1382                 _bo_idx = 0;
1383             }
1384             break;
1385
1386         /*
1387         * 3 plane YCbCr
1388         * index 0: Y plane, [7:0] Y
1389         * index 1: Cb plane, [7:0] Cb
1390         * index 2: Cr plane, [7:0] Cr
1391         * or
1392         * index 1: Cr plane, [7:0] Cr
1393         * index 2: Cb plane, [7:0] Cb
1394         */
1395         /*
1396         NATIVE_BUFFER_FORMAT_YV12
1397         NATIVE_BUFFER_FORMAT_I420
1398         */
1399         case TBM_FORMAT_YUV410:
1400         case TBM_FORMAT_YVU410:
1401             bpp = 9;
1402             _bo_idx = 0;
1403             break;
1404         case TBM_FORMAT_YUV411:
1405         case TBM_FORMAT_YVU411:
1406         case TBM_FORMAT_YUV420:
1407         case TBM_FORMAT_YVU420:
1408             bpp = 12;
1409             //if(plane_idx == 0)
1410             {
1411                 _offset = 0;
1412                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1413                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1414                 _bo_idx = 0;
1415                         if(plane_idx == 0)
1416                                 break;
1417             }
1418             //else if( plane_idx == 1 )
1419             {
1420                 _offset += _size;
1421                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1422                         _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1423                 _bo_idx = 0;
1424                         if(plane_idx == 1)
1425                                 break;
1426             }
1427             //else if (plane_idx == 2 )
1428             {
1429                 _offset += _size;
1430                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1431                 _size = SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1432                 _bo_idx = 0;
1433             }
1434             break;
1435         case TBM_FORMAT_YUV422:
1436         case TBM_FORMAT_YVU422:
1437             bpp = 16;
1438             //if(plane_idx == 0)
1439             {
1440                 _offset = 0;
1441                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1442                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1443                 _bo_idx = 0;
1444                         if(plane_idx == 0)
1445                                 break;
1446             }
1447             //else if( plane_idx == 1 )
1448             {
1449                 _offset += _size;
1450                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1451                         _size = SIZE_ALIGN(_pitch*(height),TBM_SURFACE_ALIGNMENT_PLANE);
1452                 _bo_idx = 0;
1453                         if(plane_idx == 1)
1454                                 break;
1455             }
1456             //else if (plane_idx == 2 )
1457             {
1458                 _offset += _size;
1459                         _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1460                 _size = SIZE_ALIGN(_pitch*(height),TBM_SURFACE_ALIGNMENT_PLANE);
1461                 _bo_idx = 0;
1462             }
1463             break;
1464         case TBM_FORMAT_YUV444:
1465         case TBM_FORMAT_YVU444:
1466             bpp = 24;
1467             //if(plane_idx == 0)
1468             {
1469                 _offset = 0;
1470                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1471                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1472                 _bo_idx = 0;
1473                         if(plane_idx == 0)
1474                                 break;
1475             }
1476             //else if( plane_idx == 1 )
1477             {
1478                 _offset += _size;
1479                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1480                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1481                 _bo_idx = 0;
1482                         if(plane_idx == 1)
1483                                 break;
1484             }
1485             //else if (plane_idx == 2 )
1486             {
1487                 _offset += _size;
1488                         _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1489                _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1490                _bo_idx = 0;
1491             }
1492             break;
1493         default:
1494             bpp = 0;
1495             break;
1496     }
1497
1498     *size = _size;
1499     *offset = _offset;
1500     *pitch = _pitch;
1501     *bo_idx = _bo_idx;
1502
1503     return ret;
1504 }
1505
1506 int
1507 tbm_exynos4412_surface_get_num_bos(tbm_format format)
1508 {
1509         int num = 0;
1510
1511     switch(format)
1512     {
1513         /* 16 bpp RGB */
1514         case TBM_FORMAT_XRGB4444:
1515         case TBM_FORMAT_XBGR4444:
1516         case TBM_FORMAT_RGBX4444:
1517         case TBM_FORMAT_BGRX4444:
1518         case TBM_FORMAT_ARGB4444:
1519         case TBM_FORMAT_ABGR4444:
1520         case TBM_FORMAT_RGBA4444:
1521         case TBM_FORMAT_BGRA4444:
1522         case TBM_FORMAT_XRGB1555:
1523         case TBM_FORMAT_XBGR1555:
1524         case TBM_FORMAT_RGBX5551:
1525         case TBM_FORMAT_BGRX5551:
1526         case TBM_FORMAT_ARGB1555:
1527         case TBM_FORMAT_ABGR1555:
1528         case TBM_FORMAT_RGBA5551:
1529         case TBM_FORMAT_BGRA5551:
1530         case TBM_FORMAT_RGB565:
1531         /* 24 bpp RGB */
1532         case TBM_FORMAT_RGB888:
1533         case TBM_FORMAT_BGR888:
1534         /* 32 bpp RGB */
1535         case TBM_FORMAT_XRGB8888:
1536         case TBM_FORMAT_XBGR8888:
1537         case TBM_FORMAT_RGBX8888:
1538         case TBM_FORMAT_BGRX8888:
1539         case TBM_FORMAT_ARGB8888:
1540         case TBM_FORMAT_ABGR8888:
1541         case TBM_FORMAT_RGBA8888:
1542         case TBM_FORMAT_BGRA8888:
1543         /* packed YCbCr */
1544         case TBM_FORMAT_YUYV:
1545         case TBM_FORMAT_YVYU:
1546         case TBM_FORMAT_UYVY:
1547         case TBM_FORMAT_VYUY:
1548         case TBM_FORMAT_AYUV:
1549         /*
1550         * 2 plane YCbCr
1551         * index 0 = Y plane, [7:0] Y
1552         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1553         * or
1554         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1555         */
1556         case TBM_FORMAT_NV21:
1557         case TBM_FORMAT_NV16:
1558         case TBM_FORMAT_NV61:
1559         /*
1560         * 3 plane YCbCr
1561         * index 0: Y plane, [7:0] Y
1562         * index 1: Cb plane, [7:0] Cb
1563         * index 2: Cr plane, [7:0] Cr
1564         * or
1565         * index 1: Cr plane, [7:0] Cr
1566         * index 2: Cb plane, [7:0] Cb
1567         */
1568         case TBM_FORMAT_YUV410:
1569         case TBM_FORMAT_YVU410:
1570         case TBM_FORMAT_YUV411:
1571         case TBM_FORMAT_YVU411:
1572         case TBM_FORMAT_YUV420:
1573         case TBM_FORMAT_YVU420:
1574         case TBM_FORMAT_YUV422:
1575         case TBM_FORMAT_YVU422:
1576         case TBM_FORMAT_YUV444:
1577         case TBM_FORMAT_YVU444:
1578             num = 1;
1579             break;
1580
1581         case TBM_FORMAT_NV12:
1582             num = 2;
1583             break;
1584
1585         default:
1586             num = 0;
1587             break;
1588     }
1589
1590     return num;
1591 }
1592
1593 /**
1594 * @brief get the size of the surface with a format.
1595 * @param[in] surface : the surface
1596 * @param[in] width : the width of the surface
1597 * @param[in] height : the height of the surface
1598 * @param[in] format : the format of the surface
1599 * @return size of the surface if this function succeeds, otherwise 0.
1600 */
1601
1602 int
1603 tbm_exynos4412_surface_get_size(tbm_surface_h surface, int width, int height, tbm_format format)
1604 {
1605         int ret = 0;
1606         int bpp = 0;
1607         int _pitch =0;
1608         int _size =0;
1609         int align =TBM_SURFACE_ALIGNMENT_PLANE;
1610
1611     switch(format)
1612     {
1613         /* 16 bpp RGB */
1614         case TBM_FORMAT_XRGB4444:
1615         case TBM_FORMAT_XBGR4444:
1616         case TBM_FORMAT_RGBX4444:
1617         case TBM_FORMAT_BGRX4444:
1618         case TBM_FORMAT_ARGB4444:
1619         case TBM_FORMAT_ABGR4444:
1620         case TBM_FORMAT_RGBA4444:
1621         case TBM_FORMAT_BGRA4444:
1622         case TBM_FORMAT_XRGB1555:
1623         case TBM_FORMAT_XBGR1555:
1624         case TBM_FORMAT_RGBX5551:
1625         case TBM_FORMAT_BGRX5551:
1626         case TBM_FORMAT_ARGB1555:
1627         case TBM_FORMAT_ABGR1555:
1628         case TBM_FORMAT_RGBA5551:
1629         case TBM_FORMAT_BGRA5551:
1630         case TBM_FORMAT_RGB565:
1631             bpp = 16;
1632                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1633             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1634             break;
1635         /* 24 bpp RGB */
1636         case TBM_FORMAT_RGB888:
1637         case TBM_FORMAT_BGR888:
1638             bpp = 24;
1639                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1640             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1641             break;
1642         /* 32 bpp RGB */
1643         case TBM_FORMAT_XRGB8888:
1644         case TBM_FORMAT_XBGR8888:
1645         case TBM_FORMAT_RGBX8888:
1646         case TBM_FORMAT_BGRX8888:
1647         case TBM_FORMAT_ARGB8888:
1648         case TBM_FORMAT_ABGR8888:
1649         case TBM_FORMAT_RGBA8888:
1650         case TBM_FORMAT_BGRA8888:
1651             bpp = 32;
1652                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_RGB);
1653             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1654             break;
1655         /* packed YCbCr */
1656         case TBM_FORMAT_YUYV:
1657         case TBM_FORMAT_YVYU:
1658         case TBM_FORMAT_UYVY:
1659         case TBM_FORMAT_VYUY:
1660         case TBM_FORMAT_AYUV:
1661             bpp = 32;
1662                         _pitch = SIZE_ALIGN((width*bpp)>>3,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1663             _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1664             break;
1665         /*
1666         * 2 plane YCbCr
1667         * index 0 = Y plane, [7:0] Y
1668         * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
1669         * or
1670         * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
1671         */
1672         case TBM_FORMAT_NV12:
1673         case TBM_FORMAT_NV21:
1674                         bpp = 12;
1675                          //plane_idx == 0
1676                          {
1677                                  _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1678                                  _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1679                          }
1680                          //plane_idx ==1
1681                          {
1682                                  _pitch = SIZE_ALIGN( width ,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1683                                  _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1684                          }
1685                          break;
1686
1687             break;
1688         case TBM_FORMAT_NV16:
1689         case TBM_FORMAT_NV61:
1690             bpp = 16;
1691             //plane_idx == 0
1692             {
1693                                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1694                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1695             }
1696             //plane_idx ==1
1697             {
1698                             _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1699                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1700             }
1701
1702             break;
1703         /*
1704         * 3 plane YCbCr
1705         * index 0: Y plane, [7:0] Y
1706         * index 1: Cb plane, [7:0] Cb
1707         * index 2: Cr plane, [7:0] Cr
1708         * or
1709         * index 1: Cr plane, [7:0] Cr
1710         * index 2: Cb plane, [7:0] Cb
1711         */
1712         case TBM_FORMAT_YUV410:
1713         case TBM_FORMAT_YVU410:
1714             bpp = 9;
1715             align = TBM_SURFACE_ALIGNMENT_PITCH_YUV;
1716             break;
1717         case TBM_FORMAT_YUV411:
1718         case TBM_FORMAT_YVU411:
1719         case TBM_FORMAT_YUV420:
1720         case TBM_FORMAT_YVU420:
1721             bpp = 12;
1722             //plane_idx == 0
1723             {
1724                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1725                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1726             }
1727             //plane_idx == 1
1728             {
1729                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1730                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1731             }
1732             //plane_idx == 2
1733             {
1734                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1735                 _size += SIZE_ALIGN(_pitch*(height/2),TBM_SURFACE_ALIGNMENT_PLANE);
1736             }
1737
1738             break;
1739         case TBM_FORMAT_YUV422:
1740         case TBM_FORMAT_YVU422:
1741             bpp = 16;
1742             //plane_idx == 0
1743             {
1744                 _pitch = SIZE_ALIGN(width,TBM_SURFACE_ALIGNMENT_PITCH_YUV);
1745                 _size = SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1746             }
1747             //plane_idx == 1
1748             {
1749                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1750                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1751             }
1752             //plane_idx == 2
1753             {
1754                 _pitch = SIZE_ALIGN(width/2,TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
1755                 _size += SIZE_ALIGN(_pitch*height,TBM_SURFACE_ALIGNMENT_PLANE);
1756             }
1757             break;
1758         case TBM_FORMAT_YUV444:
1759         case TBM_FORMAT_YVU444:
1760             bpp = 24;
1761             align = TBM_SURFACE_ALIGNMENT_PITCH_YUV;
1762             break;
1763
1764         default:
1765             bpp = 0;
1766             break;
1767     }
1768
1769         if(_size > 0)
1770                 ret = _size;
1771         else
1772             ret =  SIZE_ALIGN( (width * height * bpp) >> 3, align);
1773
1774     return ret;
1775
1776 }
1777
1778 tbm_bo_handle
1779 tbm_exynos4412_fd_to_handle(tbm_bufmgr bufmgr, tbm_fd fd, int device)
1780 {
1781     EXYNOS4412_RETURN_VAL_IF_FAIL (bufmgr!=NULL, (tbm_bo_handle) NULL);
1782     EXYNOS4412_RETURN_VAL_IF_FAIL (fd > 0, (tbm_bo_handle) NULL);
1783
1784     tbm_bo_handle bo_handle;
1785     memset (&bo_handle, 0x0, sizeof (uint64_t));
1786
1787     tbm_bufmgr_exynos4412 bufmgr_exynos4412 = (tbm_bufmgr_exynos4412)tbm_backend_get_priv_from_bufmgr(bufmgr);
1788
1789     switch(device)
1790     {
1791     case TBM_DEVICE_DEFAULT:
1792     case TBM_DEVICE_2D:
1793     {
1794         //getting handle from fd
1795         struct drm_prime_handle arg = {0, };
1796
1797         arg.fd = fd;
1798         arg.flags = 0;
1799         if (drmIoctl (bufmgr_exynos4412->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg))
1800         {
1801             TBM_EXYNOS4412_LOG ("error Cannot get gem handle from fd:%d (%s)\n",
1802                      arg.fd, strerror(errno));
1803             return (tbm_bo_handle) NULL;
1804         }
1805
1806         bo_handle.u32 = (uint32_t)arg.handle;;
1807         break;
1808     }
1809     case TBM_DEVICE_CPU:
1810         TBM_EXYNOS4412_LOG ("Not supported device:%d\n", device);
1811         bo_handle.ptr = (void *) NULL;
1812         break;
1813     case TBM_DEVICE_3D:
1814     case TBM_DEVICE_MM:
1815         bo_handle.u32 = (uint32_t)fd;
1816         break;
1817     default:
1818         TBM_EXYNOS4412_LOG ("error Not supported device:%d\n", device);
1819         bo_handle.ptr = (void *) NULL;
1820         break;
1821     }
1822
1823     return bo_handle;
1824 }
1825
1826 int
1827 tbm_exynos4412_bo_get_flags (tbm_bo bo)
1828 {
1829     EXYNOS4412_RETURN_VAL_IF_FAIL (bo != NULL, 0);
1830
1831     tbm_bo_exynos4412 bo_exynos4412;
1832
1833     bo_exynos4412 = (tbm_bo_exynos4412)tbm_backend_get_bo_priv(bo);
1834     EXYNOS4412_RETURN_VAL_IF_FAIL (bo_exynos4412 != NULL, 0);
1835
1836     return bo_exynos4412->flags_tbm;
1837 }
1838
1839 MODULEINITPPROTO (init_tbm_bufmgr_priv);
1840
1841 static TBMModuleVersionInfo Exynos4412VersRec =
1842 {
1843     "exynos4412",
1844     "Samsung",
1845     TBM_ABI_VERSION,
1846 };
1847
1848 TBMModuleData tbmModuleData = { &Exynos4412VersRec, init_tbm_bufmgr_priv};
1849
1850 int
1851 init_tbm_bufmgr_priv (tbm_bufmgr bufmgr, int fd)
1852 {
1853     tbm_bufmgr_exynos4412 bufmgr_exynos4412;
1854     tbm_bufmgr_backend bufmgr_backend;
1855
1856     if (!bufmgr)
1857         return 0;
1858
1859     bufmgr_exynos4412 = calloc (1, sizeof(struct _tbm_bufmgr_exynos4412));
1860     if (!bufmgr_exynos4412)
1861     {
1862         TBM_EXYNOS4412_LOG ("error: Fail to alloc bufmgr_exynos4412!\n");
1863         return 0;
1864     }
1865
1866     bufmgr_exynos4412->fd = fd;
1867     if (bufmgr_exynos4412->fd < 0)
1868     {
1869         TBM_EXYNOS4412_LOG ("error: Fail to create drm!\n");
1870         free (bufmgr_exynos4412);
1871         return 0;
1872     }
1873
1874     //Create Hash Table
1875     bufmgr_exynos4412->hashBos = drmHashCreate ();
1876
1877     //Check if the tbm manager supports dma fence or not.
1878     int fp = open("/sys/module/dmabuf_sync/parameters/enabled", O_RDONLY);
1879     int length;
1880     char buf[1];
1881     if (fp != -1)
1882     {
1883         length = read(fp, buf, 1);
1884
1885         if (length == 1 && buf[0] == '1')
1886             bufmgr_exynos4412->use_dma_fence = 1;
1887
1888         close(fp);
1889     }
1890
1891     bufmgr_backend = tbm_backend_alloc();
1892     if (!bufmgr_backend)
1893     {
1894         TBM_EXYNOS4412_LOG ("error: Fail to create drm!\n");
1895         if (bufmgr_exynos4412->hashBos)
1896             drmHashDestroy (bufmgr_exynos4412->hashBos);
1897         free (bufmgr_exynos4412);
1898         return 0;
1899     }
1900
1901     bufmgr_backend->priv = (void *)bufmgr_exynos4412;
1902     bufmgr_backend->bufmgr_deinit = tbm_exynos4412_bufmgr_deinit,
1903     bufmgr_backend->bo_size = tbm_exynos4412_bo_size,
1904     bufmgr_backend->bo_alloc = tbm_exynos4412_bo_alloc,
1905     bufmgr_backend->bo_free = tbm_exynos4412_bo_free,
1906     bufmgr_backend->bo_import = tbm_exynos4412_bo_import,
1907     bufmgr_backend->bo_import_fd = tbm_exynos4412_bo_import_fd,
1908     bufmgr_backend->bo_export = tbm_exynos4412_bo_export,
1909     bufmgr_backend->bo_export_fd = tbm_exynos4412_bo_export_fd,
1910     bufmgr_backend->bo_get_handle = tbm_exynos4412_bo_get_handle,
1911     bufmgr_backend->bo_map = tbm_exynos4412_bo_map,
1912     bufmgr_backend->bo_unmap = tbm_exynos4412_bo_unmap,
1913     bufmgr_backend->bo_cache_flush = tbm_exynos4412_bo_cache_flush,
1914     bufmgr_backend->bo_get_global_key = tbm_exynos4412_bo_get_global_key;
1915     bufmgr_backend->surface_get_plane_data = tbm_exynos4412_surface_get_plane_data;
1916     bufmgr_backend->surface_get_size = tbm_exynos4412_surface_get_size;
1917     bufmgr_backend->surface_supported_format = tbm_exynos4412_surface_supported_format;
1918     bufmgr_backend->fd_to_handle = tbm_exynos4412_fd_to_handle;
1919     bufmgr_backend->surface_get_num_bos = tbm_exynos4412_surface_get_num_bos;
1920     bufmgr_backend->bo_get_flags = tbm_exynos4412_bo_get_flags;
1921
1922     if (bufmgr_exynos4412->use_dma_fence)
1923     {
1924         bufmgr_backend->flags = (TBM_LOCK_CTRL_BACKEND | TBM_CACHE_CTRL_BACKEND);
1925         bufmgr_backend->bo_lock = NULL;
1926         bufmgr_backend->bo_lock2 = tbm_exynos4412_bo_lock;
1927         bufmgr_backend->bo_unlock = tbm_exynos4412_bo_unlock;
1928     }
1929     else
1930     {
1931         bufmgr_backend->flags = 0;
1932         bufmgr_backend->bo_lock = NULL;
1933         bufmgr_backend->bo_unlock = NULL;
1934     }
1935
1936     if (!tbm_backend_init (bufmgr, bufmgr_backend))
1937     {
1938         TBM_EXYNOS4412_LOG ("error: Fail to init backend!\n");
1939         tbm_backend_free (bufmgr_backend);
1940         free (bufmgr_exynos4412);
1941         return 0;
1942     }
1943
1944 #ifdef DEBUG
1945     {
1946         char* env;
1947         env = getenv ("TBM_EXYNOS4412_DEBUG");
1948         if (env)
1949         {
1950             bDebug = atoi (env);
1951             TBM_EXYNOS4412_LOG ("TBM_EXYNOS4412_DEBUG=%s\n", env);
1952         }
1953         else
1954         {
1955             bDebug = 0;
1956         }
1957     }
1958 #endif
1959
1960     DBG ("[%s] DMABUF FENCE is %s\n", target_name(),
1961           bufmgr_exynos4412->use_dma_fence ? "supported!" : "NOT supported!");
1962
1963     DBG ("[%s] drm_fd:%d\n", target_name(),
1964           bufmgr_exynos4412->fd);
1965
1966     return 1;
1967 }
1968
1969