From e1ca5754089df4673703be346d741c05018d2c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Le=20Page?= Date: Thu, 19 Oct 2023 14:10:16 +0200 Subject: [PATCH] gl: add support for surfaceless display in GstGL Use of the EGL_MESA_platform_surfaceless EGL extension to create an EGL display that is not depending on any kind of windowing system. Part-of: --- girs/GstGL-1.0.gir | 4 +- .../gst-libs/gst/gl/egl/gstgldisplay_egl.c | 54 ++++++++++++++++--- .../gst-libs/gst/gl/egl/gstgldisplay_egl.h | 3 ++ .../gst-libs/gst/gl/gstgldisplay.c | 9 +++- .../gst-libs/gst/gl/gstgldisplay.h | 9 ++++ .../gst-libs/gst/gl/gstglwindow.c | 3 ++ .../gst-libs/gst/gl/meson.build | 33 ++++++++++-- .../gst-plugins-base/meson_options.txt | 2 +- subprojects/gstreamer/docs/gst/running.md | 2 +- subprojects/gstreamer/docs/index.md | 2 +- 10 files changed, 107 insertions(+), 14 deletions(-) diff --git a/girs/GstGL-1.0.gir b/girs/GstGL-1.0.gir index 2626db4479..87d7645c00 100644 --- a/girs/GstGL-1.0.gir +++ b/girs/GstGL-1.0.gir @@ -3016,7 +3016,7 @@ a #GstGLDisplay. There are a number of environment variables that influence the choice of platform and window system specific functionality. - GST_GL_WINDOW influences the window system to use. Common values are - 'x11', 'wayland', 'win32' or 'cocoa'. + 'x11', 'wayland', 'surfaceless', 'win32' or 'cocoa'. - GST_GL_PLATFORM influences the OpenGL platform to use. Common values are 'egl', 'glx', 'wgl' or 'cgl'. - GST_GL_API influences the OpenGL API requested by the OpenGL platform. @@ -3453,6 +3453,8 @@ display's object lock held. + + any display type diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.c index e617b8adb8..902416c19f 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.c @@ -25,8 +25,8 @@ * @see_also: #GstGLDisplay * * #GstGLDisplayEGL represents a connection to an EGL `EGLDisplay` handle created - * internally (gst_gl_display_egl_new()) or wrapped by the application - * (gst_gl_display_egl_new_with_egl_display()) + * internally (gst_gl_display_egl_new() or gst_gl_display_egl_new_surfaceless()) + * or wrapped by the application (gst_gl_display_egl_new_with_egl_display()) */ #ifdef HAVE_CONFIG_H @@ -122,8 +122,8 @@ gst_gl_display_egl_finalize (GObject * object) * @display: pointer to a display (or 0) * * Attempts to create a new `EGLDisplay` from @display. If @type is - * %GST_GL_DISPLAY_TYPE_ANY, then @display must be 0. @type must not be - * %GST_GL_DISPLAY_TYPE_NONE. + * %GST_GL_DISPLAY_TYPE_ANY or %GST_GL_DISPLAY_TYPE_EGL_SURFACELESS, then + * @display must be 0. @type must not be %GST_GL_DISPLAY_TYPE_NONE. * * Returns: (nullable): A `EGLDisplay` or `EGL_NO_DISPLAY` * @@ -137,8 +137,11 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) _gst_eglGetPlatformDisplay_type _gst_eglGetPlatformDisplay = NULL; g_return_val_if_fail (type != GST_GL_DISPLAY_TYPE_NONE, EGL_NO_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); + g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && + type != GST_GL_DISPLAY_TYPE_EGL_SURFACELESS && display != 0) + || ((type == GST_GL_DISPLAY_TYPE_ANY || + type == GST_GL_DISPLAY_TYPE_EGL_SURFACELESS) && display == 0), + EGL_NO_DISPLAY); init_debug (); @@ -233,6 +236,11 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display) NULL); } /* android only has one winsys/display connection */ + if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_EGL_SURFACELESS) && + gst_gl_check_extension ("EGL_MESA_platform_surfaceless", egl_exts)) { + ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_SURFACELESS_MESA, + (gpointer) display, NULL); + } if (ret != EGL_NO_DISPLAY) return ret; @@ -272,6 +280,40 @@ gst_gl_display_egl_new (void) return ret; } +/** + * gst_gl_display_egl_new_surfaceless: + * + * Create a new surfaceless #GstGLDisplayEGL using the Mesa3D + * EGL_PLATFORM_SURFACELESS_MESA extension. + * + * Returns: (transfer full) (nullable): a new #GstGLDisplayEGL or %NULL + * + * Since: 1.24 + */ +GstGLDisplayEGL * +gst_gl_display_egl_new_surfaceless (void) +{ + GstGLDisplayEGL *ret; + gpointer display; + + init_debug (); + + display = + gst_gl_display_egl_get_from_native (GST_GL_DISPLAY_TYPE_EGL_SURFACELESS, + 0); + + if (!display) { + GST_INFO ("Failed to create a surfaceless EGL display"); + return NULL; + } + + ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL); + gst_object_ref_sink (ret); + ret->display = display; + + return ret; +} + /** * gst_gl_display_egl_new_with_display: * @display: an existing and connected EGLDisplay diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.h b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.h index 23dc01a9dd..f7e27de5f9 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.h +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/egl/gstgldisplay_egl.h @@ -66,6 +66,9 @@ struct _GstGLDisplayEGLClass GST_GL_API GstGLDisplayEGL *gst_gl_display_egl_new (void); +GST_GL_API +GstGLDisplayEGL *gst_gl_display_egl_new_surfaceless (void); + GST_GL_API GstGLDisplayEGL *gst_gl_display_egl_new_with_egl_display (gpointer display); diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.c index 304c0e09a0..d51863c4be 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.c @@ -34,7 +34,7 @@ * There are a number of environment variables that influence the choice of * platform and window system specific functionality. * - GST_GL_WINDOW influences the window system to use. Common values are - * 'x11', 'wayland', 'win32' or 'cocoa'. + * 'x11', 'wayland', 'surfaceless', 'win32' or 'cocoa'. * - GST_GL_PLATFORM influences the OpenGL platform to use. Common values are * 'egl', 'glx', 'wgl' or 'cgl'. * - GST_GL_API influences the OpenGL API requested by the OpenGL platform. @@ -310,6 +310,8 @@ gst_gl_display_type_from_environment (void) return GST_GL_DISPLAY_TYPE_EGL; } else if (g_strstr_len (env, 5, "winrt")) { return GST_GL_DISPLAY_TYPE_EGL; + } else if (g_strstr_len (env, 11, "surfaceless")) { + return GST_GL_DISPLAY_TYPE_EGL_SURFACELESS; } else { return GST_GL_DISPLAY_TYPE_NONE; } @@ -393,9 +395,14 @@ gst_gl_display_new_with_type (GstGLDisplayType type) if (!display && (type & GST_GL_DISPLAY_TYPE_EGL)) { display = GST_GL_DISPLAY (gst_gl_display_egl_new ()); } + + if (!display && (type & GST_GL_DISPLAY_TYPE_EGL_SURFACELESS)) { + display = GST_GL_DISPLAY (gst_gl_display_egl_new_surfaceless ()); + } #endif custom_new_types |= GST_GL_DISPLAY_TYPE_EGL_DEVICE; custom_new_types |= GST_GL_DISPLAY_TYPE_EGL; + custom_new_types |= GST_GL_DISPLAY_TYPE_EGL_SURFACELESS; custom_new_types |= GST_GL_DISPLAY_TYPE_DISPMANX; custom_new_types |= GST_GL_DISPLAY_TYPE_WINRT; custom_new_types |= GST_GL_DISPLAY_TYPE_ANDROID; diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h index 0fbefde07f..2448218d63 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h @@ -80,6 +80,14 @@ GType gst_gl_display_get_type (void); * * Since: 1.20 */ +/** + * GST_GL_DISPLAY_TYPE_EGL_SURFACELESS: + * + * Mesa3D surfaceless display using the EGL_PLATFORM_SURFACELESS_MESA + * extension. + * + * Since: 1.24 + */ typedef enum { GST_GL_DISPLAY_TYPE_NONE = 0, @@ -95,6 +103,7 @@ typedef enum GST_GL_DISPLAY_TYPE_EAGL = (1 << 9), GST_GL_DISPLAY_TYPE_WINRT = (1 << 10), GST_GL_DISPLAY_TYPE_ANDROID = (1 << 11), + GST_GL_DISPLAY_TYPE_EGL_SURFACELESS = (1 << 12), GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32 } GstGLDisplayType; diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c index 91c1ae0513..a6f95b17af 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c @@ -334,6 +334,9 @@ gst_gl_window_new (GstGLDisplay * display) if (!window && (!user_choice || g_strstr_len (user_choice, 5, "winrt"))) window = GST_GL_WINDOW (gst_gl_window_winrt_egl_new (display)); #endif + if (!window && (!user_choice + || g_strstr_len (user_choice, 11, "surfaceless"))) + window = GST_GL_WINDOW (gst_gl_dummy_window_new ()); if (!window) { /* subclass returned a NULL window */ diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/meson.build b/subprojects/gst-plugins-base/gst-libs/gst/gl/meson.build index ebdab9089a..b97ec0c049 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/meson.build +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/meson.build @@ -253,6 +253,7 @@ if gl_winsys.contains('auto') need_win_winrt = 'auto' need_win_cocoa = 'auto' need_win_egl = 'auto' + need_win_surfaceless = 'auto' need_win_eagl = 'auto' need_win_dispmanx = 'auto' need_win_viv_fb = 'auto' @@ -265,6 +266,7 @@ else need_win_winrt = 'no' need_win_cocoa = 'no' need_win_egl = 'no' + need_win_surfaceless = 'no' need_win_eagl = 'no' need_win_dispmanx = 'no' need_win_viv_fb = 'no' @@ -283,6 +285,8 @@ else need_win_cocoa = 'yes' elif winsys == 'egl' need_win_egl = 'yes' + elif winsys == 'surfaceless' + need_win_surfaceless = 'yes' elif winsys == 'eagl' need_win_eagl = 'yes' elif winsys == 'dispmanx' @@ -578,16 +582,39 @@ if need_platform_egl != 'no' endif # winsys_egl checks -if need_win_egl == 'yes' +if need_win_egl != 'no' if need_platform_egl == 'no' - error('Impossible situation requested: Cannot use Winsys egl without EGL support') + if need_win_egl == 'yes' + error ('Impossible situation requested: Cannot use Winsys egl without EGL support') + endif elif not egl_dep.found() - error ('Could not find EGL libraries for Winsys egl') + if need_win_egl == 'yes' + error ('Could not find EGL libraries for Winsys egl') + else + message ('Could not find EGL libraries for Winsys egl') + endif else enabled_gl_winsys += 'egl' endif endif +# winsys_surfaceless checks +if need_win_surfaceless != 'no' + if need_platform_egl == 'no' + if need_win_surfaceless == 'yes' + error ('Impossible situation requested: Cannot use Winsys surfaceless without EGL support') + endif + elif not egl_dep.found() + if need_win_surfaceless == 'yes' + error ('Could not find EGL libraries for Winsys surfaceless') + else + message ('Could not find EGL libraries for Winsys surfaceless') + endif + else + enabled_gl_winsys += 'surfaceless' + endif +endif + # wayland checks wayland_client_dep = unneeded_dep wayland_cursor_dep = unneeded_dep diff --git a/subprojects/gst-plugins-base/meson_options.txt b/subprojects/gst-plugins-base/meson_options.txt index 2fb13cfafb..45d0fed0aa 100644 --- a/subprojects/gst-plugins-base/meson_options.txt +++ b/subprojects/gst-plugins-base/meson_options.txt @@ -12,7 +12,7 @@ option('gl_platform', type : 'array', choices : ['glx', 'egl', 'cgl', 'wgl', 'eagl', 'auto'], value : ['auto'], description : 'A comma separated list of opengl platforms to enable building against') option('gl_winsys', type : 'array', - choices : ['x11', 'wayland', 'win32', 'winrt', 'cocoa', 'dispmanx', 'egl', 'viv-fb', 'gbm', 'android', 'auto'], value : ['auto'], + choices : ['x11', 'wayland', 'win32', 'winrt', 'cocoa', 'dispmanx', 'egl', 'surfaceless', 'viv-fb', 'gbm', 'android', 'auto'], value : ['auto'], description : 'A comma separated list of opengl windows systems to enable building against. Supported values are x11, wayland, win32, winrt, cocoa, dispmanx, egl, viv-fb, gbm, and android') option('egl_module_name', type : 'string', value : '', description : 'The file to pass to g_module_open to open the libEGL library (default: libEGL)') diff --git a/subprojects/gstreamer/docs/gst/running.md b/subprojects/gstreamer/docs/gst/running.md index 08eb86cc1d..436a7900d3 100644 --- a/subprojects/gstreamer/docs/gst/running.md +++ b/subprojects/gstreamer/docs/gst/running.md @@ -315,7 +315,7 @@ the encoding does not look like UTF-8. **`GST_GL_WINDOW`.** Influences the window system to use by the GStreamer OpenGL library. -Common values are 'x11', 'wayland', 'win32' or 'cocoa'. +Common values are 'x11', 'wayland', 'surfaceless', 'win32' or 'cocoa'. **`GST_GL_PLATFORM`.** diff --git a/subprojects/gstreamer/docs/index.md b/subprojects/gstreamer/docs/index.md index 14b0450350..72bf530beb 100644 --- a/subprojects/gstreamer/docs/index.md +++ b/subprojects/gstreamer/docs/index.md @@ -325,7 +325,7 @@ the encoding does not look like UTF-8. **GST_GL_WINDOW.** Influences the window system to use by the GStreamer OpenGL library. -Common values are 'x11', 'wayland', 'win32' or 'cocoa'. +Common values are 'x11', 'wayland', 'surfaceless', 'win32' or 'cocoa'. **GST_GL_PLATFORM.**