texturebuilder: Add ::udpate-region and ::update-texture
authorBenjamin Otte <otte@redhat.com>
Fri, 28 Apr 2023 03:40:14 +0000 (05:40 +0200)
committerBenjamin Otte <otte@redhat.com>
Mon, 1 May 2023 22:30:58 +0000 (00:30 +0200)
gdk/gdkgltexture.c
gdk/gdkgltexturebuilder.c
gdk/gdkgltexturebuilder.h

index b409ae852d6d299434eabf08ba58d7490d1a54cd..e08711aaf2fa50dffff9d80cffe2a9a0534fa753 100644 (file)
@@ -338,6 +338,7 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
                                  gpointer             data)
 {
   GdkGLTexture *self;
+  GdkTexture *update_texture;
 
   self = g_object_new (GDK_TYPE_GL_TEXTURE,
                        "width", gdk_gl_texture_builder_get_width (builder),
@@ -353,6 +354,22 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
   self->destroy = destroy;
   self->data = data;
 
+  update_texture = gdk_gl_texture_builder_get_update_texture (builder);
+  if (update_texture)
+    {
+      cairo_region_t *update_region = gdk_gl_texture_builder_get_update_region (builder);
+      if (update_region)
+        {
+          update_region = cairo_region_copy (update_region);
+          cairo_region_intersect_rectangle (update_region,
+                                            &(cairo_rectangle_int_t) {
+                                              0, 0,
+                                              update_texture->width, update_texture->height
+                                            });
+          gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
+        }
+    }
+
   return GDK_TEXTURE (self);
 }
 
index ceaf44a9c80b5b639074bce2dd15bd0e08bf9c8c..ec885fea728d7f8c3d7256f80b4aaf81320b9d0d 100644 (file)
@@ -25,6 +25,8 @@
 #include "gdkglcontext.h"
 #include "gdkgltextureprivate.h"
 
+#include <cairo-gobject.h>
+
 struct _GdkGLTextureBuilder
 {
   GObject parent_instance;
@@ -36,6 +38,9 @@ struct _GdkGLTextureBuilder
   GdkMemoryFormat format;
   gboolean has_mipmap;
   gpointer sync;
+
+  GdkTexture *update_texture;
+  cairo_region_t *update_region;
 };
 
 struct _GdkGLTextureBuilderClass
@@ -70,6 +75,8 @@ enum
   PROP_HEIGHT,
   PROP_ID,
   PROP_SYNC,
+  PROP_UPDATE_REGION,
+  PROP_UPDATE_TEXTURE,
   PROP_WIDTH,
 
   N_PROPS
@@ -86,6 +93,9 @@ gdk_gl_texture_builder_dispose (GObject *object)
 
   g_clear_object (&self->context);
 
+  g_clear_object (&self->update_texture);
+  g_clear_pointer (&self->update_region, cairo_region_destroy);
+
   G_OBJECT_CLASS (gdk_gl_texture_builder_parent_class)->dispose (object);
 }
 
