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