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
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.</doc>
</member>
<member name="android" value="2048" c:identifier="GST_GL_DISPLAY_TYPE_ANDROID" glib:nick="android">
</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">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstgldisplay.h">any display type</doc>
</member>

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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'
if need_win_egl == 'yes'
error ('Impossible situation requested: Cannot use Winsys egl without EGL support')
endif
elif not egl_dep.found()
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

View file

@ -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)')

View file

@ -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`.**

View file

@ -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.**