0545bb33cb3d209589a7db30003e0ddb5cd91be6
[blender-staging.git] / source / blender / imbuf / intern / allocimbuf.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/imbuf/intern/allocimbuf.c
29  *  \ingroup imbuf
30  */
31
32
33 /* It's become a bit messy... Basically, only the IMB_ prefixed files
34  * should remain. */
35
36 #include <stddef.h>
37
38 #include "IMB_imbuf.h"
39 #include "IMB_imbuf_types.h"
40
41 #include "IMB_allocimbuf.h"
42 #include "IMB_filetype.h"
43 #include "IMB_metadata.h"
44 #include "IMB_colormanagement.h"
45
46 #include "imbuf.h"
47
48 #include "MEM_guardedalloc.h"
49 #include "MEM_CacheLimiterC-Api.h"
50
51 void imb_freemipmapImBuf(ImBuf *ibuf)
52 {
53         int a;
54         
55         for (a = 1; a < ibuf->miptot; a++) {
56                 if (ibuf->mipmap[a - 1])
57                         IMB_freeImBuf(ibuf->mipmap[a - 1]);
58                 ibuf->mipmap[a - 1] = NULL;
59         }
60
61         ibuf->miptot = 0;
62 }
63
64 /* any free rect frees mipmaps to be sure, creation is in render on first request */
65 void imb_freerectfloatImBuf(ImBuf *ibuf)
66 {
67         if (ibuf == NULL) return;
68         
69         if (ibuf->rect_float && (ibuf->mall & IB_rectfloat)) {
70                 MEM_freeN(ibuf->rect_float);
71                 ibuf->rect_float = NULL;
72         }
73
74         imb_freemipmapImBuf(ibuf);
75         
76         ibuf->rect_float = NULL;
77         ibuf->mall &= ~IB_rectfloat;
78 }
79
80 /* any free rect frees mipmaps to be sure, creation is in render on first request */
81 void imb_freerectImBuf(ImBuf *ibuf)
82 {
83         if (ibuf == NULL) return;
84
85         if (ibuf->rect && (ibuf->mall & IB_rect))
86                 MEM_freeN(ibuf->rect);
87         ibuf->rect = NULL;
88         
89         imb_freemipmapImBuf(ibuf);
90
91         ibuf->mall &= ~IB_rect;
92 }
93
94 void imb_freetilesImBuf(ImBuf *ibuf)
95 {
96         int tx, ty;
97
98         if (ibuf == NULL) return;
99
100         if (ibuf->tiles && (ibuf->mall & IB_tiles)) {
101                 for (ty = 0; ty < ibuf->ytiles; ty++) {
102                         for (tx = 0; tx < ibuf->xtiles; tx++) {
103                                 if (ibuf->tiles[ibuf->xtiles * ty + tx]) {
104                                         imb_tile_cache_tile_free(ibuf, tx, ty);
105                                         MEM_freeN(ibuf->tiles[ibuf->xtiles * ty + tx]);
106                                 }
107                         }
108                 }
109
110                 MEM_freeN(ibuf->tiles);
111         }
112
113         ibuf->tiles = NULL;
114         ibuf->mall &= ~IB_tiles;
115 }
116
117 static void freeencodedbufferImBuf(ImBuf *ibuf)
118 {
119         if (ibuf == NULL) return;
120
121         if (ibuf->encodedbuffer && (ibuf->mall & IB_mem))
122                 MEM_freeN(ibuf->encodedbuffer);
123
124         ibuf->encodedbuffer = NULL;
125         ibuf->encodedbuffersize = 0;
126         ibuf->encodedsize = 0;
127         ibuf->mall &= ~IB_mem;
128 }
129
130 void IMB_freezbufImBuf(ImBuf *ibuf)
131 {
132         if (ibuf == NULL) return;
133
134         if (ibuf->zbuf && (ibuf->mall & IB_zbuf))
135                 MEM_freeN(ibuf->zbuf);
136
137         ibuf->zbuf = NULL;
138         ibuf->mall &= ~IB_zbuf;
139 }
140
141 void IMB_freezbuffloatImBuf(ImBuf *ibuf)
142 {
143         if (ibuf == NULL) return;
144
145         if (ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat))
146                 MEM_freeN(ibuf->zbuf_float);
147
148         ibuf->zbuf_float = NULL;
149         ibuf->mall &= ~IB_zbuffloat;
150 }
151
152 void IMB_freeImBuf(ImBuf *ibuf)
153 {
154         if (ibuf) {
155                 if (ibuf->refcounter > 0) {
156                         ibuf->refcounter--;
157                 }
158                 else {
159                         imb_freerectImBuf(ibuf);
160                         imb_freerectfloatImBuf(ibuf);
161                         imb_freetilesImBuf(ibuf);
162                         IMB_freezbufImBuf(ibuf);
163                         IMB_freezbuffloatImBuf(ibuf);
164                         freeencodedbufferImBuf(ibuf);
165                         IMB_metadata_free(ibuf);
166                         IMB_colormanage_flags_free(ibuf);
167                         IMB_colormanage_cache_data_free(ibuf);
168
169                         if (ibuf->dds_data.data != NULL) {
170                                 free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
171                         }
172                         MEM_freeN(ibuf);
173                 }
174         }
175 }
176
177 void IMB_refImBuf(ImBuf *ibuf)
178 {
179         ibuf->refcounter++;
180 }
181
182 ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
183 {
184         ImBuf *rval;
185
186         if (!ibuf || ibuf->refcounter == 0) { return ibuf; }
187
188         rval = IMB_dupImBuf(ibuf);
189
190         IMB_freeImBuf(ibuf);
191
192         return rval;
193 }
194
195 short addzbufImBuf(ImBuf *ibuf)
196 {
197         int size;
198         
199         if (ibuf == NULL) return FALSE;
200         
201         IMB_freezbufImBuf(ibuf);
202         
203         size = ibuf->x * ibuf->y * sizeof(unsigned int);
204         if ((ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf"))) {
205                 ibuf->mall |= IB_zbuf;
206                 ibuf->flags |= IB_zbuf;
207                 return TRUE;
208         }
209         
210         return FALSE;
211 }
212
213 short addzbuffloatImBuf(ImBuf *ibuf)
214 {
215         int size;
216         
217         if (ibuf == NULL) return FALSE;
218         
219         IMB_freezbuffloatImBuf(ibuf);
220         
221         size = ibuf->x * ibuf->y * sizeof(float);
222         if ((ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf"))) {
223                 ibuf->mall |= IB_zbuffloat;
224                 ibuf->flags |= IB_zbuffloat;
225                 return TRUE;
226         }
227         
228         return FALSE;
229 }
230
231
232 short imb_addencodedbufferImBuf(ImBuf *ibuf)
233 {
234         if (ibuf == NULL) return FALSE;
235
236         freeencodedbufferImBuf(ibuf);
237
238         if (ibuf->encodedbuffersize == 0)
239                 ibuf->encodedbuffersize = 10000;
240
241         ibuf->encodedsize = 0;
242
243         if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf"))) {
244                 ibuf->mall |= IB_mem;
245                 ibuf->flags |= IB_mem;
246                 return TRUE;
247         }
248
249         return FALSE;
250 }
251
252
253 short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
254 {
255         unsigned int newsize, encodedsize;
256         void *newbuffer;
257
258         if (ibuf == NULL) return FALSE;
259
260         if (ibuf->encodedbuffersize < ibuf->encodedsize) {
261                 printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
262                 return FALSE;
263         }
264
265         newsize = 2 * ibuf->encodedbuffersize;
266         if (newsize < 10000) newsize = 10000;
267
268         newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
269         if (newbuffer == NULL) return FALSE;
270
271         if (ibuf->encodedbuffer) {
272                 memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
273         }
274         else {
275                 ibuf->encodedsize = 0;
276         }
277
278         encodedsize = ibuf->encodedsize;
279
280         freeencodedbufferImBuf(ibuf);
281
282         ibuf->encodedbuffersize = newsize;
283         ibuf->encodedsize = encodedsize;
284         ibuf->encodedbuffer = newbuffer;
285         ibuf->mall |= IB_mem;
286         ibuf->flags |= IB_mem;
287
288         return TRUE;
289 }
290
291 short imb_addrectfloatImBuf(ImBuf *ibuf)
292 {
293         int size;
294         
295         if (ibuf == NULL) return FALSE;
296         
297         if (ibuf->rect_float)
298                 imb_freerectfloatImBuf(ibuf);  /* frees mipmap too, hrm */
299         
300         size = ibuf->x * ibuf->y;
301         size = size * 4 * sizeof(float);
302         ibuf->channels = 4;
303         
304         if ((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
305                 ibuf->mall |= IB_rectfloat;
306                 ibuf->flags |= IB_rectfloat;
307                 return TRUE;
308         }
309         
310         return FALSE;
311 }
312
313 /* question; why also add zbuf? */
314 short imb_addrectImBuf(ImBuf *ibuf)
315 {
316         int size;
317
318         if (ibuf == NULL) return FALSE;
319         
320         /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
321         if (ibuf->rect && (ibuf->mall & IB_rect))
322                 MEM_freeN(ibuf->rect);
323         ibuf->rect = NULL;
324         
325         size = ibuf->x * ibuf->y;
326         size = size * sizeof(unsigned int);
327
328         if ((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
329                 ibuf->mall |= IB_rect;
330                 ibuf->flags |= IB_rect;
331                 if (ibuf->planes > 32) return (addzbufImBuf(ibuf));
332                 else return TRUE;
333         }
334
335         return FALSE;
336 }
337
338 short imb_addtilesImBuf(ImBuf *ibuf)
339 {
340         if (ibuf == NULL) return FALSE;
341
342         if (!ibuf->tiles)
343                 if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles, "imb_tiles")))
344                         ibuf->mall |= IB_tiles;
345
346         return (ibuf->tiles != NULL);
347 }
348
349 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int flags)
350 {
351         ImBuf *ibuf;
352
353         ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
354
355         if (ibuf) {
356                 ibuf->x = x;
357                 ibuf->y = y;
358                 ibuf->planes = planes;
359                 ibuf->ftype = TGA;
360                 ibuf->channels = 4;  /* float option, is set to other values when buffers get assigned */
361                 ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254; /* IMB_DPI_DEFAULT -> pixels-per-meter */
362                 
363                 if (flags & IB_rect) {
364                         if (imb_addrectImBuf(ibuf) == FALSE) {
365                                 IMB_freeImBuf(ibuf);
366                                 return NULL;
367                         }
368                 }
369                 
370                 if (flags & IB_rectfloat) {
371                         if (imb_addrectfloatImBuf(ibuf) == FALSE) {
372                                 IMB_freeImBuf(ibuf);
373                                 return NULL;
374                         }
375                 }
376                 
377                 if (flags & IB_zbuf) {
378                         if (addzbufImBuf(ibuf) == FALSE) {
379                                 IMB_freeImBuf(ibuf);
380                                 return NULL;
381                         }
382                 }
383                 
384                 if (flags & IB_zbuffloat) {
385                         if (addzbuffloatImBuf(ibuf) == FALSE) {
386                                 IMB_freeImBuf(ibuf);
387                                 return NULL;
388                         }
389                 }
390         }
391         return (ibuf);
392 }
393
394 /* does no zbuffers? */
395 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
396 {
397         ImBuf *ibuf2, tbuf;
398         int flags = 0;
399         int a, x, y;
400         
401         if (ibuf1 == NULL) return NULL;
402
403         if (ibuf1->rect) flags |= IB_rect;
404         if (ibuf1->rect_float) flags |= IB_rectfloat;
405
406         x = ibuf1->x;
407         y = ibuf1->y;
408         if (ibuf1->flags & IB_fields) y *= 2;
409         
410         ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags);
411         if (ibuf2 == NULL) return NULL;
412
413         if (flags & IB_rect)
414                 memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
415         
416         if (flags & IB_rectfloat)
417                 memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float));
418
419         if (ibuf1->encodedbuffer) {
420                 ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
421                 if (imb_addencodedbufferImBuf(ibuf2) == FALSE) {
422                         IMB_freeImBuf(ibuf2);
423                         return NULL;
424                 }
425
426                 memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
427         }
428
429         /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
430         tbuf = *ibuf1;
431         
432         // fix pointers 
433         tbuf.rect          = ibuf2->rect;
434         tbuf.rect_float    = ibuf2->rect_float;
435         tbuf.encodedbuffer = ibuf2->encodedbuffer;
436         tbuf.zbuf          = NULL;
437         tbuf.zbuf_float    = NULL;
438         for (a = 0; a < IB_MIPMAP_LEVELS; a++)
439                 tbuf.mipmap[a] = NULL;
440         
441         // set malloc flag
442         tbuf.mall               = ibuf2->mall;
443         tbuf.c_handle           = NULL;
444         tbuf.refcounter         = 0;
445
446         // for now don't duplicate metadata
447         tbuf.metadata = NULL;
448
449         *ibuf2 = tbuf;
450
451         IMB_display_buffer_invalidate(ibuf2);
452         IMB_colormanage_cache_data_free(ibuf2);
453
454         ibuf2->colormanage_flags &= ~ IMB_COLORMANAGED;
455
456         return(ibuf2);
457 }
458
459 #if 0 /* remove? - campbell */
460 /* support for cache limiting */
461
462 static void imbuf_cache_destructor(void *data)
463 {
464         ImBuf *ibuf = (ImBuf *) data;
465
466         imb_freerectImBuf(ibuf);
467         imb_freerectfloatImBuf(ibuf);
468         IMB_freezbufImBuf(ibuf);
469         IMB_freezbuffloatImBuf(ibuf);
470         freeencodedbufferImBuf(ibuf);
471
472         ibuf->c_handle = NULL;
473 }
474
475
476 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
477 {
478         static MEM_CacheLimiterC *c = NULL;
479
480         if (!c)
481                 c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
482
483         return &c;
484 }
485 #endif