gegl r2200 - in trunk: . gegl/buffer
- From: ok svn gnome org
- To: svn-commits-list gnome org
- Subject: gegl r2200 - in trunk: . gegl/buffer
- Date: Sat, 19 Apr 2008 18:07:03 +0100 (BST)
Author: ok
Date: Sat Apr 19 17:07:03 2008
New Revision: 2200
URL: http://svn.gnome.org/viewvc/gegl?rev=2200&view=rev
Log:
* gegl/buffer/gegl-buffer-index.h: new file with structures for on
disk serialization of indexes for tiles in files/on swap.
* gegl/buffer/gegl-buffer-save.[ch]: changed to use new structures
large amount of sanity code added.
* gegl/buffer/gegl-buffer-load.[ch]: adapted to use new structures.
* gegl/buffer/gegl-buffer-private.h: some stuff moved from here to
index.
* gegl/buffer/Makefile.am: added gegl-buffer-index.h
Added:
trunk/gegl/buffer/gegl-buffer-index.h
Modified:
trunk/ChangeLog
trunk/gegl/buffer/Makefile.am
trunk/gegl/buffer/gegl-buffer-load.c
trunk/gegl/buffer/gegl-buffer-private.h
trunk/gegl/buffer/gegl-buffer-save.c
trunk/gegl/buffer/gegl-buffer-save.h
Modified: trunk/gegl/buffer/Makefile.am
==============================================================================
--- trunk/gegl/buffer/Makefile.am (original)
+++ trunk/gegl/buffer/Makefile.am Sat Apr 19 17:07:03 2008
@@ -4,6 +4,7 @@
gegl-buffer.c \
gegl-buffer-access.c \
gegl-buffer-share.c \
+ gegl-buffer-index.h \
gegl-buffer-save.c \
gegl-buffer-load.c \
gegl-cache.c \
Added: trunk/gegl/buffer/gegl-buffer-index.h
==============================================================================
--- (empty file)
+++ trunk/gegl/buffer/gegl-buffer-index.h Sat Apr 19 17:07:03 2008
@@ -0,0 +1,89 @@
+/* File format building blocks
+
+GeglBuffer on disk representation
+=================================
+
+*/
+
+#define GEGL_MAGIC {'G','E','G','L'}
+#define GEGL_FLAG_HEADER 1
+#define GEGL_FLAG_TILE 2
+#define GEGL_FLAG_TILE_IS_FREE 4
+#define GEGL_FLAG_TILE_FREE (GEGL_FLAG_TILE|GEGL_FLAG_TILE_IS_FREE)
+
+
+/*
+ * This header is the first 256 bytes of the GEGL buffer.
+ */
+typedef struct {
+ gchar magic[4]; /* - a 4 byte identifier */
+ guint32 flags;
+ guint64 next; /* offset to next GeglBufferBlock */
+
+ guint32 tile_width;
+ guint32 tile_height;
+ guint16 bytes_per_pixel;
+
+ gchar description[64]; /* GEGL stores the string of the babl format
+ * here, as well as after the \0 a debug string
+ * describing the buffer.
+ */
+ gint32 x; /* indication of bounding box for tiles stored. */
+ gint32 y; /* this isn't really needed as each GeglBuffer as */
+ guint32 width; /* represented on disk doesn't really have any */
+ guint32 height; /* dimension restriction. */
+
+ guint32 entry_count; /* for integrity check. */
+ gint32 padding[36]; /* Pad the structure to be 256 bytes long */
+} GeglBufferHeader;
+
+
+/* The GeglBuffer index is written to the file as a linked list with encoded
+ * offsets. Each element in the list has a GeglBufferBlock header, GeglBufferHeader
+ * abuses the length field to construct a magic marker to recognise the file.
+ */
+
+typedef struct {
+ guint32 length; /* the length of this block */
+ guint32 flags; /* flags (can be used to handle different block types
+ * differently
+ */
+ guint64 next; /*next block element in file */
+} GeglBufferBlock;
+
+/* The header is followed by elements describing tiles stored in the swap,
+ */
+typedef struct {
+ GeglBufferBlock blockdef; /* The block definition for this tile entry */
+ gint32 x; /* upperleft of tile % tile_width coordinates */
+ gint32 y;
+
+ gint32 z; /* mipmap subdivision level of tile (0=100%) */
+ guint64 offset; /* offset into file for this tile */
+ guint32 padding[23];
+} GeglBufferTile;
+
+/* A convenience union to allow quick and simple casting */
+typedef union {
+ guint32 length;
+ GeglBufferBlock block;
+ GeglBufferHeader def;
+ GeglBufferTile tile;
+} GeglBufferItem;
+
+#define struct_check_padding(type, size) \
+ if (sizeof (type) != size) \
+ {\
+ g_warning ("%s %s is %i bytes, should be %i padding is off by: %i bytes %i ints", G_STRFUNC, #type,\
+ (int) sizeof (type),\
+ size,\
+ (int) sizeof (type) - size,\
+ (int)(sizeof (type) - size) / 4);\
+ return;\
+ }
+#define GEGL_BUFFER_STRUCT_CHECK_PADDING \
+ {struct_check_padding (GeglBufferBlock, 16);\
+ struct_check_padding (GeglBufferHeader, 256);\
+ struct_check_padding (GeglBufferTile, 128);}
+#define GEGL_BUFFER_SANITY {static gboolean done=FALSE;if(!done){GEGL_BUFFER_STRUCT_CHECK_PADDING;done=TRUE;}}
+
Modified: trunk/gegl/buffer/gegl-buffer-load.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-load.c (original)
+++ trunk/gegl/buffer/gegl-buffer-load.c Sat Apr 19 17:07:03 2008
@@ -50,19 +50,84 @@
#include "gegl-buffer-save.h"
#include "gegl-cache.h"
#include "gegl-region.h"
+#include "gegl-buffer-index.h"
typedef struct
{
- GeglBufferFileHeader header;
- GList *tiles;
- gchar *path;
- gint fd;
- gint tile_size;
- gint x_tile_shift;
- gint y_tile_shift;
- Babl *format;
+ GeglBufferHeader header;
+ GList *tiles;
+ gchar *path;
+ gint fd;
+ gint tile_size;
+ Babl *format;
+ gint pos;
+ glong next_block;
+ gboolean got_header;
} LoadInfo;
+static GeglBufferItem *read_header (LoadInfo *info)
+{
+ GeglBufferBlock block;
+ GeglBufferItem *ret;
+
+ /* XXX: initialize synchronize buffer state */
+
+ if (info->pos != 0)
+ {
+ g_print ("%s must seek\n", G_STRFUNC);
+ }
+
+ info->pos += read (info->fd, &block, sizeof (GeglBufferBlock));
+
+ if (info->got_header)
+ {
+ ret = g_malloc (block.length);
+ memcpy (ret, &block, sizeof (GeglBufferBlock));
+ info->pos+=read (info->fd, ((gchar*)ret) + sizeof(GeglBufferBlock),
+ block.length - sizeof(GeglBufferBlock));
+ }
+ else
+ {
+ info->got_header = TRUE;
+ ret = g_malloc (sizeof (GeglBufferHeader));
+ memcpy (ret, &block, sizeof (GeglBufferBlock));
+ info->pos+=read (info->fd, ((gchar*)ret) + sizeof(GeglBufferBlock),
+ sizeof(GeglBufferHeader) - sizeof(GeglBufferBlock));
+ }
+ info->next_block = ret->block.next;
+ return ret;
+}
+
+
+static GeglBufferItem *read_block (LoadInfo *info)
+{
+ GeglBufferBlock block;
+ GeglBufferItem *ret;
+
+ if (info->pos != info->next_block)
+ {
+ g_print ("must seek\n");
+ }
+
+ info->pos+=read (info->fd, &block, sizeof (GeglBufferBlock));
+ if (info->got_header)
+ {
+ ret = g_malloc (block.length);
+ memcpy (ret, &block, sizeof (GeglBufferBlock));
+ info->pos+=read (info->fd, ((gchar*)ret) + sizeof(GeglBufferBlock),
+ block.length - sizeof(GeglBufferBlock));
+ }
+ else
+ {
+ info->got_header = TRUE;
+ ret = g_malloc (sizeof (GeglBufferHeader));
+ memcpy (ret, &block, sizeof (GeglBufferBlock));
+ info->pos+=read (info->fd, ((gchar*)ret) + sizeof(GeglBufferBlock),
+ sizeof(GeglBufferHeader) - sizeof(GeglBufferBlock));
+ }
+ info->next_block = ret->block.next;
+ return ret;
+}
static void
load_info_destroy (LoadInfo *info)
@@ -79,7 +144,7 @@
GList *iter;
for (iter = info->tiles; iter; iter = iter->next)
{
- g_slice_free (GeglTileEntry, iter->data);
+ g_free (iter->data);
}
g_list_free (info->tiles);
info->tiles = NULL;
@@ -87,22 +152,14 @@
g_slice_free (LoadInfo, info);
}
+
void
gegl_buffer_load (GeglBuffer *buffer,
const gchar *path)
{
LoadInfo *info = g_slice_new0 (LoadInfo);
- if (sizeof (GeglBufferFileHeader) != 256)
- {
- g_warning ("GeglBufferFileHeader is %i bytes, should be 256 padding is off by: %i bytes %i ints", (int) sizeof (GeglBufferFileHeader), (int) sizeof (GeglBufferFileHeader) - 256, (int) (sizeof (GeglBufferFileHeader) - 256) / 4);
- return;
- }
-
- if (!strcmp (info->header.magic, "_G_E_G_L"))
- {
- g_warning ("Magic is wrong!");
- }
+ GEGL_BUFFER_SANITY;
info->path = g_strdup (path);
info->fd = g_open (info->path, O_RDONLY, 0);
@@ -118,23 +175,35 @@
return;
}
- read (info->fd, &(info->header), sizeof (GeglBufferFileHeader));
+ {
+ GeglBufferItem *header= read_header (info);
+ g_assert (header);
+ memcpy (&(info->header), header, sizeof (GeglBufferHeader));
+ /*g_free (header);*/ /* is there a pointer to a string or something we're missing? */
+ }
+
+
+ if (!(info->header.magic[0]=='G' &&
+ info->header.magic[1]=='E' &&
+ info->header.magic[2]=='G' &&
+ info->header.magic[3]=='L'))
+ {
+ g_warning ("Magic is wrong! %s", info->header.magic);
+ }
- info->tile_size = info->header.tile_width * info->header.tile_height * info->header.bpp;
- info->format = babl_format (info->header.format);
- info->x_tile_shift = buffer->shift_x / info->header.tile_width;
- info->y_tile_shift = buffer->shift_y / info->header.tile_height;
+ info->tile_size = info->header.tile_width *
+ info->header.tile_height *
+ info->header.bytes_per_pixel;
+ info->format = babl_format (info->header.description);
/* load the index */
{
gint i;
- for (i = 0; i < info->header.tile_count; i++)
+ for (i = 0; i < info->header.entry_count; i++)
{
- GeglTileEntry *entry = g_slice_new0 (GeglTileEntry);
-
- read (info->fd, entry, sizeof (GeglTileEntry));
-
- info->tiles = g_list_prepend (info->tiles, entry);
+ GeglBufferItem *item = read_block (info);
+ g_assert (item);
+ info->tiles = g_list_prepend (info->tiles, item);
}
info->tiles = g_list_reverse (info->tiles);
}
@@ -145,32 +214,38 @@
gint i = 0;
for (iter = info->tiles; iter; iter = iter->next)
{
- GeglTileEntry *entry = iter->data;
- guchar *data;
- GeglTile *tile;
- gint factor = 1 << entry->z;
+ GeglBufferTile *entry = iter->data;
+ guchar *data;
+ GeglTile *tile;
tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (buffer),
- entry->x + info->x_tile_shift / factor,
- entry->y + info->y_tile_shift / factor,
- entry->z);
+ entry->x,
+ entry->y,
+ entry->z);
g_assert (tile);
gegl_tile_lock (tile);
data = gegl_tile_get_data (tile);
g_assert (data);
- read (info->fd, data, info->tile_size);
+ if (info->pos != entry->offset)
+ {
+ g_warning ("%s must seek", G_STRFUNC);
+ }
+
+ info->pos += read (info->fd, data, info->tile_size);
+ /*g_print ("%i %i\n", i, data[0]);
+ g_print ("%i %i %i %i %i %i\n", entry->x, entry->y, entry->z, tile->x, tile->y, tile->z);*/
gegl_tile_unlock (tile);
g_object_unref (G_OBJECT (tile));
- /*fprintf (stderr, "\r%f %i %i %i ", (1.0*i)/info->header.tile_count, entry->x - info->x_tile_shift, entry->y, entry->z);*/
i++;
if (GEGL_IS_CACHE (buffer) && entry->z == 0)
{
GeglRectangle rect;
+
gegl_rectangle_set (&rect, entry->x * info->header.tile_width,
entry->y * info->header.tile_height,
info->header.tile_width,
@@ -181,6 +256,5 @@
/*fprintf (stderr, "done \n");*/
}
-
load_info_destroy (info);
}
Modified: trunk/gegl/buffer/gegl-buffer-private.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-private.h (original)
+++ trunk/gegl/buffer/gegl-buffer-private.h Sat Apr 19 17:07:03 2008
@@ -1,4 +1,5 @@
/* This file is part of GEGL.
+ * ck
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Modified: trunk/gegl/buffer/gegl-buffer-save.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-save.c (original)
+++ trunk/gegl/buffer/gegl-buffer-save.c Sat Apr 19 17:07:03 2008
@@ -54,26 +54,27 @@
#include "gegl-types.h"
#include "gegl-utils.h"
#include "gegl-buffer-save.h"
+#include "gegl-buffer-index.h"
typedef struct
{
- GeglBufferFileHeader header;
- GList *tiles;
- gchar *path;
- gint fd;
- gint tile_size;
- gint x_tile_shift;
- gint y_tile_shift;
- gint offset;
+ GeglBufferHeader header;
+ GList *tiles;
+ gchar *path;
+ gint fd;
+ gint tile_size;
+ gint x_tile_shift;
+ gint y_tile_shift;
+ gint offset;
} SaveInfo;
-static GeglTileEntry *
+static GeglBufferTile *
tile_entry_new (gint x,
gint y,
gint z)
{
- GeglTileEntry *entry = g_slice_new0 (GeglTileEntry);
+ GeglBufferTile *entry = g_slice_new0 (GeglBufferTile);
entry->x = x;
entry->y = y;
@@ -82,9 +83,9 @@
}
static void
-tile_entry_destroy (GeglTileEntry *entry)
+tile_entry_destroy (GeglBufferTile *entry)
{
- g_slice_free (GeglTileEntry, entry);
+ g_slice_free (GeglBufferTile, entry);
}
static void
@@ -110,7 +111,7 @@
-static glong z_order (const GeglTileEntry *entry)
+static glong z_order (const GeglBufferTile *entry)
{
glong value;
@@ -140,8 +141,8 @@
static gint z_order_compare (gconstpointer a,
gconstpointer b)
{
- const GeglTileEntry *entryA = a;
- const GeglTileEntry *entryB = b;
+ const GeglBufferTile *entryA = a;
+ const GeglBufferTile *entryB = b;
return z_order (entryB) - z_order (entryA);
}
@@ -153,16 +154,19 @@
{
SaveInfo *info = g_slice_new0 (SaveInfo);
- if (sizeof (GeglBufferFileHeader) != 256)
- {
- g_warning ("GeglBufferFileHeader is %i bytes, should be 256 padding is off by: %i bytes %i ints",
- (int) sizeof (GeglBufferFileHeader),
- (int) sizeof (GeglBufferFileHeader) - 256,
- (int)(sizeof (GeglBufferFileHeader) - 256) / 4);
- return;
- }
+ glong prediction = 0;
+
+ GEGL_BUFFER_SANITY;
+
+ strcpy (info->header.magic, "GEGL");
+
+ /* a header should follow the same structure as a blockdef with
+ * respect to the flags and next offsets, thus this is a valid
+ * cast shortcut.
+ */
+ info->header.flags = GEGL_FLAG_HEADER;
+ info->header.next = (prediction += sizeof (GeglBufferHeader));
- strcpy (info->header.magic, "_G_E_G_L");
info->path = g_strdup (path);
info->fd = g_open (info->path,
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
@@ -178,18 +182,29 @@
return;
}
- info->header.width = buffer->extent.width;
- info->header.height = buffer->extent.height;
- info->header.x = buffer->extent.x;
- info->header.y = buffer->extent.y;
info->header.tile_width = buffer->tile_storage->tile_width;
info->header.tile_height = buffer->tile_storage->tile_height;
+ g_object_get (buffer, "px-size", &(info->header.bytes_per_pixel), NULL);
+ {
+ gchar buf[64];
+ g_snprintf (buf, 64, "%s%c\n%iÃ%i %ibpp\n\n\n\n\n\n\n\n\n\n",
+ ((Babl *) (buffer->tile_storage->format))->instance.name, 0,
+ info->header.tile_width,
+ info->header.tile_height,
+ info->header.bytes_per_pixel);
+ memcpy (info->header.description, buf, 64);
+ }
- g_object_get (buffer, "px-size", &(info->header.bpp), NULL);
-/* = gegl_buffer_px_size (buffer);*/
+ info->header.x = buffer->extent.x;
+ info->header.y = buffer->extent.y;
+ info->header.width = buffer->extent.width;
+ info->header.height = buffer->extent.height;
+
+ info->tile_size = info->header.tile_width *
+ info->header.tile_height *
+ info->header.bytes_per_pixel;
- info->tile_size = info->header.tile_width * info->header.tile_height * info->header.bpp;
- strcpy (info->header.format, ((Babl *) (buffer->tile_storage->format))->instance.name);
+ g_assert (info->tile_size % 16 == 0);
/* collect list of tiles to be written */
{
@@ -213,22 +228,21 @@
info->x_tile_shift = -buffer->shift_x / tile_width;
info->y_tile_shift = -buffer->shift_y / tile_height;
-
{
gint z;
gint factor = 1;
- for (z = 0; z < 10; z++)
+ for (z = 0; z < 1; z++)
{
bufy = y;
while (bufy < buffer->extent.y + height)
{
- gint tiledy = buffer->extent.y + buffer->shift_y + bufy;
+ gint tiledy = buffer->extent.y + bufy;
gint offsety = gegl_tile_offset (tiledy, tile_height);
gint bufx = x;
while (bufx < buffer->extent.x + width)
{
- gint tiledx = buffer->extent.x + bufx + buffer->shift_x;
+ gint tiledx = buffer->extent.x + bufx;
gint offsetx = gegl_tile_offset (tiledx, tile_width);
gint tx = gegl_tile_indice (tiledx / factor, tile_width);
@@ -236,12 +250,13 @@
if (gegl_tile_source_exist (GEGL_TILE_SOURCE (buffer), tx, ty, z))
{
- tx += info->x_tile_shift / factor;
- ty += info->y_tile_shift / factor;
+ GeglBufferTile *entry;
- info->tiles = g_list_prepend (info->tiles,
- tile_entry_new (tx, ty, z));
- info->header.tile_count++;
+ entry = tile_entry_new (tx, ty, z);
+ entry->blockdef.length = sizeof (GeglBufferTile);
+ entry->blockdef.flags = GEGL_FLAG_TILE;
+ info->tiles = g_list_prepend (info->tiles, entry);
+ info->header.entry_count++;
}
bufx += (tile_width - offsetx) * factor;
}
@@ -251,7 +266,10 @@
}
}
- info->tiles = g_list_reverse (info->tiles);
+
+ /* XXX:why was the list reversed here when it is just about to be sorted?
+ */
+/* info->tiles = g_list_reverse (info->tiles);*/
}
/* sort the list of tiles into zorder */
@@ -260,27 +278,36 @@
/* set the offset in the file each tile will be stored on */
{
GList *iter;
- gint offset = sizeof (GeglBufferFileHeader) + sizeof (GeglTileEntry) * info->header.tile_count;
+ gint predicted_offset = sizeof (GeglBufferHeader) + sizeof (GeglBufferTile) * (info->header.entry_count);
+ GeglBufferTile *last_entry = NULL;
for (iter = info->tiles; iter; iter = iter->next)
{
- GeglTileEntry *entry = iter->data;
- entry->offset = offset;
- offset += info->tile_size;
+ GeglBufferTile *entry = iter->data;
+ entry->blockdef.next = iter->next?
+ (prediction += sizeof (GeglBufferTile)):0;
+ entry->offset = predicted_offset;
+ predicted_offset += info->tile_size;
+ last_entry = entry;
}
+ last_entry->blockdef.next=0; /* terminate */
}
/* save the header */
- info->offset += write (info->fd, &info->header, sizeof (GeglBufferFileHeader));
+ info->offset += write (info->fd, &info->header, sizeof (GeglBufferHeader));
+ g_assert (info->offset == info->header.next);
/* save the index */
-
{
GList *iter;
for (iter = info->tiles; iter; iter = iter->next)
{
- GeglTileEntry *entry = iter->data;
- info->offset += write (info->fd, entry, sizeof (GeglTileEntry));
+ GeglBufferTile *entry = iter->data;
+ info->offset += write (info->fd, entry, sizeof (GeglBufferTile));
+ if (entry->blockdef.next)
+ {
+ g_assert (info->offset == entry->blockdef.next);
+ }
}
}
@@ -290,28 +317,24 @@
gint i = 0;
for (iter = info->tiles; iter; iter = iter->next)
{
- GeglTileEntry *entry = iter->data;
- guchar *data;
- GeglTile *tile;
- gint factor = 1 << entry->z;
+ GeglBufferTile *entry = iter->data;
+ guchar *data;
+ GeglTile *tile;
tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (buffer),
- entry->x - info->x_tile_shift / factor,
- entry->y - info->y_tile_shift / factor,
- entry->z);
+ entry->x,
+ entry->y,
+ entry->z);
g_assert (tile);
data = gegl_tile_get_data (tile);
g_assert (data);
+ g_assert (info->offset == entry->offset);
info->offset += write (info->fd, data, info->tile_size);
g_object_unref (G_OBJECT (tile));
- /*fprintf (stderr, "\r%f%% (%ikb)", (1.0*i)/info->header.tile_count, info->offset /1024);*/
i++;
}
- /*fprintf (stderr, "done \n");*/
+ g_assert (i == info->header.entry_count);
}
-
-
save_info_destroy (info);
}
-
Modified: trunk/gegl/buffer/gegl-buffer-save.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-save.h (original)
+++ trunk/gegl/buffer/gegl-buffer-save.h Sat Apr 19 17:07:03 2008
@@ -23,27 +23,6 @@
#include "gegl-buffer.h"
-typedef struct {
- gchar magic[16];
- gint width, height, x, y;
- gchar format[32];
- guint tile_width, tile_height;
- guint bpp;
- gint tile_count;
-
- guint padding1[12];
- guint padding[32];
-} GeglBufferFileHeader;
-
-typedef struct {
- gint x;
- gint y;
- gint z;
- guint offset; /* offset into file */
- guint flags; /* flags? not used? */
-
- guint padding1[8];
-} GeglTileEntry;
void gegl_buffer_save (GeglBuffer *buffer,
const gchar *path,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]