14 #include <tbm_bufmgr.h>
15 #include <tbm_surface.h>
16 #include <tbm_surface_internal.h>
20 #include <dri2/dri2.h>
22 #include "Ecore_Buffer.h"
23 #include "ecore_buffer_private.h"
25 typedef struct _Ecore_Buffer_Module_X11_Dri2_Data Ecore_Buffer_Module_X11_Dri2_Data;
26 typedef struct _Ecore_Buffer_X11_Dri2_Data Ecore_Buffer_X11_Dri2_Data;
28 struct _Ecore_Buffer_Module_X11_Dri2_Data {
32 struct _Ecore_Buffer_X11_Dri2_Data {
33 Ecore_X_Pixmap pixmap;
37 Ecore_Buffer_Format format;
38 Eina_Bool is_imported;
48 _buf_get_num_planes(Ecore_Buffer_Format format)
54 case ECORE_BUFFER_FORMAT_C8:
55 case ECORE_BUFFER_FORMAT_RGB332:
56 case ECORE_BUFFER_FORMAT_BGR233:
57 case ECORE_BUFFER_FORMAT_XRGB4444:
58 case ECORE_BUFFER_FORMAT_XBGR4444:
59 case ECORE_BUFFER_FORMAT_RGBX4444:
60 case ECORE_BUFFER_FORMAT_BGRX4444:
61 case ECORE_BUFFER_FORMAT_ARGB4444:
62 case ECORE_BUFFER_FORMAT_ABGR4444:
63 case ECORE_BUFFER_FORMAT_RGBA4444:
64 case ECORE_BUFFER_FORMAT_BGRA4444:
65 case ECORE_BUFFER_FORMAT_XRGB1555:
66 case ECORE_BUFFER_FORMAT_XBGR1555:
67 case ECORE_BUFFER_FORMAT_RGBX5551:
68 case ECORE_BUFFER_FORMAT_BGRX5551:
69 case ECORE_BUFFER_FORMAT_ARGB1555:
70 case ECORE_BUFFER_FORMAT_ABGR1555:
71 case ECORE_BUFFER_FORMAT_RGBA5551:
72 case ECORE_BUFFER_FORMAT_BGRA5551:
73 case ECORE_BUFFER_FORMAT_RGB565:
74 case ECORE_BUFFER_FORMAT_BGR565:
75 case ECORE_BUFFER_FORMAT_RGB888:
76 case ECORE_BUFFER_FORMAT_BGR888:
77 case ECORE_BUFFER_FORMAT_XRGB8888:
78 case ECORE_BUFFER_FORMAT_XBGR8888:
79 case ECORE_BUFFER_FORMAT_RGBX8888:
80 case ECORE_BUFFER_FORMAT_BGRX8888:
81 case ECORE_BUFFER_FORMAT_ARGB8888:
82 case ECORE_BUFFER_FORMAT_ABGR8888:
83 case ECORE_BUFFER_FORMAT_RGBA8888:
84 case ECORE_BUFFER_FORMAT_BGRA8888:
85 case ECORE_BUFFER_FORMAT_XRGB2101010:
86 case ECORE_BUFFER_FORMAT_XBGR2101010:
87 case ECORE_BUFFER_FORMAT_RGBX1010102:
88 case ECORE_BUFFER_FORMAT_BGRX1010102:
89 case ECORE_BUFFER_FORMAT_ARGB2101010:
90 case ECORE_BUFFER_FORMAT_ABGR2101010:
91 case ECORE_BUFFER_FORMAT_RGBA1010102:
92 case ECORE_BUFFER_FORMAT_BGRA1010102:
93 case ECORE_BUFFER_FORMAT_YUYV:
94 case ECORE_BUFFER_FORMAT_YVYU:
95 case ECORE_BUFFER_FORMAT_UYVY:
96 case ECORE_BUFFER_FORMAT_VYUY:
97 case ECORE_BUFFER_FORMAT_AYUV:
100 case ECORE_BUFFER_FORMAT_NV12:
101 case ECORE_BUFFER_FORMAT_NV21:
102 case ECORE_BUFFER_FORMAT_NV16:
103 case ECORE_BUFFER_FORMAT_NV61:
106 case ECORE_BUFFER_FORMAT_YUV410:
107 case ECORE_BUFFER_FORMAT_YVU410:
108 case ECORE_BUFFER_FORMAT_YUV411:
109 case ECORE_BUFFER_FORMAT_YVU411:
110 case ECORE_BUFFER_FORMAT_YUV420:
111 case ECORE_BUFFER_FORMAT_YVU420:
112 case ECORE_BUFFER_FORMAT_YUV422:
113 case ECORE_BUFFER_FORMAT_YVU422:
114 case ECORE_BUFFER_FORMAT_YUV444:
115 case ECORE_BUFFER_FORMAT_YVU444:
127 _buf_get_bpp(Ecore_Buffer_Format format)
133 case ECORE_BUFFER_FORMAT_C8:
134 case ECORE_BUFFER_FORMAT_RGB332:
135 case ECORE_BUFFER_FORMAT_BGR233:
138 case ECORE_BUFFER_FORMAT_XRGB4444:
139 case ECORE_BUFFER_FORMAT_XBGR4444:
140 case ECORE_BUFFER_FORMAT_RGBX4444:
141 case ECORE_BUFFER_FORMAT_BGRX4444:
142 case ECORE_BUFFER_FORMAT_ARGB4444:
143 case ECORE_BUFFER_FORMAT_ABGR4444:
144 case ECORE_BUFFER_FORMAT_RGBA4444:
145 case ECORE_BUFFER_FORMAT_BGRA4444:
146 case ECORE_BUFFER_FORMAT_XRGB1555:
147 case ECORE_BUFFER_FORMAT_XBGR1555:
148 case ECORE_BUFFER_FORMAT_RGBX5551:
149 case ECORE_BUFFER_FORMAT_BGRX5551:
150 case ECORE_BUFFER_FORMAT_ARGB1555:
151 case ECORE_BUFFER_FORMAT_ABGR1555:
152 case ECORE_BUFFER_FORMAT_RGBA5551:
153 case ECORE_BUFFER_FORMAT_BGRA5551:
154 case ECORE_BUFFER_FORMAT_RGB565:
155 case ECORE_BUFFER_FORMAT_BGR565:
158 case ECORE_BUFFER_FORMAT_RGB888:
159 case ECORE_BUFFER_FORMAT_BGR888:
162 case ECORE_BUFFER_FORMAT_XRGB8888:
163 case ECORE_BUFFER_FORMAT_XBGR8888:
164 case ECORE_BUFFER_FORMAT_RGBX8888:
165 case ECORE_BUFFER_FORMAT_BGRX8888:
166 case ECORE_BUFFER_FORMAT_ARGB8888:
167 case ECORE_BUFFER_FORMAT_ABGR8888:
168 case ECORE_BUFFER_FORMAT_RGBA8888:
169 case ECORE_BUFFER_FORMAT_BGRA8888:
170 case ECORE_BUFFER_FORMAT_XRGB2101010:
171 case ECORE_BUFFER_FORMAT_XBGR2101010:
172 case ECORE_BUFFER_FORMAT_RGBX1010102:
173 case ECORE_BUFFER_FORMAT_BGRX1010102:
174 case ECORE_BUFFER_FORMAT_ARGB2101010:
175 case ECORE_BUFFER_FORMAT_ABGR2101010:
176 case ECORE_BUFFER_FORMAT_RGBA1010102:
177 case ECORE_BUFFER_FORMAT_BGRA1010102:
178 case ECORE_BUFFER_FORMAT_YUYV:
179 case ECORE_BUFFER_FORMAT_YVYU:
180 case ECORE_BUFFER_FORMAT_UYVY:
181 case ECORE_BUFFER_FORMAT_VYUY:
182 case ECORE_BUFFER_FORMAT_AYUV:
185 case ECORE_BUFFER_FORMAT_NV12:
186 case ECORE_BUFFER_FORMAT_NV21:
189 case ECORE_BUFFER_FORMAT_NV16:
190 case ECORE_BUFFER_FORMAT_NV61:
193 case ECORE_BUFFER_FORMAT_YUV410:
194 case ECORE_BUFFER_FORMAT_YVU410:
197 case ECORE_BUFFER_FORMAT_YUV411:
198 case ECORE_BUFFER_FORMAT_YVU411:
199 case ECORE_BUFFER_FORMAT_YUV420:
200 case ECORE_BUFFER_FORMAT_YVU420:
203 case ECORE_BUFFER_FORMAT_YUV422:
204 case ECORE_BUFFER_FORMAT_YVU422:
207 case ECORE_BUFFER_FORMAT_YUV444:
208 case ECORE_BUFFER_FORMAT_YVU444:
218 static Ecore_Buffer_Module_Data
219 _ecore_buffer_x11_dri2_init(const char *context EINA_UNUSED, const char *options EINA_UNUSED)
221 Ecore_X_Display *xdpy;
225 char *driver_name = NULL;
226 char *device_name = NULL;
229 Ecore_Buffer_Module_X11_Dri2_Data *mdata = NULL;
231 if (!ecore_x_init(NULL))
234 xdpy = ecore_x_display_get();
238 root = ecore_x_window_root_first_get();
242 mdata = calloc(1, sizeof(Ecore_Buffer_Module_X11_Dri2_Data));
247 DRI2QueryExtension(xdpy, &eb, &ee);
248 DRI2QueryVersion(xdpy, &major, &minor);
249 DRI2Connect(xdpy, root, &driver_name, &device_name);
251 fd = open (device_name, O_RDWR);
255 if (drmGetMagic(fd, &magic) < 0)
258 if (!(DRI2Authenticate(xdpy, root, magic)))
261 mdata->tbm_mgr = tbm_bufmgr_init(fd);
275 if (driver_name) free(driver_name);
276 if (device_name) free(device_name);
277 if (mdata) free(mdata);
284 _ecore_buffer_x11_dri2_shutdown(Ecore_Buffer_Module_Data bmdata)
286 Ecore_Buffer_Module_X11_Dri2_Data *bm = bmdata;
289 tbm_bufmgr_deinit(bm->tbm_mgr);
294 static Ecore_Buffer_Data
295 _ecore_buffer_x11_dri2_buffer_alloc(Ecore_Buffer_Module_Data bmdata, int width, int height, Ecore_Buffer_Format format, unsigned int flags EINA_UNUSED)
297 Ecore_X_Display *xdpy;
298 Ecore_X_Pixmap pixmap;
299 Ecore_Buffer_X11_Dri2_Data *buf;
300 Ecore_Buffer_Module_X11_Dri2_Data *bm = bmdata;
301 DRI2Buffer *bufs = NULL;
306 unsigned int attachment = DRI2BufferFrontLeft;
307 tbm_surface_info_s info;
310 bpp = _buf_get_bpp(format);
314 num_plane = _buf_get_num_planes(format);
318 xdpy = ecore_x_display_get();
319 pixmap = ecore_x_pixmap_new(0, width, height, bpp);
323 buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri2_Data));
326 ecore_x_pixmap_free(pixmap);
332 buf->format = format;
333 buf->pixmap = pixmap;
334 buf->is_imported = EINA_FALSE;
337 DRI2CreateDrawable(xdpy, buf->pixmap);
338 bufs = DRI2GetBuffers(xdpy, buf->pixmap, &rw, &rh, &attachment, 1, &rcount);
339 if (!(bufs) || (buf->w != rw) || (buf->h != rh))
342 buf->stride = bufs->pitch;
345 bo = tbm_bo_import(bm->tbm_mgr, bufs->name);
350 info.height = height;
351 info.format = format;
353 info.size = height * bufs->pitch;
354 info.num_planes = num_plane;
355 for ( i = 0 ; i < num_plane ; i++)
357 info.planes[i].size = height * bufs->pitch;
358 info.planes[i].stride = bufs->pitch;
359 info.planes[i].offset = 0;
362 buf->tbm.surface = tbm_surface_internal_create_with_bos(&info, &bo, 1);
363 if (!buf->tbm.surface)
366 buf->tbm.owned = EINA_TRUE;
373 if (bo) tbm_bo_unref(bo);
374 if (bufs) free(bufs);
375 ecore_x_pixmap_free(buf->pixmap);
376 DRI2DestroyDrawable(xdpy, buf->pixmap);
382 static Ecore_Buffer_Data
383 _ecore_buffer_x11_dri2_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 EINA_UNUSED)
385 Ecore_Buffer_X11_Dri2_Data *buf;
387 EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
389 buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri2_Data));
393 buf->w = tbm_surface_get_width(tbm_surface);
394 buf->h = tbm_surface_get_height(tbm_surface);
395 buf->format = tbm_surface_get_format(tbm_surface);
397 buf->tbm.surface = tbm_surface;
398 buf->tbm.owned = EINA_FALSE;
399 buf->is_imported = EINA_FALSE;
401 if (ret_w) *ret_w = buf->w;
402 if (ret_h) *ret_h = buf->h;
403 if (ret_format) *ret_format = buf->format;
409 _ecore_buffer_x11_dri2_buffer_info_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata, Ecore_Buffer_Info *info)
411 Ecore_Buffer_X11_Dri2_Data *buf = bdata;
412 tbm_surface_info_s tinfo;
415 if (!buf->tbm.surface)
418 res = tbm_surface_get_info(buf->tbm.surface, &tinfo);
419 if (res != TBM_SURFACE_ERROR_NONE)
424 info->width = tinfo.width;
425 info->height = tinfo.height;
426 info->format = tinfo.format;
427 info->bpp = tinfo.bpp;
428 info->size = tinfo.size;
429 info->num_planes = tinfo.num_planes;
430 info->pixmap = buf->pixmap;
432 for (i = 0; i < tinfo.num_planes; i++)
434 info->planes[i].size = tinfo.planes[i].size;
435 info->planes[i].offset = tinfo.planes[i].offset;
436 info->planes[i].stride = tinfo.planes[i].stride;
444 _ecore_buffer_x11_dri2_buffer_free(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
446 Ecore_Buffer_X11_Dri2_Data *buf = bdata;
450 DRI2DestroyDrawable(ecore_x_display_get(), buf->pixmap);
452 if (!buf->is_imported)
453 ecore_x_pixmap_free(buf->pixmap);
456 if (buf->tbm.surface)
457 tbm_surface_destroy(buf->tbm.surface);
464 static Ecore_Export_Type
465 _ecore_buffer_x11_dri2_buffer_export(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata, int *id)
467 Ecore_Buffer_X11_Dri2_Data *buf = bdata;
477 /* NOTE: constraints - cannot support more than two bos */
478 bo = tbm_surface_internal_get_bo(buf->tbm.surface, 0);
479 *id = (int)(tbm_bo_export(bo));
483 return EXPORT_TYPE_ID;
487 _x11_dri2_bo_get_from_pixmap(tbm_bufmgr tbm_mgr, Ecore_Pixmap pixmap, int width, int height)
489 Ecore_X_Display *xdpy;
490 DRI2Buffer *bufs = NULL;
494 unsigned int attachment = DRI2BufferFrontLeft;
496 // Check valid pixmap
497 ecore_x_pixmap_geometry_get(pixmap, &rx, &ry, &rw, &rh);
498 if ((rw != width) || (rh != height))
501 xdpy = ecore_x_display_get();
502 DRI2CreateDrawable(xdpy, pixmap);
503 bufs = DRI2GetBuffers(xdpy, pixmap, &rw, &rh, &attachment, 1, &rcount);
504 if ((!bufs) || (width != rw) || (height != rh))
507 bo = tbm_bo_import(tbm_mgr, bufs->name);
514 DRI2DestroyDrawable(xdpy, pixmap);
519 _ecore_buffer_x11_dri2_buffer_import(Ecore_Buffer_Module_Data bmdata, Ecore_Buffer_Info *einfo, Ecore_Export_Type type, int export_id, unsigned int flags EINA_UNUSED)
521 Ecore_Buffer_Module_X11_Dri2_Data *bm = bmdata;
522 Ecore_Buffer_X11_Dri2_Data *buf;
524 tbm_surface_h surface;
525 tbm_surface_info_s tinfo;
528 if (type != EXPORT_TYPE_ID)
535 bo = _x11_dri2_bo_get_from_pixmap(bm->tbm_mgr, einfo->pixmap, einfo->width, einfo->height);
537 bo = tbm_bo_import(bm->tbm_mgr, export_id);
542 tinfo.width = einfo->width;
543 tinfo.height = einfo->height;
544 tinfo.format = einfo->format;
545 tinfo.bpp = _buf_get_bpp(einfo->format);
546 tinfo.size = einfo->height * einfo->planes[0].stride;
547 tinfo.num_planes = _buf_get_num_planes(einfo->format);
548 for (i = 0; i < tinfo.num_planes; i++)
550 tinfo.planes[i].size = einfo->height * einfo->planes[i].stride;
551 tinfo.planes[i].stride = einfo->planes[i].stride;
552 tinfo.planes[i].offset = einfo->planes[i].offset;
555 surface = tbm_surface_internal_create_with_bos(&tinfo, &bo, 1);
560 buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri2_Data));
564 buf->w = einfo->width;
565 buf->h = einfo->height;
566 buf->format = einfo->format;
567 buf->pixmap = einfo->pixmap;
568 buf->stride = einfo->planes[0].stride;
569 buf->is_imported = EINA_TRUE;
570 buf->tbm.surface = surface;
571 buf->tbm.owned = EINA_TRUE;
575 tbm_surface_internal_unref(surface);
577 if ((bo) && (einfo->pixmap))
578 DRI2DestroyDrawable(ecore_x_display_get(), einfo->pixmap);
586 _ecore_buffer_x11_dri2_pixmap_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
588 Ecore_Buffer_X11_Dri2_Data *buf = bdata;
600 _ecore_buffer_x11_dri2_tbm_bo_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
602 Ecore_Buffer_X11_Dri2_Data *buf = bdata;
607 return buf->tbm.surface;
610 static Ecore_Buffer_Backend _ecore_buffer_x11_dri2_backend = {
612 &_ecore_buffer_x11_dri2_init,
613 &_ecore_buffer_x11_dri2_shutdown,
614 &_ecore_buffer_x11_dri2_buffer_alloc,
615 &_ecore_buffer_x11_dri2_buffer_alloc_with_tbm_surface,
616 &_ecore_buffer_x11_dri2_buffer_info_get,
617 &_ecore_buffer_x11_dri2_buffer_free,
618 &_ecore_buffer_x11_dri2_buffer_export,
619 &_ecore_buffer_x11_dri2_buffer_import,
620 &_ecore_buffer_x11_dri2_pixmap_get,
621 &_ecore_buffer_x11_dri2_tbm_bo_get,
624 Eina_Bool x11_dri2_init(void)
626 return ecore_buffer_register(&_ecore_buffer_x11_dri2_backend);
629 void x11_dri2_shutdown(void)
631 ecore_buffer_unregister(&_ecore_buffer_x11_dri2_backend);
634 EINA_MODULE_INIT(x11_dri2_init);
635 EINA_MODULE_SHUTDOWN(x11_dri2_shutdown);