Tizen 2.4 SDK Rev6 Release
[framework/uifw/efl.git] / src / modules / ecore_buffer / x11_dri3 / ecore_buffer_x11_dri3.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9
10 #include <X11/Xlib.h>
11 #include <X11/Xlib-xcb.h>
12 #include <X11/xshmfence.h>
13 #include <xcb/xcb.h>
14 #include <xcb/dri3.h>
15 #include <xcb/sync.h>
16
17 #include <Eina.h>
18 #include <Ecore.h>
19 #include <Ecore_X.h>
20 #include <Ecore_Buffer.h>
21
22 #include <tbm_bufmgr.h>
23 #include <tbm_surface.h>
24 #include <tbm_surface_internal.h>
25
26 #include "ecore_buffer_private.h"
27
28 typedef struct _Ecore_Buffer_Module_X11_Dri3_Data Ecore_Buffer_Module_X11_Dri3_Data;
29 typedef struct _Ecore_Buffer_X11_Dri3_Data Ecore_Buffer_X11_Dri3_Data;
30
31 struct _Ecore_Buffer_Module_X11_Dri3_Data {
32      tbm_bufmgr tbm_mgr;
33 };
34
35 struct _Ecore_Buffer_X11_Dri3_Data {
36      Ecore_X_Pixmap pixmap;
37      void *tbm_surface;
38      int w;
39      int h;
40      int stride;
41      unsigned int flags;
42      Ecore_Buffer_Format format;
43      Eina_Bool is_imported;
44 };
45
46 static Ecore_Pixmap  _ecore_buffer_x11_dri3_pixmap_get(Ecore_Buffer_Module_Data bmdata, Ecore_Buffer_Data bdata);
47
48 static int
49 _buf_get_num_planes(Ecore_Buffer_Format format)
50 {
51    int num_planes = 0;
52
53    switch (format)
54      {
55       case ECORE_BUFFER_FORMAT_C8:
56       case ECORE_BUFFER_FORMAT_RGB332:
57       case ECORE_BUFFER_FORMAT_BGR233:
58       case ECORE_BUFFER_FORMAT_XRGB4444:
59       case ECORE_BUFFER_FORMAT_XBGR4444:
60       case ECORE_BUFFER_FORMAT_RGBX4444:
61       case ECORE_BUFFER_FORMAT_BGRX4444:
62       case ECORE_BUFFER_FORMAT_ARGB4444:
63       case ECORE_BUFFER_FORMAT_ABGR4444:
64       case ECORE_BUFFER_FORMAT_RGBA4444:
65       case ECORE_BUFFER_FORMAT_BGRA4444:
66       case ECORE_BUFFER_FORMAT_XRGB1555:
67       case ECORE_BUFFER_FORMAT_XBGR1555:
68       case ECORE_BUFFER_FORMAT_RGBX5551:
69       case ECORE_BUFFER_FORMAT_BGRX5551:
70       case ECORE_BUFFER_FORMAT_ARGB1555:
71       case ECORE_BUFFER_FORMAT_ABGR1555:
72       case ECORE_BUFFER_FORMAT_RGBA5551:
73       case ECORE_BUFFER_FORMAT_BGRA5551:
74       case ECORE_BUFFER_FORMAT_RGB565:
75       case ECORE_BUFFER_FORMAT_BGR565:
76       case ECORE_BUFFER_FORMAT_RGB888:
77       case ECORE_BUFFER_FORMAT_BGR888:
78       case ECORE_BUFFER_FORMAT_XRGB8888:
79       case ECORE_BUFFER_FORMAT_XBGR8888:
80       case ECORE_BUFFER_FORMAT_RGBX8888:
81       case ECORE_BUFFER_FORMAT_BGRX8888:
82       case ECORE_BUFFER_FORMAT_ARGB8888:
83       case ECORE_BUFFER_FORMAT_ABGR8888:
84       case ECORE_BUFFER_FORMAT_RGBA8888:
85       case ECORE_BUFFER_FORMAT_BGRA8888:
86       case ECORE_BUFFER_FORMAT_XRGB2101010:
87       case ECORE_BUFFER_FORMAT_XBGR2101010:
88       case ECORE_BUFFER_FORMAT_RGBX1010102:
89       case ECORE_BUFFER_FORMAT_BGRX1010102:
90       case ECORE_BUFFER_FORMAT_ARGB2101010:
91       case ECORE_BUFFER_FORMAT_ABGR2101010:
92       case ECORE_BUFFER_FORMAT_RGBA1010102:
93       case ECORE_BUFFER_FORMAT_BGRA1010102:
94       case ECORE_BUFFER_FORMAT_YUYV:
95       case ECORE_BUFFER_FORMAT_YVYU:
96       case ECORE_BUFFER_FORMAT_UYVY:
97       case ECORE_BUFFER_FORMAT_VYUY:
98       case ECORE_BUFFER_FORMAT_AYUV:
99          num_planes = 1;
100          break;
101       case ECORE_BUFFER_FORMAT_NV12:
102       case ECORE_BUFFER_FORMAT_NV21:
103       case ECORE_BUFFER_FORMAT_NV16:
104       case ECORE_BUFFER_FORMAT_NV61:
105          num_planes = 2;
106          break;
107       case ECORE_BUFFER_FORMAT_YUV410:
108       case ECORE_BUFFER_FORMAT_YVU410:
109       case ECORE_BUFFER_FORMAT_YUV411:
110       case ECORE_BUFFER_FORMAT_YVU411:
111       case ECORE_BUFFER_FORMAT_YUV420:
112       case ECORE_BUFFER_FORMAT_YVU420:
113       case ECORE_BUFFER_FORMAT_YUV422:
114       case ECORE_BUFFER_FORMAT_YVU422:
115       case ECORE_BUFFER_FORMAT_YUV444:
116       case ECORE_BUFFER_FORMAT_YVU444:
117          num_planes = 3;
118          break;
119
120       default :
121          break;
122      }
123
124    return num_planes;
125 }
126
127 static int
128 _buf_get_bpp(Ecore_Buffer_Format format)
129 {
130    int bpp = 0;
131
132    switch (format)
133      {
134       case ECORE_BUFFER_FORMAT_C8:
135       case ECORE_BUFFER_FORMAT_RGB332:
136       case ECORE_BUFFER_FORMAT_BGR233:
137          bpp = 8;
138          break;
139       case ECORE_BUFFER_FORMAT_XRGB4444:
140       case ECORE_BUFFER_FORMAT_XBGR4444:
141       case ECORE_BUFFER_FORMAT_RGBX4444:
142       case ECORE_BUFFER_FORMAT_BGRX4444:
143       case ECORE_BUFFER_FORMAT_ARGB4444:
144       case ECORE_BUFFER_FORMAT_ABGR4444:
145       case ECORE_BUFFER_FORMAT_RGBA4444:
146       case ECORE_BUFFER_FORMAT_BGRA4444:
147       case ECORE_BUFFER_FORMAT_XRGB1555:
148       case ECORE_BUFFER_FORMAT_XBGR1555:
149       case ECORE_BUFFER_FORMAT_RGBX5551:
150       case ECORE_BUFFER_FORMAT_BGRX5551:
151       case ECORE_BUFFER_FORMAT_ARGB1555:
152       case ECORE_BUFFER_FORMAT_ABGR1555:
153       case ECORE_BUFFER_FORMAT_RGBA5551:
154       case ECORE_BUFFER_FORMAT_BGRA5551:
155       case ECORE_BUFFER_FORMAT_RGB565:
156       case ECORE_BUFFER_FORMAT_BGR565:
157          bpp = 16;
158          break;
159       case ECORE_BUFFER_FORMAT_RGB888:
160       case ECORE_BUFFER_FORMAT_BGR888:
161          bpp = 24;
162          break;
163       case ECORE_BUFFER_FORMAT_XRGB8888:
164       case ECORE_BUFFER_FORMAT_XBGR8888:
165       case ECORE_BUFFER_FORMAT_RGBX8888:
166       case ECORE_BUFFER_FORMAT_BGRX8888:
167       case ECORE_BUFFER_FORMAT_ARGB8888:
168       case ECORE_BUFFER_FORMAT_ABGR8888:
169       case ECORE_BUFFER_FORMAT_RGBA8888:
170       case ECORE_BUFFER_FORMAT_BGRA8888:
171       case ECORE_BUFFER_FORMAT_XRGB2101010:
172       case ECORE_BUFFER_FORMAT_XBGR2101010:
173       case ECORE_BUFFER_FORMAT_RGBX1010102:
174       case ECORE_BUFFER_FORMAT_BGRX1010102:
175       case ECORE_BUFFER_FORMAT_ARGB2101010:
176       case ECORE_BUFFER_FORMAT_ABGR2101010:
177       case ECORE_BUFFER_FORMAT_RGBA1010102:
178       case ECORE_BUFFER_FORMAT_BGRA1010102:
179       case ECORE_BUFFER_FORMAT_YUYV:
180       case ECORE_BUFFER_FORMAT_YVYU:
181       case ECORE_BUFFER_FORMAT_UYVY:
182       case ECORE_BUFFER_FORMAT_VYUY:
183       case ECORE_BUFFER_FORMAT_AYUV:
184          bpp = 32;
185          break;
186       case ECORE_BUFFER_FORMAT_NV12:
187       case ECORE_BUFFER_FORMAT_NV21:
188          bpp = 12;
189          break;
190       case ECORE_BUFFER_FORMAT_NV16:
191       case ECORE_BUFFER_FORMAT_NV61:
192          bpp = 16;
193          break;
194       case ECORE_BUFFER_FORMAT_YUV410:
195       case ECORE_BUFFER_FORMAT_YVU410:
196          bpp = 9;
197          break;
198       case ECORE_BUFFER_FORMAT_YUV411:
199       case ECORE_BUFFER_FORMAT_YVU411:
200       case ECORE_BUFFER_FORMAT_YUV420:
201       case ECORE_BUFFER_FORMAT_YVU420:
202          bpp = 12;
203          break;
204       case ECORE_BUFFER_FORMAT_YUV422:
205       case ECORE_BUFFER_FORMAT_YVU422:
206          bpp = 16;
207          break;
208       case ECORE_BUFFER_FORMAT_YUV444:
209       case ECORE_BUFFER_FORMAT_YVU444:
210          bpp = 24;
211          break;
212       default :
213          break;
214      }
215
216    return bpp;
217 }
218
219 static int
220 _buf_get_depth(Ecore_Buffer_Format format)
221 {
222    int depth = 0;
223
224    switch (format)
225      {
226       case ECORE_BUFFER_FORMAT_C8:
227       case ECORE_BUFFER_FORMAT_RGB332:
228       case ECORE_BUFFER_FORMAT_BGR233:
229          depth = 8;
230          break;
231       case ECORE_BUFFER_FORMAT_XRGB4444:
232       case ECORE_BUFFER_FORMAT_XBGR4444:
233       case ECORE_BUFFER_FORMAT_RGBX4444:
234       case ECORE_BUFFER_FORMAT_BGRX4444:
235          depth = 12;
236          break;
237       case ECORE_BUFFER_FORMAT_ARGB4444:
238       case ECORE_BUFFER_FORMAT_ABGR4444:
239       case ECORE_BUFFER_FORMAT_RGBA4444:
240       case ECORE_BUFFER_FORMAT_BGRA4444:
241          depth = 16;
242          break;
243       case ECORE_BUFFER_FORMAT_XRGB1555:
244       case ECORE_BUFFER_FORMAT_XBGR1555:
245       case ECORE_BUFFER_FORMAT_RGBX5551:
246       case ECORE_BUFFER_FORMAT_BGRX5551:
247          depth = 15;
248          break;
249       case ECORE_BUFFER_FORMAT_ARGB1555:
250       case ECORE_BUFFER_FORMAT_ABGR1555:
251       case ECORE_BUFFER_FORMAT_RGBA5551:
252       case ECORE_BUFFER_FORMAT_BGRA5551:
253       case ECORE_BUFFER_FORMAT_RGB565:
254       case ECORE_BUFFER_FORMAT_BGR565:
255          depth = 16;
256          break;
257       case ECORE_BUFFER_FORMAT_RGB888:
258       case ECORE_BUFFER_FORMAT_BGR888:
259          depth = 24;
260          break;
261       case ECORE_BUFFER_FORMAT_XRGB8888:
262       case ECORE_BUFFER_FORMAT_XBGR8888:
263       case ECORE_BUFFER_FORMAT_RGBX8888:
264       case ECORE_BUFFER_FORMAT_BGRX8888:
265          depth = 24;
266          break;
267       case ECORE_BUFFER_FORMAT_ARGB8888:
268       case ECORE_BUFFER_FORMAT_ABGR8888:
269       case ECORE_BUFFER_FORMAT_RGBA8888:
270       case ECORE_BUFFER_FORMAT_BGRA8888:
271          depth = 32;
272          break;
273       case ECORE_BUFFER_FORMAT_XRGB2101010:
274       case ECORE_BUFFER_FORMAT_XBGR2101010:
275       case ECORE_BUFFER_FORMAT_RGBX1010102:
276       case ECORE_BUFFER_FORMAT_BGRX1010102:
277          depth = 30;
278          break;
279       case ECORE_BUFFER_FORMAT_ARGB2101010:
280       case ECORE_BUFFER_FORMAT_ABGR2101010:
281       case ECORE_BUFFER_FORMAT_RGBA1010102:
282       case ECORE_BUFFER_FORMAT_BGRA1010102:
283          depth = 32;
284          break;
285       case ECORE_BUFFER_FORMAT_YUYV:
286       case ECORE_BUFFER_FORMAT_YVYU:
287       case ECORE_BUFFER_FORMAT_UYVY:
288       case ECORE_BUFFER_FORMAT_VYUY:
289       case ECORE_BUFFER_FORMAT_AYUV:
290       case ECORE_BUFFER_FORMAT_NV12:
291       case ECORE_BUFFER_FORMAT_NV21:
292       case ECORE_BUFFER_FORMAT_NV16:
293       case ECORE_BUFFER_FORMAT_NV61:
294       case ECORE_BUFFER_FORMAT_YUV410:
295       case ECORE_BUFFER_FORMAT_YVU410:
296       case ECORE_BUFFER_FORMAT_YUV411:
297       case ECORE_BUFFER_FORMAT_YVU411:
298       case ECORE_BUFFER_FORMAT_YUV420:
299       case ECORE_BUFFER_FORMAT_YVU420:
300       case ECORE_BUFFER_FORMAT_YUV422:
301       case ECORE_BUFFER_FORMAT_YVU422:
302       case ECORE_BUFFER_FORMAT_YUV444:
303       case ECORE_BUFFER_FORMAT_YVU444:
304       default :
305          depth = 0; //unknown in X
306          break;
307      }
308
309    return depth;
310 }
311
312 static int
313 _dri3_open(Ecore_X_Display *dpy, Ecore_X_Window root, unsigned provider)
314 {
315    xcb_connection_t *c = XGetXCBConnection(dpy);
316    xcb_dri3_open_cookie_t cookie;
317    xcb_dri3_open_reply_t *reply;
318
319    cookie = xcb_dri3_open(c, root, provider);
320    reply = xcb_dri3_open_reply(c, cookie, NULL);
321    if ((!reply) || (reply->nfd != 1))
322      return -1;
323
324    return xcb_dri3_open_reply_fds(c, reply)[0];
325 }
326
327 static Ecore_X_Pixmap
328 _dri3_pixmap_from_fd(Ecore_X_Display *dpy, Ecore_X_Drawable draw, int width, int height, int depth, int fd, int bpp, int stride, int size)
329 {
330    xcb_connection_t *c;
331    Ecore_X_Pixmap pixmap;
332
333    if (!dpy)
334      return 0;
335
336    c = XGetXCBConnection(dpy);
337    if (!c)
338      return 0;
339
340    pixmap = xcb_generate_id(c);
341    if (!pixmap)
342      return 0;
343
344    xcb_dri3_pixmap_from_buffer(c, pixmap, draw, size, width, height, stride, depth, bpp, fd);
345
346    return pixmap;
347 }
348
349 static Ecore_Buffer_Module_Data
350 _ecore_buffer_x11_dri3_init(const char *context EINA_UNUSED, const char *options EINA_UNUSED)
351 {
352    Ecore_X_Display *xdpy;
353    Ecore_X_Window root;
354    Ecore_Buffer_Module_X11_Dri3_Data *mdata = NULL;
355    int fd = 0;
356
357    if (!ecore_x_init(NULL))
358      return NULL;
359
360    xdpy = ecore_x_display_get();
361    if (!xdpy)
362      goto on_error;
363
364    root = ecore_x_window_root_first_get();
365    if (!root)
366      goto on_error;
367
368    mdata = calloc(1, sizeof(Ecore_Buffer_Module_X11_Dri3_Data));
369    if (!mdata)
370      goto on_error;
371
372    //Init DRI3 and TBM
373    fd = _dri3_open(xdpy, root, 0);
374    if (fd < 0)
375      goto on_error;
376
377    mdata->tbm_mgr = tbm_bufmgr_init(fd);
378    if (!mdata->tbm_mgr)
379      goto on_error;
380
381    close(fd);
382
383    return mdata;
384
385 on_error:
386    if (fd > 0) close(fd);
387    if (mdata) free(mdata);
388    ecore_x_shutdown();
389
390    return NULL;
391 }
392
393 static void
394 _ecore_buffer_x11_dri3_shutdown(Ecore_Buffer_Module_Data bmdata)
395 {
396    Ecore_Buffer_Module_X11_Dri3_Data *bm = bmdata;
397
398    if (!bm)
399      return;
400
401    if (bm->tbm_mgr)
402      tbm_bufmgr_deinit(bm->tbm_mgr);
403
404    ecore_x_shutdown();
405 }
406
407 static Ecore_Buffer_Data
408 _ecore_buffer_x11_dri3_buffer_alloc(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, int width, int height, Ecore_Buffer_Format format, unsigned int flags)
409 {
410    Ecore_Buffer_X11_Dri3_Data *buf;
411
412    buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri3_Data));
413    if (!buf)
414      return NULL;
415
416    buf->w = width;
417    buf->h = height;
418    buf->format = format;
419    buf->flags = flags;
420    buf->is_imported = EINA_FALSE;
421    buf->tbm_surface = tbm_surface_create(width,height,(tbm_format)format);
422    if (!buf->tbm_surface)
423      {
424         free(buf);
425         return NULL;
426      }
427
428    return buf;
429 }
430
431 static Ecore_Buffer_Data
432 _ecore_buffer_x11_dri3_buffer_alloc_with_tbm_surface(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, void *tbm_surface, int *ret_w, int *ret_h, Ecore_Buffer_Format *ret_format, unsigned int flags)
433 {
434    Ecore_Buffer_X11_Dri3_Data *buf;
435
436    EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
437
438    buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri3_Data));
439    if (!buf)
440      return NULL;
441
442    buf->w = tbm_surface_get_width(tbm_surface);
443    buf->h = tbm_surface_get_height(tbm_surface);
444    buf->format = tbm_surface_get_format(tbm_surface);
445    buf->flags = flags;
446    buf->is_imported = EINA_FALSE;
447    buf->tbm_surface = tbm_surface;
448
449    if (ret_w) *ret_w = buf->w;
450    if (ret_h) *ret_h = buf->h;
451    if (ret_format) *ret_format = buf->format;
452
453    return buf;
454 }
455
456 static Eina_Bool
457 _ecore_buffer_x11_dri3_buffer_info_get(Ecore_Buffer_Module_Data bmdata, Ecore_Buffer_Data bdata, Ecore_Buffer_Info *info)
458 {
459    Ecore_Buffer_X11_Dri3_Data *buf = bdata;
460    tbm_surface_info_s tinfo;
461    int i, res;
462
463    if (!buf->tbm_surface)
464      return EINA_FALSE;
465
466    res = tbm_surface_get_info(buf->tbm_surface, &tinfo);
467    if (res != TBM_SURFACE_ERROR_NONE)
468      return EINA_FALSE;
469
470    if (info)
471      {
472         info->width = tinfo.width;
473         info->height = tinfo.height;
474         info->format = tinfo.format;
475         info->bpp = tinfo.bpp;
476         info->size = tinfo.size;
477         info->num_planes = tinfo.num_planes;
478         info->pixmap = _ecore_buffer_x11_dri3_pixmap_get(bmdata, bdata);
479
480         for (i = 0; i < tinfo.num_planes; i++)
481           {
482              info->planes[i].size = tinfo.planes[i].size;
483              info->planes[i].offset = tinfo.planes[i].offset;
484              info->planes[i].stride = tinfo.planes[i].stride;
485           }
486      }
487
488    return EINA_TRUE;
489 }
490
491 static void
492 _ecore_buffer_x11_dri3_buffer_free(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
493 {
494    Ecore_Buffer_X11_Dri3_Data *buf = bdata;
495
496    if (!buf)
497      return;
498
499    if (buf->pixmap)
500      ecore_x_pixmap_free(buf->pixmap);
501
502    if (buf->tbm_surface)
503      tbm_surface_destroy(buf->tbm_surface);
504
505    free(buf);
506 }
507
508 static Ecore_Export_Type
509 _ecore_buffer_x11_dri3_buffer_export(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata, int *id)
510 {
511    Ecore_Buffer_X11_Dri3_Data *buf = bdata;
512    tbm_bo bo;
513
514    if (_buf_get_num_planes(buf->format) != 1)
515      return EXPORT_TYPE_INVALID;
516
517    bo = tbm_surface_internal_get_bo(buf->tbm_surface, 0);
518    if (!bo)
519      return EXPORT_TYPE_INVALID;
520
521    if (id) *id = tbm_bo_export_fd(bo);
522
523    return EXPORT_TYPE_FD;
524 }
525
526 static Ecore_Buffer_Data
527 _ecore_buffer_x11_dri3_buffer_import(Ecore_Buffer_Module_Data bmdata, Ecore_Buffer_Info *einfo, Ecore_Export_Type type, int export_id, unsigned int flags)
528 {
529    Ecore_Buffer_Module_X11_Dri3_Data *bm = bmdata;
530    Ecore_Buffer_X11_Dri3_Data *buf;
531    tbm_bo bo;
532    tbm_surface_info_s tinfo;
533    int i;
534
535    if (!bm)
536      return NULL;
537
538    if (type != EXPORT_TYPE_FD)
539      return NULL;
540
541    if (export_id < 1)
542      return NULL;
543
544    buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri3_Data));
545    if (!buf)
546      return NULL;
547
548    buf->w = einfo->width;
549    buf->h = einfo->height;
550    buf->format = einfo->format;
551    buf->flags = flags;
552    buf->is_imported = EINA_TRUE;
553
554    //Import tbm_surface
555    bo = tbm_bo_import_fd(bm->tbm_mgr, export_id);
556    if (!bo)
557      {
558         free(buf);
559         return NULL;
560      }
561
562    tinfo.width = buf->w = einfo->width;
563    tinfo.height = buf->h = einfo->height;
564    tinfo.format = buf->format = einfo->format;
565    tinfo.bpp = _buf_get_bpp(einfo->format);
566    tinfo.size = einfo->height * einfo->planes[0].stride;
567    tinfo.num_planes = _buf_get_num_planes(einfo->format);
568    for (i = 0; i < tinfo.num_planes; i++)
569    {
570       tinfo.planes[i].size = einfo->height * einfo->planes[i].stride;
571       tinfo.planes[i].stride = einfo->planes[i].stride;
572       tinfo.planes[i].offset = einfo->planes[i].offset;
573    }
574
575    buf->tbm_surface = tbm_surface_internal_create_with_bos(&tinfo, &bo, 1);
576    if (!buf->tbm_surface)
577      {
578         tbm_bo_unref(bo);
579         free(buf);
580         return NULL;
581      }
582
583    tbm_bo_unref(bo);
584
585    return buf;
586 }
587
588 static Ecore_Pixmap
589 _ecore_buffer_x11_dri3_pixmap_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
590 {
591    Ecore_Buffer_X11_Dri3_Data *buf = bdata;
592    Ecore_X_Display *xdpy;
593    Ecore_X_Window root;
594    tbm_surface_info_s info;
595    tbm_bo bo;
596    int ret;
597
598    if (!buf)
599      return 0;
600
601    if (buf->pixmap)
602      return buf->pixmap;
603
604    ret = tbm_surface_get_info(buf->tbm_surface, &info);
605    if (ret != 0)
606      return 0;
607
608    if (info.num_planes != 1)
609      return 0;
610
611    bo = tbm_surface_internal_get_bo(buf->tbm_surface, 0);
612    if (!bo)
613      return 0;
614
615    xdpy = ecore_x_display_get();
616    root = ecore_x_window_root_first_get();
617    buf->pixmap = _dri3_pixmap_from_fd(xdpy, root,
618                                       buf->w, buf->h,
619                                       _buf_get_depth(buf->format),
620                                       tbm_bo_export_fd(bo),
621                                       _buf_get_bpp(buf->format),
622                                       info.planes[0].stride,
623                                       info.planes[0].size);
624
625    return buf->pixmap;
626 }
627
628 static void *
629 _ecore_buffer_x11_dri3_tbm_bo_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
630 {
631    Ecore_Buffer_X11_Dri3_Data *buf = bdata;
632
633    if (!buf)
634      return NULL;
635
636    return buf->tbm_surface;
637 }
638
639 static Ecore_Buffer_Backend _ecore_buffer_x11_dri3_backend = {
640      "x11_dri3",
641      &_ecore_buffer_x11_dri3_init,
642      &_ecore_buffer_x11_dri3_shutdown,
643      &_ecore_buffer_x11_dri3_buffer_alloc,
644      &_ecore_buffer_x11_dri3_buffer_alloc_with_tbm_surface,
645      &_ecore_buffer_x11_dri3_buffer_info_get,
646      &_ecore_buffer_x11_dri3_buffer_free,
647      &_ecore_buffer_x11_dri3_buffer_export,
648      &_ecore_buffer_x11_dri3_buffer_import,
649      &_ecore_buffer_x11_dri3_pixmap_get,
650      &_ecore_buffer_x11_dri3_tbm_bo_get,
651 };
652
653 Eina_Bool x11_dri3_init(void)
654 {
655    return ecore_buffer_register(&_ecore_buffer_x11_dri3_backend);
656 }
657
658 void x11_dri3_shutdown(void)
659 {
660    ecore_buffer_unregister(&_ecore_buffer_x11_dri3_backend);
661 }
662
663 EINA_MODULE_INIT(x11_dri3_init);
664 EINA_MODULE_SHUTDOWN(x11_dri3_shutdown);