surface: Add a dmabuf-formats property
Add a property to GdkSurface that carries the effective dmabuf formats for the surface. This will be either the formats according to the surfaces own Wayland dmabuf feedback, or the formats of the topmost subsurface.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "gdksubsurfaceprivate.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkdebugprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GdkSubsurface, gdk_subsurface, G_TYPE_OBJECT)
|
||||
|
||||
@@ -35,6 +36,7 @@ gdk_subsurface_finalize (GObject *object)
|
||||
|
||||
g_ptr_array_remove (subsurface->parent->subsurfaces, subsurface);
|
||||
g_clear_object (&subsurface->parent);
|
||||
g_clear_pointer (&subsurface->dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_subsurface_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -107,6 +109,28 @@ insert_subsurface (GdkSubsurface *subsurface,
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_topmost_subsurface (GdkSubsurface *subsurface)
|
||||
{
|
||||
GdkSurface *parent = subsurface->parent;
|
||||
|
||||
return !subsurface->sibling_above && parent->subsurfaces_below != subsurface;
|
||||
}
|
||||
|
||||
static inline GdkSubsurface *
|
||||
find_topmost_subsurface (GdkSurface *surface)
|
||||
{
|
||||
GdkSubsurface *top = surface->subsurfaces_above;
|
||||
|
||||
if (top)
|
||||
{
|
||||
while (top->sibling_above)
|
||||
top = top->sibling_above;
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
@@ -115,6 +139,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
GdkSurface *parent = subsurface->parent;
|
||||
gboolean was_topmost, is_topmost;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
@@ -125,6 +150,8 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
|
||||
remove_subsurface (subsurface);
|
||||
|
||||
was_topmost = is_topmost_subsurface (subsurface);
|
||||
|
||||
if (sibling)
|
||||
{
|
||||
insert_subsurface (subsurface, above, sibling);
|
||||
@@ -148,16 +175,54 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
}
|
||||
}
|
||||
|
||||
is_topmost = is_topmost_subsurface (subsurface);
|
||||
|
||||
if (!was_topmost && is_topmost)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (parent->display, DMABUF, "Using formats of topmost subsurface %p", subsurface);
|
||||
gdk_surface_set_effective_dmabuf_formats (parent, subsurface->dmabuf_formats);
|
||||
}
|
||||
else if (was_topmost && !is_topmost)
|
||||
{
|
||||
GdkSubsurface *top = find_topmost_subsurface (parent);
|
||||
|
||||
if (top)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (parent->display, DMABUF, "Using formats of topmost subsurface %p", top);
|
||||
gdk_surface_set_effective_dmabuf_formats (parent, top->dmabuf_formats);
|
||||
}
|
||||
else
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (parent->display, DMABUF, "Using formats of main surface");
|
||||
gdk_surface_set_effective_dmabuf_formats (parent, parent->dmabuf_formats);
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, rect, above, sibling);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_subsurface_detach (GdkSubsurface *subsurface)
|
||||
{
|
||||
gboolean was_topmost;
|
||||
|
||||
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
|
||||
|
||||
was_topmost = is_topmost_subsurface (subsurface);
|
||||
|
||||
remove_subsurface (subsurface);
|
||||
|
||||
if (was_topmost)
|
||||
{
|
||||
GdkSurface *parent = subsurface->parent;
|
||||
GdkSubsurface *top = find_topmost_subsurface (parent);
|
||||
|
||||
if (top)
|
||||
gdk_surface_set_effective_dmabuf_formats (parent, top->dmabuf_formats);
|
||||
else
|
||||
gdk_surface_set_effective_dmabuf_formats (parent, parent->dmabuf_formats);
|
||||
}
|
||||
|
||||
GDK_SUBSURFACE_GET_CLASS (subsurface)->detach (subsurface);
|
||||
}
|
||||
|
||||
@@ -186,3 +251,17 @@ gdk_subsurface_is_above_parent (GdkSubsurface *subsurface)
|
||||
|
||||
return subsurface->above_parent;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_subsurface_set_dmabuf_formats (GdkSubsurface *subsurface,
|
||||
GdkDmabufFormats *formats)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
|
||||
g_return_if_fail (formats != NULL);
|
||||
|
||||
g_clear_pointer (&subsurface->dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
subsurface->dmabuf_formats = gdk_dmabuf_formats_ref (formats);
|
||||
|
||||
if (is_topmost_subsurface (subsurface))
|
||||
gdk_surface_set_effective_dmabuf_formats (subsurface->parent, formats);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdkdmabufformats.h"
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -45,6 +46,8 @@ struct _GdkSubsurface
|
||||
gboolean above_parent;
|
||||
GdkSubsurface *sibling_above;
|
||||
GdkSubsurface *sibling_below;
|
||||
|
||||
GdkDmabufFormats *dmabuf_formats;
|
||||
};
|
||||
|
||||
|
||||
@@ -77,6 +80,8 @@ void gdk_subsurface_get_rect (GdkSubsurface *subsurfac
|
||||
graphene_rect_t *rect);
|
||||
gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface);
|
||||
|
||||
void gdk_subsurface_set_dmabuf_formats (GdkSubsurface *subsurface,
|
||||
GdkDmabufFormats *formats);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ enum {
|
||||
PROP_0,
|
||||
PROP_CURSOR,
|
||||
PROP_DISPLAY,
|
||||
PROP_DMABUF_FORMATS,
|
||||
PROP_FRAME_CLOCK,
|
||||
PROP_MAPPED,
|
||||
PROP_WIDTH,
|
||||
@@ -548,6 +549,18 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkSurface:dmabuf-formats: (attributes org.gtk.Property.get=gdk_surface_get_dmabuf_formats)
|
||||
*
|
||||
* The dmabuf formats that can be used with this surface.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
properties[PROP_DMABUF_FORMATS] =
|
||||
g_param_spec_boxed ("dmabuf-formats", NULL, NULL,
|
||||
GDK_TYPE_DMABUF_FORMATS,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkSurface:frame-clock: (attributes org.gtk.Property.get=gdk_surface_get_frame_clock)
|
||||
*
|
||||
@@ -773,6 +786,9 @@ gdk_surface_finalize (GObject *object)
|
||||
|
||||
g_ptr_array_unref (surface->subsurfaces);
|
||||
|
||||
g_clear_pointer (&surface->dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
g_clear_pointer (&surface->effective_dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_surface_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -827,6 +843,10 @@ gdk_surface_get_property (GObject *object,
|
||||
g_value_set_object (value, surface->display);
|
||||
break;
|
||||
|
||||
case PROP_DMABUF_FORMATS:
|
||||
g_value_set_boxed (value, surface->effective_dmabuf_formats);
|
||||
break;
|
||||
|
||||
case PROP_FRAME_CLOCK:
|
||||
g_value_set_object (value, surface->frame_clock);
|
||||
break;
|
||||
@@ -3076,3 +3096,70 @@ gdk_surface_get_subsurface (GdkSurface *surface,
|
||||
{
|
||||
return g_ptr_array_index (surface->subsurfaces, idx);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_surface_set_dmabuf_formats (GdkSurface *surface,
|
||||
GdkDmabufFormats *formats)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
g_return_if_fail (formats != NULL);
|
||||
|
||||
g_clear_pointer (&surface->dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
surface->dmabuf_formats = gdk_dmabuf_formats_ref (formats);
|
||||
|
||||
if (surface->subsurfaces_above == NULL)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (surface->display, DMABUF, "Using main surface formats");
|
||||
gdk_surface_set_effective_dmabuf_formats (surface, formats);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gdk_surface_set_effective_dmabuf_formats (GdkSurface *surface,
|
||||
GdkDmabufFormats *formats)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_SURFACE (surface));
|
||||
|
||||
if (!formats)
|
||||
return;
|
||||
|
||||
if (gdk_dmabuf_formats_equal (surface->effective_dmabuf_formats, formats))
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (surface->display, DMABUF, "Formats unchanged");
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_pointer (&surface->effective_dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
surface->effective_dmabuf_formats = gdk_dmabuf_formats_ref (formats);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_DMABUF_FORMATS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_get_dmabuf_formats:
|
||||
* @surface: a `GdkSurface`
|
||||
*
|
||||
* Returns the dma-buf formats that are supported on this surface.
|
||||
*
|
||||
* What formats can be used may depend on the geometry and stacking
|
||||
* order of the surface, and can change over time.
|
||||
*
|
||||
* The formats returned by this function can be used for negotiating
|
||||
* buffer formats with producers such as v4l, pipewire or GStreamer.
|
||||
*
|
||||
* To learn more about dma-bufs, see [class@Gdk.DmabufTextureBuilder].
|
||||
*
|
||||
* Returns: (transfer none): a `GdkDmabufFormats` object
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
GdkDmabufFormats *
|
||||
gdk_surface_get_dmabuf_formats (GdkSurface *surface)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
|
||||
if (surface->effective_dmabuf_formats)
|
||||
return surface->effective_dmabuf_formats;
|
||||
else
|
||||
return gdk_display_get_dmabuf_formats (surface->display);
|
||||
}
|
||||
|
||||
@@ -139,6 +139,9 @@ GdkVulkanContext *
|
||||
gdk_surface_create_vulkan_context(GdkSurface *surface,
|
||||
GError **error);
|
||||
|
||||
GdkDmabufFormats *
|
||||
gdk_surface_get_dmabuf_formats (GdkSurface *surface);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GdkSurface, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -105,6 +105,9 @@ struct _GdkSurface
|
||||
*/
|
||||
GdkSubsurface *subsurfaces_above;
|
||||
GdkSubsurface *subsurfaces_below;
|
||||
|
||||
GdkDmabufFormats *dmabuf_formats;
|
||||
GdkDmabufFormats *effective_dmabuf_formats;
|
||||
};
|
||||
|
||||
struct _GdkSurfaceClass
|
||||
@@ -355,4 +358,10 @@ gsize gdk_surface_get_n_subsurfaces (GdkSurface *surface);
|
||||
GdkSubsurface * gdk_surface_get_subsurface (GdkSurface *surface,
|
||||
gsize idx);
|
||||
|
||||
void gdk_surface_set_dmabuf_formats (GdkSurface *surface,
|
||||
GdkDmabufFormats *formats);
|
||||
|
||||
void gdk_surface_set_effective_dmabuf_formats (GdkSurface *surface,
|
||||
GdkDmabufFormats *formats);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
Reference in New Issue
Block a user