Merge branch 'matthiasc/for-main' into 'main'

gstreamer: Simplify dmabuf code

See merge request GNOME/gtk!6852
This commit is contained in:
Matthias Clasen
2024-02-07 18:21:25 +00:00
18 changed files with 240 additions and 83 deletions

4
NEWS
View File

@@ -1,6 +1,9 @@
Overview of Changes in 4.13.7, xx-xx-xxxx
=========================================
* GtkFileChooser:
- Speed up opening
* Accessibility:
- Add socket support for webkit accessibility
@@ -28,6 +31,7 @@ Overview of Changes in 4.13.7, xx-xx-xxxx
* Translation updates
Galician
Georgian
Occitan
Overview of Changes in 4.13.6, 25-01-2024

View File

@@ -272,7 +272,7 @@ gdk_display_class_init (GdkDisplayClass *class)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GdkDisplay:dmabuf-formats:
* GdkDisplay:dmabuf-formats: (attributes org.gtk.Property.get=gdk_display_get_dmabuf_formats)
*
* The dma-buf formats that are supported on this display
*

View File

@@ -217,3 +217,41 @@ gdk_dmabuf_formats_peek_formats (GdkDmabufFormats *self)
{
return self->formats;
}
/**
* gdk_dmabuf_formats_equal:
* @formats1: (nullable): a `GdkDmabufFormats`
* @formats2: (nullable): another `GdkDmabufFormats`
*
* Returns whether @formats1 and @formats2 contain the
* same dmabuf formats, in the same order.
*
* Returns: `TRUE` if @formats1 and @formats2 are equal
*
* Since: 4.14
*/
gboolean
gdk_dmabuf_formats_equal (const GdkDmabufFormats *formats1,
const GdkDmabufFormats *formats2)
{
if (formats1 == formats2)
return TRUE;
if (formats1 == NULL || formats2 == NULL)
return FALSE;
if (formats1->n_formats != formats2->n_formats)
return FALSE;
for (gsize i = 0; i < formats1->n_formats; i++)
{
GdkDmabufFormat *f1 = &formats1->formats[i];
GdkDmabufFormat *f2 = &formats2->formats[i];
if (f1->fourcc != f2->fourcc ||
f1->modifier != f2->modifier)
return FALSE;
}
return TRUE;
}

View File

@@ -51,4 +51,8 @@ gboolean gdk_dmabuf_formats_contains (GdkDmabufFormats *formats
guint32 fourcc,
guint64 modifier) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_14
gboolean gdk_dmabuf_formats_equal (const GdkDmabufFormats *formats1,
const GdkDmabufFormats *formats2);
G_END_DECLS

View File

@@ -33,7 +33,7 @@
/**
* GdkDmabufTexture:
*
* A `GdkTexture` representing a dma-buf object.
* A `GdkTexture` representing a DMA buffer.
*
* To create a `GdkDmabufTexture`, use the auxiliary
* [class@Gdk.DmabufTextureBuilder] object.

View File

@@ -62,19 +62,70 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
gboolean above,
GdkSubsurface *sibling)
{
GdkSurface *parent = subsurface->parent;
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
g_return_val_if_fail (rect != NULL, FALSE);
g_return_val_if_fail (sibling == NULL || GDK_IS_SUBSURFACE (sibling), FALSE);
if (sibling)
{
subsurface->above_parent = sibling->above_parent;
if (above)
{
subsurface->sibling_above = sibling->sibling_above;
sibling->sibling_above = subsurface;
subsurface->sibling_below = sibling;
}
else
{
subsurface->sibling_below = sibling->sibling_below;
sibling->sibling_below = subsurface;
subsurface->sibling_above = sibling;
}
}
else
{
subsurface->above_parent = above;
if (above)
{
subsurface->sibling_above = parent->subsurfaces_above;
subsurface->sibling_below = NULL;
if (parent->subsurfaces_above)
parent->subsurfaces_above->sibling_below = subsurface;
parent->subsurfaces_above = subsurface;
}
else
{
subsurface->sibling_below = parent->subsurfaces_below;
subsurface->sibling_above = NULL;
if (parent->subsurfaces_below)
parent->subsurfaces_below->sibling_above = subsurface;
parent->subsurfaces_below = subsurface;
}
}
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, rect, above, sibling);
}
void
gdk_subsurface_detach (GdkSubsurface *subsurface)
{
GdkSurface *parent = subsurface->parent;
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
if (parent->subsurfaces_above == subsurface)
parent->subsurfaces_above = subsurface->sibling_above;
if (parent->subsurfaces_below == subsurface)
parent->subsurfaces_below = subsurface->sibling_below;
subsurface->sibling_above = NULL;
subsurface->sibling_below = NULL;
GDK_SUBSURFACE_GET_CLASS (subsurface)->detach (subsurface);
}
@@ -101,5 +152,5 @@ gdk_subsurface_is_above_parent (GdkSubsurface *subsurface)
{
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), TRUE);
return GDK_SUBSURFACE_GET_CLASS (subsurface)->is_above_parent (subsurface);
return subsurface->above_parent;
}

View File

@@ -41,6 +41,10 @@ struct _GdkSubsurface
GdkSurface *parent;
int ref_count;
gboolean above_parent;
gpointer sibling_above;
gpointer sibling_below;
};
@@ -57,7 +61,6 @@ struct _GdkSubsurfaceClass
GdkTexture * (* get_texture) (GdkSubsurface *subsurface);
void (* get_rect) (GdkSubsurface *subsurface,
graphene_rect_t *rect);
gboolean (* is_above_parent) (GdkSubsurface *subsurface);
};
GType gdk_subsurface_get_type (void) G_GNUC_CONST;

View File

@@ -99,6 +99,12 @@ struct _GdkSurface
GdkSeat *current_shortcuts_inhibited_seat;
GPtrArray *subsurfaces;
/* We keep the subsurfaces above and below the surface in two linked
* lists, which start here.
*/
GdkSubsurface *subsurfaces_above;
GdkSubsurface *subsurfaces_below;
};
struct _GdkSurfaceClass

