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