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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5511>
This commit is contained in:
Loïc Le Page 2023-10-19 14:10:16 +02:00 committed by GStreamer Marge Bot
parent 34694bbfcf
commit e1ca575408
10 changed files with 107 additions and 14 deletions

View file

@ -3016,7 +3016,7 @@ a #GstGLDisplay.
There are a number of environment variables that influence the choice of There are a number of environment variables that influence the choice of
platform and window system specific functionality. platform and window system specific functionality.
- GST_GL_WINDOW influences the window system to use. Common values are - 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 - GST_GL_PLATFORM influences the OpenGL platform to use. Common values are
'egl', 'glx', 'wgl' or 'cgl'. 'egl', 'glx', 'wgl' or 'cgl'.
- GST_GL_API influences the OpenGL API requested by the OpenGL platform. - GST_GL_API influences the OpenGL API requested by the OpenGL platform.
@ -3453,6 +3453,8 @@ display's object lock held.</doc>
</member> </member>
<member name="android" value="2048" c:identifier="GST_GL_DISPLAY_TYPE_ANDROID" glib:nick="android"> <member name="android" value="2048" c:identifier="GST_GL_DISPLAY_TYPE_ANDROID" glib:nick="android">
</member> </member>
<member name="egl_surfaceless" value="4096" c:identifier="GST_GL_DISPLAY_TYPE_EGL_SURFACELESS" glib:nick="egl-surfaceless">
</member>
<member name="any" value="4294967295" c:identifier="GST_GL_DISPLAY_TYPE_ANY" glib:nick="any"> <member name="any" value="4294967295" c:identifier="GST_GL_DISPLAY_TYPE_ANY" glib:nick="any">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h">any display type</doc> <doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h">any display type</doc>
</member> </member>

View file

@ -25,8 +25,8 @@
* @see_also: #GstGLDisplay * @see_also: #GstGLDisplay
* *
* #GstGLDisplayEGL represents a connection to an EGL `EGLDisplay` handle created * #GstGLDisplayEGL represents a connection to an EGL `EGLDisplay` handle created
* internally (gst_gl_display_egl_new()) or wrapped by the application * internally (gst_gl_display_egl_new() or gst_gl_display_egl_new_surfaceless())
* (gst_gl_display_egl_new_with_egl_display()) * or wrapped by the application (gst_gl_display_egl_new_with_egl_display())
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -122,8 +122,8 @@ gst_gl_display_egl_finalize (GObject * object)
* @display: pointer to a display (or 0) * @display: pointer to a display (or 0)
* *
* Attempts to create a new `EGLDisplay` from @display. If @type is * 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_ANY or %GST_GL_DISPLAY_TYPE_EGL_SURFACELESS, then
* %GST_GL_DISPLAY_TYPE_NONE. * @display must be 0. @type must not be %GST_GL_DISPLAY_TYPE_NONE.
* *
* Returns: (nullable): A `EGLDisplay` or `EGL_NO_DISPLAY` * 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; _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_NONE, EGL_NO_DISPLAY);
g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0) g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY &&
|| (type == GST_GL_DISPLAY_TYPE_ANY && display == 0), EGL_NO_DISPLAY); 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 (); init_debug ();
@ -233,6 +236,11 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display)
NULL); NULL);
} }
/* android only has one winsys/display connection */ /* 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) if (ret != EGL_NO_DISPLAY)
return ret; return ret;
@ -272,6 +280,40 @@ gst_gl_display_egl_new (void)
return ret; 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: * gst_gl_display_egl_new_with_display:
* @display: an existing and connected EGLDisplay * @display: an existing and connected EGLDisplay

View file

@ -66,6 +66,9 @@ struct _GstGLDisplayEGLClass
GST_GL_API GST_GL_API
GstGLDisplayEGL *gst_gl_display_egl_new (void); GstGLDisplayEGL *gst_gl_display_egl_new (void);
GST_GL_API
GstGLDisplayEGL *gst_gl_display_egl_new_surfaceless (void);
GST_GL_API GST_GL_API
GstGLDisplayEGL *gst_gl_display_egl_new_with_egl_display (gpointer display); GstGLDisplayEGL *gst_gl_display_egl_new_with_egl_display (gpointer display);

View file

@ -34,7 +34,7 @@
* There are a number of environment variables that influence the choice of * There are a number of environment variables that influence the choice of
* platform and window system specific functionality. * platform and window system specific functionality.
* - GST_GL_WINDOW influences the window system to use. Common values are * - 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 * - GST_GL_PLATFORM influences the OpenGL platform to use. Common values are
* 'egl', 'glx', 'wgl' or 'cgl'. * 'egl', 'glx', 'wgl' or 'cgl'.
* - GST_GL_API influences the OpenGL API requested by the OpenGL platform. * - 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; return GST_GL_DISPLAY_TYPE_EGL;
} else if (g_strstr_len (env, 5, "winrt")) { } else if (g_strstr_len (env, 5, "winrt")) {
return GST_GL_DISPLAY_TYPE_EGL; return GST_GL_DISPLAY_TYPE_EGL;
} else if (g_strstr_len (env, 11, "surfaceless")) {
return GST_GL_DISPLAY_TYPE_EGL_SURFACELESS;
} else { } else {
return GST_GL_DISPLAY_TYPE_NONE; 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)) { if (!display && (type & GST_GL_DISPLAY_TYPE_EGL)) {
display = GST_GL_DISPLAY (gst_gl_display_egl_new ()); 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 #endif
custom_new_types |= GST_GL_DISPLAY_TYPE_EGL_DEVICE; 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;
custom_new_types |= GST_GL_DISPLAY_TYPE_EGL_SURFACELESS;
custom_new_types |= GST_GL_DISPLAY_TYPE_DISPMANX; custom_new_types |= GST_GL_DISPLAY_TYPE_DISPMANX;
custom_new_types |= GST_GL_DISPLAY_TYPE_WINRT; custom_new_types |= GST_GL_DISPLAY_TYPE_WINRT;
custom_new_types |= GST_GL_DISPLAY_TYPE_ANDROID; custom_new_types |= GST_GL_DISPLAY_TYPE_ANDROID;

View file

@ -80,6 +80,14 @@ GType gst_gl_display_get_type (void);
* *
* Since: 1.20 * Since: 1.20
*/ */
/**
* GST_GL_DISPLAY_TYPE_EGL_SURFACELESS:
*
* Mesa3D surfaceless display using the EGL_PLATFORM_SURFACELESS_MESA
* extension.
*
* Since: 1.24
*/
typedef enum typedef enum
{ {
GST_GL_DISPLAY_TYPE_NONE = 0, GST_GL_DISPLAY_TYPE_NONE = 0,
@ -95,6 +103,7 @@ typedef enum
GST_GL_DISPLAY_TYPE_EAGL = (1 << 9), GST_GL_DISPLAY_TYPE_EAGL = (1 << 9),
GST_GL_DISPLAY_TYPE_WINRT = (1 << 10), GST_GL_DISPLAY_TYPE_WINRT = (1 << 10),
GST_GL_DISPLAY_TYPE_ANDROID = (1 << 11), GST_GL_DISPLAY_TYPE_ANDROID = (1 << 11),
GST_GL_DISPLAY_TYPE_EGL_SURFACELESS = (1 << 12),
GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32 GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32
} GstGLDisplayType; } GstGLDisplayType;

