#ifndef __GEGL_BUFFER_INDEX_H #define __GEGL_BUFFER_INDEX_H /* File format building blocks GeglBuffer on disk representation ================================= */ /* Increase this number when the structures change.*/ #define GEGL_FILE_SPEC_REV 0 #define GEGL_MAGIC {'G','E','G','L'} #define GEGL_FLAG_TILE 1 #define GEGL_FLAG_FREE_TILE 0xf+2 /* a VOID message, indicating that the specified tile has been rewritten */ #define GEGL_FLAG_INVALIDATED 2 /* these flags are used for the header, the lower bits of the * header store the revision */ #define GEGL_FLAG_LOCKED (1<<(8+0)) #define GEGL_FLAG_FLUSHED (1<<(8+1)) #define GEGL_FLAG_IS_HEADER (1<<(8+3)) /* The default header we expect to see on a file is that it is * flushed, and has the revision the file conforms to written * to it. */ #define GEGL_FLAG_HEADER (GEGL_FLAG_FLUSHED |\ GEGL_FLAG_IS_HEADER|\ GEGL_FILE_SPEC_REV) /* * This header is the first 256 bytes of the GEGL buffer. */ typedef struct { gchar magic[4]; /* - a 4 byte identifier */ guint32 flags; /* the header flags is used to encode state and revision */ guint64 next; /* offset to first 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. */ /* the ROI could come as a separate block */ 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 rev; /* if it changes on disk it means the index has changed */ gint32 padding[36]; /* Pad the structure to be 256 bytes long */ } GeglBufferHeader; /* the revision of the format is stored in the flags of the header in the * lower 8 bits */ #define gegl_buffer_header_get_rev(header) (((GeglBufferHeader*)(header))->flags&0xff) /* The GeglBuffer index is written to the file as a linked list of * GeglBufferBlock's, each block encodes it's own length and the offset * of the file which the next block can be found. The last block in the * list has the next offset set to 0. */ 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, this is the offset in the *file that the next block in the chain resides at */ } GeglBufferBlock; /* The header is followed by entries describing tiles stored in the swap, */ typedef struct { GeglBufferBlock block; /* The block definition for this tile entry */ guint64 offset; /* offset into file for this tile */ gint32 x; /* upperleft of tile % tile_width coordinates */ gint32 y; gint32 z; /* mipmap subdivision level of tile (0=100%) */ guint32 rev; /* revision, if a buffer is monitored for header revision changes, the existing loaded index can be compare the revision of tiles and update own state when revision differs. */ } GeglBufferTile; /* A convenience union to allow quick and simple casting */ typedef union { guint32 length; GeglBufferBlock block; GeglBufferHeader header; GeglBufferTile tile; } GeglBufferItem; /* functions to initialize data structures */ GeglBufferTile * gegl_tile_entry_new (gint x, gint y, gint z); /* intializing the header causes the format to be written out * as well as a hidden comment after the zero terminated format * with additional human readable information about the header. */ void gegl_buffer_header_init (GeglBufferHeader *header, gint tile_width, gint tile_height, gint bpp, const Babl* format); void gegl_tile_entry_destroy (GeglBufferTile *entry); GeglBufferItem *gegl_buffer_read_header(int i, goffset *offset); GList *gegl_buffer_read_index (int i, goffset *offset); #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);} #define GEGL_BUFFER_SANITY {static gboolean done=FALSE;if(!done){GEGL_BUFFER_STRUCT_CHECK_PADDING;done=TRUE;}} #endif