Commit ac01c07d authored by Øyvind Kolås's avatar Øyvind Kolås
Browse files

Make GeglBuffer able to use a serialized buffer directly as swap, as

well as synchronize a buffer so that it can be resumed from swap.
* gegl/buffer/gegl-buffer-load.c:
(gegl_buffer_read_header): moved magic check to header read.
(gegl_buffer_open): replaced by GeglBuffer being backed by a
serialized GeglBuffer.
* gegl/buffer/gegl-buffer.c: (gegl_buffer_constructor),
(gegl_buffer_class_init), (gegl_buffer_new_from_path):
made it possible to create buffer using a path.
* gegl/buffer/gegl-tile-backend-file.c: (flush),
(gegl_tile_backend_file_constructor): allow opening already
written swap files.
* gegl/buffer/gegl-tile-backend.h: provide some private storage to
store a pointer to the header used to read in a buffer.

svn path=/trunk/; revision=2217
parent feaf839c
2008-04-22 Øyvind Kolås <pippin@gimp.org>
Make GeglBuffer able to use a serialized buffer directly as swap, as
well as synchronize a buffer so that it can be resumed from swap.
* gegl/buffer/gegl-buffer-load.c:
(gegl_buffer_read_header): moved magic check to header read.
(gegl_buffer_open): replaced by GeglBuffer being backed by a
serialized GeglBuffer.
* gegl/buffer/gegl-buffer.c: (gegl_buffer_constructor),
(gegl_buffer_class_init), (gegl_buffer_new_from_path):
made it possible to create buffer using a path.
* gegl/buffer/gegl-tile-backend-file.c: (flush),
(gegl_tile_backend_file_constructor): allow opening already
written swap files.
* gegl/buffer/gegl-tile-backend.h: provide some private storage to
store a pointer to the header used to read in a buffer.
2008-04-22 Øyvind Kolås <pippin@gimp.org>
 
