summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2023-04-28 00:12:49 +0200
committerBenjamin Otte <otte@redhat.com>2023-05-01 22:24:14 +0200
commit1883035d34f01ee6aba135d6c534d6c566dd9c7d (patch)
tree8186794735d559d7ccfedde76e0faf68fedf6b61 /gdk
parentc542351a73538b42bb820324c6590350b14a48b7 (diff)
downloadgtk+-1883035d34f01ee6aba135d6c534d6c566dd9c7d.tar.gz
texture: Add gdk_texture_diff()
... and use it in rendernodes. Setting up textures for diffing is done via gdk_texture_set_diff() which should only be used during texture construction. Note that the pointers to next/previous are allowed to dangle if one of the textures is finalized, but that's fine because we always check both textures' links to each other before we consider the pointer valid.
Diffstat (limited to 'gdk')
-rw-r--r--gdk/gdktexture.c44
-rw-r--r--gdk/gdktextureprivate.h14
2 files changed, 57 insertions, 1 deletions
diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c
index 41cb8ea11a..b392b90222 100644
--- a/gdk/gdktexture.c
+++ b/gdk/gdktexture.c
@@ -282,6 +282,8 @@ gdk_texture_dispose (GObject *object)
{
GdkTexture *self = GDK_TEXTURE (object);
+ g_clear_pointer (&self->diff_to_previous, cairo_region_destroy);
+
gdk_texture_clear_render_data (self);
G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object);
@@ -671,7 +673,47 @@ gdk_texture_do_download (GdkTexture *texture,
guchar *data,
gsize stride)
{
- GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data,stride);
+ GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data, stride);
+}
+
+void
+gdk_texture_diff (GdkTexture *self,
+ GdkTexture *other,
+ cairo_region_t *region)
+{
+ if (self == other)
+ return;
+
+ if (self->previous_texture == other &&
+ g_atomic_pointer_get (&other->next_texture) == self)
+ {
+ cairo_region_union (region, self->diff_to_previous);
+ }
+ else if (other->previous_texture == self &&
+ g_atomic_pointer_get (&self->next_texture) == other)
+ {
+ cairo_region_union (region, other->diff_to_previous);
+ }
+ else
+ {
+ cairo_region_union_rectangle (region,
+ &(cairo_rectangle_int_t) {
+ 0,
+ 0,
+ MAX (self->width, other->width),
+ MAX (self->height, other->height)
+ });
+ }
+}
+
+void
+gdk_texture_set_diff (GdkTexture *self,
+ GdkTexture *previous,
+ cairo_region_t *diff)
+{
+ self->previous_texture = previous;
+ self->diff_to_previous = diff;
+ g_atomic_pointer_set (&previous->next_texture, self);
}
cairo_surface_t *
diff --git a/gdk/gdktextureprivate.h b/gdk/gdktextureprivate.h
index fccf380d7c..b0fc2a8785 100644
--- a/gdk/gdktextureprivate.h
+++ b/gdk/gdktextureprivate.h
@@ -21,6 +21,12 @@ struct _GdkTexture
gpointer render_key;
gpointer render_data;
GDestroyNotify render_notify;
+
+ /* for diffing swapchain-like textures.
+ * Links are only valid if both textures agree on them */
+ gpointer next_texture; /* atomic, no reference, may be invalid pointer */
+ gpointer previous_texture; /* no reference, may be invalid pointer */
+ cairo_region_t *diff_to_previous;
};
struct _GdkTextureClass {
@@ -42,6 +48,14 @@ void gdk_texture_do_download (GdkTexture
GdkMemoryFormat format,
guchar *data,
gsize stride);
+void gdk_texture_diff (GdkTexture *self,
+ GdkTexture *other,
+ cairo_region_t *region);
+
+void gdk_texture_set_diff (GdkTexture *self,
+ GdkTexture *previous,
+ cairo_region_t *diff);
+
gboolean gdk_texture_set_render_data (GdkTexture *self,
gpointer key,
gpointer data,