gl/window: add support for configuring whether a backing surface is needed

Fixes videotestsrc ! glimagesink videotestsrc ! glimagesink under Wayland (at
least).

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2997

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9007>
This commit is contained in:
Matthew Waters 2025-05-17 20:20:03 +10:00 committed by GStreamer Marge Bot
parent 6fc32cbe0e
commit daae2c18a4
7 changed files with 134 additions and 34 deletions

View File

@ -8608,6 +8608,19 @@ require this to be called with a valid handle before drawing can commence.</doc>
</instance-parameter>
</parameters>
</method>
<method name="get_request_output_surface" c:identifier="gst_gl_window_get_request_output_surface" version="1.28">
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.h"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c">whether an visible output surface has been requested</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<instance-parameter name="window" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c">a #GstGLWindow</doc>
<type name="GLWindow" c:type="GstGLWindow*"/>
</instance-parameter>
</parameters>
</method>
<method name="get_surface_dimensions" c:identifier="gst_gl_window_get_surface_dimensions" version="1.6">
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.h"/>
<return-value transfer-ownership="none">
@ -8957,6 +8970,23 @@ according to the #GstVideoOverlay interface.</doc>
</parameter>
</parameters>
</method>
<method name="set_request_output_surface" c:identifier="gst_gl_window_set_request_output_surface" version="1.28">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c">Configure whether a visible output surface is requested.</doc>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.h"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<instance-parameter name="window" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c">a #GstGLWindow</doc>
<type name="GLWindow" c:type="GstGLWindow*"/>
</instance-parameter>
<parameter name="output_surface" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c">whether to request an output surface.</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</method>
<method name="set_resize_callback" c:identifier="gst_gl_window_set_resize_callback" version="1.4">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.c">Sets the resize callback called every time a resize of the window occurs.</doc>
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/gl/gstglwindow.h"/>

View File

@ -1067,13 +1067,35 @@ _ensure_gl_setup (GstGLImageSink * gl_sink)
gst_gl_display_get_gl_context_for_thread (gl_sink->display, NULL);
}
if (!gst_gl_display_create_context (gl_sink->display,
other_context, &context, &error)) {
if (other_context)
gst_object_unref (other_context);
GST_OBJECT_UNLOCK (gl_sink->display);
goto context_error;
g_signal_emit_by_name (gl_sink->display, "create-context", other_context,
&context);
if (!context) {
GstGLWindow *window;
context = gst_gl_context_new (gl_sink->display);
if (!context) {
g_set_error (&error, GST_GL_CONTEXT_ERROR,
GST_GL_CONTEXT_ERROR_FAILED, "Failed to create GL context");
gst_clear_object (&other_context);
GST_OBJECT_UNLOCK (gl_sink->display);
goto context_error;
}
GST_DEBUG_OBJECT (gl_sink,
"creating context %" GST_PTR_FORMAT " from other context %"
GST_PTR_FORMAT, context, other_context);
window = gst_gl_display_create_window (context->display);
gst_gl_window_set_request_output_surface (window, TRUE);
gst_gl_context_set_window (context, window);
gst_clear_object (&window);
if (!gst_gl_context_create (context, other_context, &error)) {
gst_clear_object (&other_context);
gst_clear_object (&context);
GST_OBJECT_UNLOCK (gl_sink->display);
goto context_error;
}
}
_set_context (gl_sink, context);
context = NULL;

View File

@ -164,10 +164,14 @@ gst_gl_window_dispmanx_egl_open (GstGLWindow * window, GError ** error)
gboolean
gst_gl_window_dispmanx_egl_create_window (GstGLWindowDispmanxEGL * window_egl)
{
GstGLWindow *window = GST_GL_WINDOW (window_egl);
window_egl->native.width = 0;
window_egl->native.height = 0;
window_egl->display = vc_dispmanx_display_open (0);
window_resize (window_egl, 16, 16, FALSE);
if (gst_gl_window_get_request_output_window (window)) {
window_egl->display = vc_dispmanx_display_open (0);
window_resize (window_egl, 16, 16, FALSE);
}
return TRUE;
}

View File

@ -1089,41 +1089,36 @@ gst_gl_context_egl_create_context (GstGLContext * context,
gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window);
}
#endif
if (other_context == NULL) {
/* FIXME: fails to show two outputs at all. We need a property/option for
* glimagesink to say its a visible context */
#if GST_GL_HAVE_WINDOW_WAYLAND
if (GST_IS_GL_WINDOW_WAYLAND_EGL (context->window)) {
gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *)
context->window);
}
if (GST_IS_GL_WINDOW_WAYLAND_EGL (context->window)) {
gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *)
context->window);
}
#endif
#if GST_GL_HAVE_WINDOW_WIN32
if (GST_IS_GL_WINDOW_WIN32 (context->window)) {
gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window,
NULL);
}
if (GST_IS_GL_WINDOW_WIN32 (context->window)) {
gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window,
NULL);
}
#endif
#if GST_GL_HAVE_WINDOW_DISPMANX
if (GST_IS_GL_WINDOW_DISPMANX_EGL (context->window)) {
gst_gl_window_dispmanx_egl_create_window ((GstGLWindowDispmanxEGL *)
context->window);
}
if (GST_IS_GL_WINDOW_DISPMANX_EGL (context->window)) {
gst_gl_window_dispmanx_egl_create_window ((GstGLWindowDispmanxEGL *)
context->window);
}
#endif
#if GST_GL_HAVE_WINDOW_GBM
if (GST_IS_GL_WINDOW_GBM_EGL (context->window)) {
gst_gl_window_gbm_egl_create_window ((GstGLWindowGBMEGL *)
context->window);
}
if (GST_IS_GL_WINDOW_GBM_EGL (context->window)) {
gst_gl_window_gbm_egl_create_window ((GstGLWindowGBMEGL *)
context->window);
}
#endif
#if GST_GL_HAVE_WINDOW_VIV_FB
if (GST_IS_GL_WINDOW_VIV_FB_EGL (context->window)) {
gst_gl_window_viv_fb_egl_create_window ((GstGLWindowVivFBEGL *)
context->window);
}
#endif
if (GST_IS_GL_WINDOW_VIV_FB_EGL (context->window)) {
gst_gl_window_viv_fb_egl_create_window ((GstGLWindowVivFBEGL *)
context->window);
}
#endif
if (window)
window_handle = gst_gl_window_get_window_handle (window);