@@ -123,6 +133,14 @@ gdk_gl_texture_builder_get_property (GObject    *object,
       g_value_set_pointer (value, self->sync);
       break;
 
+    case PROP_UPDATE_REGION:
+      g_value_set_boxed (value, self->update_region);
+      break;
+
+    case PROP_UPDATE_TEXTURE:
+      g_value_set_object (value, self->update_texture);
+      break;
+
     case PROP_WIDTH:
       g_value_set_int (value, self->width);
       break;
@@ -167,6 +185,14 @@ gdk_gl_texture_builder_set_property (GObject      *object,
       gdk_gl_texture_builder_set_sync (self, g_value_get_pointer (value));
       break;
 
+    case PROP_UPDATE_REGION:
+      gdk_gl_texture_builder_set_update_region (self, g_value_get_boxed (value));
+      break;
+
+    case PROP_UPDATE_TEXTURE:
+      gdk_gl_texture_builder_set_update_texture (self, g_value_get_object (value));
+      break;
+
     case PROP_WIDTH:
       gdk_gl_texture_builder_set_width (self, g_value_get_int (value));
       break;
@@ -260,6 +286,30 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass)
     g_param_spec_pointer ("sync", NULL, NULL,
                           G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
 
+  /**
+   * GdkGLTextureBuilder:update-region: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_update_region org.gdk.Property.set=gdk_gl_texture_builder_set_update_region)
+   *
+   * The update region for [property@Gdk.GLTextureBuilder:update-texture].
+   *
+   * Since: 4.12
+   */
+  properties[PROP_UPDATE_REGION] =
+    g_param_spec_boxed ("update-region", NULL, NULL,
+                        CAIRO_GOBJECT_TYPE_REGION,
+                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+  /**
+   * GdkGLTextureBuilder:update-texture: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_update_texture org.gdk.Property.set=gdk_gl_texture_builder_set_update_texture)
+   *
+   * The texture [property@Gdk.GLTextureBuilder:update-region] is an update for.
+   *
+   * Since: 4.12
+   */
+  properties[PROP_UPDATE_TEXTURE] =
+    g_param_spec_object ("update-texture", NULL, NULL,
+                         GDK_TYPE_TEXTURE,
+                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
   /**
    * GdkGLTextureBuilder:width: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_width org.gdk.Property.set=gdk_gl_texture_builder_set_width)
    *
@@ -271,6 +321,7 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass)
     g_param_spec_int ("width", NULL, NULL,
                       G_MININT, G_MAXINT, 0,
                       G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (gobject_class, N_PROPS, properties);
 }
 
@@ -613,6 +664,102 @@ gdk_gl_texture_builder_set_format (GdkGLTextureBuilder *self,
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FORMAT]);
 }
 
+/**
+ * gdk_gl_texture_builder_get_update_texture: (attributes org.gdk.Method.get_property=update_texture)
+ * @self: a `GdkGLTextureBuilder`
+ *
+ * Gets the texture previously set via gdk_gl_texture_builder_set_update_texture() or
+ * %NULL if none was set.
+ *
+ * Returns: (transfer none) (nullable): The texture 
+ *
+ * Since: 4.12
+ */
+GdkTexture *
+gdk_gl_texture_builder_get_update_texture (GdkGLTextureBuilder *self)
+{
+  g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL);
+
+  return self->update_texture;
+}
+
+/**
+ * gdk_gl_texture_builder_set_update_texture: (attributes org.gdk.Method.set_property=update_texture)
+ * @self: a `GdkGLTextureBuilder`
+ * @texture: (nullable): the texture to update
+ *
+ * Sets the texture to be updated by this texture. See
+ * [method@Gdk.GLTextureBuilder.set_update_region] for an explanation.
+ *
+ * Since: 4.12
+ */
+void
+gdk_gl_texture_builder_set_update_texture (GdkGLTextureBuilder *self,
+                                           GdkTexture          *texture)
+{
+  g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self));
+  g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
+
+  if (!g_set_object (&self->update_texture, texture))
+    return;
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_TEXTURE]);
+}
+
+/**
+ * gdk_gl_texture_builder_get_update_region: (attributes org.gdk.Method.get_property=update_region)
+ * @self: a `GdkGLTextureBuilder`
+ *
+ * Gets the region previously set via gdk_gl_texture_builder_set_update_region() or
+ * %NULL if none was set.
+ *
+ * Returns: (transfer none) (nullable): The region 
+ *
+ * Since: 4.12
+ */
+cairo_region_t *
+gdk_gl_texture_builder_get_update_region (GdkGLTextureBuilder *self)
+{
+  g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL);
+
+  return self->update_region;
+}
+
+/**
+ * gdk_gl_texture_builder_set_update_region: (attributes org.gdk.Method.set_property=update_region)
+ * @self: a `GdkGLTextureBuilder`
+ * @region: (nullable): the region to update
+ *
+ * Sets the region to be updated by this texture. Together with
+ * [property@Gdk.GLTextureBuilder:update-texture] this describes an
+ * update of a previous texture.
+ *
+ * When rendering animations of large textures, it is possible that
+ * consecutive textures are only updating contents in parts of the texture.
+ * It is then possible to describe this update via these two properties,
+ * so that GTK can avoid rerendering parts that did not change.
+ *
+ * An example would be a screen recording where only the mouse pointer moves.
+ *
+ * Since: 4.12
+ */
+void
+gdk_gl_texture_builder_set_update_region (GdkGLTextureBuilder *self,
+                                         cairo_region_t      *region)
+{
+  g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self));
+
+  if (self->update_region == region)
+    return;
+
+  g_clear_pointer (&self->update_region, cairo_region_destroy);
+
+  if (region)
+    self->update_region = cairo_region_reference (region);
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_REGION]);
+}
+
 /**
  * gdk_gl_texture_builder_build:
  * @self: a `GdkGLTextureBuilder`
index 03ee185e0c16071d914359ce280e17507689a45b..042bcc96cb49dfc7984ad87b4ae120e0a6753bab 100644 (file)
@@ -78,6 +78,18 @@ GDK_AVAILABLE_IN_4_12
 void                    gdk_gl_texture_builder_set_sync         (GdkGLTextureBuilder    *self,
                                                                  gpointer                sync);
 
+GDK_AVAILABLE_IN_4_12
+GdkTexture *            gdk_gl_texture_builder_get_update_texture (GdkGLTextureBuilder  *self) G_GNUC_PURE;
+GDK_AVAILABLE_IN_4_12
+void                    gdk_gl_texture_builder_set_update_texture (GdkGLTextureBuilder  *self,
+                                                                 GdkTexture             *texture);
+
+GDK_AVAILABLE_IN_4_12
+cairo_region_t *        gdk_gl_texture_builder_get_update_region (GdkGLTextureBuilder   *self) G_GNUC_PURE;
+GDK_AVAILABLE_IN_4_12
+void                    gdk_gl_texture_builder_set_update_region (GdkGLTextureBuilder   *self,
+                                                                 cairo_region_t         *region);
+
 GDK_AVAILABLE_IN_4_12
 GdkTexture *            gdk_gl_texture_builder_build            (GdkGLTextureBuilder    *self,
                                                                  GDestroyNotify          destroy,