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