doxygen: prevent GPL license block from being parsed as doxygen comment.
[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         if(ibuf->rect_float)
281                 imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */
282         
283         size = ibuf->x *ibuf->y;
284         size = size *4 *sizeof(float);
285         ibuf->channels= 4;
286         
287         if((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
288                 ibuf->mall |= IB_rectfloat;
289                 ibuf->flags |= IB_rectfloat;
290                 return TRUE;
291         }
292         
293         return FALSE;
294 }
295
296 /* question; why also add zbuf? */
297 short imb_addrectImBuf(ImBuf *ibuf)
298 {
299         int size;
300
301         if(ibuf==NULL) return FALSE;
302         
303         /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
304         if(ibuf->rect && (ibuf->mall & IB_rect))
305                 MEM_freeN(ibuf->rect);
306         ibuf->rect= NULL;
307         
308         size = ibuf->x*ibuf->y;
309         size = size*sizeof(unsigned int);
310
311         if((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
312                 ibuf->mall |= IB_rect;
313                 ibuf->flags |= IB_rect;
314                 if(ibuf->depth > 32) return (addzbufImBuf(ibuf));
315                 else return TRUE;
316         }
317
318         return FALSE;
319 }
320
321 short imb_addtilesImBuf(ImBuf *ibuf)
322 {
323         if(ibuf==NULL) return FALSE;
324
325         if(!ibuf->tiles)
326                 if((ibuf->tiles = MEM_callocN(sizeof(unsigned int*)*ibuf->xtiles*ibuf->ytiles, "imb_tiles")))
327                         ibuf->mall |= IB_tiles;
328
329         return (ibuf->tiles != NULL);
330 }
331
332 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar d, unsigned int flags)
333 {
334         ImBuf *ibuf;
335
336         ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
337
338         if(ibuf) {
339                 ibuf->x= x;
340                 ibuf->y= y;
341                 ibuf->depth= d;
342                 ibuf->ftype= TGA;
343                 ibuf->channels= 4;      /* float option, is set to other values when buffers get assigned */
344                 
345                 if(flags & IB_rect) {
346                         if(imb_addrectImBuf(ibuf)==FALSE) {
347                                 IMB_freeImBuf(ibuf);
348                                 return NULL;
349                         }
350                 }
351                 
352                 if(flags & IB_rectfloat) {
353                         if(imb_addrectfloatImBuf(ibuf)==FALSE) {
354                                 IMB_freeImBuf(ibuf);
355                                 return NULL;
356                         }
357                 }
358                 
359                 if(flags & IB_zbuf) {
360                         if(addzbufImBuf(ibuf)==FALSE) {
361                                 IMB_freeImBuf(ibuf);
362                                 return NULL;
363                         }
364                 }
365                 
366                 if(flags & IB_zbuffloat) {
367                         if(addzbuffloatImBuf(ibuf)==FALSE) {
368                                 IMB_freeImBuf(ibuf);
369                                 return NULL;
370                         }
371                 }
372         }
373         return (ibuf);
374 }
375
376 /* does no zbuffers? */
377 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
378 {
379         ImBuf *ibuf2, tbuf;
380         int flags = 0;
381         int a, x, y;
382         
383         if(ibuf1 == NULL) return NULL;
384
385         if(ibuf1->rect) flags |= IB_rect;
386         if(ibuf1->rect_float) flags |= IB_rectfloat;
387
388         x = ibuf1->x;
389         y = ibuf1->y;
390         if(ibuf1->flags & IB_fields) y *= 2;
391         
392         ibuf2 = IMB_allocImBuf(x, y, ibuf1->depth, flags);
393         if(ibuf2 == NULL) return NULL;
394
395         if(flags & IB_rect)
396                 memcpy(ibuf2->rect, ibuf1->rect, x *y *sizeof(int));
397         
398         if(flags & IB_rectfloat)
399                 memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels *x *y *sizeof(float));
400
401         if(ibuf1->encodedbuffer) {
402                 ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
403                 if(imb_addencodedbufferImBuf(ibuf2) == FALSE) {
404                         IMB_freeImBuf(ibuf2);
405                         return NULL;
406                 }
407
408                 memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
409         }
410
411         /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
412         tbuf = *ibuf1;
413         
414         // fix pointers 
415         tbuf.rect               = ibuf2->rect;
416         tbuf.rect_float = ibuf2->rect_float;
417         tbuf.encodedbuffer = ibuf2->encodedbuffer;
418         tbuf.zbuf= NULL;
419         tbuf.zbuf_float= NULL;
420         for(a=0; a<IB_MIPMAP_LEVELS; a++)
421                 tbuf.mipmap[a]= NULL;
422         
423         // set malloc flag
424         tbuf.mall               = ibuf2->mall;
425         tbuf.c_handle           = 0;
426         tbuf.refcounter         = 0;
427
428         // for now don't duplicate metadata
429         tbuf.metadata = 0;
430
431         *ibuf2 = tbuf;
432         
433         return(ibuf2);
434 }
435
436 /* support for cache limiting */
437
438 static void imbuf_cache_destructor(void *data)
439 {
440         ImBuf *ibuf = (ImBuf*) data;
441
442         imb_freerectImBuf(ibuf);
443         imb_freerectfloatImBuf(ibuf);
444         IMB_freezbufImBuf(ibuf);
445         IMB_freezbuffloatImBuf(ibuf);
446         freeencodedbufferImBuf(ibuf);
447
448         ibuf->c_handle = 0;
449 }
450
451 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
452 {
453         static MEM_CacheLimiterC *c = 0;
454
455         if(!c)
456                 c = new_MEM_CacheLimiter(imbuf_cache_destructor);
457
458         return &c;
459 }
460
461 void IMB_free_cache_limiter(void)
462 {
463         delete_MEM_CacheLimiter(*get_imbuf_cache_limiter());
464         *get_imbuf_cache_limiter() = 0;
465 }
466
467 void IMB_cache_limiter_insert(ImBuf *i)
468 {
469         if(!i->c_handle) {
470                 i->c_handle = MEM_CacheLimiter_insert(
471                         *get_imbuf_cache_limiter(), i);
472                 MEM_CacheLimiter_ref(i->c_handle);
473                 MEM_CacheLimiter_enforce_limits(
474                         *get_imbuf_cache_limiter());
475                 MEM_CacheLimiter_unref(i->c_handle);
476         }
477 }
478
479 void IMB_cache_limiter_unmanage(ImBuf *i)
480 {
481         if(i->c_handle) {
482                 MEM_CacheLimiter_unmanage(i->c_handle);
483                 i->c_handle = 0;
484         }
485 }
486
487 void IMB_cache_limiter_touch(ImBuf *i)
488 {
489         if(i->c_handle)
490                 MEM_CacheLimiter_touch(i->c_handle);
491 }
492
493 void IMB_cache_limiter_ref(ImBuf *i)
494 {
495         if(i->c_handle)
496                 MEM_CacheLimiter_ref(i->c_handle);
497 }
498
499 void IMB_cache_limiter_unref(ImBuf *i)
500 {
501         if(i->c_handle)
502                 MEM_CacheLimiter_unref(i->c_handle);
503 }
504
505 int IMB_cache_limiter_get_refcount(ImBuf *i)
506 {
507         if(i->c_handle)
508                 return MEM_CacheLimiter_get_refcount(i->c_handle);
509
510         return 0;
511 }
512