View file

@ -334,6 +334,9 @@ gst_gl_window_new (GstGLDisplay * display)
if (!window && (!user_choice || g_strstr_len (user_choice, 5, "winrt"))) if (!window && (!user_choice || g_strstr_len (user_choice, 5, "winrt")))
window = GST_GL_WINDOW (gst_gl_window_winrt_egl_new (display)); window = GST_GL_WINDOW (gst_gl_window_winrt_egl_new (display));
#endif #endif
if (!window && (!user_choice
|| g_strstr_len (user_choice, 11, "surfaceless")))
window = GST_GL_WINDOW (gst_gl_dummy_window_new ());
if (!window) { if (!window) {
/* subclass returned a NULL window */ /* subclass returned a NULL window */

View file

@ -253,6 +253,7 @@ if gl_winsys.contains('auto')
need_win_winrt = 'auto' need_win_winrt = 'auto'
need_win_cocoa = 'auto' need_win_cocoa = 'auto'
need_win_egl = 'auto' need_win_egl = 'auto'
need_win_surfaceless = 'auto'
need_win_eagl = 'auto' need_win_eagl = 'auto'
need_win_dispmanx = 'auto' need_win_dispmanx = 'auto'
need_win_viv_fb = 'auto' need_win_viv_fb = 'auto'
@ -265,6 +266,7 @@ else
need_win_winrt = 'no' need_win_winrt = 'no'
need_win_cocoa = 'no' need_win_cocoa = 'no'
need_win_egl = 'no' need_win_egl = 'no'
need_win_surfaceless = 'no'
need_win_eagl = 'no' need_win_eagl = 'no'
need_win_dispmanx = 'no' need_win_dispmanx = 'no'
need_win_viv_fb = 'no' need_win_viv_fb = 'no'
@ -283,6 +285,8 @@ else
need_win_cocoa = 'yes' need_win_cocoa = 'yes'
elif winsys == 'egl' elif winsys == 'egl'
need_win_egl = 'yes' need_win_egl = 'yes'
elif winsys == 'surfaceless'
need_win_surfaceless = 'yes'
elif winsys == 'eagl' elif winsys == 'eagl'
need_win_eagl = 'yes' need_win_eagl = 'yes'
elif winsys == 'dispmanx' elif winsys == 'dispmanx'
@ -578,16 +582,39 @@ if need_platform_egl != 'no'
endif endif
# winsys_egl checks # winsys_egl checks
if need_win_egl == 'yes' if need_win_egl != 'no'
if need_platform_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() 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 else
enabled_gl_winsys += 'egl' enabled_gl_winsys += 'egl'
endif endif
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 checks
wayland_client_dep = unneeded_dep wayland_client_dep = unneeded_dep
wayland_cursor_dep = unneeded_dep wayland_cursor_dep = unneeded_dep

View file

@ -12,7 +12,7 @@ option('gl_platform', type : 'array',
choices : ['glx', 'egl', 'cgl', 'wgl', 'eagl', 'auto'], value : ['auto'], choices : ['glx', 'egl', 'cgl', 'wgl', 'eagl', 'auto'], value : ['auto'],
description : 'A comma separated list of opengl platforms to enable building against') description : 'A comma separated list of opengl platforms to enable building against')
option('gl_winsys', type : 'array', 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') 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 : '', option('egl_module_name', type : 'string', value : '',
description : 'The file to pass to g_module_open to open the libEGL library (default: libEGL)') description : 'The file to pass to g_module_open to open the libEGL library (default: libEGL)')

View file

@ -315,7 +315,7 @@ the encoding does not look like UTF-8.
**`GST_GL_WINDOW`.** **`GST_GL_WINDOW`.**
Influences the window system to use by the GStreamer OpenGL library. 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`.** **`GST_GL_PLATFORM`.**

View file

@ -325,7 +325,7 @@ the encoding does not look like UTF-8.
**GST_GL_WINDOW.** **GST_GL_WINDOW.**
Influences the window system to use by the GStreamer OpenGL library. 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.** **GST_GL_PLATFORM.**