View File

@@ -26,8 +26,6 @@ struct _GdkWaylandSubsurface
struct wl_region *opaque_region;
struct wl_callback *frame_callback;
gboolean above_parent;
};
struct _GdkWaylandSubsurfaceClass

View File

@@ -166,8 +166,8 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
graphene_rect_t device_rect;
cairo_rectangle_int_t device_dest;
if (sib)
will_be_above = sib->above_parent;
if (sibling)
will_be_above = sibling->above_parent;
else
will_be_above = above;
@@ -322,8 +322,6 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
wl_subsurface_place_above (self->subsurface, sib->surface);
else
wl_subsurface_place_below (self->subsurface, sib->surface);
self->above_parent = sib->above_parent;
}
else
{
@@ -333,7 +331,6 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
else
wl_subsurface_place_below (self->subsurface,
GDK_WAYLAND_SURFACE (sub->parent)->display_server.wl_surface);
self->above_parent = above;
}
wl_surface_commit (self->surface);
@@ -384,14 +381,6 @@ gdk_wayland_subsurface_get_rect (GdkSubsurface *sub,
rect->size.height = self->dest.height;
}
static gboolean
gdk_wayland_subsurface_is_above_parent (GdkSubsurface *sub)
{
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
return self->above_parent;
}
static void
gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
{
@@ -404,7 +393,6 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
subsurface_class->detach = gdk_wayland_subsurface_detach;
subsurface_class->get_texture = gdk_wayland_subsurface_get_texture;
subsurface_class->get_rect = gdk_wayland_subsurface_get_rect;
subsurface_class->is_above_parent = gdk_wayland_subsurface_is_above_parent;
};
static void
@@ -478,8 +466,6 @@ gdk_wayland_surface_create_subsurface (GdkSurface *surface)
wl_region_add (sub->opaque_region, 0, 0, G_MAXINT, G_MAXINT);
wl_surface_set_opaque_region (sub->surface, sub->opaque_region);
sub->above_parent = TRUE;
GDK_DISPLAY_DEBUG (display, OFFLOAD, "Subsurface %p of surface %p created", sub, impl);
return GDK_SUBSURFACE (sub);

View File

@@ -646,9 +646,12 @@ gdk_wayland_surface_sync_opaque_region (GdkSurface *surface)
cairo_region_t *region = cairo_region_copy (impl->opaque_region);
for (gsize i = 0; i < gdk_surface_get_n_subsurfaces (surface); i++)
{
GdkWaylandSubsurface *sub = (GdkWaylandSubsurface *)gdk_surface_get_subsurface (surface, i);
if (sub->above_parent)
GdkSubsurface *subsurface = gdk_surface_get_subsurface (surface, i);
GdkWaylandSubsurface *sub = (GdkWaylandSubsurface *) subsurface;
if (subsurface->above_parent)
continue;
if (sub->texture != NULL)
cairo_region_subtract_rectangle (region, &sub->dest);
}

View File

