LCMS code removed, was an experiment but never finished.
[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 short addzbufImBuf(ImBuf *ibuf)
181 {
182         int size;
183         
184         if(ibuf==NULL) return FALSE;
185         
186         IMB_freezbufImBuf(ibuf);
187         
188         size = ibuf->x *ibuf->y *sizeof(unsigned int);
189         if((ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf"))) {
190                 ibuf->mall |= IB_zbuf;
191                 ibuf->flags |= IB_zbuf;
192                 return TRUE;
193         }
194         
195         return FALSE;
196 }
197
198 short addzbuffloatImBuf(ImBuf *ibuf)
199 {
200         int size;
201         
202         if(ibuf==NULL) return FALSE;
203         
204         IMB_freezbuffloatImBuf(ibuf);
205         
206         size = ibuf->x *ibuf->y *sizeof(float);
207         if((ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf"))) {
208                 ibuf->mall |= IB_zbuffloat;
209                 ibuf->flags |= IB_zbuffloat;
210                 return TRUE;
211         }
212         
213         return FALSE;
214 }
215
216
217 short imb_addencodedbufferImBuf(ImBuf *ibuf)
218 {
219         if(ibuf==NULL) return FALSE;
220
221         freeencodedbufferImBuf(ibuf);
222
223         if(ibuf->encodedbuffersize == 0) 
224                 ibuf->encodedbuffersize = 10000;
225
226         ibuf->encodedsize = 0;
227
228         if((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf"))) {
229                 ibuf->mall |= IB_mem;
230                 ibuf->flags |= IB_mem;
231                 return TRUE;
232         }
233
234         return FALSE;
235 }
236
237
238 short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
239 {
240         unsigned int newsize, encodedsize;
241         void *newbuffer;
242
243         if(ibuf==NULL) return FALSE;
244
245         if(ibuf->encodedbuffersize < ibuf->encodedsize) {
246                 printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
247                 return FALSE;
248         }
249
250         newsize = 2 *ibuf->encodedbuffersize;
251         if(newsize < 10000) newsize = 10000;
252
253         newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
254         if(newbuffer == NULL) return FALSE;
255
256         if(ibuf->encodedbuffer) {
257                 memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
258         } else {
259                 ibuf->encodedsize = 0;
260         }
261
262         encodedsize = ibuf->encodedsize;
263
264         freeencodedbufferImBuf(ibuf);
265
266         ibuf->encodedbuffersize = newsize;
267         ibuf->encodedsize = encodedsize;
268         ibuf->encodedbuffer = newbuffer;
269         ibuf->mall |= IB_mem;
270         ibuf->flags |= IB_mem;
271
272         return TRUE;
273 }
274
275 short imb_addrectfloatImBuf(ImBuf *ibuf)
276 {
277         int size;
278         
279         if(ibuf==NULL) return FALSE;
280         
281         if(ibuf->rect_float)
282                 imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */
283         
284         size = ibuf->x *ibuf->y;
285         size = size *4 *sizeof(float);
286         ibuf->channels= 4;
287         
288         if((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
289                 ibuf->mall |= IB_rectfloat;
290                 ibuf->flags |= IB_rectfloat;
291                 return TRUE;
292         }
293         
294         return FALSE;
295 }
296
297 /* question; why also add zbuf? */
298 short imb_addrectImBuf(ImBuf *ibuf)
299 {
300         int size;
301
302         if(ibuf==NULL) return FALSE;
303         
304         /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
305         if(ibuf->rect && (ibuf->mall & IB_rect))
306                 MEM_freeN(ibuf->rect);
307         ibuf->rect= NULL;
308         
309         size = ibuf->x*ibuf->y;
310         size = size*sizeof(unsigned int);
311
312         if((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
313                 ibuf->mall |= IB_rect;
314                 ibuf->flags |= IB_rect;
315                 if(ibuf->depth > 32) return (addzbufImBuf(ibuf));
316                 else return TRUE;
317         }
318
319         return FALSE;
320 }
321
322 short imb_addtilesImBuf(ImBuf *ibuf)
323 {
324         if(ibuf==NULL) return FALSE;
325
326         if(!ibuf->tiles)
327                 if((ibuf->tiles = MEM_callocN(sizeof(unsigned int*)*ibuf->xtiles*ibuf->ytiles, "imb_tiles")))
328                         ibuf->mall |= IB_tiles;
329
330         return (ibuf->tiles != NULL);
331 }
332
333 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar d, unsigned int flags)
334 {
335         ImBuf *ibuf;
336
337         ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
338
339         if(ibuf) {
340                 ibuf->x= x;
341                 ibuf->y= y;
342                 ibuf->depth= d;
343                 ibuf->ftype= TGA;
344                 ibuf->channels= 4;      /* float option, is set to other values when buffers get assigned */
345                 ibuf->ppm[0]= ibuf->ppm[1]= 150.0 / 0.0254; /* 150dpi -> pixels-per-meter */
346                 
347                 if(flags & IB_rect) {
348                         if(imb_addrectImBuf(ibuf)==FALSE) {
349                                 IMB_freeImBuf(ibuf);
350                                 return NULL;
351                         }
352                 }
353                 
354                 if(flags & IB_rectfloat) {
355                         if(imb_addrectfloatImBuf(ibuf)==FALSE) {
356                                 IMB_freeImBuf(ibuf);
357                                 return NULL;
358                         }
359                 }
360                 
361                 if(flags & IB_zbuf) {
362                         if(addzbufImBuf(ibuf)==FALSE) {
363                                 IMB_freeImBuf(ibuf);
364                                 return NULL;
365                         }
366                 }
367                 
368                 if(flags & IB_zbuffloat) {
369                         if(addzbuffloatImBuf(ibuf)==FALSE) {
370                                 IMB_freeImBuf(ibuf);
371                                 return NULL;
372                         }
373                 }
374         }
375         return (ibuf);
376 }
377
378 /* does no zbuffers? */
379 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
380 {
381         ImBuf *ibuf2, tbuf;
382         int flags = 0;
383         int a, x, y;
384         
385         if(ibuf1 == NULL) return NULL;
386
387         if(ibuf1->rect) flags |= IB_rect;
388         if(ibuf1->rect_float) flags |= IB_rectfloat;
389
390         x = ibuf1->x;
391         y = ibuf1->y;
392         if(ibuf1->flags & IB_fields) y *= 2;
393         
394         ibuf2 = IMB_allocImBuf(x, y, ibuf1->depth, flags);
395         if(ibuf2 == NULL) return NULL;
396
397         if(flags & IB_rect)
398                 memcpy(ibuf2->rect, ibuf1->rect, x *y *sizeof(int));
399         
400         if(flags & IB_rectfloat)
401                 memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels *x *y *sizeof(float));
402
403         if(ibuf1->encodedbuffer) {
404                 ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
405                 if(imb_addencodedbufferImBuf(ibuf2) == FALSE) {
406                         IMB_freeImBuf(ibuf2);
407                         return NULL;
408                 }
409
410                 memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
411         }
412
413         /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
414         tbuf = *ibuf1;
415         
416         // fix pointers 
417         tbuf.rect               = ibuf2->rect;
418         tbuf.rect_float = ibuf2->rect_float;
419         tbuf.encodedbuffer = ibuf2->encodedbuffer;
420         tbuf.zbuf= NULL;
421         tbuf.zbuf_float= NULL;
422         for(a=0; a<IB_MIPMAP_LEVELS; a++)
423                 tbuf.mipmap[a]= NULL;
424         
425         // set malloc flag
426         tbuf.mall               = ibuf2->mall;
427         tbuf.c_handle           = NULL;
428         tbuf.refcounter         = 0;
429
430         // for now don't duplicate metadata
431         tbuf.metadata = NULL;
432
433         *ibuf2 = tbuf;
434         
435         return(ibuf2);
436 }
437
438 /* support for cache limiting */
439
440 static void imbuf_cache_destructor(void *data)
441 {
442         ImBuf *ibuf = (ImBuf*) data;
443
444         imb_freerectImBuf(ibuf);
445         imb_freerectfloatImBuf(ibuf);
446         IMB_freezbufImBuf(ibuf);
447         IMB_freezbuffloatImBuf(ibuf);
448         freeencodedbufferImBuf(ibuf);
449
450         ibuf->c_handle = NULL;
451 }
452
453 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
454 {
455         static MEM_CacheLimiterC *c = NULL;
456
457         if(!c)
458                 c = new_MEM_CacheLimiter(imbuf_cache_destructor);
459
460         return &c;
461 }
462
463 void IMB_free_cache_limiter(void)
464 {
465         delete_MEM_CacheLimiter(*get_imbuf_cache_limiter());
466         *get_imbuf_cache_limiter() = NULL;
467 }
468
469 void IMB_cache_limiter_insert(ImBuf *i)
470 {
471         if(!i->c_handle) {
472                 i->c_handle = MEM_CacheLimiter_insert(
473                         *get_imbuf_cache_limiter(), i);
474                 MEM_CacheLimiter_ref(i->c_handle);
475                 MEM_CacheLimiter_enforce_limits(
476                         *get_imbuf_cache_limiter());
477                 MEM_CacheLimiter_unref(i->c_handle);
478         }
479 }
480
481 void IMB_cache_limiter_unmanage(ImBuf *i)
482 {
483         if(i->c_handle) {
484                 MEM_CacheLimiter_unmanage(i->c_handle);
485                 i->c_handle = NULL;
486         }
487 }
488
489 void IMB_cache_limiter_touch(ImBuf *i)
490 {
491         if(i->c_handle)
492                 MEM_CacheLimiter_touch(i->c_handle);
493 }
494
495 void IMB_cache_limiter_ref(ImBuf *i)
496 {
497         if(i->c_handle)
498                 MEM_CacheLimiter_ref(i->c_handle);
499 }
500
501 void IMB_cache_limiter_unref(ImBuf *i)
502 {
503         if(i->c_handle)
504                 MEM_CacheLimiter_unref(i->c_handle);
505 }
506
507 int IMB_cache_limiter_get_refcount(ImBuf *i)
508 {
509         if(i->c_handle)
510                 return MEM_CacheLimiter_get_refcount(i->c_handle);
511
512         return 0;
513 }
514