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