diff --git a/docs/meson.build b/docs/meson.build index c4b5fe48fe..a285f191e8 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -98,6 +98,7 @@ if build_gstgl join_paths('../gst-libs/gst', 'gl', 'egl', 'gstegl.[ch]'), join_paths('../gst-libs/gst', 'gl', 'egl', 'gsteglimage.[ch]'), join_paths('../gst-libs/gst', 'gl', 'egl', 'gstgldisplay_egl.[ch]'), + join_paths('../gst-libs/gst', 'gl', 'egl', 'gstgldisplay_egl_device.[ch]'), join_paths('../gst-libs/gst', 'gl', 'egl', 'gstglmemoryegl.[ch]'), join_paths('../gst-libs/gst', 'gl', 'x11', 'gstgldisplay_x11.[ch]'), join_paths('../gst-libs/gst', 'gl', 'wayland', 'gstgldisplay_wayland.[ch]'), diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index ffe70e86a8..7977748d64 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -149,7 +149,9 @@ if USE_EGL SUBDIRS += egl libgstgl_@GST_API_VERSION@_la_LIBADD += egl/libgstgl-egl.la gstgl_gir_headers += egl/gstgldisplay_egl.h +gstgl_gir_headers += egl/gstgldisplay_egl_device.h gstgl_gir_sources += egl/gstgldisplay_egl.c +gstgl_gir_sources += egl/gstgldisplay_egl_device.c endif configexecincludedir = $(libdir)/gstreamer-@GST_API_VERSION@/include/gst/gl diff --git a/gst-libs/gst/gl/egl/Makefile.am b/gst-libs/gst/gl/egl/Makefile.am index a22be8ba54..53e5b14153 100644 --- a/gst-libs/gst/gl/egl/Makefile.am +++ b/gst-libs/gst/gl/egl/Makefile.am @@ -7,7 +7,8 @@ libgstgl_egl_la_SOURCES = \ gstglcontext_egl.c \ gstglmemoryegl.c \ gsteglimage.c \ - gstegl.c + gstegl.c \ + gstgldisplay_egl_device.c noinst_HEADERS = \ gstglcontext_egl.h @@ -17,7 +18,8 @@ libgstgl_eglinclude_HEADERS = \ gstgldisplay_egl.h \ gstglmemoryegl.h \ gsteglimage.h \ - gstegl.h + gstegl.h \ + gstgldisplay_egl_device.h libgstgl_egl_la_CFLAGS = \ -I$(top_srcdir)/gst-libs \ diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index ae992c8414..49175300bf 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -409,6 +409,16 @@ gst_gl_context_egl_choose_config (GstGLContextEGL * egl, GstGLAPI gl_api, EGLint config_attrib[20]; EGLint egl_api = 0; EGLBoolean ret = EGL_FALSE; + EGLint surface_type = EGL_WINDOW_BIT; + GstGLWindow *window; + + window = gst_gl_context_get_window (GST_GL_CONTEXT (egl)); + + if (!window || !gst_gl_window_has_output_surface (window)) { + GST_INFO_OBJECT (egl, + "gl window has no output surface, use pixel buffer surfaces"); + surface_type = EGL_PBUFFER_BIT; + } create_context = gst_gl_check_extension ("EGL_KHR_create_context", egl->egl_exts); @@ -432,7 +442,7 @@ gst_gl_context_egl_choose_config (GstGLContextEGL * egl, GstGLAPI gl_api, egl_api = EGL_OPENGL_BIT; config_attrib[i++] = EGL_SURFACE_TYPE; - config_attrib[i++] = EGL_WINDOW_BIT; + config_attrib[i++] = surface_type; config_attrib[i++] = EGL_RENDERABLE_TYPE; config_attrib[i++] = egl_api; #if defined(USE_EGL_RPI) && GST_GL_HAVE_WINDOW_WAYLAND diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl.c b/gst-libs/gst/gl/egl/gstgldisplay_egl.c index 89aaca3de3..9961ca0ea6 100644 --- a/gst-libs/gst/gl/egl/gstgldisplay_egl.c +++ b/gst-libs/gst/gl/egl/gstgldisplay_egl.c @@ -56,6 +56,9 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); #ifndef EGL_PLATFORM_ANDROID #define EGL_PLATFORM_ANDROID 0x3141 #endif +#ifndef EGL_PLATFORM_DEVICE_EXT +#define EGL_PLATFORM_DEVICE_EXT 0x313F +#endif typedef EGLDisplay (*_gst_eglGetPlatformDisplay_type) (EGLenum platform, void *native_display, const EGLint * attrib_list); @@ -125,6 +128,8 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0) || (type == GST_GL_DISPLAY_TYPE_ANY && display == 0), EGL_NO_DISPLAY); + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + /* given an EGLDisplay already */ if (type == GST_GL_DISPLAY_TYPE_EGL) return (gpointer) display; @@ -175,6 +180,14 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) NULL); } #endif + if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_EGL_DEVICE) && + (gst_gl_check_extension ("EGL_EXT_device_base", egl_exts) && + gst_gl_check_extension ("EGL_EXT_platform_device", egl_exts))) { + ret = + _gst_eglGetPlatformDisplay (EGL_PLATFORM_DEVICE_EXT, (gpointer) display, + NULL); + } + /* android only has one winsys/display connection */ if (ret != EGL_NO_DISPLAY) diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl_device.c b/gst-libs/gst/gl/egl/gstgldisplay_egl_device.c new file mode 100644 index 0000000000..3db8253209 --- /dev/null +++ b/gst-libs/gst/gl/egl/gstgldisplay_egl_device.c @@ -0,0 +1,162 @@ +/* + * GStreamer + * Copyright (C) 2014 Matthew Waters + * Copyright (C) 2019 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:gstgldisplay_egl_device + * @short_description: EGL EGLDeviceEXT object + * @title: GstGLDisplayEGLDevice + * @see_also: #GstGLDisplay, #GstGLDisplayEGL + * + * #GstGLDisplayEGLDevice represents a `EGLDeviceEXT` handle created internally + * (gst_gl_display_egl_device_new()) or wrapped by the application + * (gst_gl_display_egl_device_new_with_egl_device()) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstgldisplay_egl.h" +#include "gstgldisplay_egl_device.h" + +#include + +#include "gstegl.h" +#include "gstglmemoryegl.h" + +GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); +#define GST_CAT_DEFAULT gst_gl_display_debug + +typedef EGLBoolean (*eglQueryDevicesEXT_type) (EGLint max_devices, + EGLDeviceEXT * devices, EGLint * num_devices); + +G_DEFINE_TYPE (GstGLDisplayEGLDevice, gst_gl_display_egl_device, + GST_TYPE_GL_DISPLAY); + +static guintptr gst_gl_display_egl_device_get_handle (GstGLDisplay * display); + +static void +gst_gl_display_egl_device_class_init (GstGLDisplayEGLDeviceClass * klass) +{ + GstGLDisplayClass *display_class = GST_GL_DISPLAY_CLASS (klass); + + display_class->get_handle = + GST_DEBUG_FUNCPTR (gst_gl_display_egl_device_get_handle); +} + +static void +gst_gl_display_egl_device_init (GstGLDisplayEGLDevice * self) +{ + GstGLDisplay *display = GST_GL_DISPLAY (self); + + display->type = GST_GL_DISPLAY_TYPE_EGL_DEVICE; + + gst_gl_memory_egl_init_once (); +} + +static guintptr +gst_gl_display_egl_device_get_handle (GstGLDisplay * display) +{ + GstGLDisplayEGLDevice *self = GST_GL_DISPLAY_EGL_DEVICE (display); + + return (guintptr) self->device; +} + +/** + * gst_gl_display_egl_device_new: + * @device_index: the index of device to use + * + * Create a new #GstGLDisplayEGLDevice with an EGLDevice supported device + * + * Returns: (transfer full): a new #GstGLDisplayEGLDevice or %NULL + * + * Since: 1.18 + */ +GstGLDisplayEGLDevice * +gst_gl_display_egl_device_new (guint device_index) +{ + GstGLDisplayEGLDevice *ret; + eglQueryDevicesEXT_type query_device_func; + EGLint num_devices = 0; + EGLDeviceEXT *device_list; + + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + + query_device_func = + (eglQueryDevicesEXT_type) eglGetProcAddress ("eglQueryDevicesEXT"); + + if (!query_device_func) { + GST_ERROR ("eglQueryDevicesEXT is unavailable"); + return NULL; + } + + if (query_device_func (0, NULL, &num_devices) == EGL_FALSE) { + GST_ERROR ("eglQueryDevicesEXT fail"); + return NULL; + } else if (num_devices < 1) { + GST_ERROR ("no EGLDevice supported device"); + return NULL; + } + + if (num_devices <= device_index) { + GST_ERROR ("requested index %d exceeds the number of devices %d", + device_index, num_devices); + return NULL; + } + + device_list = g_alloca (sizeof (EGLDeviceEXT) * num_devices); + query_device_func (num_devices, device_list, &num_devices); + + ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL_DEVICE, NULL); + gst_object_ref_sink (ret); + + ret->device = device_list[device_index]; + + return ret; +} + +/** + * gst_gl_display_egl_device_new_with_egl_device: + * @device: an existing EGLDeviceEXT + * + * Creates a new #GstGLDisplayEGLDevice with EGLDeviceEXT . + * The @device must be created using EGLDevice enumeration. + * + * Returns: (transfer full): a new #GstGLDisplayEGLDevice + * + * Since: 1.18 + */ +GstGLDisplayEGLDevice * +gst_gl_display_egl_device_new_with_egl_device (gpointer device) +{ + GstGLDisplayEGLDevice *ret; + + g_return_val_if_fail (device != NULL, NULL); + + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + + ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL_DEVICE, NULL); + gst_object_ref_sink (ret); + + ret->device = device; + + return ret; +} diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl_device.h b/gst-libs/gst/gl/egl/gstgldisplay_egl_device.h new file mode 100644 index 0000000000..ab1aefa1b3 --- /dev/null +++ b/gst-libs/gst/gl/egl/gstgldisplay_egl_device.h @@ -0,0 +1,82 @@ +/* + * GStreamer + * Copyright (C) 2014 Matthew Waters + * Copyright (C) 2019 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_DISPLAY_EGL_DEVICE_H__ +#define __GST_GL_DISPLAY_EGL_DEVICE_H__ + +#include + +G_BEGIN_DECLS + +GST_GL_API +GType gst_gl_display_egl_device_get_type (void); + +#define GST_TYPE_GL_DISPLAY_EGL_DEVICE (gst_gl_display_egl_device_get_type()) +#define GST_GL_DISPLAY_EGL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY_EGL_DEVICE,GstGLDisplayEGLDevice)) +#define GST_GL_DISPLAY_EGL_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GL_DISPLAY_EGL_DEVICE,GstGLDisplayEGLDeviceClass)) +#define GST_IS_GL_DISPLAY_EGL_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY_EGL_DEVICE)) +#define GST_IS_GL_DISPLAY_EGL_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GL_DISPLAY_EGL_DEVICE)) +#define GST_GL_DISPLAY_EGL_DEVICE_CAST(obj) ((GstGLDisplayEGLDevice*)(obj)) + +typedef struct _GstGLDisplayEGLDevice GstGLDisplayEGLDevice; +typedef struct _GstGLDisplayEGLDeviceClass GstGLDisplayEGLDeviceClass; + +/** + * GstGLDisplayEGLDevice: + * + * the contents of a #GstGLDisplayEGLDevice are private and should only be accessed + * through the provided API + * + * Since: 1.18 + */ +struct _GstGLDisplayEGLDevice +{ + GstGLDisplay parent; + + gpointer device; + + gpointer _padding[GST_PADDING]; +}; + +/** + * GstGLDisplayEGLDeviceClass: + * + * Opaque #GstGLDisplayEGLDeviceClass struct + * + * Since: 1.18 + */ +struct _GstGLDisplayEGLDeviceClass +{ + GstGLDisplayClass object_class; + + gpointer _padding[GST_PADDING]; +}; + +GST_GL_API +GstGLDisplayEGLDevice *gst_gl_display_egl_device_new (guint device_index); + +GST_GL_API +GstGLDisplayEGLDevice *gst_gl_display_egl_device_new_with_egl_device (gpointer device); + + +G_END_DECLS + +#endif /* __GST_GL_DISPLAY_EGL_DEVICE_H__ */ diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 6256ec6d14..ba11328de3 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -67,6 +67,7 @@ #endif #if GST_GL_HAVE_PLATFORM_EGL #include +#include #include #include #endif @@ -321,9 +322,14 @@ gst_gl_display_new (void) } #endif #if GST_GL_HAVE_PLATFORM_EGL + if (!display && (user_choice && g_strstr_len (user_choice, 10, "egl-device"))) { + display = GST_GL_DISPLAY (gst_gl_display_egl_device_new (0)); + } + if (!display && (!platform_choice - || g_strstr_len (platform_choice, 3, "egl"))) + || g_strstr_len (platform_choice, 3, "egl"))) { display = GST_GL_DISPLAY (gst_gl_display_egl_new ()); + } #endif if (!display) { GST_INFO ("Could not create platform/winsys display. user specified %s " diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index fec528b05e..c9c5d7dd4d 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -50,6 +50,7 @@ GType gst_gl_display_get_type (void); * @GST_GL_DISPLAY_TYPE_EGL: EGL display * @GST_GL_DISPLAY_TYPE_VIV_FB: Vivante Framebuffer display * @GST_GL_DISPLAY_TYPE_GBM: Mesa3D GBM display + * @GST_GL_DISPLAY_TYPE_EGL_DEVICE: EGLDevice display (Since: 1.18) * @GST_GL_DISPLAY_TYPE_ANY: any display type */ typedef enum @@ -63,6 +64,7 @@ typedef enum GST_GL_DISPLAY_TYPE_EGL = (1 << 5), GST_GL_DISPLAY_TYPE_VIV_FB = (1 << 6), GST_GL_DISPLAY_TYPE_GBM = (1 << 7), + GST_GL_DISPLAY_TYPE_EGL_DEVICE = (1 << 8), GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32 } GstGLDisplayType; diff --git a/gst-libs/gst/gl/meson.build b/gst-libs/gst/gl/meson.build index 4aeb55938b..a5034940f3 100644 --- a/gst-libs/gst/gl/meson.build +++ b/gst-libs/gst/gl/meson.build @@ -488,12 +488,14 @@ if need_platform_egl != 'no' 'egl/gstglcontext_egl.c', 'egl/gstgldisplay_egl.c', 'egl/gstglmemoryegl.c', + 'egl/gstgldisplay_egl_device.c', ] gl_egl_headers += [ 'egl/gstegl.h', 'egl/gsteglimage.h', 'egl/gstgldisplay_egl.h', 'egl/gstglmemoryegl.h', + 'egl/gstgldisplay_egl_device.h', ] gl_platform_deps += egl_dep glconf.set10('GST_GL_HAVE_PLATFORM_EGL', 1)