[gegl] buffer: track empty tiles in the swap backend
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: track empty tiles in the swap backend
- Date: Wed, 6 May 2020 09:18:43 +0000 (UTC)
commit bb3afed500b88e3ced5c62153104319402e3b3ec
Author: Ell <ell_se yahoo com>
Date: Wed May 6 10:15:23 2020 +0300
buffer: track empty tiles in the swap backend
In GeglTileBackendSwap, track stored empty tiles on TILE_SET, and
return corresponding empty tiles on TILE_GET. We'd previously
ignore empty tiles on TILE_SET, and rely on GeglTileHandlerEmpty to
recreate them on TILE_GET.
This allows us to properly store empty tiles in the swap for
buffers with custom tile handlers, that may return non-empty tiles
when there's no existing underlying tile. More importantly, it
allows us to introduce buffers with uninitialized data, while still
being able to properly store explicitly-created empty tiles.
Note that empty tiles don't consume any disk space, and only impose
bookkeeping overhead.
gegl/buffer/gegl-tile-backend-swap.c | 74 ++++++++++++++++++++++++------------
1 file changed, 49 insertions(+), 25 deletions(-)
---
diff --git a/gegl/buffer/gegl-tile-backend-swap.c b/gegl/buffer/gegl-tile-backend-swap.c
index 58d424f29..e90bca428 100644
--- a/gegl/buffer/gegl-tile-backend-swap.c
+++ b/gegl/buffer/gegl-tile-backend-swap.c
@@ -40,6 +40,7 @@
#include "gegl-tile-alloc.h"
#include "gegl-tile-backend.h"
#include "gegl-tile-backend-swap.h"
+#include "gegl-tile-handler-empty.h"
#include "gegl-debug.h"
#include "gegl-buffer-config.h"
@@ -82,6 +83,12 @@ typedef enum
OP_DESTROY,
} ThreadOp;
+enum
+{
+ BLOCK_OFFSET_NONE = -1,
+ BLOCK_OFFSET_EMPTY = -2
+};
+
typedef struct
{
gint ref_count;
@@ -459,7 +466,7 @@ gegl_tile_backend_swap_free_block (SwapBlock *block)
start = block->offset;
end = start + block->size;
- block->offset = -1;
+ block->offset = BLOCK_OFFSET_NONE;
total -= end - start;
@@ -550,7 +557,7 @@ gegl_tile_backend_swap_free_data (ThreadParams *params)
}
}
-static void
+__attribute__ ((noinline)) static void
gegl_tile_backend_swap_write (ThreadParams *params)
{
const guint8 *data;
@@ -606,7 +613,7 @@ gegl_tile_backend_swap_write (ThreadParams *params)
gegl_tile_backend_swap_free_block (params->block);
- offset = -1;
+ offset = BLOCK_OFFSET_NONE;
}
if (offset < 0)
@@ -672,7 +679,7 @@ error:
static void
gegl_tile_backend_swap_destroy (ThreadParams *params)
{
- if (params->block->offset >= 0)
+ if (params->block->offset != BLOCK_OFFSET_NONE)
g_atomic_pointer_add (&total_uncompressed, -params->size);
gegl_tile_backend_swap_free_block (params->block);
@@ -795,12 +802,21 @@ gegl_tile_backend_swap_entry_read (GeglTileBackendSwap *self,
g_mutex_unlock (&queue_mutex);
- if (offset < 0 || in_fd < 0)
+ if (offset == BLOCK_OFFSET_NONE || in_fd < 0)
{
g_warning ("no swap storage allocated for tile");
return NULL;
}
+ if (offset == BLOCK_OFFSET_EMPTY)
+ {
+ tile = gegl_tile_handler_empty_new_tile (tile_size);
+
+ gegl_tile_mark_as_stored (tile);
+
+ return tile;
+ }
+
tile = gegl_tile_new (tile_size);
dest = gegl_tile_get_data (tile);
gegl_tile_mark_as_stored (tile);
@@ -953,7 +969,7 @@ gegl_tile_backend_swap_block_create (void)
block->ref_count = 1;
block->link = NULL;
- block->offset = -1;
+ block->offset = BLOCK_OFFSET_NONE;
return block;
}
@@ -1003,7 +1019,7 @@ gegl_tile_backend_swap_block_unref (SwapBlock *block,
g_queue_unlink (queue, link);
g_queue_push_head_link (queue, link);
}
- else
+ else if (block->offset >= 0)
{
ThreadParams *params;
@@ -1018,6 +1034,13 @@ gegl_tile_backend_swap_block_unref (SwapBlock *block,
*/
gegl_tile_backend_swap_push_queue (params, /* head = */ TRUE);
}
+ else
+ {
+ if (block->offset != BLOCK_OFFSET_NONE)
+ g_atomic_pointer_add (&total_uncompressed, -tile_size);
+
+ gegl_tile_backend_swap_block_free (block);
+ }
if (lock)
g_mutex_unlock (&queue_mutex);
@@ -1113,30 +1136,22 @@ gegl_tile_backend_swap_set_tile (GeglTileSource *self,
{
GeglTileBackendSwap *swap;
SwapEntry *entry;
+ gint tile_size;
- if (tile->is_zero_tile)
- {
- /* the tile is empty. avoid an expensive write to disk, and just drop
- * the existing tile (if there is one); the empty tile handler will serve
- * a new empty tile upon request.
- */
- gegl_tile_backend_swap_void_tile (self, x, y, z);
-
- gegl_tile_mark_as_stored (tile);
-
- return GINT_TO_POINTER (TRUE);
- }
-
- swap = GEGL_TILE_BACKEND_SWAP (self);
- entry = gegl_tile_backend_swap_lookup_entry (swap, x, y, z);
+ swap = GEGL_TILE_BACKEND_SWAP (self);
+ entry = gegl_tile_backend_swap_lookup_entry (swap, x, y, z);
+ tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (swap));
if (entry)
{
- if (! gegl_tile_backend_swap_block_is_unique (entry->block))
+ if ((! tile->is_zero_tile &&
+ ! gegl_tile_backend_swap_block_is_unique (entry->block)) ||
+ ( tile->is_zero_tile &&
+ entry->block->offset != BLOCK_OFFSET_EMPTY))
{
gegl_tile_backend_swap_block_unref (
entry->block,
- gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (swap)),
+ tile_size,
TRUE);
entry->block = gegl_tile_backend_swap_block_create ();
}
@@ -1147,7 +1162,16 @@ gegl_tile_backend_swap_set_tile (GeglTileSource *self,
g_hash_table_insert (swap->index, entry, entry);
}
- gegl_tile_backend_swap_entry_write (swap, entry, tile);
+ if (! tile->is_zero_tile)
+ {
+ gegl_tile_backend_swap_entry_write (swap, entry, tile);
+ }
+ else if (entry->block->offset != BLOCK_OFFSET_EMPTY)
+ {
+ entry->block->offset = BLOCK_OFFSET_EMPTY;
+
+ g_atomic_pointer_add (&total_uncompressed, +tile_size);
+ }
gegl_tile_mark_as_stored (tile);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]