1 #ifndef __GEGL_BUFFER_INDEX_H
2 #define __GEGL_BUFFER_INDEX_H
3 /* File format building blocks
4 
5 GeglBuffer on disk representation
6 =================================
7 
8 */
9 
10 
11 /* Increase this number when the structures change.*/
12 #define GEGL_FILE_SPEC_REV     0
13 #define GEGL_MAGIC             {'G','E','G','L'}
14 
15 #define GEGL_FLAG_TILE         1
16 #define GEGL_FLAG_FREE_TILE    0xf+2
17 
18 /* a VOID message, indicating that the specified tile has been rewritten */
19 #define GEGL_FLAG_INVALIDATED  2
20 
21 /* these flags are used for the header, the lower bits of the
22  * header store the revision
23  */
24 #define GEGL_FLAG_LOCKED       (1<<(8+0))
25 #define GEGL_FLAG_FLUSHED      (1<<(8+1))
26 #define GEGL_FLAG_IS_HEADER    (1<<(8+3))
27 
28 /* The default header we expect to see on a file is that it is
29  * flushed, and has the revision the file conforms to written
30  * to it.
31  */
32 #define  GEGL_FLAG_HEADER    (GEGL_FLAG_FLUSHED  |\
33                               GEGL_FLAG_IS_HEADER|\
34                               GEGL_FILE_SPEC_REV)
35 
36 /*
37  * This header is the first 256 bytes of the GEGL buffer.
38  */
39 typedef struct {
40   gchar   magic[4];    /* - a 4 byte identifier */
41   guint32 flags;       /* the header flags is used to encode state and revision
42                           */
43   guint64 next;        /* offset to first GeglBufferBlock */
44 
45   guint32 tile_width;
46   guint32 tile_height;
47   guint16 bytes_per_pixel;
48 
49   gchar   description[64]; /* GEGL stores the string of the babl format
50                             * here, as well as after the \0 a debug string
51                             * describing the buffer.
52                             */
53 
54   /* the ROI could come as a separate block */
55   gint32  x;               /* indication of bounding box for tiles stored. */
56   gint32  y;               /* this isn't really needed as each GeglBuffer as */
57   guint32 width;           /* represented on disk doesn't really have any */
58   guint32 height;          /* dimension restriction. */
59 
60   guint32 rev;             /* if it changes on disk it means the index has changed */
61 
62   gint32  padding[36];     /* Pad the structure to be 256 bytes long */
63 } GeglBufferHeader;
64 
65 /* the revision of the format is stored in the flags of the header in the
66  * lower 8 bits
67  */
68 #define gegl_buffer_header_get_rev(header)  (((GeglBufferHeader*)(header))->flags&0xff)
69 
70 /* The GeglBuffer index is written to the file as a linked list of
71  * GeglBufferBlock's, each block encodes it's own length and the offset
72  * of the file which the next block can be found. The last block in the
73  * list has the next offset set to 0.
74  */
75 
76 typedef struct {
77   guint32  length; /* the length of this block */
78   guint32  flags;  /* flags (can be used to handle different block types
79                     * differently
80                     */
81   guint64  next;   /*next block element in file, this is the offset in the
82                     *file that the next block in the chain resides at
83                     */
84 } GeglBufferBlock;
85 
86 /* The header is followed by entries describing tiles stored in the swap,
87  */
88 typedef struct {
89   GeglBufferBlock block; /* The block definition for this tile entry   */
90   guint64 offset;        /* offset into file for this tile             */
91   gint32  x;             /* upperleft of tile % tile_width coordinates */
92   gint32  y;
93 
94   gint32  z;             /* mipmap subdivision level of tile (0=100%)  */
95 
96   guint32 rev;           /* revision, if a buffer is monitored for header
97                             revision changes, the existing loaded index
98                             can be compare the revision of tiles and update
99                             own state when revision differs. */
100 } GeglBufferTile;
101 
102 /* A convenience union to allow quick and simple casting */
103 typedef union {
104   guint32          length;
105   GeglBufferBlock  block;
106   GeglBufferHeader header;
107   GeglBufferTile   tile;
108 } GeglBufferItem;
109 
110 /* functions to initialize data structures */
111 GeglBufferTile * gegl_tile_entry_new (gint x,
112                                       gint y,
113                                       gint z);
114 
115 /* intializing the header causes the format to be written out
116  * as well as a hidden comment after the zero terminated format
117  * with additional human readable version of information from the header.
118  */
119 void gegl_buffer_header_init (GeglBufferHeader *header,
120                               gint              tile_width,
121                               gint              tile_height,
122                               gint              bpp,
123                               const Babl*       format);
124 
125 void gegl_tile_entry_destroy (GeglBufferTile *entry);
126 
127 GeglBufferItem *gegl_buffer_read_header(int      i,
128                                         goffset *offset);
129 GList          *gegl_buffer_read_index (int      i,
130                                         goffset *offset);
131 
132 #define struct_check_padding(type, size) \
133   if (sizeof (type) != size) \
134     {\
135       g_warning ("%s %s is %i bytes, should be %i padding is off by: %i bytes %i ints", G_STRFUNC, #type,\
136          (int) sizeof (type),\
137          size,\
138          (int) sizeof (type) - size,\
139          (int)(sizeof (type) - size) / 4);\
140       return;\
141     }
142 #define GEGL_BUFFER_STRUCT_CHECK_PADDING \
143   {struct_check_padding (GeglBufferBlock, 16);\
144   struct_check_padding (GeglBufferHeader, 256);}
145 #define GEGL_BUFFER_SANITY {static gboolean done=FALSE;if(!done){GEGL_BUFFER_STRUCT_CHECK_PADDING;done=TRUE;}}
146 
147 #endif
148