* gegl/buffer/gegl-buffer-index.h: added gegl_buffer_read_header and
......
......@@ -90,6 +90,15 @@ gegl_buffer_read_header (GInputStream *i,
ret->header.tile_width,
ret->header.tile_height,
(guint)ret->block.next);
if (!(ret->header.magic[0]=='G' &&
ret->header.magic[1]=='E' &&
ret->header.magic[2]=='G' &&
ret->header.magic[3]=='L'))
{
g_warning ("Magic is wrong! %s", ret->header.magic);
}
return ret;
}
......@@ -214,10 +223,16 @@ static void sanity(void) { GEGL_BUFFER_SANITY; }
GeglBuffer *
gegl_buffer_open (const gchar *path)
{
sanity();
return g_object_new (GEGL_TYPE_BUFFER, "path", path, NULL);
#if 0 /* old code that feeds tile by tile into the buffer */
GeglBuffer *ret;
LoadInfo *info = g_slice_new0 (LoadInfo);
sanity();
LoadInfo *info = g_slice_new0 (LoadInfo);
info->path = g_strdup (path);
info->file = g_file_new_for_commandline_arg (info->path);
......@@ -241,13 +256,6 @@ gegl_buffer_open (const gchar *path)
}
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 *
......@@ -313,4 +321,5 @@ gegl_buffer_open (const gchar *path)
load_info_destroy (info);
return ret;
#endif
}
......@@ -41,6 +41,7 @@
#include <glib-object.h>
#include <glib/gstdio.h>
#include <glib/gprintf.h>
#include <gio/gio.h>
#include "gegl-types.h"
......@@ -60,6 +61,7 @@
#include "gegl-types.h"
#include "gegl-utils.h"
#include "gegl-id-pool.h"
#include "gegl-buffer-index.h"
G_DEFINE_TYPE (GeglBuffer, gegl_buffer, GEGL_TYPE_TILE_HANDLER)
......@@ -93,6 +95,8 @@ static GeglBuffer * gegl_buffer_new_from_format (const void *babl_format,
gint y,
gint width,
gint height);
static GeglBuffer *
gegl_buffer_new_from_path (const gchar *path);
static inline gint needed_tiles (gint w,
gint stride)
......@@ -375,24 +379,52 @@ gegl_buffer_constructor (GType type,
* source (this adds a redirectin buffer in between for
* all "allocated from format", type buffers.
*/
g_assert (buffer->format);
source = GEGL_TILE_SOURCE (gegl_buffer_new_from_format (buffer->format,
buffer->extent.x,
buffer->extent.y,
buffer->extent.width,
buffer->extent.height));
/* after construction,. x and y should be set to reflect
* the top level behavior exhibited by this buffer object.
*/
g_object_set (buffer,
"source", source,
NULL);
g_object_unref (source);
g_assert (source);
backend = gegl_buffer_backend (GEGL_BUFFER (source));
g_assert (backend);
if (buffer->path)
{
GeglBufferHeader *header;
source = GEGL_TILE_SOURCE (gegl_buffer_new_from_path (buffer->path));
/* after construction,. x and y should be set to reflect
* the top level behavior exhibited by this buffer object.
*/
g_object_set (buffer,
"source", source,
NULL);
g_object_unref (source);
g_assert (source);
backend = gegl_buffer_backend (GEGL_BUFFER (source));
g_assert (backend);
header = backend->header;
buffer->extent.x = header->x;
buffer->extent.y = header->y;
buffer->extent.width = header->width;
buffer->extent.height = header->height;
buffer->format = backend->format;
}
else if (buffer->format)
{
source = GEGL_TILE_SOURCE (gegl_buffer_new_from_format (buffer->format,
buffer->extent.x,
buffer->extent.y,
buffer->extent.width,
buffer->extent.height));
/* after construction,. x and y should be set to reflect
* the top level behavior exhibited by this buffer object.
*/
g_object_set (buffer,
"source", source,
NULL);
g_object_unref (source);
g_assert (source);
backend = gegl_buffer_backend (GEGL_BUFFER (source));
g_assert (backend);
}
else
{
g_warning ("not enough data to have a tile source for our buffer");
}
}
g_assert (backend);
......@@ -650,9 +682,9 @@ gegl_buffer_class_init (GeglBufferClass *class)
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class, PROP_PATH,
g_param_spec_string ("path", "Path", "URI to where the buffer is stored",
"/tmp/hm",
G_PARAM_READWRITE));
g_param_spec_string ("path", "Path",
"URI to where the buffer is stored",
NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
}
static void
......@@ -823,6 +855,30 @@ gegl_buffer_interpolation_from_string (const gchar *string)
static GeglBuffer *
gegl_buffer_new_from_path (const gchar *path)
{
GeglTileStorage *tile_storage;
GeglBuffer *buffer;
tile_storage = g_object_new (GEGL_TYPE_TILE_STORAGE,
"format", babl_format,
"path", path,
NULL);
buffer = g_object_new (GEGL_TYPE_BUFFER,
"source", tile_storage,
/*"x", x,
"y", y,
"width", width,
"height", height,*/
NULL);
/* XXX: query backend about width/height? (this seems odd) */
g_object_unref (tile_storage);
return buffer;
}
static GeglBuffer *
gegl_buffer_new_from_format (const void *babl_format,
gint x,
......
......@@ -70,6 +70,10 @@ struct _GeglTileBackendFile
* to be able to keep track of the ->next
* offsets in the blocks.
*/
/* loading buffer */
GList *tiles;
};
......@@ -468,6 +472,7 @@ flush (GeglTileSource *source,
tiles = g_hash_table_get_keys (self->index);
/* g_assert(g_seekable_seek (G_SEEKABLE (self->o), self->header.next, G_SEEK_SET, NULL, NULL));*/
/* save the index */
{
GList *iter;
......@@ -648,32 +653,71 @@ gegl_tile_backend_file_constructor (GType type,
{
GObject *object;
GeglTileBackendFile *self;
GeglTileBackend *backend;
object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
self = GEGL_TILE_BACKEND_FILE (object);
backend = GEGL_TILE_BACKEND (object);
GEGL_NOTE (TILE_BACKEND, "constructing file backend: %s", self->path);
self->file = g_file_new_for_commandline_arg (self->path);
self->o = G_OUTPUT_STREAM (g_file_replace (self->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
g_output_stream_flush (self->o, NULL, NULL);
self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
self->next_pre_alloc = 256; /* reserved space for header */
self->total = 256; /* reserved space for header */
g_assert(g_seekable_seek (G_SEEKABLE (self->o), 256, G_SEEK_SET, NULL, NULL));
self->index = g_hash_table_new (hashfunc, equalfunc);
if (!self->file)
/* if the file already exist we try to open it for appending instead of replacing */
if (g_file_query_exists (self->file, NULL))
{
g_warning ("Unable to open swap file '%s'\n",self->path);
return NULL;
goffset offset;
self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
self->o = G_OUTPUT_STREAM (g_file_append_to (self->file, G_FILE_CREATE_NONE, NULL, NULL));
self->header = gegl_buffer_read_header (self->i, &offset)->header;
backend->tile_width = self->header.tile_width;
backend->tile_height = self->header.tile_height;
backend->format = babl_format (self->header.description);
/* we are overriding all of the work of the actual constructor here */
backend->px_size = backend->format->format.bytes_per_pixel;
backend->tile_size = backend->tile_width * backend->tile_height * backend->px_size;
offset = self->header.next;
self->tiles = gegl_buffer_read_index (self->i, &offset);
/* insert each of the entries into the hash table */
{
/* compute total from and next pre alloc by monitoring tiles as they
* are added here
*/
goffset max=0;
GList *iter;
for (iter = self->tiles; iter; iter=iter->next)
{
GeglBufferItem *item = iter->data;
if (item->tile.offset > max)
max = item->tile.offset + backend->tile_size;
g_hash_table_insert (self->index, iter->data, iter->data);
}
g_list_free (self->tiles);
self->next_pre_alloc = max;
self->total = max;
self->tiles = NULL;
}
}
else
{
self->o = G_OUTPUT_STREAM (g_file_replace (self->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
g_output_stream_flush (self->o, NULL, NULL);
self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
self->next_pre_alloc = 256; /* reserved space for header */
self->total = 256; /* reserved space for header */
g_assert(g_seekable_seek (G_SEEKABLE (self->o), 256, G_SEEK_SET, NULL, NULL));
}
g_assert (self->file);
g_assert (self->i);
g_assert (self->o);
self->index = g_hash_table_new (hashfunc, equalfunc);
backend->header = &self->header;
return object;
}
......
......@@ -39,6 +39,9 @@ struct _GeglTileBackend
Babl *format; /* defaults to the babl format "R'G'B'A u8" */
gint px_size; /* size of a single pixel in bytes */
gint tile_size; /* size of an entire tile in bytes */
/* private */
gpointer header;
};
struct _GeglTileBackendClass
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment