3 * Copyright (C) 2012 Collabora Ltd.
4 * @author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
5 * Copyright (C) 2014 Julien Isorce <julien.isorce@gmail.com>
6 * Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 * @short_description: EGLImage abstraction
28 * @see_also: #GstGLMemoryEGL, #GstGLContext
30 * #GstEGLImage represents and holds an #EGLImage handle.
32 * A #GstEGLImage can be created from a dmabuf with gst_egl_image_from_dmabuf(),
33 * or gst_egl_image_from_dmabuf_direct(), or #GstGLMemoryEGL provides a
34 * #GstAllocator to allocate #EGLImage's bound to and OpenGL texture.
41 #include "gsteglimage.h"
45 #include <gst/gl/gstglfeature.h>
46 #include <gst/gl/gstglmemory.h>
48 #include "gst/gl/egl/gstegl.h"
49 #include "gst/gl/egl/gstglcontext_egl.h"
50 #include "gst/gl/egl/gstgldisplay_egl.h"
52 #if GST_GL_HAVE_DMABUF
53 #include <gst/allocators/gstdmabuf.h>
54 #include <libdrm/drm_fourcc.h>
57 #define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ')
60 #ifndef DRM_FORMAT_RG88
61 #define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8')
64 #ifndef DRM_FORMAT_GR88
65 #define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8')
69 #ifndef EGL_LINUX_DMA_BUF_EXT
70 #define EGL_LINUX_DMA_BUF_EXT 0x3270
73 #ifndef EGL_LINUX_DRM_FOURCC_EXT
74 #define EGL_LINUX_DRM_FOURCC_EXT 0x3271
77 #ifndef EGL_DMA_BUF_PLANE0_FD_EXT
78 #define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
81 #ifndef EGL_DMA_BUF_PLANE0_OFFSET_EXT
82 #define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
85 #ifndef EGL_DMA_BUF_PLANE0_PITCH_EXT
86 #define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
89 #if !GST_GL_HAVE_EGLUINT64KHR
90 typedef khronos_uint64_t EGLuint64KHR;
93 GST_DEFINE_MINI_OBJECT_TYPE (GstEGLImage, gst_egl_image);
95 #ifndef GST_DISABLE_GST_DEBUG
96 #define GST_CAT_DEFAULT gst_egl_image_ensure_debug_category()
98 static GstDebugCategory *
99 gst_egl_image_ensure_debug_category (void)
101 static gsize cat_gonce = 0;
103 if (g_once_init_enter (&cat_gonce)) {
104 GstDebugCategory *cat = NULL;
106 GST_DEBUG_CATEGORY_INIT (cat, "gleglimage", 0, "EGLImage wrapper");
108 g_once_init_leave (&cat_gonce, (gsize) cat);
111 return (GstDebugCategory *) cat_gonce;
113 #endif /* GST_DISABLE_GST_DEBUG */
116 * gst_egl_image_get_image:
117 * @image: a #GstEGLImage
119 * Returns: the #EGLImageKHR of @image
122 gst_egl_image_get_image (GstEGLImage * image)
124 g_return_val_if_fail (GST_IS_EGL_IMAGE (image), EGL_NO_IMAGE_KHR);
130 _gst_egl_image_free_thread (GstGLContext * context, GstEGLImage * image)
132 if (image->destroy_notify)
133 image->destroy_notify (image, image->destroy_data);
137 _gst_egl_image_free (GstMiniObject * object)
139 GstEGLImage *image = GST_EGL_IMAGE (object);
141 if (image->context) {
142 gst_gl_context_thread_add (GST_GL_CONTEXT (image->context),
143 (GstGLContextThreadFunc) _gst_egl_image_free_thread, image);
144 gst_object_unref (image->context);
148 static GstMiniObject *
149 _gst_egl_image_copy (GstMiniObject * obj)
151 return gst_mini_object_ref (obj);
155 * gst_egl_image_new_wrapped:
156 * @context: a #GstGLContext (must be an EGL context)
157 * @image: the image to wrap
158 * @format: the #GstGLFormat
159 * @user_data: user data
160 * @user_data_destroy: (destroy user_data): called when @user_data is no longer needed
162 * Returns: a new #GstEGLImage wrapping @image
165 gst_egl_image_new_wrapped (GstGLContext * context, gpointer image,
166 GstGLFormat format, gpointer user_data,
167 GstEGLImageDestroyNotify user_data_destroy)
169 GstEGLImage *img = NULL;
171 g_return_val_if_fail (context != NULL, NULL);
172 g_return_val_if_fail ((gst_gl_context_get_gl_platform (context) &
173 GST_GL_PLATFORM_EGL) != 0, NULL);
174 g_return_val_if_fail (image != EGL_NO_IMAGE_KHR, NULL);
176 img = g_new0 (GstEGLImage, 1);
177 gst_mini_object_init (GST_MINI_OBJECT_CAST (img), 0, GST_TYPE_EGL_IMAGE,
178 (GstMiniObjectCopyFunction) _gst_egl_image_copy, NULL,
179 (GstMiniObjectFreeFunction) _gst_egl_image_free);
181 img->context = gst_object_ref (context);
183 img->format = format;
185 img->destroy_data = user_data;
186 img->destroy_notify = user_data_destroy;
192 _gst_egl_image_create (GstGLContext * context, guint target,
193 EGLClientBuffer buffer, guintptr * attribs)
195 EGLDisplay egl_display = EGL_DEFAULT_DISPLAY;
196 EGLContext egl_context = EGL_NO_CONTEXT;
197 EGLImageKHR img = EGL_NO_IMAGE_KHR;
198 GstGLDisplayEGL *display_egl;
199 gint plat_major, plat_minor;
200 guint attrib_len = 0;
202 gst_gl_context_get_gl_platform_version (context, &plat_major, &plat_minor);
204 display_egl = gst_gl_display_egl_from_gl_display (context->display);
206 GST_WARNING_OBJECT (context, "Failed to retrieve GstGLDisplayEGL from %"
207 GST_PTR_FORMAT, context->display);
208 return EGL_NO_IMAGE_KHR;
211 (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl));
212 gst_object_unref (display_egl);
214 if (target != EGL_LINUX_DMA_BUF_EXT)
215 egl_context = (EGLContext) gst_gl_context_get_gl_context (context);
218 while (attribs[attrib_len++] != EGL_NONE) {
220 #ifdef EGL_VERSION_1_5
221 if (GST_GL_CHECK_GL_VERSION (plat_major, plat_minor, 1, 5)) {
222 EGLImageKHR (*gst_eglCreateImage) (EGLDisplay dpy, EGLContext ctx,
223 EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list);
224 EGLAttrib *egl_attribs = NULL;
227 gst_eglCreateImage = gst_gl_context_get_proc_address (context,
229 if (!gst_eglCreateImage) {
230 GST_ERROR_OBJECT (context, "\"eglCreateImage\" not exposed by the "
231 "implementation as required by EGL >= 1.5");
232 return EGL_NO_IMAGE_KHR;
236 egl_attribs = g_new0 (EGLAttrib, attrib_len);
237 for (i = 0; i < attrib_len; i++)
238 egl_attribs[i] = (EGLAttrib) attribs[i];
241 img = gst_eglCreateImage (egl_display, egl_context, target, buffer,
244 g_free (egl_attribs);
248 EGLImageKHR (*gst_eglCreateImageKHR) (EGLDisplay dpy, EGLContext ctx,
249 EGLenum target, EGLClientBuffer buffer, const EGLint * attrib_list);
250 EGLint *egl_attribs = NULL;
253 gst_eglCreateImageKHR = gst_gl_context_get_proc_address (context,
254 "eglCreateImageKHR");
255 if (!gst_eglCreateImageKHR) {
256 GST_WARNING_OBJECT (context, "\"eglCreateImageKHR\" not exposed by the "
258 return EGL_NO_IMAGE_KHR;
262 egl_attribs = g_new0 (EGLint, attrib_len);
263 for (i = 0; i < attrib_len; i++)
264 egl_attribs[i] = (EGLint) attribs[i];
267 img = gst_eglCreateImageKHR (egl_display, egl_context, target, buffer,
270 g_free (egl_attribs);
277 _gst_egl_image_destroy (GstGLContext * context, EGLImageKHR image)
279 EGLBoolean (*gst_eglDestroyImage) (EGLDisplay dpy, EGLImageKHR image);
280 EGLDisplay egl_display = EGL_DEFAULT_DISPLAY;
281 GstGLDisplayEGL *display_egl;
283 gst_eglDestroyImage = gst_gl_context_get_proc_address (context,
285 if (!gst_eglDestroyImage) {
286 gst_eglDestroyImage = gst_gl_context_get_proc_address (context,
287 "eglDestroyImageKHR");
288 if (!gst_eglDestroyImage) {
289 GST_ERROR_OBJECT (context, "\"eglDestroyImage\" not exposed by the "
295 display_egl = gst_gl_display_egl_from_gl_display (context->display);
297 GST_WARNING_OBJECT (context, "Failed to retrieve GstGLDisplayEGL from %"
298 GST_PTR_FORMAT, context->display);
302 (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl));
303 gst_object_unref (display_egl);
305 if (!gst_eglDestroyImage (egl_display, image))
306 GST_WARNING_OBJECT (context, "eglDestroyImage failed");
310 _destroy_egl_image (GstEGLImage * image, gpointer user_data)
312 _gst_egl_image_destroy (image->context, image->image);
316 * gst_egl_image_from_texture:
317 * @context: a #GstGLContext (must be an EGL context)
318 * @gl_mem: a #GstGLMemory
319 * @attribs: additional attributes to add to the eglCreateImage() call.
321 * Returns: (transfer full): a #GstEGLImage wrapping @gl_mem or %NULL on failure
324 gst_egl_image_from_texture (GstGLContext * context, GstGLMemory * gl_mem,
330 if (gl_mem->tex_target != GST_GL_TEXTURE_TARGET_2D) {
331 GST_FIXME_OBJECT (context, "Only know how to create EGLImage's from 2D "
336 egl_target = EGL_GL_TEXTURE_2D_KHR;
338 img = _gst_egl_image_create (context, egl_target,
339 (EGLClientBuffer) (guintptr) gl_mem->tex_id, attribs);
343 return gst_egl_image_new_wrapped (context, img, gl_mem->tex_format, NULL,
344 (GstEGLImageDestroyNotify) _destroy_egl_image);
347 #if GST_GL_HAVE_DMABUF
349 * GStreamer format descriptions differ from DRM formats as the representation
350 * is relative to a register, hence in native endianness. To reduce the driver
351 * requirement, we only import with a subset of texture formats and use
352 * shaders to convert. This way we avoid having to use external texture
356 _drm_rgba_fourcc_from_info (GstVideoInfo * info, int plane)
358 GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
359 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
360 const gint rgba_fourcc = DRM_FORMAT_ABGR8888;
361 const gint rgb_fourcc = DRM_FORMAT_BGR888;
362 const gint rg_fourcc = DRM_FORMAT_GR88;
364 const gint rgba_fourcc = DRM_FORMAT_RGBA8888;
365 const gint rgb_fourcc = DRM_FORMAT_RGB888;
366 const gint rg_fourcc = DRM_FORMAT_RG88;
369 GST_DEBUG ("Getting DRM fourcc for %s plane %i",
370 gst_video_format_to_string (format), plane);
373 case GST_VIDEO_FORMAT_RGB16:
374 case GST_VIDEO_FORMAT_BGR16:
375 return DRM_FORMAT_RGB565;
377 case GST_VIDEO_FORMAT_RGB:
378 case GST_VIDEO_FORMAT_BGR:
381 case GST_VIDEO_FORMAT_RGBA:
382 case GST_VIDEO_FORMAT_RGBx:
383 case GST_VIDEO_FORMAT_BGRA:
384 case GST_VIDEO_FORMAT_BGRx:
385 case GST_VIDEO_FORMAT_ARGB:
386 case GST_VIDEO_FORMAT_xRGB:
387 case GST_VIDEO_FORMAT_ABGR:
388 case GST_VIDEO_FORMAT_xBGR:
389 case GST_VIDEO_FORMAT_AYUV:
392 case GST_VIDEO_FORMAT_GRAY8:
393 return DRM_FORMAT_R8;
395 case GST_VIDEO_FORMAT_YUY2:
396 case GST_VIDEO_FORMAT_UYVY:
397 case GST_VIDEO_FORMAT_GRAY16_LE:
398 case GST_VIDEO_FORMAT_GRAY16_BE:
401 case GST_VIDEO_FORMAT_NV12:
402 case GST_VIDEO_FORMAT_NV21:
403 return plane == 0 ? DRM_FORMAT_R8 : rg_fourcc;
405 case GST_VIDEO_FORMAT_I420:
406 case GST_VIDEO_FORMAT_YV12:
407 case GST_VIDEO_FORMAT_Y41B:
408 case GST_VIDEO_FORMAT_Y42B:
409 case GST_VIDEO_FORMAT_Y444:
410 return DRM_FORMAT_R8;
413 GST_ERROR ("Unsupported format for DMABuf.");
419 * gst_egl_image_from_dmabuf:
420 * @context: a #GstGLContext (must be an EGL context)
421 * @dmabuf: the DMA-Buf file descriptor
422 * @in_info: the #GstVideoInfo in @dmabuf
423 * @plane: the plane in @in_info to create and #GstEGLImage for
424 * @offset: the byte-offset in the data
426 * Creates an EGL image that imports the dmabuf FD. The dmabuf data
427 * is passed as RGBA data. Shaders later take this "RGBA" data and
428 * convert it from its true format (described by in_info) to actual
429 * RGBA output. For example, with I420, three EGL images are created,
430 * one for each plane, each EGL image with a single-channel R format.
431 * With NV12, two EGL images are created, one with R format, one
432 * with RG format etc.
434 * Returns: a #GstEGLImage wrapping @dmabuf or %NULL on failure
437 gst_egl_image_from_dmabuf (GstGLContext * context,
438 gint dmabuf, GstVideoInfo * in_info, gint plane, gsize offset)
441 guintptr attribs[13];
447 fourcc = _drm_rgba_fourcc_from_info (in_info, plane);
448 format = gst_gl_format_from_video_info (context, in_info, plane);
450 GST_DEBUG ("fourcc %.4s (%d) plane %d (%dx%d)",
451 (char *) &fourcc, fourcc, plane,
452 GST_VIDEO_INFO_COMP_WIDTH (in_info, plane),
453 GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane));
455 attribs[atti++] = EGL_WIDTH;
456 attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, plane);
457 attribs[atti++] = EGL_HEIGHT;
458 attribs[atti++] = GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane);
459 attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
460 attribs[atti++] = fourcc;
461 attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
462 attribs[atti++] = dmabuf;
463 attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
464 attribs[atti++] = offset;
465 attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
466 attribs[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, plane);
467 attribs[atti] = EGL_NONE;
468 g_assert (atti == G_N_ELEMENTS (attribs) - 1);
470 for (i = 0; i < atti; i++)
471 GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs[i]);
473 img = _gst_egl_image_create (context, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
475 GST_WARNING ("eglCreateImage failed: %s",
476 gst_egl_get_error_string (eglGetError ()));
480 return gst_egl_image_new_wrapped (context, img, format, NULL,
481 (GstEGLImageDestroyNotify) _destroy_egl_image);
485 * Variant of _drm_rgba_fourcc_from_info() that is used in case the GPU can
486 * handle YUV formats directly (by using internal shaders, or hardwired
487 * YUV->RGB conversion matrices etc.)
490 _drm_direct_fourcc_from_info (GstVideoInfo * info)
492 GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
494 GST_DEBUG ("Getting DRM fourcc for %s", gst_video_format_to_string (format));
497 case GST_VIDEO_FORMAT_YUY2:
498 return DRM_FORMAT_YUYV;
500 case GST_VIDEO_FORMAT_YVYU:
501 return DRM_FORMAT_YVYU;
503 case GST_VIDEO_FORMAT_UYVY:
504 return DRM_FORMAT_UYVY;
506 case GST_VIDEO_FORMAT_VYUY:
507 return DRM_FORMAT_VYUY;
509 case GST_VIDEO_FORMAT_AYUV:
510 return DRM_FORMAT_AYUV;
512 case GST_VIDEO_FORMAT_NV12:
513 return DRM_FORMAT_NV12;
515 case GST_VIDEO_FORMAT_NV21:
516 return DRM_FORMAT_NV21;
518 case GST_VIDEO_FORMAT_NV16:
519 return DRM_FORMAT_NV16;
521 case GST_VIDEO_FORMAT_NV61:
522 return DRM_FORMAT_NV61;
524 case GST_VIDEO_FORMAT_NV24:
525 return DRM_FORMAT_NV24;
527 case GST_VIDEO_FORMAT_YUV9:
528 return DRM_FORMAT_YUV410;
530 case GST_VIDEO_FORMAT_YVU9:
531 return DRM_FORMAT_YVU410;
533 case GST_VIDEO_FORMAT_Y41B:
534 return DRM_FORMAT_YUV411;
536 case GST_VIDEO_FORMAT_I420:
537 return DRM_FORMAT_YUV420;
539 case GST_VIDEO_FORMAT_YV12:
540 return DRM_FORMAT_YVU420;
542 case GST_VIDEO_FORMAT_Y42B:
543 return DRM_FORMAT_YUV422;
545 case GST_VIDEO_FORMAT_Y444:
546 return DRM_FORMAT_YUV444;
548 case GST_VIDEO_FORMAT_RGB16:
549 return DRM_FORMAT_RGB565;
551 case GST_VIDEO_FORMAT_BGR16:
552 return DRM_FORMAT_BGR565;
554 case GST_VIDEO_FORMAT_RGBA:
555 return DRM_FORMAT_ABGR8888;
557 case GST_VIDEO_FORMAT_RGBx:
558 return DRM_FORMAT_XBGR8888;
560 case GST_VIDEO_FORMAT_BGRA:
561 return DRM_FORMAT_ARGB8888;
563 case GST_VIDEO_FORMAT_BGRx:
564 return DRM_FORMAT_XRGB8888;
566 case GST_VIDEO_FORMAT_ARGB:
567 return DRM_FORMAT_BGRA8888;
569 case GST_VIDEO_FORMAT_xRGB:
570 return DRM_FORMAT_BGRX8888;
572 case GST_VIDEO_FORMAT_ABGR:
573 return DRM_FORMAT_RGBA8888;
575 case GST_VIDEO_FORMAT_xBGR:
576 return DRM_FORMAT_RGBX8888;
579 GST_INFO ("Unsupported format for direct DMABuf.");
585 _gst_egl_image_check_dmabuf_direct (GstGLContext * context,
586 GstVideoInfo * in_info)
588 EGLDisplay egl_display = EGL_DEFAULT_DISPLAY;
589 GstGLDisplayEGL *display_egl;
590 EGLuint64KHR *modifiers;
591 EGLBoolean *external_only;
596 EGLBoolean (*gst_eglQueryDmaBufModifiersEXT) (EGLDisplay dpy,
597 int format, int max_modifiers, EGLuint64KHR * modifiers,
598 EGLBoolean * external_only, int *num_modifiers);
600 gst_eglQueryDmaBufModifiersEXT =
601 gst_gl_context_get_proc_address (context, "eglQueryDmaBufModifiersEXT");
603 if (!gst_eglQueryDmaBufModifiersEXT)
606 display_egl = gst_gl_display_egl_from_gl_display (context->display);
608 GST_WARNING_OBJECT (context,
609 "Failed to retrieve GstGLDisplayEGL from %" GST_PTR_FORMAT,
614 (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl));
615 gst_object_unref (display_egl);
617 ret = gst_eglQueryDmaBufModifiersEXT (egl_display,
618 _drm_direct_fourcc_from_info (in_info), 0, NULL, NULL, &num_modifiers);
619 if (!ret || num_modifiers == 0)
622 modifiers = g_new (EGLuint64KHR, num_modifiers);
623 external_only = g_new (EGLBoolean, num_modifiers);
625 ret = gst_eglQueryDmaBufModifiersEXT (egl_display,
626 _drm_direct_fourcc_from_info (in_info), num_modifiers, modifiers,
627 external_only, &num_modifiers);
628 if (!ret || num_modifiers == 0) {
630 g_free (external_only);
634 for (i = 0; i < num_modifiers; ++i) {
635 if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) {
636 ret = !external_only[i];
638 g_free (external_only);
643 g_free (external_only);
648 * gst_egl_image_from_dmabuf_direct:
649 * @context: a #GstGLContext (must be an EGL context)
650 * @fd: Array of DMABuf file descriptors
651 * @offset: Array of offsets, relative to the DMABuf
652 * @in_info: the #GstVideoInfo
654 * Creates an EGL image that imports the dmabuf FD. The dmabuf data
655 * is passed directly as the format described in in_info. This is
656 * useful if the hardware is capable of performing color space conversions
657 * internally. The appropriate DRM format is picked, and the EGL image
658 * is created with this DRM format.
660 * Another notable difference to gst_egl_image_from_dmabuf()
661 * is that this function creates one EGL image for all planes, not one for
664 * Returns: a #GstEGLImage wrapping @dmabuf or %NULL on failure
667 gst_egl_image_from_dmabuf_direct (GstGLContext * context,
668 gint * fd, gsize * offset, GstVideoInfo * in_info)
672 guint n_planes = GST_VIDEO_INFO_N_PLANES (in_info);
674 gboolean with_modifiers;
676 /* Explanation of array length:
677 * - 6 plane independent values are at the start (width, height, format FourCC)
678 * - 10 values per plane, and there are up to MAX_NUM_DMA_BUF_PLANES planes
679 * - 4 values for color space and range
680 * - 1 extra value for the EGL_NONE sentinel
682 guintptr attribs[41]; /* 6 + 10 * 3 + 4 + 1 */
685 if (!_gst_egl_image_check_dmabuf_direct (context, in_info))
688 with_modifiers = gst_gl_context_check_feature (context,
689 "EGL_EXT_image_dma_buf_import_with_modifiers");
691 /* EGL DMABuf importation supports a maximum of 3 planes */
692 if (G_UNLIKELY (n_planes > 3))
695 attribs[atti++] = EGL_WIDTH;
696 attribs[atti++] = GST_VIDEO_INFO_WIDTH (in_info);
697 attribs[atti++] = EGL_HEIGHT;
698 attribs[atti++] = GST_VIDEO_INFO_HEIGHT (in_info);
699 attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
700 attribs[atti++] = _drm_direct_fourcc_from_info (in_info);
704 attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
705 attribs[atti++] = fd[0];
706 attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
707 attribs[atti++] = offset[0];
708 attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
709 attribs[atti++] = in_info->stride[0];
710 if (with_modifiers) {
711 attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
712 attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff;
713 attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
714 attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff;
720 attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
721 attribs[atti++] = fd[1];
722 attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
723 attribs[atti++] = offset[1];
724 attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
725 attribs[atti++] = in_info->stride[1];
726 if (with_modifiers) {
727 attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
728 attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff;
729 attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
730 attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff;
736 attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
737 attribs[atti++] = fd[2];
738 attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
739 attribs[atti++] = offset[2];
740 attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
741 attribs[atti++] = in_info->stride[2];
742 if (with_modifiers) {
743 attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
744 attribs[atti++] = DRM_FORMAT_MOD_LINEAR & 0xffffffff;
745 attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
746 attribs[atti++] = (DRM_FORMAT_MOD_LINEAR >> 32) & 0xffffffff;
751 uint32_t color_space;
752 switch (in_info->colorimetry.matrix) {
753 case GST_VIDEO_COLOR_MATRIX_BT601:
754 color_space = EGL_ITU_REC601_EXT;
756 case GST_VIDEO_COLOR_MATRIX_BT709:
757 color_space = EGL_ITU_REC709_EXT;
759 case GST_VIDEO_COLOR_MATRIX_BT2020:
760 color_space = EGL_ITU_REC2020_EXT;
766 if (color_space != 0) {
767 attribs[atti++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
768 attribs[atti++] = color_space;
774 switch (in_info->colorimetry.range) {
775 case GST_VIDEO_COLOR_RANGE_0_255:
776 range = EGL_YUV_FULL_RANGE_EXT;
778 case GST_VIDEO_COLOR_RANGE_16_235:
779 range = EGL_YUV_NARROW_RANGE_EXT;
786 attribs[atti++] = EGL_SAMPLE_RANGE_HINT_EXT;
787 attribs[atti++] = range;
791 /* Add the EGL_NONE sentinel */
792 attribs[atti] = EGL_NONE;
793 g_assert (atti <= G_N_ELEMENTS (attribs) - 1);
795 for (i = 0; i < atti; i++)
796 GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs[i]);
798 img = _gst_egl_image_create (context, EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
800 GST_WARNING ("eglCreateImage failed: %s",
801 gst_egl_get_error_string (eglGetError ()));
805 return gst_egl_image_new_wrapped (context, img, GST_GL_RGBA, NULL,
806 (GstEGLImageDestroyNotify) _destroy_egl_image);
810 gst_egl_image_export_dmabuf (GstEGLImage * image, int *fd, gint * stride,
813 EGLBoolean (*gst_eglExportDMABUFImageQueryMESA) (EGLDisplay dpy,
814 EGLImageKHR image, int *fourcc, int *num_planes,
815 EGLuint64KHR * modifiers);
816 EGLBoolean (*gst_eglExportDMABUFImageMESA) (EGLDisplay dpy, EGLImageKHR image,
817 int *fds, EGLint * strides, EGLint * offsets);
818 GstGLDisplayEGL *display_egl;
819 EGLDisplay egl_display = EGL_DEFAULT_DISPLAY;
822 EGLint egl_stride = 0;
823 EGLint egl_offset = 0;
825 gst_eglExportDMABUFImageQueryMESA =
826 gst_gl_context_get_proc_address (image->context,
827 "eglExportDMABUFImageQueryMESA");
828 gst_eglExportDMABUFImageMESA =
829 gst_gl_context_get_proc_address (image->context,
830 "eglExportDMABUFImageMESA");
832 if (!gst_eglExportDMABUFImageQueryMESA || !gst_eglExportDMABUFImageMESA)
836 (GstGLDisplayEGL *) gst_gl_display_egl_from_gl_display (image->
839 GST_WARNING_OBJECT (image->context,
840 "Failed to retrieve GstGLDisplayEGL from %" GST_PTR_FORMAT,
841 image->context->display);
845 (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl));
846 gst_object_unref (display_egl);
848 if (!gst_eglExportDMABUFImageQueryMESA (egl_display, image->image,
849 NULL, &num_planes, NULL))
852 /* Don't allow multi-plane dmabufs */
856 if (!gst_eglExportDMABUFImageMESA (egl_display, image->image, &egl_fd,
857 &egl_stride, &egl_offset))
861 *stride = egl_stride;
862 *offset = egl_offset;
867 #endif /* GST_GL_HAVE_DMABUF */