subsurface: Add transforms

Allow to specify a D₂ transform when attaching a texture to a
subsurface, to handle flipped and rotated content. The Wayland
implementation handles these transforms by setting a buffer
transform on the subsurface.

All callers have been updated to pass GDK_TEXTURE_TRANSFORM_NORMAL.
This commit is contained in:
Matthias Clasen 2024-04-06 20:06:25 +02:00
parent d83ad6b505
commit 72e9f30937
6 changed files with 62 additions and 6 deletions

View File

@ -113,6 +113,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
gboolean above,
GdkSubsurface *sibling)
{
@ -155,7 +156,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
}
}
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, above, sibling);
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, transform, above, sibling);
}
void
@ -203,3 +204,12 @@ gdk_subsurface_is_above_parent (GdkSubsurface *subsurface)
return subsurface->above_parent;
}
GdkTextureTransform
gdk_subsurface_get_transform (GdkSubsurface *subsurface)
{
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), GDK_TEXTURE_TRANSFORM_NORMAL);
return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface);
}

View File

@ -47,6 +47,16 @@ struct _GdkSubsurface
GdkSubsurface *sibling_below;
};
typedef enum {
GDK_TEXTURE_TRANSFORM_NORMAL,
GDK_TEXTURE_TRANSFORM_90,
GDK_TEXTURE_TRANSFORM_180,
GDK_TEXTURE_TRANSFORM_270,
GDK_TEXTURE_TRANSFORM_FLIPPED,
GDK_TEXTURE_TRANSFORM_FLIPPED_90,
GDK_TEXTURE_TRANSFORM_FLIPPED_180,
GDK_TEXTURE_TRANSFORM_FLIPPED_270,
} GdkTextureTransform;
struct _GdkSubsurfaceClass
{
@ -56,6 +66,7 @@ struct _GdkSubsurfaceClass
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
gboolean above,
GdkSubsurface *sibling);
void (* detach) (GdkSubsurface *subsurface);
@ -64,15 +75,19 @@ struct _GdkSubsurfaceClass
graphene_rect_t *source);
void (* get_dest) (GdkSubsurface *subsurface,
graphene_rect_t *dest);
GdkTextureTransform
(* get_transform) (GdkSubsurface *subsurface);
};
GType gdk_subsurface_get_type (void) G_GNUC_CONST;
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,
gboolean above,
GdkSubsurface *sibling);
void gdk_subsurface_detach (GdkSubsurface *subsurface);
@ -82,6 +97,8 @@ void gdk_subsurface_get_source (GdkSubsurface *subsurfac
void gdk_subsurface_get_dest (GdkSubsurface *subsurface,
graphene_rect_t *dest);
gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface);
GdkTextureTransform
gdk_subsurface_get_transform (GdkSubsurface *subsurface);
G_END_DECLS

View File

@ -2,6 +2,7 @@
#include "gdksubsurfaceprivate.h"
#include "wayland-client-protocol.h"
typedef struct _GdkWaylandSubsurface GdkWaylandSubsurface;
typedef struct _GdkWaylandSubsurfaceClass GdkWaylandSubsurfaceClass;
@ -23,6 +24,7 @@ struct _GdkWaylandSubsurface
GdkTexture *texture;
cairo_rectangle_int_t dest;
graphene_rect_t source;
enum wl_output_transform transform;
struct wl_region *opaque_region;

View File

@ -149,11 +149,24 @@ get_wl_buffer (GdkWaylandSubsurface *self,
return buffer;
}
static inline enum wl_output_transform
gdk_texture_transform_to_wl (GdkTextureTransform transform)
{
return (enum wl_output_transform) transform;
}
static inline GdkTextureTransform
wl_output_transform_to_gdk (enum wl_output_transform transform)
{
return (GdkTextureTransform) transform;
}
static gboolean
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
gboolean above,
GdkSubsurface *sibling)
{
@ -188,6 +201,8 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
self->source.size.width = source->size.width;
self->source.size.height = source->size.height;
self->transform = gdk_texture_transform_to_wl (transform);
scale = gdk_fractional_scale_to_double (&parent->scale);
device_rect.origin.x = dest->origin.x * scale;
@ -302,6 +317,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
if (result)
{
wl_surface_set_buffer_transform (self->surface, self->transform);
wl_subsurface_set_position (self->subsurface, self->dest.x, self->dest.y);
wp_viewport_set_destination (self->viewport, self->dest.width, self->dest.height);
wp_viewport_set_source (self->viewport,
@ -406,6 +422,14 @@ gdk_wayland_subsurface_get_source (GdkSubsurface *sub,
source->size.height = self->source.size.height;
}
static GdkTextureTransform
gdk_wayland_subsurface_get_transform (GdkSubsurface *sub)
{
GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub);
return wl_output_transform_to_gdk (self->transform);
}
static void
gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
{
@ -419,6 +443,7 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
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_transform = gdk_wayland_subsurface_get_transform;
};
static void

View File

@ -653,12 +653,14 @@ gsk_offload_new (GdkSurface *surface,
info->texture,
&info->source,
&info->dest,
GDK_TEXTURE_TRANSFORM_NORMAL,
TRUE, NULL);
else
info->is_offloaded = gdk_subsurface_attach (info->subsurface,
info->texture,
&info->source,
&info->dest,
GDK_TEXTURE_TRANSFORM_NORMAL,
info->place_above != NULL,
info->place_above);
}

View File

@ -42,9 +42,9 @@ test_subsurface_stacking (void)
texture = gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/media-eject.png");
gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), TRUE, NULL);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), TRUE, NULL);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), TRUE, NULL);
gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL);
g_assert_true (surface->subsurfaces_above == sub2);
g_assert_true (sub2->sibling_below == NULL);
@ -67,7 +67,7 @@ test_subsurface_stacking (void)
g_assert_true (sub0->sibling_above == NULL);
g_assert_true (sub0->above_parent);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), FALSE, NULL);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, NULL);
g_assert_true (surface->subsurfaces_above == sub0);
g_assert_true (sub0->sibling_below == NULL);
@ -79,7 +79,7 @@ test_subsurface_stacking (void)
g_assert_true (sub2->sibling_above == NULL);
g_assert_false (sub2->above_parent);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), TRUE, sub2);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, sub2);
g_assert_true (surface->subsurfaces_below == sub1);
g_assert_true (sub1->sibling_above == NULL);