[gegl] buffer: keep track of damage-region of mipmapped tiles
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: keep track of damage-region of mipmapped tiles
- Date: Mon, 2 Apr 2018 11:41:05 +0000 (UTC)
commit 3210f4ffc3c569a2acd9483811cb141070112bc6
Author: Ell <ell_se yahoo com>
Date: Sat Mar 31 11:45:55 2018 -0400
buffer: keep track of damage-region of mipmapped tiles
WIP
gegl/buffer/gegl-buffer-access.c | 6 +-
gegl/buffer/gegl-buffer-iterator.c | 13 ++-
gegl/buffer/gegl-buffer-private.h | 6 +
gegl/buffer/gegl-tile-handler-cache.c | 39 ++++---
gegl/buffer/gegl-tile-handler-zoom.c | 184 +++++++++++++++++++++++---------
gegl/buffer/gegl-tile-handler.c | 52 +++++++++-
gegl/buffer/gegl-tile.c | 88 ++++++++++++++--
7 files changed, 305 insertions(+), 83 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index bb2d0eb..34e4435 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -826,12 +826,16 @@ with multi-threading - and should be added back later.
#undef CHECK_ALIGNMENT_ALIGNOF
}
- gegl_tile_unlock (tile);
+ gegl_tile_unlock_no_void (tile);
gegl_tile_unref (tile);
bufx += (tile_width - offsetx);
}
bufy += (tile_height - offsety);
}
+
+ if (level == 0)
+ gegl_tile_handler_damage_rect (GEGL_TILE_HANDLER (buffer->tile_storage),
+ roi);
}
static inline void
diff --git a/gegl/buffer/gegl-buffer-iterator.c b/gegl/buffer/gegl-buffer-iterator.c
index 7411726..9c1ea22 100644
--- a/gegl/buffer/gegl-buffer-iterator.c
+++ b/gegl/buffer/gegl-buffer-iterator.c
@@ -193,7 +193,7 @@ release_tile (GeglBufferIterator *iter,
if (sub->current_tile_mode == GeglIteratorTileMode_DirectTile)
{
if (sub->access_mode & GEGL_ACCESS_WRITE)
- gegl_tile_unlock (sub->current_tile);
+ gegl_tile_unlock_no_void (sub->current_tile);
gegl_tile_unref (sub->current_tile);
sub->current_tile = NULL;
@@ -545,10 +545,19 @@ _gegl_buffer_iterator_stop (GeglBufferIterator *iter)
if (sub->linear_tile)
{
if (sub->access_mode & GEGL_ACCESS_WRITE)
- gegl_tile_unlock (sub->linear_tile);
+ gegl_tile_unlock_no_void (sub->linear_tile);
gegl_tile_unref (sub->linear_tile);
}
+ if (sub->level == 0 &&
+ sub->access_mode & GEGL_ACCESS_WRITE &&
+ ! (sub->access_mode & GEGL_ITERATOR_INCOMPATIBLE))
+ {
+ gegl_tile_handler_damage_rect (
+ GEGL_TILE_HANDLER (sub->buffer->tile_storage),
+ &sub->full_rect);
+ }
+
gegl_buffer_unlock (sub->buffer);
if ((sub->access_mode & GEGL_ACCESS_WRITE) &&
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index 9df62bf..d7e700d 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -176,6 +176,8 @@ struct _GeglTile
* are in the cache.
*/
+ guint64 damage;
+
/* called when the tile is about to be destroyed */
GDestroyNotify destroy_notify;
gpointer destroy_notify_data;
@@ -187,6 +189,10 @@ struct _GeglTile
gpointer unlock_notify_data;
};
+void gegl_tile_unlock_no_void (GeglTile *tile);
+gboolean gegl_tile_damage (GeglTile *tile,
+ guint64 damage);
+
void _gegl_buffer_drop_hot_tile (GeglBuffer *buffer);
GeglRectangle _gegl_get_required_for_scale (const GeglRectangle *roi,
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 0688153..6914fe1 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -78,7 +78,8 @@ void gegl_tile_handler_cache_insert (GeglTileHandlerCache *cach
static void gegl_tile_handler_cache_void (GeglTileHandlerCache *cache,
gint x,
gint y,
- gint z);
+ gint z,
+ guint64 damage);
static void gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cache,
gint x,
gint y,
@@ -284,7 +285,9 @@ gegl_tile_handler_cache_command (GeglTileSource *tile_store,
gegl_tile_handler_cache_invalidate (cache, x, y, z);
break;
case GEGL_TILE_VOID:
- gegl_tile_handler_cache_void (cache, x, y, z);
+ gegl_tile_handler_cache_void (cache, x, y, z,
+ data ? *(const guint64 *) data :
+ ~(guint64) 0);
break;
case GEGL_TILE_REINIT:
gegl_tile_handler_cache_reinit (cache);
@@ -651,29 +654,33 @@ static void
gegl_tile_handler_cache_void (GeglTileHandlerCache *cache,
gint x,
gint y,
- gint z)
+ gint z,
+ guint64 damage)
{
CacheItem *item;
item = cache_lookup (cache, x, y, z);
if (item)
{
- if (g_atomic_int_dec_and_test (gegl_tile_n_cached_clones (item->tile)))
- g_atomic_pointer_add (&cache_total, -item->tile->size);
- g_atomic_pointer_add (&cache_total_uncloned, -item->tile->size);
+ drop_hot_tile (item->tile);
- g_queue_unlink (&cache->queue, &item->link);
- g_hash_table_remove (cache->items, item);
+ if (gegl_tile_damage (item->tile, damage))
+ {
+ if (g_atomic_int_dec_and_test (gegl_tile_n_cached_clones (item->tile)))
+ g_atomic_pointer_add (&cache_total, -item->tile->size);
+ g_atomic_pointer_add (&cache_total_uncloned, -item->tile->size);
- if (g_queue_is_empty (&cache->queue))
- cache->time = cache->stamp = 0;
+ g_queue_unlink (&cache->queue, &item->link);
+ g_hash_table_remove (cache->items, item);
- drop_hot_tile (item->tile);
- gegl_tile_void (item->tile);
- item->tile->tile_storage = NULL;
- gegl_tile_unref (item->tile);
+ if (g_queue_is_empty (&cache->queue))
+ cache->time = cache->stamp = 0;
- g_slice_free (CacheItem, item);
+ item->tile->tile_storage = NULL;
+ gegl_tile_unref (item->tile);
+
+ g_slice_free (CacheItem, item);
+ }
}
}
@@ -695,7 +702,7 @@ gegl_tile_handler_cache_insert (GeglTileHandlerCache *cache,
item->z = z;
// XXX : remove entry if it already exists
- gegl_tile_handler_cache_void (cache, x, y, z);
+ gegl_tile_handler_cache_void (cache, x, y, z, ~(guint64) 0);
tile->x = x;
tile->y = y;
diff --git a/gegl/buffer/gegl-tile-handler-zoom.c b/gegl/buffer/gegl-tile-handler-zoom.c
index a8037de..79fd563 100644
--- a/gegl/buffer/gegl-tile-handler-zoom.c
+++ b/gegl/buffer/gegl-tile-handler-zoom.c
@@ -29,6 +29,7 @@
#include "gegl-tile-handler-private.h"
#include "gegl-tile-handler-zoom.h"
#include "gegl-tile-storage.h"
+#include "gegl-buffer-private.h"
#include "gegl-algorithms.h"
@@ -37,52 +38,101 @@ G_DEFINE_TYPE (GeglTileHandlerZoom, gegl_tile_handler_zoom,
static guint64 total_size = 0;
-static inline void set_blank (GeglTile *dst_tile,
- gint width,
- gint height,
- const Babl *format,
- gint i,
- gint j)
+static void
+downscale (GeglTileHandlerZoom *zoom,
+ const Babl *format,
+ gint bpp,
+ guchar *src,
+ guchar *dest,
+ gint stride,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ guint damage,
+ gint i)
{
- guchar *dst_data = gegl_tile_get_data (dst_tile);
- gint bpp = babl_format_get_bytes_per_pixel (format);
- gint rowstride = width * bpp;
- gint scanline;
-
- gint bytes = width * bpp / 2;
- guchar *dst = dst_data + j * height / 2 * rowstride + i * rowstride / 2;
+ gint n = 1 << i;
+ guint mask = (1 << n) - 1;
- for (scanline = 0; scanline < height / 2; scanline++)
+ if ((damage & mask) == mask)
{
- memset (dst, 0x0, bytes);
- dst += rowstride;
- }
+ if (src)
+ {
+ if (!zoom->downscale_2x2)
+ zoom->downscale_2x2 = gegl_downscale_2x2_get_fun (format);
- total_size += (height / 2) * bytes;
-}
+ zoom->downscale_2x2 (format,
+ width, height,
+ src + y * stride + x * bpp, stride,
+ dest + (y / 2) * stride + (x / 2) * bpp, stride);
+ }
+ else
+ {
+ gint h = height / 2;
+ gint n = (width / 2) * bpp;
+ gint i;
-static inline void set_half (GeglTileHandlerZoom *zoom,
- GeglTile * dst_tile,
- GeglTile * src_tile,
- gint width,
- gint height,
- const Babl * format,
- gint i,
- gint j)
-{
- guchar *dst_data = gegl_tile_get_data (dst_tile);
- guchar *src_data = gegl_tile_get_data (src_tile);
- gint bpp = babl_format_get_bytes_per_pixel (format);
+ dest += (y / 2) * stride + (x / 2) * bpp;
- if (i) dst_data += bpp * width / 2;
- if (j) dst_data += bpp * width * height / 2;
+ for (i = 0; i < h; i++)
+ {
+ memset (dest, 0, n);
+ dest += stride;
+ }
+ }
+
+ total_size += (width / 2) * (height / 2) * bpp;
+ }
+ else
+ {
+ i--;
+ n /= 2;
+ mask >>= n;
+
+ if (damage & mask)
+ {
+ if (i & 1)
+ {
+ downscale (zoom,
+ format, bpp, src, dest, stride,
+ x, y,
+ width, height / 2,
+ damage, i);
+ }
+ else
+ {
+ downscale (zoom,
+ format, bpp, src, dest, stride,
+ x, y,
+ width / 2, height,
+ damage, i);
- if (!zoom->downscale_2x2)
- zoom->downscale_2x2 = gegl_downscale_2x2_get_fun (format);
+ }
+ }
- zoom->downscale_2x2 (format, width, height, src_data, width * bpp, dst_data, width * bpp);
+ damage >>= n;
- total_size += (width / 2) * (height / 2) * bpp;
+ if (damage & mask)
+ {
+ if (i & 1)
+ {
+ downscale (zoom,
+ format, bpp, src, dest, stride,
+ x, y + height / 2,
+ width, height / 2,
+ damage, i);
+ }
+ else
+ {
+ downscale (zoom,
+ format, bpp, src, dest, stride,
+ x + width / 2, y,
+ width / 2, height,
+ damage, i);
+ }
+ }
+ }
}
static GeglTile *
@@ -101,7 +151,7 @@ get_tile (GeglTileSource *gegl_tile_source,
if (source)
tile = gegl_tile_source_get_tile (source, x, y, z);
- if (tile || (z == 0))
+ if (z == 0 || (tile && ! tile->damage))
return tile;
tile_storage = _gegl_tile_handler_get_tile_storage ((GeglTileHandler *) zoom);
@@ -114,16 +164,27 @@ get_tile (GeglTileSource *gegl_tile_source,
{
gint i, j;
- const Babl *format = gegl_tile_backend_get_format (zoom->backend);
+ const Babl *format;
+ gint bpp;
+ gint stride;
+ guint64 damage;
GeglTile *source_tile[2][2] = { { NULL, NULL }, { NULL, NULL } };
+ if (tile)
+ damage = tile->damage;
+ else
+ damage = ~(guint64) 0;
+
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
- /* we get the tile from ourselves, to make successive rescales work
- * correctly */
- source_tile[i][j] = gegl_tile_source_get_tile (gegl_tile_source,
- x * 2 + i, y * 2 + j, z - 1);
+ if ((damage >> (32 * j + 16 * i)) & 0xffff)
+ {
+ /* we get the tile from ourselves, to make successive rescales
+ * work correctly */
+ source_tile[i][j] = gegl_tile_source_get_tile (
+ gegl_tile_source, x * 2 + i, y * 2 + j, z - 1);
+ }
}
if (source_tile[0][0] == NULL &&
@@ -135,23 +196,42 @@ get_tile (GeglTileSource *gegl_tile_source,
fill in the shared empty tile */
}
- g_assert (tile == NULL);
+ format = gegl_tile_backend_get_format (zoom->backend);
+ bpp = babl_format_get_bytes_per_pixel (format);
+ stride = tile_width * bpp;
- tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (zoom), x, y, z);
+ if (! tile)
+ tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (zoom), x, y, z);
gegl_tile_lock (tile);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
- if (source_tile[i][j])
- {
- set_half (zoom, tile, source_tile[i][j], tile_width, tile_height, format, i, j);
- gegl_tile_unref (source_tile[i][j]);
- }
- else
+ guint dmg = (damage >> (32 * j + 16 * i)) & 0xffff;
+
+ if (dmg)
{
- set_blank (tile, tile_width, tile_height, format, i, j);
+ gint x = i * tile_width / 2;
+ gint y = j * tile_height / 2;
+ guchar *src;
+ guchar *dest;
+
+ if (source_tile[i][j] && ! source_tile[i][j]->is_zero_tile)
+ src = gegl_tile_get_data (source_tile[i][j]);
+ else
+ src = NULL;
+
+ dest = gegl_tile_get_data (tile) + y * stride + x * bpp;
+
+ downscale (zoom,
+ format, bpp, src, dest, stride,
+ 0, 0,
+ tile_width, tile_height,
+ dmg, 4);
+
+ if (source_tile[i][j])
+ gegl_tile_unref (source_tile[i][j]);
}
}
gegl_tile_unlock (tile);
diff --git a/gegl/buffer/gegl-tile-handler.c b/gegl/buffer/gegl-tile-handler.c
index 53a9cda..9d9f54e 100644
--- a/gegl/buffer/gegl-tile-handler.c
+++ b/gegl/buffer/gegl-tile-handler.c
@@ -269,6 +269,8 @@ gegl_tile_handler_damage_rect (GeglTileHandler *handler,
for (z = 1; z <= handler->priv->tile_storage->seen_zoom; z++)
{
+ gint U1, V1;
+ gint U2, V2;
gint x, y;
X1 >>= 1;
@@ -281,11 +283,59 @@ gegl_tile_handler_damage_rect (GeglTileHandler *handler,
x2 >>= 1;
y2 >>= 1;
+ U1 = 8 * (X1 - x1 * tile_width) / tile_width;
+ V1 = 8 * (Y1 - y1 * tile_height) / tile_height;
+ U2 = 8 * (X2 - x2 * tile_width) / tile_width;
+ V2 = 8 * (Y2 - y2 * tile_height) / tile_height;
+
for (x = x1; x <= x2; x++)
{
+ gint u1 = x == x1 ? U1 : 0;
+ gint u2 = x == x2 ? U2 : 7;
+ guint base;
+
+ if (u1 == 0 && u2 == 7)
+ {
+ base = 0x00330033;
+ }
+ else
+ {
+ gint i;
+
+ base = 0;
+
+ for (i = u1; i <= u2; i++)
+ {
+ base |= 1 << (((i & 1) << 0) |
+ ((i & 2) << 1) |
+ ((i & 4) << 2));
+ }
+ }
+
for (y = y1; y <= y2; y++)
{
- gegl_tile_source_void (source, x, y, z);
+ gint v1 = y == y1 ? V1 : 0;
+ gint v2 = y == y2 ? V2 : 7;
+
+ if (u1 + v1 == 0 && u2 + v2 == 14)
+ {
+ gegl_tile_source_void (source, x, y, z);
+ }
+ else
+ {
+ guint64 damage = 0;
+ gint i;
+
+ for (i = v1; i <= v2; i++)
+ {
+ damage |= (guint64) base << (((i & 1) << 1) |
+ ((i & 2) << 2) |
+ ((i & 4) << 3));
+ }
+
+ gegl_tile_source_command (source, GEGL_TILE_VOID, x, y, z,
+ &damage);
+ }
}
}
}
diff --git a/gegl/buffer/gegl-tile.c b/gegl/buffer/gegl-tile.c
index 3392b49..eef551f 100644
--- a/gegl/buffer/gegl-tile.c
+++ b/gegl/buffer/gegl-tile.c
@@ -131,6 +131,7 @@ gegl_tile_dup (GeglTile *src)
GeglTile *tile = gegl_tile_new_bare_internal ();
g_warn_if_fail (src->lock_count == 0);
+ g_warn_if_fail (! src->damage);
src->clone_state = CLONE_STATE_CLONED;
@@ -282,16 +283,43 @@ static inline void
_gegl_tile_void_pyramid (GeglTileSource *source,
gint x,
gint y,
- gint z)
+ gint z,
+ guint64 damage)
{
- if (z > ((GeglTileStorage*)source)->seen_zoom)
+ guint new_damage;
+ guint mask;
+ gint i;
+
+ if (z >= ((GeglTileStorage*)source)->seen_zoom)
return;
- gegl_tile_source_void (source, x, y, z);
- _gegl_tile_void_pyramid (source, x/2, y/2, z+1);
+
+ damage |= damage >> 1;
+ damage |= damage >> 2;
+
+ new_damage = 0;
+ mask = 1;
+
+ for (i = 0; i < 16; i++)
+ {
+ new_damage |= damage & mask;
+ damage >>= 3;
+ mask <<= 1;
+ }
+
+ damage = (guint64) new_damage << (32 * (y & 1) + 16 * (x & 1));
+
+ x >>= 1;
+ y >>= 1;
+ z++;
+
+ gegl_tile_source_command (source, GEGL_TILE_VOID, x, y, z, &damage);
+
+ _gegl_tile_void_pyramid (source, x, y, z, damage);
}
static inline void
-gegl_tile_void_pyramid (GeglTile *tile)
+gegl_tile_void_pyramid (GeglTile *tile,
+ guint64 damage)
{
if (tile->tile_storage &&
tile->tile_storage->seen_zoom &&
@@ -301,9 +329,10 @@ gegl_tile_void_pyramid (GeglTile *tile)
g_rec_mutex_lock (&tile->tile_storage->mutex);
_gegl_tile_void_pyramid (GEGL_TILE_SOURCE (tile->tile_storage),
- tile->x/2,
- tile->y/2,
- tile->z+1);
+ tile->x,
+ tile->y,
+ tile->z,
+ damage);
if (gegl_config_threads()>1)
g_rec_mutex_unlock (&tile->tile_storage->mutex);
@@ -318,6 +347,7 @@ gegl_tile_unlock (GeglTile *tile)
if (g_atomic_int_dec_and_test (&tile->lock_count))
{
g_atomic_int_inc (&tile->rev);
+ tile->damage = 0;
if (tile->unlock_notify != NULL)
{
@@ -326,7 +356,22 @@ gegl_tile_unlock (GeglTile *tile)
if (tile->z == 0)
{
- gegl_tile_void_pyramid (tile);
+ gegl_tile_void_pyramid (tile, ~(guint64) 0);
+ }
+ }
+}
+
+void
+gegl_tile_unlock_no_void (GeglTile *tile)
+{
+ if (g_atomic_int_dec_and_test (&tile->lock_count))
+ {
+ g_atomic_int_inc (&tile->rev);
+ tile->damage = 0;
+
+ if (tile->unlock_notify != NULL)
+ {
+ tile->unlock_notify (tile, tile->unlock_notify_data);
}
}
}
@@ -349,7 +394,28 @@ gegl_tile_void (GeglTile *tile)
gegl_tile_mark_as_stored (tile);
if (tile->z == 0)
- gegl_tile_void_pyramid (tile);
+ gegl_tile_void_pyramid (tile, ~(guint64) 0);
+}
+
+gboolean
+gegl_tile_damage (GeglTile *tile,
+ guint64 damage)
+{
+ tile->damage |= damage;
+
+ if (! ~tile->damage)
+ {
+ gegl_tile_void (tile);
+
+ return TRUE;
+ }
+ else
+ {
+ if (tile->z == 0)
+ gegl_tile_void_pyramid (tile, damage);
+
+ return FALSE;
+ }
}
gboolean gegl_tile_store (GeglTile *tile)
@@ -357,7 +423,7 @@ gboolean gegl_tile_store (GeglTile *tile)
gboolean ret;
if (gegl_tile_is_stored (tile))
return TRUE;
- if (tile->tile_storage == NULL)
+ if (tile->tile_storage == NULL || tile->damage)
return FALSE;
if (gegl_config_threads()>1)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]