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