1
#define __NR_PIXBLOCK_C__
4
* \brief Allocation/Setup of NRPixBlock objects. Pixel store functions.
7
* (C) 1999-2002 Lauris Kaplinski <lauris@kaplinski.com>
8
* 2008, Jasper van de Gronde <th.v.d.gonde@hccnet.nl>
10
* This code is in the Public Domain
16
#include <glib/gmem.h>
17
#include "nr-pixblock.h"
19
/// Size of buffer that needs no allocation (default 4).
20
#define NR_TINY_MAX sizeof (unsigned char *)
23
* Pixbuf initialisation using homegrown memory handling ("pixelstore").
25
* Pixbuf sizes are differentiated into tiny, <4K, <16K, <64K, and more,
26
* with each type having its own method of memory handling. After allocating
27
* memory, the buffer is cleared if the clear flag is set. Intended to
28
* reduce memory fragmentation.
29
* \param pb Pointer to the pixbuf struct.
30
* \param mode Indicates grayscale/RGB/RGBA.
31
* \param clear True if buffer should be cleared.
32
* \pre x1>=x0 && y1>=y0 && pb!=NULL
35
nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
42
bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
46
if (size <= NR_TINY_MAX) {
47
pb->size = NR_PIXBLOCK_SIZE_TINY;
48
if (clear) memset (pb->data.p, 0x0, size);
49
} else if (size <= 4096) {
50
pb->size = NR_PIXBLOCK_SIZE_4K;
51
pb->data.px = nr_pixelstore_4K_new (clear, 0x0);
52
} else if (size <= 16384) {
53
pb->size = NR_PIXBLOCK_SIZE_16K;
54
pb->data.px = nr_pixelstore_16K_new (clear, 0x0);
55
} else if (size <= 65536) {
56
pb->size = NR_PIXBLOCK_SIZE_64K;
57
pb->data.px = nr_pixelstore_64K_new (clear, 0x0);
58
} else if (size <= 262144) {
59
pb->size = NR_PIXBLOCK_SIZE_256K;
60
pb->data.px = nr_pixelstore_256K_new (clear, 0x0);
61
} else if (size <= 1048576) {
62
pb->size = NR_PIXBLOCK_SIZE_1M;
63
pb->data.px = nr_pixelstore_1M_new (clear, 0x0);
65
pb->size = NR_PIXBLOCK_SIZE_BIG;
67
if (size > 100000000) { // Don't even try to allocate more than 100Mb (5000x5000 RGBA
68
// pixels). It'll just bog the system down even if successful. FIXME:
69
// Can anyone suggest something better than the magic number?
70
g_warning ("%lu bytes requested for pixel buffer, I won't try to allocate that.", (long unsigned) size);
73
pb->data.px = g_try_new (unsigned char, size);
74
if (pb->data.px == NULL) { // memory allocation failed
75
g_warning ("Could not allocate %lu bytes for pixel buffer!", (long unsigned) size);
78
if (clear) memset (pb->data.px, 0x0, size);
83
pb->visible_area.x0 = pb->area.x0 = x0;
84
pb->visible_area.y0 = pb->area.y0 = y0;
85
pb->visible_area.x1 = pb->area.x1 = x1;
86
pb->visible_area.y1 = pb->area.y1 = y1;
91
* Pixbuf initialisation using g_new.
93
* After allocating memory, the buffer is cleared if the clear flag is set.
94
* \param pb Pointer to the pixbuf struct.
95
* \param mode Indicates grayscale/RGB/RGBA.
96
* \param clear True if buffer should be cleared.
97
* \pre x1>=x0 && y1>=y0 && pb!=NULL
98
FIXME: currently unused except for nr_pixblock_new and pattern tiles, replace with _fast and delete?
101
nr_pixblock_setup (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
108
bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
112
if (size <= NR_TINY_MAX) {
113
pb->size = NR_PIXBLOCK_SIZE_TINY;
114
if (clear) memset (pb->data.p, 0x0, size);
116
pb->size = NR_PIXBLOCK_SIZE_BIG;
117
pb->data.px = g_new (unsigned char, size);
118
if (clear) memset (pb->data.px, 0x0, size);
123
pb->visible_area.x0 = pb->area.x0 = x0;
124
pb->visible_area.y0 = pb->area.y0 = y0;
125
pb->visible_area.x1 = pb->area.x1 = x1;
126
pb->visible_area.y1 = pb->area.y1 = y1;
131
* Pixbuf initialisation with preset values.
133
* After copying all parameters into the NRPixBlock struct, the pixel buffer is cleared if the clear flag is set.
134
* \param pb Pointer to the pixbuf struct.
135
* \param mode Indicates grayscale/RGB/RGBA.
136
* \param clear True if buffer should be cleared.
137
* \pre x1>=x0 && y1>=y0 && pb!=NULL
140
nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, unsigned char *px, int rs, bool empty, bool clear)
145
bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
147
pb->size = NR_PIXBLOCK_SIZE_STATIC;
150
pb->visible_area.x0 = pb->area.x0 = x0;
151
pb->visible_area.y0 = pb->area.y0 = y0;
152
pb->visible_area.x1 = pb->area.x1 = x1;
153
pb->visible_area.y1 = pb->area.y1 = y1;
157
g_assert (pb->data.px != NULL);
160
/// \todo How do you recognise if
161
/// px was an uncleared tiny buffer?
163
memset (pb->data.px, 0x0, bpp * (y1 - y0) * w);
166
for (y = y0; y < y1; y++) {
167
memset (pb->data.px + (y - y0) * rs, 0x0, bpp * w);
174
* Frees memory taken by pixel data in NRPixBlock.
175
* \param pb Pointer to pixblock.
176
* \pre pb and pb->data.px point to valid addresses.
178
* According to pb->size, one of the functions for freeing the pixelstore
179
* is called. May be called regardless of how pixbuf was set up.
182
nr_pixblock_release (NRPixBlock *pb)
185
case NR_PIXBLOCK_SIZE_TINY:
187
case NR_PIXBLOCK_SIZE_4K:
188
nr_pixelstore_4K_free (pb->data.px);
190
case NR_PIXBLOCK_SIZE_16K:
191
nr_pixelstore_16K_free (pb->data.px);
193
case NR_PIXBLOCK_SIZE_64K:
194
nr_pixelstore_64K_free (pb->data.px);
196
case NR_PIXBLOCK_SIZE_256K:
197
nr_pixelstore_256K_free (pb->data.px);
199
case NR_PIXBLOCK_SIZE_1M:
200
nr_pixelstore_1M_free (pb->data.px);
202
case NR_PIXBLOCK_SIZE_BIG:
203
g_free (pb->data.px);
205
case NR_PIXBLOCK_SIZE_STATIC:
213
* Allocates NRPixBlock and sets it up.
215
* \return Pointer to fresh pixblock.
216
* Calls g_new() and nr_pixblock_setup().
217
FIXME: currently unused, delete? JG: Should be used more often! (To simplify memory management.)
220
nr_pixblock_new (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
224
pb = g_new (NRPixBlock, 1);
227
nr_pixblock_setup (pb, mode, x0, y0, x1, y1, clear);
228
if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) {
237
* Allocates NRPixBlock and sets it up.
239
* \return Pointer to fresh pixblock.
240
* Calls g_new() and nr_pixblock_setup().
243
nr_pixblock_new_fast (NR_PIXBLOCK_MODE mode, int x0, int y0, int x1, int y1, bool clear)
247
pb = g_new (NRPixBlock, 1);
250
nr_pixblock_setup_fast (pb, mode, x0, y0, x1, y1, clear);
251
if (pb->size!=NR_PIXBLOCK_SIZE_TINY && !pb->data.px) {
260
* Frees all memory taken by pixblock.
265
nr_pixblock_free (NRPixBlock *pb)
267
nr_pixblock_release (pb);
274
/* PixelStore operations */
276
#define NR_4K_BLOCK 32
277
static unsigned char **nr_4K_px = NULL;
278
static unsigned int nr_4K_len = 0;
279
static unsigned int nr_4K_size = 0;
282
nr_pixelstore_4K_new (bool clear, unsigned char val)
286
if (nr_4K_len != 0) {
288
px = nr_4K_px[nr_4K_len];
290
px = g_new (unsigned char, 4096);
293
if (clear) memset (px, val, 4096);
299
nr_pixelstore_4K_free (unsigned char *px)
301
if (nr_4K_len == nr_4K_size) {
302
nr_4K_size += NR_4K_BLOCK;
303
nr_4K_px = g_renew (unsigned char *, nr_4K_px, nr_4K_size);
306
nr_4K_px[nr_4K_len] = px;
310
#define NR_16K_BLOCK 32
311
static unsigned char **nr_16K_px = NULL;
312
static unsigned int nr_16K_len = 0;
313
static unsigned int nr_16K_size = 0;
316
nr_pixelstore_16K_new (bool clear, unsigned char val)
320
if (nr_16K_len != 0) {
322
px = nr_16K_px[nr_16K_len];
324
px = g_new (unsigned char, 16384);
327
if (clear) memset (px, val, 16384);
333
nr_pixelstore_16K_free (unsigned char *px)
335
if (nr_16K_len == nr_16K_size) {
336
nr_16K_size += NR_16K_BLOCK;
337
nr_16K_px = g_renew (unsigned char *, nr_16K_px, nr_16K_size);
340
nr_16K_px[nr_16K_len] = px;
344
#define NR_64K_BLOCK 32
345
static unsigned char **nr_64K_px = NULL;
346
static unsigned int nr_64K_len = 0;
347
static unsigned int nr_64K_size = 0;
350
nr_pixelstore_64K_new (bool clear, unsigned char val)
354
if (nr_64K_len != 0) {
356
px = nr_64K_px[nr_64K_len];
358
px = g_new (unsigned char, 65536);
361
if (clear) memset (px, val, 65536);
367
nr_pixelstore_64K_free (unsigned char *px)
369
if (nr_64K_len == nr_64K_size) {
370
nr_64K_size += NR_64K_BLOCK;
371
nr_64K_px = g_renew (unsigned char *, nr_64K_px, nr_64K_size);
374
nr_64K_px[nr_64K_len] = px;
378
#define NR_256K_BLOCK 32
379
#define NR_256K 262144
380
static unsigned char **nr_256K_px = NULL;
381
static unsigned int nr_256K_len = 0;
382
static unsigned int nr_256K_size = 0;
385
nr_pixelstore_256K_new (bool clear, unsigned char val)
389
if (nr_256K_len != 0) {
391
px = nr_256K_px[nr_256K_len];
393
px = g_new (unsigned char, NR_256K);
396
if (clear) memset (px, val, NR_256K);
402
nr_pixelstore_256K_free (unsigned char *px)
404
if (nr_256K_len == nr_256K_size) {
405
nr_256K_size += NR_256K_BLOCK;
406
nr_256K_px = g_renew (unsigned char *, nr_256K_px, nr_256K_size);
409
nr_256K_px[nr_256K_len] = px;
413
#define NR_1M_BLOCK 32
414
#define NR_1M 1048576
415
static unsigned char **nr_1M_px = NULL;
416
static unsigned int nr_1M_len = 0;
417
static unsigned int nr_1M_size = 0;
420
nr_pixelstore_1M_new (bool clear, unsigned char val)
424
if (nr_1M_len != 0) {
426
px = nr_1M_px[nr_1M_len];
428
px = g_new (unsigned char, NR_1M);
431
if (clear) memset (px, val, NR_1M);
437
nr_pixelstore_1M_free (unsigned char *px)
439
if (nr_1M_len == nr_1M_size) {
440
nr_1M_size += NR_1M_BLOCK;
441
nr_1M_px = g_renew (unsigned char *, nr_1M_px, nr_1M_size);
444
nr_1M_px[nr_1M_len] = px;
451
c-file-style:"stroustrup"
452
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
457
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :