From 933a0e5a98166fb8e1e47c1f292959fdd65ffeda Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 14 Apr 2024 18:25:41 -0400 Subject: [PATCH] subsurface: Some api revision and documentation Rename things so they make more sense. The dest/source naming got a bit unclear when we added background into the mix. Now we're going for: source_rect - the texture region to display texture_rect - dimensions of the subsurface showing the texture background_rect - dimensions of the background subsurface bounds - union of texture_rect and background_rect Also use this opportunity to add some api docs. --- gdk/gdksubsurface.c | 143 +++++++++++++++++++++++++--- gdk/gdksubsurfaceprivate.h | 76 ++++++++------- gdk/wayland/gdksubsurface-wayland.c | 46 ++++----- gsk/gskoffload.c | 4 +- gtk/inspector/subsurfaceoverlay.c | 2 +- testsuite/gdk/subsurface.c | 6 +- 6 files changed, 198 insertions(+), 79 deletions(-) diff --git a/gdk/gdksubsurface.c b/gdk/gdksubsurface.c index 9f124639d2..128a7f26d7 100644 --- a/gdk/gdksubsurface.c +++ b/gdk/gdksubsurface.c @@ -48,6 +48,14 @@ gdk_subsurface_class_init (GdkSubsurfaceClass *class) object_class->finalize = gdk_subsurface_finalize; } +/*< private > + * gdk_subsurface_get_parent: + * @subsurface: a `GdkSubsurface` + * + * Returns the parent surface of @subsurface. + * + * Returns: the parent surface + */ GdkSurface * gdk_subsurface_get_parent (GdkSubsurface *subsurface) { @@ -108,6 +116,29 @@ insert_subsurface (GdkSubsurface *subsurface, } } +/*< private > + * gdk_subsurface_attach: + * @subsurface: the `GdkSubsurface` + * @texture: the texture to attach. This typically has to be a `GdkDmabufTexture` + * @source: the source rectangle (i.e. the subset of the texture) to display + * @dest: the dest rectangle, in application pixels, relative to the parent surface. + * It must be integral in application and device pixels, or attaching will fail + * @transform: the transform to apply to the texture contents before displaying + * @background: (nullable): the background rectangle, in application pixels relative + * to the parent surface. This tells GDK to put a black background of this + * size below the subsurface. It must be integral in application and device pixels, + * or attaching will fail + * @above: whether the subsurface should be above its sibling + * @sibling: (nullable): the sibling subsurface to stack relative to, or `NULL` to + * stack relative to the parent surface + * + * Attaches content to a subsurface. + * + * This function takes all the necessary arguments to determine the subsurface + * configuration, including its position, size, content, background and stacking. + * + * Returns: `TRUE` if the attaching succeeded + */ gboolean gdk_subsurface_attach (GdkSubsurface *subsurface, GdkTexture *texture, @@ -167,6 +198,14 @@ gdk_subsurface_attach (GdkSubsurface *subsurface, sibling); } +/*< private > + * gdk_subsurface_detach: + * @subsurface: a `GdkSubsurface` + * + * Hides the subsurface. + * + * To show it again, you need to call gdk_subsurface_attach(). + */ void gdk_subsurface_detach (GdkSubsurface *subsurface) { @@ -177,6 +216,14 @@ gdk_subsurface_detach (GdkSubsurface *subsurface) GDK_SUBSURFACE_GET_CLASS (subsurface)->detach (subsurface); } +/*< private > + * gdk_subsurface_get_texture: + * @subsurface: a `GdkSubsurface` + * + * Gets the texture that is currently displayed by the subsurface. + * + * Returns: (nullable): the texture that is displayed + */ GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurface) { @@ -185,26 +232,52 @@ gdk_subsurface_get_texture (GdkSubsurface *subsurface) return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_texture (subsurface); } +/*< private > + * gdk_subsurface_get_source_rect: + * @subsurface: a `GdkSubsurface` + * @rect: (out caller-allocates): return location for the rectangle + * + * Returns the source rect that was specified in the most recent + * gdk_subsurface_attach() call for @subsurface. + */ void -gdk_subsurface_get_source (GdkSubsurface *subsurface, - graphene_rect_t *source) +gdk_subsurface_get_source_rect (GdkSubsurface *subsurface, + graphene_rect_t *rect) { g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); - g_return_if_fail (source != NULL); + g_return_if_fail (rect != NULL); - GDK_SUBSURFACE_GET_CLASS (subsurface)->get_source (subsurface, source); + GDK_SUBSURFACE_GET_CLASS (subsurface)->get_source_rect (subsurface, rect); } +/*< private > + * gdk_subsurface_get_texture_rect: + * @subsurface: a `GdkSubsurface` + * @rect: (out caller-allocates): return location for the rectangle + * + * Returns the texture rect that was specified in the most recent + * gdk_subsurface_attach() call for @subsurface. + */ void -gdk_subsurface_get_dest (GdkSubsurface *subsurface, - graphene_rect_t *dest) +gdk_subsurface_get_texture_rect (GdkSubsurface *subsurface, + graphene_rect_t *rect) { g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); - g_return_if_fail (dest != NULL); + g_return_if_fail (rect != NULL); - GDK_SUBSURFACE_GET_CLASS (subsurface)->get_dest (subsurface, dest); + GDK_SUBSURFACE_GET_CLASS (subsurface)->get_texture_rect (subsurface, rect); } +/*< private > + * gdk_subsurface_is_above_parent: + * @subsurface: a `GdkSubsurface` + * + * Returns whether the subsurface is above the parent surface + * or below. Note that a subsurface can be above its parent + * surface, and still be covered by sibling subsurfaces. + * + * Returns: `TRUE` if @subsurface is above its parent + */ gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface) { @@ -213,6 +286,15 @@ gdk_subsurface_is_above_parent (GdkSubsurface *subsurface) return subsurface->above_parent; } +/*< private > + * gdk_subsurface_get_transform: + * @subsurface: a `GdkSubsurface` + * + * Returns the transform that was specified in the most recent call to + * gdk_subsurface_attach() call for @subsurface. + * + * Returns: the transform + */ GdkTextureTransform gdk_subsurface_get_transform (GdkSubsurface *subsurface) { @@ -221,12 +303,45 @@ gdk_subsurface_get_transform (GdkSubsurface *subsurface) return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface); } -void -gdk_subsurface_get_background (GdkSubsurface *subsurface, - graphene_rect_t *background) +/*< private > + * gdk_subsurface_get_background_rect: + * @subsurface: a `GdkSubsurface` + * @rect: (out caller-allocates): return location for the rectangle + * + * Obtains the background rect that was specified in the most recent + * gdk_subsurface_attach() call for @subsurface. + * + * Returns: `TRUE` if @subsurface has a background + */ +gboolean +gdk_subsurface_get_background_rect (GdkSubsurface *subsurface, + graphene_rect_t *rect) { - g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); - g_return_if_fail (background != NULL); + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE); + g_return_val_if_fail (rect != NULL, FALSE); - GDK_SUBSURFACE_GET_CLASS (subsurface)->get_background (subsurface, background); + return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_background_rect (subsurface, rect); +} + +/*< private > + * gdk_subsurface_get_bounds: + * @subsurface: a `GdkSubsurface` + * @bounds: (out caller-allocates): return location for the bounds + * + * Returns the bounds of the subsurface. + * + * The bounds are the union of the texture and background rects. + */ +void +gdk_subsurface_get_bounds (GdkSubsurface *subsurface, + graphene_rect_t *bounds) +{ + graphene_rect_t background; + + g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); + g_return_if_fail (bounds != NULL); + + gdk_subsurface_get_texture_rect (subsurface, bounds); + if (gdk_subsurface_get_background_rect (subsurface, &background)) + graphene_rect_union (bounds, &background, bounds); } diff --git a/gdk/gdksubsurfaceprivate.h b/gdk/gdksubsurfaceprivate.h index f7efc5add5..c588676e6c 100644 --- a/gdk/gdksubsurfaceprivate.h +++ b/gdk/gdksubsurfaceprivate.h @@ -62,49 +62,51 @@ struct _GdkSubsurfaceClass { GObjectClass parent_class; - gboolean (* attach) (GdkSubsurface *subsurface, - GdkTexture *texture, - const graphene_rect_t *source, - const graphene_rect_t *dest, - GdkTextureTransform transform, - const graphene_rect_t *bg, - gboolean above, - GdkSubsurface *sibling); - void (* detach) (GdkSubsurface *subsurface); - GdkTexture * (* get_texture) (GdkSubsurface *subsurface); - void (* get_source) (GdkSubsurface *subsurface, - graphene_rect_t *source); - void (* get_dest) (GdkSubsurface *subsurface, - graphene_rect_t *dest); + gboolean (* attach) (GdkSubsurface *subsurface, + GdkTexture *texture, + const graphene_rect_t *source, + const graphene_rect_t *dest, + GdkTextureTransform transform, + const graphene_rect_t *bg, + gboolean above, + GdkSubsurface *sibling); + void (* detach) (GdkSubsurface *subsurface); + GdkTexture * (* get_texture) (GdkSubsurface *subsurface); + void (* get_source_rect) (GdkSubsurface *subsurface, + graphene_rect_t *rect); + void (* get_texture_rect) (GdkSubsurface *subsurface, + graphene_rect_t *rect); GdkTextureTransform - (* get_transform) (GdkSubsurface *subsurface); - void (* get_background) (GdkSubsurface *subsurface, - graphene_rect_t *background); + (* get_transform) (GdkSubsurface *subsurface); + gboolean (* get_background_rect) (GdkSubsurface *subsurface, + graphene_rect_t *rect); }; -GType gdk_subsurface_get_type (void) G_GNUC_CONST; +GType gdk_subsurface_get_type (void) G_GNUC_CONST; -GdkSurface * gdk_subsurface_get_parent (GdkSubsurface *subsurface); +GdkSurface * gdk_subsurface_get_parent (GdkSubsurface *subsurface); -gboolean gdk_subsurface_attach (GdkSubsurface *subsurface, - GdkTexture *texture, - const graphene_rect_t *source, - const graphene_rect_t *dest, - GdkTextureTransform transform, - const graphene_rect_t *background, - gboolean above, - GdkSubsurface *sibling); -void gdk_subsurface_detach (GdkSubsurface *subsurface); -GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurface); -void gdk_subsurface_get_source (GdkSubsurface *subsurface, - graphene_rect_t *source); -void gdk_subsurface_get_dest (GdkSubsurface *subsurface, - graphene_rect_t *dest); -gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface); +gboolean gdk_subsurface_attach (GdkSubsurface *subsurface, + GdkTexture *texture, + const graphene_rect_t *source, + const graphene_rect_t *dest, + GdkTextureTransform transform, + const graphene_rect_t *background, + gboolean above, + GdkSubsurface *sibling); +void gdk_subsurface_detach (GdkSubsurface *subsurface); +GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurface); +void gdk_subsurface_get_source_rect (GdkSubsurface *subsurface, + graphene_rect_t *rect); +void gdk_subsurface_get_texture_rect (GdkSubsurface *subsurface, + graphene_rect_t *rect); +gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface); GdkTextureTransform - gdk_subsurface_get_transform (GdkSubsurface *subsurface); -void gdk_subsurface_get_background (GdkSubsurface *subsurface, - graphene_rect_t *background); + gdk_subsurface_get_transform (GdkSubsurface *subsurface); +gboolean gdk_subsurface_get_background_rect (GdkSubsurface *subsurface, + graphene_rect_t *rect); +void gdk_subsurface_get_bounds (GdkSubsurface *subsurface, + graphene_rect_t *bounds); G_END_DECLS diff --git a/gdk/wayland/gdksubsurface-wayland.c b/gdk/wayland/gdksubsurface-wayland.c index c27643f781..8d05e06995 100644 --- a/gdk/wayland/gdksubsurface-wayland.c +++ b/gdk/wayland/gdksubsurface-wayland.c @@ -601,27 +601,27 @@ gdk_wayland_subsurface_get_texture (GdkSubsurface *sub) } static void -gdk_wayland_subsurface_get_dest (GdkSubsurface *sub, - graphene_rect_t *dest) +gdk_wayland_subsurface_get_texture_rect (GdkSubsurface *sub, + graphene_rect_t *rect) { GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub); - dest->origin.x = self->dest.x; - dest->origin.y = self->dest.y; - dest->size.width = self->dest.width; - dest->size.height = self->dest.height; + rect->origin.x = self->dest.x; + rect->origin.y = self->dest.y; + rect->size.width = self->dest.width; + rect->size.height = self->dest.height; } static void -gdk_wayland_subsurface_get_source (GdkSubsurface *sub, - graphene_rect_t *source) +gdk_wayland_subsurface_get_source_rect (GdkSubsurface *sub, + graphene_rect_t *rect) { GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub); - source->origin.x = self->source.origin.x; - source->origin.y = self->source.origin.y; - source->size.width = self->source.size.width; - source->size.height = self->source.size.height; + rect->origin.x = self->source.origin.x; + rect->origin.y = self->source.origin.y; + rect->size.width = self->source.size.width; + rect->size.height = self->source.size.height; } static GdkTextureTransform @@ -632,16 +632,18 @@ gdk_wayland_subsurface_get_transform (GdkSubsurface *sub) return wl_output_transform_to_gdk (self->transform); } -static void -gdk_wayland_subsurface_get_background (GdkSubsurface *sub, - graphene_rect_t *background) +static gboolean +gdk_wayland_subsurface_get_background_rect (GdkSubsurface *sub, + graphene_rect_t *rect) { GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub); - background->origin.x = self->bg_rect.x; - background->origin.y = self->bg_rect.y; - background->size.width = self->bg_rect.width; - background->size.height = self->bg_rect.height; + rect->origin.x = self->bg_rect.x; + rect->origin.y = self->bg_rect.y; + rect->size.width = self->bg_rect.width; + rect->size.height = self->bg_rect.height; + + return rect->size.width > 0 && rect->size.height > 0; } static void @@ -655,10 +657,10 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class) subsurface_class->attach = gdk_wayland_subsurface_attach; subsurface_class->detach = gdk_wayland_subsurface_detach; subsurface_class->get_texture = gdk_wayland_subsurface_get_texture; - subsurface_class->get_source = gdk_wayland_subsurface_get_source; - subsurface_class->get_dest = gdk_wayland_subsurface_get_dest; + subsurface_class->get_source_rect = gdk_wayland_subsurface_get_source_rect; + subsurface_class->get_texture_rect = gdk_wayland_subsurface_get_texture_rect; subsurface_class->get_transform = gdk_wayland_subsurface_get_transform; - subsurface_class->get_background = gdk_wayland_subsurface_get_background; + subsurface_class->get_background_rect = gdk_wayland_subsurface_get_background_rect; }; static void diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index 55fd14e7b4..226ab7d85c 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -725,8 +725,8 @@ gsk_offload_new (GdkSurface *surface, graphene_rect_t old_dest; graphene_rect_t old_background; - gdk_subsurface_get_dest (info->subsurface, &old_dest); - gdk_subsurface_get_background (info->subsurface, &old_background); + gdk_subsurface_get_texture_rect (info->subsurface, &old_dest); + gdk_subsurface_get_background_rect (info->subsurface, &old_background); if (info->can_offload) { diff --git a/gtk/inspector/subsurfaceoverlay.c b/gtk/inspector/subsurfaceoverlay.c index 8e5a203365..7701ebcff3 100644 --- a/gtk/inspector/subsurfaceoverlay.c +++ b/gtk/inspector/subsurfaceoverlay.c @@ -50,7 +50,7 @@ gtk_subsurface_overlay_snapshot (GtkInspectorOverlay *overlay, else gdk_rgba_parse (&color, "magenta"); - gdk_subsurface_get_dest (subsurface, &dest); + gdk_subsurface_get_texture_rect (subsurface, &dest); /* Use 4 color nodes since a border node overlaps and prevents * the subsurface from being raised. diff --git a/testsuite/gdk/subsurface.c b/testsuite/gdk/subsurface.c index 383b936029..3a63fe44b9 100644 --- a/testsuite/gdk/subsurface.c +++ b/testsuite/gdk/subsurface.c @@ -47,11 +47,11 @@ test_subsurface_basics (void) g_assert_true (gdk_subsurface_get_texture (sub) == texture); g_assert_true (gdk_subsurface_is_above_parent (sub)); g_assert_true (gdk_subsurface_get_transform (sub) == GDK_TEXTURE_TRANSFORM_90); - gdk_subsurface_get_source (sub, &rect); + gdk_subsurface_get_source_rect (sub, &rect); g_assert_true (graphene_rect_equal (&rect, &TEXTURE_RECT (texture))); - gdk_subsurface_get_dest (sub, &rect); + gdk_subsurface_get_texture_rect (sub, &rect); g_assert_true (graphene_rect_equal (&rect, &GRAPHENE_RECT_INIT (0, 0, 10, 10))); - gdk_subsurface_get_background (sub, &rect); + gdk_subsurface_get_background_rect (sub, &rect); g_assert_true (graphene_rect_equal (&rect, &GRAPHENE_RECT_INIT (0, 0, 20, 20))); g_object_unref (sub);