View File

@ -99,6 +99,8 @@ struct _GstGLWindowPrivate
GMutex sync_message_lock;
GCond sync_message_cond;
gboolean request_output_surface;
};
#define gst_gl_window_parent_class parent_class
@ -1140,6 +1142,44 @@ gst_gl_window_controls_viewport (GstGLWindow * window)
return window_class->controls_viewport (window);
}
/**
* gst_gl_window_set_request_output_surface:
* @window: a #GstGLWindow
* @output_surface: whether to request an output surface.
*
* Configure whether a visible output surface is requested.
*
* Since: 1.28
*/
void
gst_gl_window_set_request_output_surface (GstGLWindow * window,
gboolean output_surface)
{
GstGLWindowPrivate *priv = gst_gl_window_get_instance_private (window);
g_return_if_fail (GST_IS_GL_WINDOW (window));
priv->request_output_surface = output_surface;
}
/**
* gst_gl_window_get_request_output_surface:
* @window: a #GstGLWindow
*
* Returns: whether an visible output surface has been requested
*
* Since: 1.28
*/
gboolean
gst_gl_window_get_request_output_surface (GstGLWindow * window)
{
GstGLWindowPrivate *priv = gst_gl_window_get_instance_private (window);
g_return_val_if_fail (GST_IS_GL_WINDOW (window), FALSE);
return priv->request_output_surface;
}
static GType gst_gl_dummy_window_get_type (void);
static gboolean

View File

@ -277,6 +277,12 @@ guintptr gst_gl_window_get_display (GstGLWindow *window);
GST_GL_API
gboolean gst_gl_window_has_output_surface (GstGLWindow *window);
GST_GL_API
void gst_gl_window_set_request_output_surface (GstGLWindow *window, gboolean output_surface);
GST_GL_API
gboolean gst_gl_window_get_request_output_surface (GstGLWindow *window);
G_END_DECLS
#endif /* __GST_GL_WINDOW_H__ */

View File

@ -624,7 +624,10 @@ gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error)
void
gst_gl_window_wayland_egl_create_window (GstGLWindowWaylandEGL * window_egl)
{
create_surfaces (window_egl);
GstGLWindow *window = GST_GL_WINDOW (window_egl);
if (gst_gl_window_get_request_output_surface (window))
create_surfaces (window_egl);
}
static guintptr