Compare commits

...

1 Commits

Author SHA1 Message Date
Matthias Clasen
d7f6e0804b wip: Play with rotations
Experiments with rotations for offloaded dmabufs.

The way this currently works is by analyzing transforms
between the subsurface node and the texture node.

There is a table that maps the 2D transform components of
the accumulated transform to the texture transform enum that
needs completing.
2024-04-08 06:35:06 -04:00
10 changed files with 185 additions and 56 deletions

View File

@@ -204,6 +204,24 @@ gtk_shadertoy_finalize (GObject *obj)
G_OBJECT_CLASS (gtk_shadertoy_parent_class)->finalize (obj);
}
static void
gtk_shadertoy_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
float factor;
factor = MIN (gtk_widget_get_width (widget) / (float) gtk_widget_get_height (widget),
gtk_widget_get_height (widget) / (float) gtk_widget_get_width (widget));
gtk_snapshot_save (snapshot);
//gtk_snapshot_scale (snapshot, factor, factor);
gtk_snapshot_rotate (snapshot, 90);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, //-gtk_widget_get_width (widget),
-gtk_widget_get_height (widget)));
GTK_WIDGET_CLASS (gtk_shadertoy_parent_class)->snapshot (widget, snapshot);
gtk_snapshot_restore (snapshot);
}
static void
gtk_shadertoy_class_init (GtkShadertoyClass *klass)
{
@@ -213,6 +231,8 @@ gtk_shadertoy_class_init (GtkShadertoyClass *klass)
GTK_WIDGET_CLASS (klass)->realize = gtk_shadertoy_realize;
GTK_WIDGET_CLASS (klass)->unrealize = gtk_shadertoy_unrealize;
GTK_WIDGET_CLASS (klass)->snapshot = gtk_shadertoy_snapshot;
G_OBJECT_CLASS (klass)->finalize = gtk_shadertoy_finalize;
}

View File

@@ -122,6 +122,7 @@ create_shadertoy_window (GtkWidget *do_widget)
shadertoy = new_shadertoy ("/shadertoy/alienplanet.glsl");
gtk_aspect_frame_set_child (GTK_ASPECT_FRAME (aspect), gtk_graphics_offload_new (shadertoy));
#if 0
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 250);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
@@ -145,6 +146,7 @@ create_shadertoy_window (GtkWidget *do_widget)
gtk_text_buffer_set_text (textbuffer,
gtk_shadertoy_get_image_shader (GTK_SHADERTOY (shadertoy)),
-1);
#endif
centerbox = gtk_center_box_new ();
gtk_box_append (GTK_BOX (box), centerbox);

View File

@@ -543,4 +543,15 @@ typedef enum {
GDK_MEMORY_N_FORMATS
} GdkMemoryFormat;
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;
G_END_DECLS

View File

