1 /* This file is part of GEGL.
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, see <https://www.gnu.org/licenses/>.
15  *
16  * Copyright 2006-2008 Øyvind Kolås <pippin@gimp.org>
17  */
18 
19 #ifndef __GEGL_BUFFER_PRIVATE_H__
20 #define __GEGL_BUFFER_PRIVATE_H__
21 
22 #include "gegl-buffer-types.h"
23 #include "gegl-buffer.h"
24 #include "gegl-tile-handler.h"
25 #include "gegl-buffer-iterator.h"
26 
27 #define GEGL_BUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GEGL_TYPE_BUFFER, GeglBufferClass))
28 #define GEGL_IS_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GEGL_TYPE_BUFFER))
29 #define GEGL_BUFFER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GEGL_TYPE_BUFFER, GeglBufferClass))
30 
31 typedef struct _GeglBufferClass GeglBufferClass;
32 
33 struct _GeglBuffer
34 {
35   GeglTileHandler   parent_instance; /* which is a GeglTileHandler which has a
36                                         source field which is used for chaining
37                                         sub buffers with their anchestors */
38 
39   GeglRectangle     extent;        /* the dimensions of the buffer */
40 
41   const Babl       *format;  /* the pixel format used for pixels in this
42                                 buffer */
43   const Babl  *soft_format;  /* the format the buffer pretends to be, might
44                                 be different from format */
45 
46   gint              shift_x; /* The relative offset of origins compared with */
47   gint              shift_y; /* anchestral tile_storage buffer, during       */
48                              /* construction relative to immediate source    */
49 
50   GeglRectangle     abyss;
51   gboolean          abyss_tracks_extent; /* specifies whether the abyss rectangle
52                                             should track any modifications to the
53                                             extent rectangle */
54 
55   GeglTileStorage  *tile_storage;
56 
57   gint              tile_width;
58   gint              tile_height;
59   gchar            *path;
60 
61   gint              lock_count;
62 
63   gpointer         *alloc_stack_trace; /* Stack trace for allocation,
64                                           useful for debugging */
65   gint              alloc_stack_size;
66 
67   gint              changed_signal_connections; /* to avoid firing changed signals
68                                                    with no listeners */
69   gint              changed_signal_freeze_count;
70   GeglRectangle     changed_signal_accumulator;
71 
72   GeglTileBackend  *backend;
73 
74   gboolean          initialized;
75 };
76 
77 struct _GeglBufferClass
78 {
79   GeglTileHandlerClass parent_class;
80 };
81 
82 
83 gint              gegl_buffer_leaks       (void);
84 
85 void              gegl_buffer_stats       (void);
86 
87 void              gegl_tile_cache_init    (void);
88 
89 void              gegl_tile_cache_destroy (void);
90 
91 void              gegl_tile_backend_swap_cleanup (void);
92 
93 GeglTileBackend * gegl_buffer_backend     (GeglBuffer *buffer);
94 GeglTileBackend * gegl_buffer_backend2    (GeglBuffer *buffer); /* non-cached */
95 
96 gboolean          gegl_buffer_is_shared   (GeglBuffer *buffer);
97 
98 #define GEGL_BUFFER_DISABLE_LOCKS 1
99 
100 #ifdef GEGL_BUFFER_DISABLE_LOCKS
101 #define           gegl_buffer_try_lock(a)   (TRUE)
102 #define           gegl_buffer_lock(a)       do{}while(0)
103 #define           gegl_buffer_unlock(a)       do{}while(0)
104 #else
105 gboolean          gegl_buffer_try_lock    (GeglBuffer *buffer);
106 gboolean          gegl_buffer_lock        (GeglBuffer *buffer);
107 gboolean          gegl_buffer_unlock      (GeglBuffer *buffer);
108 #endif
109 
110 void              gegl_buffer_set_unlocked (GeglBuffer          *buffer,
111                                             const GeglRectangle *rect,
112                                             gint                 level,
113                                             const Babl          *format,
114                                             const void          *src,
115                                             gint                 rowstride);
116 
117 void              gegl_buffer_set_unlocked_no_notify (GeglBuffer          *buffer,
118                                                       const GeglRectangle *rect,
119                                                       gint                 level,
120                                                       const Babl          *format,
121                                                       const void          *src,
122                                                       gint                 rowstride);
123 
124 void              gegl_buffer_get_unlocked (GeglBuffer          *buffer,
125                                             gdouble              scale,
126                                             const GeglRectangle *rect,
127                                             const Babl          *format,
128                                             gpointer             dest_buf,
129                                             gint                 rowstride,
130                                             GeglAbyssPolicy      repeat_mode);
131 
132 GeglBuffer *      gegl_buffer_new_ram     (const GeglRectangle *extent,
133                                            const Babl          *format);
134 
135 void              gegl_buffer_emit_changed_signal (GeglBuffer *buffer,
136                                                    const GeglRectangle *rect);
137 
138 /* the instance size of a GeglTile is a bit large, and should if possible be
139  * trimmed down
140  */
141 struct _GeglTile
142 {
143  /* GObject          parent_instance;*/
144   gint             ref_count;
145 
146   guchar          *data;        /* actual pixel data for tile, a linear buffer*/
147   gint             size;        /* The size of the linear buffer */
148 
149   GeglTileStorage *tile_storage; /* the buffer from which this tile was
150                                   * retrieved needed for the tile to be able to
151                                   * store itself back (for instance when it is
152                                   * unreffed for the last time)
153                                   */
154   gint             x, y, z;
155 
156 
157   guint            rev;         /* this tile revision */
158   guint            stored_rev;  /* what revision was we when we from tile_storage?
159                                    (currently set to 1 when loaded from disk */
160 
161   gint             lock_count;       /* number of outstanding write locks */
162   gint             read_lock_count;  /* number of outstanding read locks */
163   guint            is_zero_tile:1;   /* whether the tile data is fully zeroed
164                                       * (allowing for false negatives, but not
165                                       * false positives)
166                                       */
167   guint            is_global_tile:1; /* whether the tile data is global (and
168                                       * therefore can never be owned by a
169                                       * single mutable tile)
170                                       */
171   guint            keep_identity:1;  /* maintain data pointer identity, rather
172                                       * than data content only
173                                       */
174 
175   gint             clone_state; /* tile clone/unclone state & spinlock */
176   gint            *n_clones;    /* an array of two atomic counters, shared
177                                  * among all tiles sharing the same data.
178                                  * the first counter indicates the number of
179                                  * tiles sharing the data, and the second
180                                  * counter indicates how many of those tiles
181                                  * are in the cache.
182                                  */
183 
184   guint64          damage;
185 
186   /* called when the tile is about to be destroyed */
187   GDestroyNotify   destroy_notify;
188   gpointer         destroy_notify_data;
189 
190   /* called when the tile has been unlocked which typically means tile
191    * data has changed
192    */
193   GeglTileCallback unlock_notify;
194   gpointer         unlock_notify_data;
195 };
196 
197 gboolean gegl_tile_needs_store    (GeglTile *tile);
198 void     gegl_tile_unlock_no_void (GeglTile *tile);
199 gboolean gegl_tile_damage         (GeglTile *tile,
200                                    guint64   damage);
201 
202 void _gegl_buffer_drop_hot_tile (GeglBuffer *buffer);
203 
204 GeglRectangle _gegl_get_required_for_scale (const GeglRectangle *roi,
205                                             gdouble              scale);
206 
207 gboolean gegl_buffer_scan_compatible (GeglBuffer *bufferA,
208                                       gint        xA,
209                                       gint        yA,
210                                       GeglBuffer *bufferB,
211                                       gint        xB,
212                                       gint        yB);
213 
214 
215 extern void (*gegl_tile_handler_cache_ext_flush) (void *tile_handler_cache, const GeglRectangle *rect);
216 extern void (*gegl_buffer_ext_flush) (GeglBuffer *buffer, const GeglRectangle *rect);
217 extern void (*gegl_buffer_ext_invalidate) (GeglBuffer *buffer, const GeglRectangle *rect);
218 
219 
220 #ifndef __GEGL_TILE_H__
221 #define gegl_tile_get_data(tile)  ((tile)->data)
222 #endif
223 
224 #define gegl_tile_n_clones(tile)         (&(tile)->n_clones[0])
225 #define gegl_tile_n_cached_clones(tile)  (&(tile)->n_clones[1])
226 
227 /* computes the positive integer remainder (also for negative dividends)
228  */
229 #define GEGL_REMAINDER(dividend, divisor) \
230                    (((dividend) < 0) ? \
231                     (divisor) - 1 - ((-((dividend) + 1)) % (divisor)) : \
232                     (dividend) % (divisor))
233 
234 #define gegl_tile_offset(coordinate, stride) GEGL_REMAINDER((coordinate), (stride))
235 
236 /* helper function to compute tile indices and offsets for coordinates
237  * based on a tile stride (tile_width or tile_height)
238  */
239 #define gegl_tile_indice(coordinate,stride) \
240   (((coordinate) >= 0)?\
241       (coordinate) / (stride):\
242       ((((coordinate) + 1) /(stride)) - 1))
243 
244 #endif
245