From d13303496fc17435fa88c0834280556c0aa38380 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 2 Oct 2024 21:24:37 -0400 Subject: [PATCH] gstreamer: Make dmabufs work without GL We only need a display to negotiate dmabuf formats. Pass that directly, instead of getting the display of the GL context as we did so far. With this, GSK_RENDERER=vulkan GL_DISABLE=gl gtk4-demo --run video_player still uses dmabufs. Related: #7048 --- modules/media/gtkgstpaintable.c | 19 ++++++++++++++----- modules/media/gtkgstsink.c | 30 ++++++++++++++++++++++-------- modules/media/gtkgstsinkprivate.h | 13 +++++++------ 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/modules/media/gtkgstpaintable.c b/modules/media/gtkgstpaintable.c index 66bb29985d..f4e24fd132 100644 --- a/modules/media/gtkgstpaintable.c +++ b/modules/media/gtkgstpaintable.c @@ -37,6 +37,7 @@ struct _GtkGstPaintable graphene_rect_t viewport; GdkGLContext *context; + GdkSurface *surface; }; struct _GtkGstPaintableClass @@ -134,10 +135,14 @@ gtk_gst_paintable_video_renderer_create_video_sink (GstPlayerVideoRenderer *rend GtkGstPaintable *self = GTK_GST_PAINTABLE (renderer); GstElement *sink; GdkGLContext *ctx; + GdkDisplay *display; + + display = self->surface ? gdk_surface_get_display (self->surface) : NULL; sink = g_object_new (GTK_TYPE_GST_SINK, "paintable", self, "gl-context", self->context, + "display", display, NULL); if (self->context != NULL) @@ -164,6 +169,7 @@ gtk_gst_paintable_video_renderer_create_video_sink (GstPlayerVideoRenderer *rend g_object_unref (sink); sink = g_object_new (GTK_TYPE_GST_SINK, "paintable", self, + "display", display, NULL); } @@ -218,9 +224,11 @@ gtk_gst_paintable_realize (GtkGstPaintable *self, { GError *error = NULL; - if (self->context) + if (self->surface) return; + self->surface = surface; + self->context = gdk_surface_create_gl_context (surface, &error); if (self->context == NULL) { @@ -246,11 +254,12 @@ gtk_gst_paintable_unrealize (GtkGstPaintable *self, * - track how often we were realized with that surface * - track alternate surfaces */ - if (self->context == NULL) - return; - if (gdk_gl_context_get_surface (self->context) == surface) - g_clear_object (&self->context); + if (self->surface == surface) + { + g_clear_object (&self->context); + self->surface = NULL; + } } static void diff --git a/modules/media/gtkgstsink.c b/modules/media/gtkgstsink.c index 5242bfd03e..8376942dd5 100644 --- a/modules/media/gtkgstsink.c +++ b/modules/media/gtkgstsink.c @@ -59,6 +59,7 @@ enum { PROP_0, PROP_PAINTABLE, PROP_GL_CONTEXT, + PROP_DISPLAY, N_PROPS, }; @@ -207,10 +208,9 @@ gtk_gst_sink_get_caps (GstBaseSink *bsink, GstCaps *tmp; GstCaps *result; - if (self->gst_context) + if (self->gdk_display) { - GdkDisplay *display = gdk_gl_context_get_display (self->gdk_context); - GdkDmabufFormats *formats = gdk_display_get_dmabuf_formats (display); + GdkDmabufFormats *formats = gdk_display_get_dmabuf_formats (self->gdk_display); tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink)); tmp = gst_caps_make_writable (tmp); @@ -299,9 +299,6 @@ gtk_gst_sink_propose_allocation (GstBaseSink *bsink, gboolean need_pool; GstVideoInfo info; - if (!self->gst_context) - return FALSE; - gst_query_parse_allocation (query, &caps, &need_pool); if (caps == NULL) @@ -316,6 +313,9 @@ gtk_gst_sink_propose_allocation (GstBaseSink *bsink, return TRUE; } + if (!self->gst_context) + return FALSE; + if (!gst_caps_features_contains (gst_caps_get_features (caps, 0), GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) return FALSE; @@ -418,11 +418,10 @@ gtk_gst_sink_texture_from_buffer (GtkGstSink *self, g_clear_pointer (&frame, g_free); g_return_val_if_fail (vmeta, NULL); - g_return_val_if_fail (self->gdk_context, NULL); g_return_val_if_fail (self->drm_info.drm_fourcc != DRM_FORMAT_INVALID, NULL); builder = gdk_dmabuf_texture_builder_new (); - gdk_dmabuf_texture_builder_set_display (builder, gdk_gl_context_get_display (self->gdk_context)); + gdk_dmabuf_texture_builder_set_display (builder, self->gdk_display); gdk_dmabuf_texture_builder_set_fourcc (builder, self->drm_info.drm_fourcc); gdk_dmabuf_texture_builder_set_modifier (builder, self->drm_info.drm_modifier); gdk_dmabuf_texture_builder_set_width (builder, vmeta->width); @@ -766,6 +765,10 @@ gtk_gst_sink_set_property (GObject *object, g_clear_object (&self->gdk_context); break; + case PROP_DISPLAY: + self->gdk_display = g_value_dup_object (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -785,10 +788,15 @@ gtk_gst_sink_get_property (GObject *object, case PROP_PAINTABLE: g_value_set_object (value, self->paintable); break; + case PROP_GL_CONTEXT: g_value_set_object (value, self->gdk_context); break; + case PROP_DISPLAY: + g_value_set_object (value, self->gdk_display); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -805,6 +813,7 @@ gtk_gst_sink_dispose (GObject *object) g_clear_object (&self->gst_gdk_context); g_clear_object (&self->gst_display); g_clear_object (&self->gdk_context); + g_clear_object (&self->gdk_display); G_OBJECT_CLASS (gtk_gst_sink_parent_class)->dispose (object); } @@ -849,6 +858,11 @@ gtk_gst_sink_class_init (GtkGstSinkClass * klass) GDK_TYPE_GL_CONTEXT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + properties[PROP_DISPLAY] = + g_param_spec_object ("display", NULL, NULL, + GDK_TYPE_DISPLAY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (gobject_class, N_PROPS, properties); gst_element_class_set_metadata (gstelement_class, diff --git a/modules/media/gtkgstsinkprivate.h b/modules/media/gtkgstsinkprivate.h index 3c139c1785..af791a2824 100644 --- a/modules/media/gtkgstsinkprivate.h +++ b/modules/media/gtkgstsinkprivate.h @@ -49,12 +49,13 @@ struct _GtkGstSink GstVideoInfo v_info; GstVideoInfoDmaDrm drm_info; - GtkGstPaintable * paintable; - GdkGLContext * gdk_context; - GstGLDisplay * gst_display; - GstGLContext * gst_gdk_context; - GstGLContext * gst_context; - GdkColorState * color_state; + GtkGstPaintable *paintable; + GdkDisplay *gdk_display; + GdkGLContext *gdk_context; + GstGLDisplay *gst_display; + GstGLContext *gst_gdk_context; + GstGLContext *gst_context; + GdkColorState *color_state; }; struct _GtkGstSinkClass