@@ -54,6 +54,7 @@ enum {
PROP_HEIGHT_MM,
PROP_REFRESH_RATE,
PROP_SUBPIXEL_LAYOUT,
PROP_TRANSFORM,
PROP_VALID,
LAST_PROP
};
@@ -75,6 +76,7 @@ gdk_monitor_init (GdkMonitor *monitor)
monitor->scale_factor = 1;
monitor->scale = 1.0;
monitor->scale_set = FALSE;
monitor->transform = GDK_TEXTURE_TRANSFORM_NORMAL,
monitor->valid = TRUE;
}
@@ -136,6 +138,10 @@ gdk_monitor_get_property (GObject *object,
g_value_set_enum (value, monitor->subpixel_layout);
break;
case PROP_TRANSFORM:
g_value_set_enum (value, monitor->transform);
break;
case PROP_VALID:
g_value_set_boolean (value, monitor->valid);
break;
@@ -318,6 +324,17 @@ gdk_monitor_class_init (GdkMonitorClass *class)
GDK_SUBPIXEL_LAYOUT_UNKNOWN,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GdkMonitor:transform: (attributes org.gtk.Property.get=gdk_monitor_get_transform)
*
* The transform that is applied when showing content on the monitor.
*/
props[PROP_TRANSFORM] =
g_param_spec_enum ("transform", NULL, NULL,
GDK_TYPE_TEXTURE_TRANSFORM,
GDK_TEXTURE_TRANSFORM_NORMAL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GdkMonitor:valid: (attributes org.gtk.Property.get=gdk_monitor_is_valid)
*
@@ -744,3 +761,21 @@ gdk_monitor_set_description (GdkMonitor *monitor,
g_object_notify_by_pspec (G_OBJECT (monitor), props[PROP_DESCRIPTION]);
}
GdkTextureTransform
gdk_monitor_get_transform (GdkMonitor *monitor)
{
g_return_val_if_fail (GDK_IS_MONITOR (monitor), GDK_TEXTURE_TRANSFORM_NORMAL);
return monitor->transform;
}
void
gdk_monitor_set_transform (GdkMonitor *monitor,
GdkTextureTransform transform)
{
if (monitor->transform == transform)
return;
monitor->transform = transform;
g_object_notify_by_pspec (G_OBJECT (monitor), props[PROP_TRANSFORM]);
}

View File

@@ -88,6 +88,10 @@ gboolean gdk_monitor_is_valid (GdkMonitor *monitor);
GDK_AVAILABLE_IN_4_10
const char * gdk_monitor_get_description (GdkMonitor *monitor);
GDK_AVAILABLE_IN_4_16
GdkTextureTransform
gdk_monitor_get_transform (GdkMonitor *monitor);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMonitor, g_object_unref)
G_END_DECLS

View File

@@ -46,6 +46,7 @@ struct _GdkMonitor {
gboolean valid;
double scale;
gboolean scale_set;
GdkTextureTransform transform;
};
struct _GdkMonitorClass {
@@ -76,6 +77,8 @@ void gdk_monitor_set_subpixel_layout (GdkMonitor *monitor,
void gdk_monitor_invalidate (GdkMonitor *monitor);
void gdk_monitor_set_description (GdkMonitor *monitor,
const char *description);
void gdk_monitor_set_transform (GdkMonitor *monitor,
GdkTextureTransform transform);
G_END_DECLS

View File

@@ -121,11 +121,6 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
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 (source != NULL &&
gsk_rect_contains_rect (&GRAPHENE_RECT_INIT (0, 0,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture)),
source), FALSE);
g_return_val_if_fail (dest != NULL, FALSE);
g_return_val_if_fail (sibling != subsurface, FALSE);
g_return_val_if_fail (sibling == NULL || GDK_IS_SUBSURFACE (sibling), FALSE);

View File

@@ -47,17 +47,6 @@ 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
{
GObjectClass parent_class;

View File

@@ -2602,17 +2602,18 @@ output_handle_geometry (void *data,
const char *model,
int32_t transform)
{
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
GdkMonitor *monitor = GDK_MONITOR (data);
GdkWaylandMonitor *wayland_monitor = (GdkWaylandMonitor *)monitor;
GDK_DEBUG (MISC, "handle geometry output %d, position %d %d, phys. size %d %d, subpixel layout %s, manufacturer %s, model %s, transform %s",
monitor->id, x, y,
wayland_monitor->id, x, y,
physical_width, physical_height,
subpixel_to_string (subpixel),
make, model,
transform_to_string (transform));
monitor->output_geometry.x = x;
monitor->output_geometry.y = y;
wayland_monitor->output_geometry.x = x;
wayland_monitor->output_geometry.y = y;
switch (transform)
{
@@ -2620,20 +2621,19 @@ output_handle_geometry (void *data,
case WL_OUTPUT_TRANSFORM_270:
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
gdk_monitor_set_physical_size (GDK_MONITOR (monitor),
physical_height, physical_width);
gdk_monitor_set_physical_size (monitor, physical_height, physical_width);
break;
default:
gdk_monitor_set_physical_size (GDK_MONITOR (monitor),
physical_width, physical_height);
gdk_monitor_set_physical_size (monitor, physical_width, physical_height);
}
gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), subpixel);
gdk_monitor_set_manufacturer (GDK_MONITOR (monitor), make);
gdk_monitor_set_model (GDK_MONITOR (monitor), model);
gdk_monitor_set_subpixel_layout (monitor, subpixel);
gdk_monitor_set_manufacturer (monitor, make);
gdk_monitor_set_model (monitor, model);
gdk_monitor_set_transform (monitor, (GdkTextureTransform) transform);
if (should_update_monitor (monitor) || !monitor_has_xdg_output (monitor))
apply_monitor_change (monitor);
if (should_update_monitor (wayland_monitor) || !monitor_has_xdg_output (wayland_monitor))
apply_monitor_change (wayland_monitor);
}
static void

View File

@@ -55,29 +55,71 @@ struct _GskOffload
GskOffloadInfo *last_info;
};
static GdkTextureTransform
find_texture_transform (GskTransform *transform)
static inline gboolean
texture_transform_flips (GdkTextureTransform transform)
{
float sx, sy, dx, dy;
g_assert (gsk_transform_get_category (transform) >= GSK_TRANSFORM_CATEGORY_2D_AFFINE);
gsk_transform_to_affine (transform, &sx, &sy, &dx, &dy);
if (sx > 0)
switch ((int)transform)
{
if (sy > 0)
return GDK_TEXTURE_TRANSFORM_NORMAL;
else
return GDK_TEXTURE_TRANSFORM_FLIPPED_180;
case GDK_TEXTURE_TRANSFORM_90:
case GDK_TEXTURE_TRANSFORM_270:
case GDK_TEXTURE_TRANSFORM_FLIPPED_90:
case GDK_TEXTURE_TRANSFORM_FLIPPED_270:
return TRUE;
default:
return FALSE;
}
else
}
static gboolean
find_texture_transform (GskTransform *transform,
GdkTextureTransform *out)
{
float skx, sky, sx, sy, angle, dx, dy;
int idx;
GdkTextureTransform transforms[16] = {
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,
GDK_TEXTURE_TRANSFORM_FLIPPED_270,
0,
0,
0,
0,
0,
0,
0,
0,
};
g_assert (gsk_transform_get_category (transform) >= GSK_TRANSFORM_CATEGORY_2D);
gsk_transform_to_2d_components (transform, &skx, &sky, &sx, &sy, &angle, &dx, &dy);
if (skx != 0 || sky != 0)
{
if (sy > 0)
return GDK_TEXTURE_TRANSFORM_FLIPPED;
else
return GDK_TEXTURE_TRANSFORM_180;
g_print ("transform has skew: %f %f\n", skx, sky);
return FALSE;
}
if (angle < 0)
angle += 360;
if (angle != 0 && angle != 90 && angle != 180 && angle != 270)
{
g_print ("transform has rotation: %f\n", angle);
return FALSE;
}
idx = (((int)angle)/90) | ((sy < 0) << 2) | ((sx < 0) << 3);
*out = transforms[idx];
g_print ("texture transform: flips %d %d angle %d -> idx %d, transform %d\n", sx < 0, sy < 0, (int)angle, idx, *out);
return TRUE;
}
static GdkTexture *
@@ -115,11 +157,11 @@ find_texture_to_attach (GskOffload *self,
{
GskTransform *t = gsk_transform_node_get_transform (node);
if (gsk_transform_get_category (t) < GSK_TRANSFORM_CATEGORY_2D_AFFINE)
if (gsk_transform_get_category (t) < GSK_TRANSFORM_CATEGORY_2D)
{
char *s = gsk_transform_to_string (t);
GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD,
"Can't offload subsurface %p: transform %s is not just scale/translate",
"Can't offload subsurface %p: transform %s is not a 2D transform",
subsurface, s);
g_free (s);
goto out;
@@ -165,14 +207,34 @@ find_texture_to_attach (GskOffload *self,
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
*out_texture_transform = find_texture_transform (transform);
if (!find_texture_transform (transform, out_texture_transform))
{
char *s = gsk_transform_to_string (transform);
GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD,
"Can't offload subsurface %p: transform %s is not suitable",
subsurface, s);
g_free (s);
goto out;
}
if (has_clip)
{
float dx = node->bounds.origin.x;
float dy = node->bounds.origin.y;
float sx = gdk_texture_get_width (texture) / node->bounds.size.width;
float sy = gdk_texture_get_height (texture) / node->bounds.size.height;
float dx, dy, sx, sy;
if (texture_transform_flips (*out_texture_transform))
{
dx = node->bounds.origin.y;
dy = node->bounds.origin.x;
sx = gdk_texture_get_height (texture) / node->bounds.size.width;
sy = gdk_texture_get_width (texture) / node->bounds.size.height;
}
else
{
dx = node->bounds.origin.x;
dy = node->bounds.origin.y;
sx = gdk_texture_get_width (texture) / node->bounds.size.width;
sy = gdk_texture_get_height (texture) / node->bounds.size.height;
}
gsk_rect_intersection (&node->bounds, &clip, &clip);
@@ -185,8 +247,16 @@ find_texture_to_attach (GskOffload *self,
{
out_clip->origin.x = 0;
out_clip->origin.y = 0;
out_clip->size.width = gdk_texture_get_width (texture);
out_clip->size.height = gdk_texture_get_height (texture);
if (texture_transform_flips (*out_texture_transform))
{
out_clip->size.width = gdk_texture_get_height (texture);
out_clip->size.height = gdk_texture_get_width (texture);
}
else
{
out_clip->size.width = gdk_texture_get_width (texture);
out_clip->size.height = gdk_texture_get_height (texture);
}
}
ret = texture;