[gegl] buffer: use empty tiles when filling buffer with 0-valued color
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: use empty tiles when filling buffer with 0-valued color
- Date: Fri, 30 Nov 2018 10:40:13 +0000 (UTC)
commit b2345ad0203c26a186bc01f9529a031de1d40662
Author: Ell <ell_se yahoo com>
Date: Fri Nov 30 05:31:29 2018 -0500
buffer: use empty tiles when filling buffer with 0-valued color
In gegl_buffer_set_color_from_pixel(), if the pixel data, after
conversion to the buffer format, is fully zeroed, use clones of the
global empty tile for filling whole tiles, instead of creating a
new 0-filled tile. This allows us to share memory with the global
empty tile, and makes uncloning the affected tiles more efficient.
Note that we deliberately don't just clear the corresponding area
of the buffer in this case, and make sure that there are actual
empty tiles in the requested area, to stay on the safe side (mostly
w.r.t. user-provided tile handlers, which may create non-zero tiles
when the underlying handler returns a NULL tile).
gegl/buffer/gegl-buffer-access.c | 37 +++++++++----
gegl/buffer/gegl-tile-handler-empty.c | 100 +++++++++++++++++-----------------
gegl/buffer/gegl-tile-handler-empty.h | 2 +
3 files changed, 78 insertions(+), 61 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 05bcdd2b1..eb4c6e97f 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -33,6 +33,7 @@
#include "gegl-buffer.h"
#include "gegl-buffer-private.h"
#include "gegl-tile-storage.h"
+#include "gegl-tile-handler-empty.h"
#include "gegl-sampler.h"
#include "gegl-tile-backend.h"
#include "gegl-buffer-iterator.h"
@@ -2880,26 +2881,40 @@ gegl_buffer_set_color_from_pixel_tile (GeglBuffer *dst,
{
GeglTile *tile;
- if (! data->tile)
+ if (data->tile)
{
- data->tile = gegl_tile_new (dst->tile_storage->tile_size);
+ tile = gegl_tile_dup (data->tile);
+ }
+ else
+ {
+ gint tile_size = dst->tile_storage->tile_size;
+
+ if (gegl_memeq_zero (data->pixel, data->bpp))
+ {
+ tile = gegl_tile_handler_empty_new_tile (tile_size);
+ }
+ else
+ {
+ tile = gegl_tile_new (tile_size);
- gegl_tile_lock (data->tile);
+ gegl_tile_lock (tile);
- gegl_memset_pattern (gegl_tile_get_data (data->tile),
- data->pixel,
- data->bpp,
- dst->tile_storage->tile_size / data->bpp);
+ gegl_memset_pattern (gegl_tile_get_data (tile),
+ data->pixel,
+ data->bpp,
+ tile_size / data->bpp);
- gegl_tile_unlock (data->tile);
+ gegl_tile_unlock (tile);
+ }
}
- tile = gegl_tile_dup (data->tile);
-
gegl_tile_handler_cache_insert (dst->tile_storage->cache, tile,
tile_x, tile_y, 0);
- gegl_tile_unref (tile);
+ if (data->tile)
+ gegl_tile_unref (tile);
+ else
+ data->tile = tile;
}
static void
diff --git a/gegl/buffer/gegl-tile-handler-empty.c b/gegl/buffer/gegl-tile-handler-empty.c
index 9c2d0a860..23c45b594 100644
--- a/gegl/buffer/gegl-tile-handler-empty.c
+++ b/gegl/buffer/gegl-tile-handler-empty.c
@@ -38,55 +38,6 @@ finalize (GObject *object)
G_OBJECT_CLASS (gegl_tile_handler_empty_parent_class)->finalize (object);
}
-static GeglTile *
-_new_empty_tile (const gint tile_size)
-{
- static GeglTile *common_tile = NULL;
- static const gint common_empty_size = sizeof (gdouble) * 4 * 128 * 128;
-
- GeglTile *tile;
-
- if (tile_size > common_empty_size)
- {
- /* The tile size is too big to use the shared buffer */
- tile = gegl_tile_new (tile_size);
-
- memset (gegl_tile_get_data (tile), 0x00, tile_size);
- tile->is_zero_tile = TRUE;
- }
- else
- {
- if (!g_atomic_pointer_get (&common_tile) &&
- g_once_init_enter (&common_tile))
- {
- GeglTile *allocated_tile = gegl_tile_new_bare ();
- guchar *allocated_buffer = gegl_malloc (common_empty_size);
- memset (allocated_buffer, 0x00, common_empty_size);
-
- allocated_tile->data = allocated_buffer;
- allocated_tile->destroy_notify = NULL;
- allocated_tile->size = common_empty_size;
- allocated_tile->is_zero_tile = TRUE;
- allocated_tile->is_global_tile = TRUE;
-
- /* avoid counting duplicates of the empty tile towards the total
- * cache size, both since this is unnecessary, and since they may
- * have different sizes, which is inconsistent with the duplicate-
- * tracking cache logic.
- */
- (*gegl_tile_n_cached_clones (allocated_tile))++;
-
- g_once_init_leave (&common_tile, allocated_tile);
- }
-
- tile = gegl_tile_dup (common_tile);
-
- tile->size = tile_size;
- }
-
- return tile;
-}
-
static GeglTile *
get_tile (GeglTileSource *gegl_tile_source,
gint x,
@@ -105,7 +56,7 @@ get_tile (GeglTileSource *gegl_tile_source,
if (!empty->tile)
{
gint tile_size = gegl_tile_backend_get_tile_size (empty->backend);
- empty->tile = _new_empty_tile (tile_size);
+ empty->tile = gegl_tile_handler_empty_new_tile (tile_size);
}
tile = gegl_tile_handler_dup_tile (GEGL_TILE_HANDLER (empty),
@@ -157,3 +108,52 @@ gegl_tile_handler_empty_new (GeglTileBackend *backend)
return (void*)empty;
}
+
+GeglTile *
+gegl_tile_handler_empty_new_tile (gint tile_size)
+{
+ static GeglTile *common_tile = NULL;
+ static const gint common_empty_size = sizeof (gdouble) * 4 * 128 * 128;
+
+ GeglTile *tile;
+
+ if (tile_size > common_empty_size)
+ {
+ /* The tile size is too big to use the shared buffer */
+ tile = gegl_tile_new (tile_size);
+
+ memset (gegl_tile_get_data (tile), 0x00, tile_size);
+ tile->is_zero_tile = TRUE;
+ }
+ else
+ {
+ if (!g_atomic_pointer_get (&common_tile) &&
+ g_once_init_enter (&common_tile))
+ {
+ GeglTile *allocated_tile = gegl_tile_new_bare ();
+ guchar *allocated_buffer = gegl_malloc (common_empty_size);
+ memset (allocated_buffer, 0x00, common_empty_size);
+
+ allocated_tile->data = allocated_buffer;
+ allocated_tile->destroy_notify = NULL;
+ allocated_tile->size = common_empty_size;
+ allocated_tile->is_zero_tile = TRUE;
+ allocated_tile->is_global_tile = TRUE;
+
+ /* avoid counting duplicates of the empty tile towards the total
+ * cache size, both since this is unnecessary, and since they may
+ * have different sizes, which is inconsistent with the duplicate-
+ * tracking cache logic.
+ */
+ (*gegl_tile_n_cached_clones (allocated_tile))++;
+
+ g_once_init_leave (&common_tile, allocated_tile);
+ }
+
+ tile = gegl_tile_dup (common_tile);
+
+ tile->size = tile_size;
+ }
+
+ return tile;
+}
diff --git a/gegl/buffer/gegl-tile-handler-empty.h b/gegl/buffer/gegl-tile-handler-empty.h
index 9b069f03e..b4ed66e4b 100644
--- a/gegl/buffer/gegl-tile-handler-empty.h
+++ b/gegl/buffer/gegl-tile-handler-empty.h
@@ -58,6 +58,8 @@ GType gegl_tile_handler_empty_get_type (void) G_GNUC_CONST;
GeglTileHandler * gegl_tile_handler_empty_new (GeglTileBackend *backend);
+GeglTile * gegl_tile_handler_empty_new_tile (gint tile_size);
+
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]