[gegl] buffer: allow creating buffers with uninitialized data



commit 49d0b4146cef8fc88f6d72ad7f0952b413931158
Author: Ell <ell_se yahoo com>
Date:   Wed May 6 11:34:12 2020 +0300

    buffer: allow creating buffers with uninitialized data
    
    Add a new construct-only GeglBuffer::initlalized boolean property,
    which, when FALSE, allows the buffer to avoid zero-initializing
    empty tiles.  This property defaults to TRUE, and is mostly meant
    to be used internally for now.
    
    When set to TRUE, empty tiles are created fully damaged, so that
    their data is not unnecessarily initialized when uncloned.  Note
    that we already avoid initializing or copying uncloned tile data
    when overwriting the full tile content, but this allows us to avoid
    initialization even when writing partial content.
    
    This optimization is currently limited to level-0 tiles, to
    simplify the code.

 gegl/buffer/gegl-buffer-private.h     |  2 ++
 gegl/buffer/gegl-buffer.c             | 22 ++++++++++++++++++++--
 gegl/buffer/gegl-tile-handler-empty.c | 18 +++++++++++++++---
 gegl/buffer/gegl-tile-handler-empty.h |  6 ++++--
 gegl/buffer/gegl-tile-storage.c       |  5 +++--
 gegl/buffer/gegl-tile-storage.h       |  3 ++-
 6 files changed, 46 insertions(+), 10 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index 164f554d9..62e4716d2 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -70,6 +70,8 @@ struct _GeglBuffer
   GeglRectangle     changed_signal_accumulator;
 
   GeglTileBackend  *backend;
+
+  gboolean          initialized;
 };
 
 struct _GeglBufferClass
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index 826b00b41..2bbc6b687 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -77,7 +77,8 @@ enum
   PROP_PX_SIZE,
   PROP_PIXELS,
   PROP_PATH,
-  PROP_BACKEND
+  PROP_BACKEND,
+  PROP_INITIALIZED
 };
 
 enum
@@ -165,6 +166,10 @@ gegl_buffer_get_property (GObject    *gobject,
         g_value_set_int (value, buffer->abyss.height);
         break;
 
+      case PROP_INITIALIZED:
+        g_value_set_boolean (value, buffer->initialized);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
@@ -264,6 +269,10 @@ gegl_buffer_set_property (GObject      *gobject,
         buffer->backend = g_value_dup_object (value);
         break;
 
+      case PROP_INITIALIZED:
+        buffer->initialized = g_value_get_boolean (value);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
@@ -573,7 +582,8 @@ gegl_buffer_constructor (GType                  type,
           buffer->backend = backend;
         }
 
-      source = GEGL_TILE_SOURCE (gegl_tile_storage_new (backend));
+      source = GEGL_TILE_SOURCE (gegl_tile_storage_new (backend,
+                                                        buffer->initialized));
       gegl_tile_handler_set_source ((GeglTileHandler*)(buffer), source);
       g_object_unref (source);
     }
@@ -882,6 +892,14 @@ gegl_buffer_class_init (GeglBufferClass *class)
                                                         G_PARAM_CONSTRUCT_ONLY |
                                                         G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_INITIALIZED,
+                                   g_param_spec_boolean ("initialized",
+                                                         NULL, NULL,
+                                                         TRUE,
+                                                         G_PARAM_READWRITE |
+                                                         G_PARAM_CONSTRUCT_ONLY |
+                                                         G_PARAM_STATIC_STRINGS));
+
   gegl_buffer_signals[CHANGED] =
     g_signal_new ("changed",
                   G_TYPE_FROM_CLASS (gobject_class),
diff --git a/gegl/buffer/gegl-tile-handler-empty.c b/gegl/buffer/gegl-tile-handler-empty.c
index 23c45b594..cb6400bd1 100644
--- a/gegl/buffer/gegl-tile-handler-empty.c
+++ b/gegl/buffer/gegl-tile-handler-empty.c
@@ -62,6 +62,16 @@ get_tile (GeglTileSource *gegl_tile_source,
   tile = gegl_tile_handler_dup_tile (GEGL_TILE_HANDLER (empty),
                                      empty->tile, x, y, z);
 
+  /* if empty tiles don't have to be zero-initialized, mark them as fully
+   * damaged, so that their data is not unnecessarily initialized when
+   * uncloned.
+   *
+   * we currently only do this for level-0 tiles, since it simplifies the rest
+   * of the code.
+   */
+  if (z == 0 && ! empty->initialized)
+    tile->damage = ~0ull;
+
   /* no need to store the tile, since we'll just create another empty tile on-
    * demand if it's dropped.
    */
@@ -99,12 +109,14 @@ gegl_tile_handler_empty_init (GeglTileHandlerEmpty *self)
 }
 
 GeglTileHandler *
-gegl_tile_handler_empty_new (GeglTileBackend *backend)
+gegl_tile_handler_empty_new (GeglTileBackend *backend,
+                             gboolean         initialized)
 {
   GeglTileHandlerEmpty *empty = g_object_new (GEGL_TYPE_TILE_HANDLER_EMPTY, NULL);
 
-  empty->backend = backend;
-  empty->tile    = NULL;
+  empty->backend     = backend;
+  empty->tile        = NULL;
+  empty->initialized = initialized;
 
   return (void*)empty;
 }
diff --git a/gegl/buffer/gegl-tile-handler-empty.h b/gegl/buffer/gegl-tile-handler-empty.h
index b4ed66e4b..42409585b 100644
--- a/gegl/buffer/gegl-tile-handler-empty.h
+++ b/gegl/buffer/gegl-tile-handler-empty.h
@@ -47,6 +47,7 @@ struct _GeglTileHandlerEmpty
 
   GeglTile               *tile;
   GeglTileBackend        *backend;
+  gboolean                initialized;
 };
 
 struct _GeglTileHandlerEmptyClass
