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