@@ -115,15 +115,12 @@ gtk_gst_paintable_video_renderer_create_video_sink (GstPlayerVideoRenderer *rend
GstPlayer *player)
{
GtkGstPaintable *self = GTK_GST_PAINTABLE (renderer);
GdkDmabufFormats *dmabuf_formats;
GstElement *sink;
GdkGLContext *ctx;
dmabuf_formats = gdk_display_get_dmabuf_formats (gdk_display_get_default ());
sink = g_object_new (GTK_TYPE_GST_SINK,
"paintable", self,
"gl-context", self->context,
"dmabuf-formats", dmabuf_formats,
NULL);
if (self->context != NULL)

View File

@@ -61,7 +61,6 @@ enum {
PROP_0,
PROP_PAINTABLE,
PROP_GL_CONTEXT,
PROP_DMABUF_FORMATS,
N_PROPS,
};
@@ -157,8 +156,7 @@ add_drm_formats_and_modifiers (GstCaps *caps,
gst_value_list_append_and_take_value (&dmabuf_list, &value);
}
gst_structure_take_value (gst_caps_get_structure (caps, 0), "drm-format",
&dmabuf_list);
gst_structure_take_value (gst_caps_get_structure (caps, 0), "drm-format", &dmabuf_list);
}
#endif
@@ -174,11 +172,13 @@ gtk_gst_sink_get_caps (GstBaseSink *bsink,
{
tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink));
#ifdef HAVE_GSTREAMER_DRM
if (self->dmabuf_formats)
{
tmp = gst_caps_make_writable (tmp);
add_drm_formats_and_modifiers (tmp, self->dmabuf_formats);
}
{
GdkDisplay *display = gdk_gl_context_get_display (self->gdk_context);
GdkDmabufFormats *formats = gdk_display_get_dmabuf_formats (display);
tmp = gst_caps_make_writable (tmp);
add_drm_formats_and_modifiers (tmp, formats);
}
#endif
}
else
@@ -370,6 +370,7 @@ gtk_gst_sink_texture_from_buffer (GtkGstSink *self,
g_autoptr (GdkDmabufTextureBuilder) builder = NULL;
const GstVideoMeta *vmeta = gst_buffer_get_video_meta (buffer);
GError *error = NULL;
GdkDisplay *display;
int i;
/* We don't map dmabufs */
@@ -379,8 +380,17 @@ gtk_gst_sink_texture_from_buffer (GtkGstSink *self,
g_return_val_if_fail (self->gdk_context, NULL);
g_return_val_if_fail (self->drm_info.drm_fourcc != DRM_FORMAT_INVALID, NULL);
display = gdk_gl_context_get_display (self->gdk_context);
GDK_DISPLAY_DEBUG (display, DMABUF,
"Got %dx%d dmabuf from gstreamer, format %.4s:%#" G_GINT64_MODIFIER "x, %d planes",
GSK_VIDEO_INFO_WIDTH (&self->v_info),
GSK_VIDEO_INFO_HEIGHT (&self->v_info),
(char *) self->drm_info.drm_fourcc, self->drm_info.drm_modifier,
vmeta->n_planes);
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, 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);
// Padded width/height is set into the vmeta, perhaps we should import using these ?
@@ -730,10 +740,6 @@ gtk_gst_sink_set_property (GObject *object,
g_clear_object (&self->gdk_context);
break;
case PROP_DMABUF_FORMATS:
self->dmabuf_formats = g_value_get_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -756,9 +762,6 @@ gtk_gst_sink_get_property (GObject *object,
case PROP_GL_CONTEXT:
g_value_set_object (value, self->gdk_context);
break;
case PROP_DMABUF_FORMATS:
g_value_set_boxed (value, self->dmabuf_formats);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -819,19 +822,6 @@ gtk_gst_sink_class_init (GtkGstSinkClass * klass)
GDK_TYPE_GL_CONTEXT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
/**
* GtkGstSink:dmabuf-formats:
*
* The #GdkDmabufFormats that are supported by the #GdkDisplay and can be used
* with #GdkDmabufTextureBuilder.
*
* Since: 4.14
*/
properties[PROP_DMABUF_FORMATS] =
g_param_spec_boxed ("dmabuf-formats", NULL, NULL,
GDK_TYPE_DMABUF_FORMATS,
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,

View File

@@ -643,6 +643,7 @@ main (int argc, char *argv[])
gboolean disjoint = FALSE;
gboolean premultiplied = TRUE;
gboolean decorated = TRUE;
gboolean fullscreen = FALSE;
unsigned int i;
const char *save_filename = NULL;
@@ -652,6 +653,8 @@ main (int argc, char *argv[])
disjoint = TRUE;
else if (g_str_equal (argv[i], "--undecorated"))
decorated = FALSE;
else if (g_str_equal (argv[i], "--fullscreen"))
fullscreen = TRUE;
else if (g_str_equal (argv[i], "--unpremultiplied"))
premultiplied = FALSE;
else if (g_str_equal (argv[i], "--download-to"))
@@ -687,6 +690,8 @@ main (int argc, char *argv[])
window = gtk_window_new ();
gtk_window_set_decorated (GTK_WINDOW (window), decorated);
if (fullscreen)
gtk_window_fullscreen (GTK_WINDOW (window));
picture = gtk_picture_new_for_paintable (GDK_PAINTABLE (texture));

View File

@@ -0,0 +1,97 @@
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdkdisplayprivate.h>
#include <gdk/gdkglcontextprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
#ifdef HAVE_DMABUF
#include <drm_fourcc.h>
#endif
static void
test_dmabuf_formats_basic (void)
{
GdkDisplay *display;
GdkDmabufFormats *formats;
display = gdk_display_get_default ();
formats = gdk_display_get_dmabuf_formats (display);
#ifdef HAVE_DMABUF
/* We always have basic linear formats */
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) >= 6);
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGRA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ABGR16161616F, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGB888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGR888, DRM_FORMAT_MOD_LINEAR));
#else
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) == 0);
#endif
}
static void
test_dmabuf_formats_builder (void)
{
GdkDmabufFormatsBuilder *builder;
GdkDmabufFormats *formats1, *formats2;
guint32 fourcc;
guint64 modifier;
builder = gdk_dmabuf_formats_builder_new ();
gdk_dmabuf_formats_builder_add_format (builder, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_formats_builder_add_format (builder, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR);
formats1 = gdk_dmabuf_formats_builder_free_to_formats (builder);
g_assert_true (gdk_dmabuf_formats_contains (formats1, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats1, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_false (gdk_dmabuf_formats_contains (formats1, DRM_FORMAT_BGRA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats1) == 2);
gdk_dmabuf_formats_get_format (formats1, 0, &fourcc, &modifier);
g_assert_true (fourcc == DRM_FORMAT_ARGB8888 || fourcc == DRM_FORMAT_RGBA8888);
g_assert_true (modifier == DRM_FORMAT_MOD_LINEAR);
g_assert_false (gdk_dmabuf_formats_equal (formats1, NULL));
builder = gdk_dmabuf_formats_builder_new ();
gdk_dmabuf_formats_builder_add_formats (builder, formats1);
formats2 = gdk_dmabuf_formats_builder_free_to_formats (builder);
g_assert_true (gdk_dmabuf_formats_equal (formats1, formats2));
gdk_dmabuf_formats_unref (formats2);
builder = gdk_dmabuf_formats_builder_new ();
gdk_dmabuf_formats_builder_add_format (builder, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_formats_builder_add_format (builder, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR);
formats2 = gdk_dmabuf_formats_builder_free_to_formats (builder);
g_assert_true (gdk_dmabuf_formats_equal (formats1, formats2));
gdk_dmabuf_formats_unref (formats2);
builder = gdk_dmabuf_formats_builder_new ();
gdk_dmabuf_formats_builder_add_formats (builder, formats1);
gdk_dmabuf_formats_builder_add_format (builder, DRM_FORMAT_RGB888, DRM_FORMAT_MOD_LINEAR);
formats2 = gdk_dmabuf_formats_builder_free_to_formats (builder);
g_assert_false (gdk_dmabuf_formats_equal (formats1, formats2));
gdk_dmabuf_formats_unref (formats2);
gdk_dmabuf_formats_unref (formats1);
}
int
main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/dmabuf/formats/basic", test_dmabuf_formats_basic);
g_test_add_func ("/dmabuf/formats/builder", test_dmabuf_formats_builder);
return g_test_run ();
}

View File

@@ -9,31 +9,6 @@
#include <drm_fourcc.h>
#endif
static void
test_dmabuf_formats (void)
{
GdkDisplay *display;
GdkDmabufFormats *formats;
display = gdk_display_get_default ();
formats = gdk_display_get_dmabuf_formats (display);
#ifdef HAVE_DMABUF
/* We always have basic linear formats */
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) >= 6);
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGRA8888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_ABGR16161616F, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_RGB888, DRM_FORMAT_MOD_LINEAR));
g_assert_true (gdk_dmabuf_formats_contains (formats, DRM_FORMAT_BGR888, DRM_FORMAT_MOD_LINEAR));
#else
g_assert_true (gdk_dmabuf_formats_get_n_formats (formats) == 0);
#endif
}
static cairo_surface_t *
make_surface (int width,
int height)
@@ -290,7 +265,6 @@ main (int argc, char *argv[])
{
gtk_test_init (&argc, &argv, NULL);
g_test_add_func ("/dmabuf/formats", test_dmabuf_formats);
g_test_add_func ("/dmabuf/export", test_dmabuf_export);
g_test_add_func ("/dmabuf/import", test_dmabuf_import);

View File

@@ -63,6 +63,7 @@ internal_tests = [
]
if host_machine.system() != 'windows'
internal_tests += { 'name': 'dmabufformats' }
internal_tests += { 'name': 'dmabuftexture', 'suites': 'failing' }
endif

View File

@@ -465,7 +465,7 @@ if os_linux
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir())
],
protocol: 'exitcode',
suite: 'gsk',
suite: ['gsk', 'offload'],
)
endif
endforeach