Merged changes in the trunk up to revision 49986.
[blender.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
45 #include "imbuf.h"
46
47 #include "MEM_guardedalloc.h"
48 #include "MEM_CacheLimiterC-Api.h"
49
50 void imb_freemipmapImBuf(ImBuf *ibuf)
51 {
52         int a;
53         
54         for (a = 1; a < ibuf->miptot; a++) {
55                 if (ibuf->mipmap[a - 1])
56                         IMB_freeImBuf(ibuf->mipmap[a - 1]);
57                 ibuf->mipmap[a - 1] = NULL;
58         }
59
60         ibuf->miptot = 0;
61 }
62
63 /* any free rect frees mipmaps to be sure, creation is in render on first request */
64 void imb_freerectfloatImBuf(ImBuf *ibuf)
65 {
66         if (ibuf == NULL) return;
67         
68         if (ibuf->rect_float && (ibuf->mall & IB_rectfloat)) {
69                 MEM_freeN(ibuf->rect_float);
70                 ibuf->rect_float = NULL;
71         }
72
73         imb_freemipmapImBuf(ibuf);
74         
75         ibuf->rect_float = NULL;
76         ibuf->mall &= ~IB_rectfloat;
77 }
78
79 /* any free rect frees mipmaps to be sure, creation is in render on first request */
80 void imb_freerectImBuf(ImBuf *ibuf)
81 {
82         if (ibuf == NULL) return;
83
84         if (ibuf->rect && (ibuf->mall & IB_rect))
85                 MEM_freeN(ibuf->rect);
86         ibuf->rect = NULL;
87         
88         imb_freemipmapImBuf(ibuf);
89
90         ibuf->mall &= ~IB_rect;
91 }
92
93 void imb_freetilesImBuf(ImBuf *ibuf)
94 {
95         int tx, ty;
96
97         if (ibuf == NULL) return;
98
99         if (ibuf->tiles && (ibuf->mall & IB_tiles)) {
100                 for (ty = 0; ty < ibuf->ytiles; ty++) {
101                         for (tx = 0; tx < ibuf->xtiles; tx++) {
102                                 if (ibuf->tiles[ibuf->xtiles * ty + tx]) {
103                                         imb_tile_cache_tile_free(ibuf, tx, ty);
104                                         MEM_freeN(ibuf->tiles[ibuf->xtiles * ty + tx]);
105                                 }
106                         }
107                 }
108
109                 MEM_freeN(ibuf->tiles);
110         }
111
112         ibuf->tiles = NULL;
113         ibuf->mall &= ~IB_tiles;
114 }
115
116 static void freeencodedbufferImBuf(ImBuf *ibuf)
117 {
118         if (ibuf == NULL) return;
119
120         if (ibuf->encodedbuffer && (ibuf->mall & IB_mem))
121                 MEM_freeN(ibuf->encodedbuffer);
122
123         ibuf->encodedbuffer = NULL;
124         ibuf->encodedbuffersize = 0;
125         ibuf->encodedsize = 0;
126         ibuf->mall &= ~IB_mem;
127 }
128
129 void IMB_freezbufImBuf(ImBuf *ibuf)
130 {
131         if (ibuf == NULL) return;
132
133         if (ibuf->zbuf && (ibuf->mall & IB_zbuf))
134                 MEM_freeN(ibuf->zbuf);
135
136         ibuf->zbuf = NULL;
137         ibuf->mall &= ~IB_zbuf;
138 }
139
140 void IMB_freezbuffloatImBuf(ImBuf *ibuf)
141 {
142         if (ibuf == NULL) return;
143
144         if (ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat))
145                 MEM_freeN(ibuf->zbuf_float);
146
147         ibuf->zbuf_float = NULL;
148         ibuf->mall &= ~IB_zbuffloat;
149 }
150
151 void IMB_freeImBuf(ImBuf *ibuf)
152 {
153         if (ibuf) {
154                 if (ibuf->refcounter > 0) {
155                         ibuf->refcounter--;
156                 }
157                 else {
158                         imb_freerectImBuf(ibuf);
159                         imb_freerectfloatImBuf(ibuf);
160                         imb_freetilesImBuf(ibuf);
161                         IMB_freezbufImBuf(ibuf);
162                         IMB_freezbuffloatImBuf(ibuf);
163                         freeencodedbufferImBuf(ibuf);
164                         IMB_metadata_free(ibuf);
165                         if (ibuf->dds_data.data != NULL)
166                                 free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
167                         MEM_freeN(ibuf);
168                 }
169         }
170 }
171
172 void IMB_refImBuf(ImBuf *ibuf)
173 {
174         ibuf->refcounter++;
175 }
176
177 ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
178 {
179         ImBuf *rval;
180
181         if (!ibuf || ibuf->refcounter == 0) { return ibuf; }
182
183         rval = IMB_dupImBuf(ibuf);
184
185         IMB_freeImBuf(ibuf);
186
187         return rval;
188 }
189
190 short addzbufImBuf(ImBuf *ibuf)
191 {
192         int size;
193         
194         if (ibuf == NULL) return FALSE;
195         
196         IMB_freezbufImBuf(ibuf);
197         
198         size = ibuf->x * ibuf->y * sizeof(unsigned int);
199         if ((ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf"))) {
200                 ibuf->mall |= IB_zbuf;
201                 ibuf->flags |= IB_zbuf;
202                 return TRUE;
203         }
204         
205         return FALSE;
206 }
207
208 short addzbuffloatImBuf(ImBuf *ibuf)
209 {
210         int size;
211         
212         if (ibuf == NULL) return FALSE;
213         
214         IMB_freezbuffloatImBuf(ibuf);
215         
216         size = ibuf->x * ibuf->y * sizeof(float);
217         if ((ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf"))) {
218                 ibuf->mall |= IB_zbuffloat;
219                 ibuf->flags |= IB_zbuffloat;
220                 return TRUE;
221         }
222         
223         return FALSE;
224 }
225
226
227 short imb_addencodedbufferImBuf(ImBuf *ibuf)
228 {
229         if (ibuf == NULL) return FALSE;
230
231         freeencodedbufferImBuf(ibuf);
232
233         if (ibuf->encodedbuffersize == 0)
234                 ibuf->encodedbuffersize = 10000;
235
236         ibuf->encodedsize = 0;
237
238         if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf"))) {
239                 ibuf->mall |= IB_mem;
240                 ibuf->flags |= IB_mem;
241                 return TRUE;
242         }
243
244         return FALSE;
245 }
246
247
248 short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
249 {
250         unsigned int newsize, encodedsize;
251         void *newbuffer;
252
253         if (ibuf == NULL) return FALSE;
254
255         if (ibuf->encodedbuffersize < ibuf->encodedsize) {
256                 printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
257                 return FALSE;
258         }
259
260         newsize = 2 * ibuf->encodedbuffersize;
261         if (newsize < 10000) newsize = 10000;
262
263         newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
264         if (newbuffer == NULL) return FALSE;
265
266         if (ibuf->encodedbuffer) {
267                 memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
268         }
269         else {
270                 ibuf->encodedsize = 0;
271         }
272
273         encodedsize = ibuf->encodedsize;
274
275         freeencodedbufferImBuf(ibuf);
276
277         ibuf->encodedbuffersize = newsize;
278         ibuf->encodedsize = encodedsize;
279         ibuf->encodedbuffer = newbuffer;
280         ibuf->mall |= IB_mem;
281         ibuf->flags |= IB_mem;
282
283         return TRUE;
284 }
285
286 short imb_addrectfloatImBuf(ImBuf *ibuf)
287 {
288         int size;
289         
290         if (ibuf == NULL) return FALSE;
291         
292         if (ibuf->rect_float)
293                 imb_freerectfloatImBuf(ibuf);  /* frees mipmap too, hrm */
294         
295         size = ibuf->x * ibuf->y;
296         size = size * 4 * sizeof(float);
297         ibuf->channels = 4;
298         
299         if ((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
300                 ibuf->mall |= IB_rectfloat;
301                 ibuf->flags |= IB_rectfloat;
302                 return TRUE;
303         }
304         
305         return FALSE;
306 }
307
308 /* question; why also add zbuf? */
309 short imb_addrectImBuf(ImBuf *ibuf)
310 {
311         int size;
312
313         if (ibuf == NULL) return FALSE;
314         
315         /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
316         if (ibuf->rect && (ibuf->mall & IB_rect))
317                 MEM_freeN(ibuf->rect);
318         ibuf->rect = NULL;
319         
320         size = ibuf->x * ibuf->y;
321         size = size * sizeof(unsigned int);
322
323         if ((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
324                 ibuf->mall |= IB_rect;
325                 ibuf->flags |= IB_rect;
326                 if (ibuf->planes > 32) return (addzbufImBuf(ibuf));
327                 else return TRUE;
328         }
329
330         return FALSE;
331 }
332
333 short imb_addtilesImBuf(ImBuf *ibuf)
334 {
335         if (ibuf == NULL) return FALSE;
336
337         if (!ibuf->tiles)
338                 if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles, "imb_tiles")))
339                         ibuf->mall |= IB_tiles;
340
341         return (ibuf->tiles != NULL);
342 }
343
344 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int flags)
345 {
346         ImBuf *ibuf;
347
348         ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
349
350         if (ibuf) {
351                 ibuf->x = x;
352                 ibuf->y = y;
353                 ibuf->planes = planes;
354                 ibuf->ftype = TGA;
355                 ibuf->channels = 4;  /* float option, is set to other values when buffers get assigned */
356                 ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254; /* IMB_DPI_DEFAULT -> pixels-per-meter */
357                 
358                 if (flags & IB_rect) {
359                         if (imb_addrectImBuf(ibuf) == FALSE) {
360                                 IMB_freeImBuf(ibuf);
361                                 return NULL;
362                         }
363                 }
364                 
365                 if (flags & IB_rectfloat) {
366                         if (imb_addrectfloatImBuf(ibuf) == FALSE) {
367                                 IMB_freeImBuf(ibuf);
368                                 return NULL;
369                         }
370                 }
371                 
372                 if (flags & IB_zbuf) {
373                         if (addzbufImBuf(ibuf) == FALSE) {
374                                 IMB_freeImBuf(ibuf);
375                                 return NULL;
376                         }
377                 }
378                 
379                 if (flags & IB_zbuffloat) {
380                         if (addzbuffloatImBuf(ibuf) == FALSE) {
381                                 IMB_freeImBuf(ibuf);
382                                 return NULL;
383                         }
384                 }
385         }
386         return (ibuf);
387 }
388
389 /* does no zbuffers? */
390 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
391 {
392         ImBuf *ibuf2, tbuf;
393         int flags = 0;
394         int a, x, y;
395         
396         if (ibuf1 == NULL) return NULL;
397
398         if (ibuf1->rect) flags |= IB_rect;
399         if (ibuf1->rect_float) flags |= IB_rectfloat;
400
401         x = ibuf1->x;
402         y = ibuf1->y;
403         if (ibuf1->flags & IB_fields) y *= 2;
404         
405         ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags);
406         if (ibuf2 == NULL) return NULL;
407
408         if (flags & IB_rect)
409                 memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
410         
411         if (flags & IB_rectfloat)
412                 memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float));
413
414         if (ibuf1->encodedbuffer) {
415                 ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
416                 if (imb_addencodedbufferImBuf(ibuf2) == FALSE) {
417                         IMB_freeImBuf(ibuf2);
418                         return NULL;
419                 }
420
421                 memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
422         }
423
424         /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
425         tbuf = *ibuf1;
426         
427         /* fix pointers */
428         tbuf.rect          = ibuf2->rect;
429         tbuf.rect_float    = ibuf2->rect_float;
430         tbuf.encodedbuffer = ibuf2->encodedbuffer;
431         tbuf.zbuf          = NULL;
432         tbuf.zbuf_float    = NULL;
433         for (a = 0; a < IB_MIPMAP_LEVELS; a++)
434                 tbuf.mipmap[a] = NULL;
435         tbuf.dds_data.data = NULL;
436         
437         /* set malloc flag */
438         tbuf.mall               = ibuf2->mall;
439         tbuf.c_handle           = NULL;
440         tbuf.refcounter         = 0;
441
442         /* for now don't duplicate metadata */
443         tbuf.metadata = NULL;
444
445         *ibuf2 = tbuf;
446         
447         return(ibuf2);
448 }
449
450 #if 0 /* remove? - campbell */
451 /* support for cache limiting */
452
453 static void imbuf_cache_destructor(void *data)
454 {
455         ImBuf *ibuf = (ImBuf *) data;
456
457         imb_freerectImBuf(ibuf);
458         imb_freerectfloatImBuf(ibuf);
459         IMB_freezbufImBuf(ibuf);
460         IMB_freezbuffloatImBuf(ibuf);
461         freeencodedbufferImBuf(ibuf);
462
463         ibuf->c_handle = NULL;
464 }
465
466
467 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
468 {
469         static MEM_CacheLimiterC *c = NULL;
470
471         if (!c)
472                 c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
473
474         return &c;
475 }
476 #endif