@@ -56,9 +57,10 @@ struct _GeglTileHandlerEmptyClass
 
 GType             gegl_tile_handler_empty_get_type (void) G_GNUC_CONST;
 
-GeglTileHandler * gegl_tile_handler_empty_new      (GeglTileBackend *backend);
+GeglTileHandler * gegl_tile_handler_empty_new      (GeglTileBackend *backend,
+                                                    gboolean         initialized);
 
-GeglTile        * gegl_tile_handler_empty_new_tile (gint tile_size);
+GeglTile        * gegl_tile_handler_empty_new_tile (gint             tile_size);
 
 G_END_DECLS
 
diff --git a/gegl/buffer/gegl-tile-storage.c b/gegl/buffer/gegl-tile-storage.c
index 5c1fd89b0..bfc56c711 100644
--- a/gegl/buffer/gegl-tile-storage.c
+++ b/gegl/buffer/gegl-tile-storage.c
@@ -42,7 +42,8 @@ enum
 guint gegl_tile_storage_signals[LAST_SIGNAL] = { 0 };
 
 GeglTileStorage *
-gegl_tile_storage_new (GeglTileBackend *backend)
+gegl_tile_storage_new (GeglTileBackend *backend,
+                       gboolean         initialized)
 {
   GeglTileStorage *tile_storage = g_object_new (GEGL_TYPE_TILE_STORAGE, NULL);
   GeglTileHandlerChain  *tile_handler_chain;
@@ -63,7 +64,7 @@ gegl_tile_storage_new (GeglTileBackend *backend)
   gegl_tile_handler_set_source (handler, GEGL_TILE_SOURCE (backend));
 
   cache = gegl_tile_handler_cache_new ();
-  empty = gegl_tile_handler_empty_new (backend);
+  empty = gegl_tile_handler_empty_new (backend, initialized);
   zoom = gegl_tile_handler_zoom_new (backend);
 
   /* set storage and cache on ourself so chain_add() can use it */
diff --git a/gegl/buffer/gegl-tile-storage.h b/gegl/buffer/gegl-tile-storage.h
index d707cfbc9..a80fa2950 100644
--- a/gegl/buffer/gegl-tile-storage.h
+++ b/gegl/buffer/gegl-tile-storage.h
@@ -64,7 +64,8 @@ struct _GeglTileStorageClass
 GType gegl_tile_storage_get_type (void) G_GNUC_CONST;
 
 GeglTileStorage *
-gegl_tile_storage_new (GeglTileBackend *backend);
+gegl_tile_storage_new (GeglTileBackend *backend,
+                       gboolean         initialized);
 
 void gegl_tile_storage_add_handler (GeglTileStorage *tile_storage, GeglTileHandler *handler);
 void gegl_tile_storage_remove_handler (GeglTileStorage *tile_storage, GeglTileHandler *handler);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]