Fix msvc 2013 compiler errors after the ingenious cleanup in 4ca67869cc7a.
[blender.git] / source / blender / imbuf / intern / allocimbuf.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/imbuf/intern/allocimbuf.c
29  *  \ingroup imbuf
30  */
31
32
33 /* It's become a bit messy... Basically, only the IMB_ prefixed files
34  * should remain. */
35
36 #include <stddef.h>
37
38 #include "IMB_imbuf.h"
39 #include "IMB_imbuf_types.h"
40
41 #include "IMB_allocimbuf.h"
42 #include "IMB_filetype.h"
43 #include "IMB_metadata.h"
44 #include "IMB_colormanagement_intern.h"
45
46 #include "imbuf.h"
47
48 #include "MEM_guardedalloc.h"
49
50 #include "BLI_utildefines.h"
51 #include "BLI_threads.h"
52
53 static SpinLock refcounter_spin;
54
55 void imb_refcounter_lock_init(void)
56 {
57         BLI_spin_init(&refcounter_spin);
58 }
59
60 void imb_refcounter_lock_exit(void)
61 {
62         BLI_spin_end(&refcounter_spin);
63 }
64
65 void imb_freemipmapImBuf(ImBuf *ibuf)
66 {
67         int a;
68         
69         for (a = 1; a < ibuf->miptot; a++) {
70                 if (ibuf->mipmap[a - 1])
71                         IMB_freeImBuf(ibuf->mipmap[a - 1]);
72                 ibuf->mipmap[a - 1] = NULL;
73         }
74
75         ibuf->miptot = 0;
76 }
77
78 /* any free rect frees mipmaps to be sure, creation is in render on first request */
79 void imb_freerectfloatImBuf(ImBuf *ibuf)
80 {
81         if (ibuf == NULL) return;
82         
83         if (ibuf->rect_float && (ibuf->mall & IB_rectfloat)) {
84                 MEM_freeN(ibuf->rect_float);
85                 ibuf->rect_float = NULL;
86         }
87
88         imb_freemipmapImBuf(ibuf);
89         
90         ibuf->rect_float = NULL;
91         ibuf->mall &= ~IB_rectfloat;
92 }
93
94 /* any free rect frees mipmaps to be sure, creation is in render on first request */
95 void imb_freerectImBuf(ImBuf *ibuf)
96 {
97         if (ibuf == NULL) return;
98
99         if (ibuf->rect && (ibuf->mall & IB_rect))
100                 MEM_freeN(ibuf->rect);
101         ibuf->rect = NULL;
102         
103         imb_freemipmapImBuf(ibuf);
104
105         ibuf->mall &= ~IB_rect;
106 }
107
108 void imb_freetilesImBuf(ImBuf *ibuf)
109 {
110         int tx, ty;
111
112         if (ibuf == NULL) return;
113
114         if (ibuf->tiles && (ibuf->mall & IB_tiles)) {
115                 for (ty = 0; ty < ibuf->ytiles; ty++) {
116                         for (tx = 0; tx < ibuf->xtiles; tx++) {
117                                 if (ibuf->tiles[ibuf->xtiles * ty + tx]) {
118                                         imb_tile_cache_tile_free(ibuf, tx, ty);
119                                         MEM_freeN(ibuf->tiles[ibuf->xtiles * ty + tx]);
120                                 }
121                         }
122                 }
123
124                 MEM_freeN(ibuf->tiles);
125         }
126
127         ibuf->tiles = NULL;
128         ibuf->mall &= ~IB_tiles;
129 }
130
131 static void freeencodedbufferImBuf(ImBuf *ibuf)
132 {
133         if (ibuf == NULL) return;
134
135         if (ibuf->encodedbuffer && (ibuf->mall & IB_mem))
136                 MEM_freeN(ibuf->encodedbuffer);
137
138         ibuf->encodedbuffer = NULL;
139         ibuf->encodedbuffersize = 0;
140         ibuf->encodedsize = 0;
141         ibuf->mall &= ~IB_mem;
142 }
143
144 void IMB_freezbufImBuf(ImBuf *ibuf)
145 {
146         if (ibuf == NULL) return;
147
148         if (ibuf->zbuf && (ibuf->mall & IB_zbuf))
149                 MEM_freeN(ibuf->zbuf);
150
151         ibuf->zbuf = NULL;
152         ibuf->mall &= ~IB_zbuf;
153 }
154
155 void IMB_freezbuffloatImBuf(ImBuf *ibuf)
156 {
157         if (ibuf == NULL) return;
158
159         if (ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat))
160                 MEM_freeN(ibuf->zbuf_float);
161
162         ibuf->zbuf_float = NULL;
163         ibuf->mall &= ~IB_zbuffloat;
164 }
165
166 void IMB_freeImBuf(ImBuf *ibuf)
167 {
168         if (ibuf) {
169                 bool needs_free = false;
170
171                 BLI_spin_lock(&refcounter_spin);
172                 if (ibuf->refcounter > 0) {
173                         ibuf->refcounter--;
174                 }
175                 else {
176                         needs_free = true;
177                 }
178                 BLI_spin_unlock(&refcounter_spin);
179
180                 if (needs_free) {
181                         imb_freerectImBuf(ibuf);
182                         imb_freerectfloatImBuf(ibuf);
183                         imb_freetilesImBuf(ibuf);
184                         IMB_freezbufImBuf(ibuf);
185                         IMB_freezbuffloatImBuf(ibuf);
186                         freeencodedbufferImBuf(ibuf);
187                         IMB_metadata_free(ibuf);
188                         colormanage_cache_free(ibuf);
189
190                         if (ibuf->dds_data.data != NULL) {
191                                 free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
192                         }
193                         MEM_freeN(ibuf);
194                 }
195         }
196 }
197
198 void IMB_refImBuf(ImBuf *ibuf)
199 {
200         BLI_spin_lock(&refcounter_spin);
201         ibuf->refcounter++;
202         BLI_spin_unlock(&refcounter_spin);
203 }
204
205 ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
206 {
207         ImBuf *rval;
208
209         if (!ibuf || ibuf->refcounter == 0) { return ibuf; }
210
211         rval = IMB_dupImBuf(ibuf);
212
213         IMB_freeImBuf(ibuf);
214
215         return rval;
216 }
217
218 bool addzbufImBuf(ImBuf *ibuf)
219 {
220         size_t size;
221         
222         if (ibuf == NULL) return false;
223         
224         IMB_freezbufImBuf(ibuf);
225         
226         size = (size_t)ibuf->x * (size_t)ibuf->y * sizeof(unsigned int);
227
228         if ((ibuf->zbuf = MEM_mapallocN(size, __func__))) {
229                 ibuf->mall |= IB_zbuf;
230                 ibuf->flags |= IB_zbuf;
231                 return true;
232         }
233         
234         return false;
235 }
236
237 bool addzbuffloatImBuf(ImBuf *ibuf)
238 {
239         size_t size;
240         
241         if (ibuf == NULL) return false;
242         
243         IMB_freezbuffloatImBuf(ibuf);
244         
245         size = (size_t)ibuf->x * (size_t)ibuf->y * sizeof(float);
246
247         if ((ibuf->zbuf_float = MEM_mapallocN(size, __func__))) {
248                 ibuf->mall |= IB_zbuffloat;
249                 ibuf->flags |= IB_zbuffloat;
250                 return true;
251         }
252         
253         return false;
254 }
255
256
257 bool imb_addencodedbufferImBuf(ImBuf *ibuf)
258 {
259         if (ibuf == NULL) return false;
260
261         freeencodedbufferImBuf(ibuf);
262
263         if (ibuf->encodedbuffersize == 0)
264                 ibuf->encodedbuffersize = 10000;
265
266         ibuf->encodedsize = 0;
267
268         if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, __func__))) {
269                 ibuf->mall |= IB_mem;
270                 ibuf->flags |= IB_mem;
271                 return true;
272         }
273
274         return false;
275 }
276
277
278 bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
279 {
280         unsigned int newsize, encodedsize;
281         void *newbuffer;
282
283         if (ibuf == NULL) return false;
284
285         if (ibuf->encodedbuffersize < ibuf->encodedsize) {
286                 printf("%s: error in parameters\n", __func__);
287                 return false;
288         }
289
290         newsize = 2 * ibuf->encodedbuffersize;
291         if (newsize < 10000) newsize = 10000;
292
293         newbuffer = MEM_mallocN(newsize, __func__);
294         if (newbuffer == NULL) return false;
295
296         if (ibuf->encodedbuffer) {
297                 memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
298         }
299         else {
300                 ibuf->encodedsize = 0;
301         }
302
303         encodedsize = ibuf->encodedsize;
304
305         freeencodedbufferImBuf(ibuf);
306
307         ibuf->encodedbuffersize = newsize;
308         ibuf->encodedsize = encodedsize;
309         ibuf->encodedbuffer = newbuffer;
310         ibuf->mall |= IB_mem;
311         ibuf->flags |= IB_mem;
312
313         return true;
314 }
315
316 bool imb_addrectfloatImBuf(ImBuf *ibuf)
317 {
318         size_t size;
319         
320         if (ibuf == NULL) return false;
321         
322         if (ibuf->rect_float)
323                 imb_freerectfloatImBuf(ibuf);  /* frees mipmap too, hrm */
324         
325         size = (size_t)ibuf->x * (size_t)ibuf->y * sizeof(float[4]);
326
327         ibuf->channels = 4;
328         if ((ibuf->rect_float = MEM_mapallocN(size, __func__))) {
329                 ibuf->mall |= IB_rectfloat;
330                 ibuf->flags |= IB_rectfloat;
331                 return true;
332         }
333         
334         return false;
335 }
336
337 /* question; why also add zbuf? */
338 bool imb_addrectImBuf(ImBuf *ibuf)
339 {
340         size_t size;
341
342         if (ibuf == NULL) return false;
343         
344         /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
345         if (ibuf->rect && (ibuf->mall & IB_rect))
346                 MEM_freeN(ibuf->rect);
347         ibuf->rect = NULL;
348         
349         size = (size_t)ibuf->x * (size_t)ibuf->y * sizeof(unsigned int);
350
351         if ((ibuf->rect = MEM_mapallocN(size, __func__))) {
352                 ibuf->mall |= IB_rect;
353                 ibuf->flags |= IB_rect;
354                 if (ibuf->planes > 32) {
355                         return (addzbufImBuf(ibuf));
356                 }
357                 else {
358                         return true;
359                 }
360         }
361
362         return false;
363 }
364
365 bool imb_addtilesImBuf(ImBuf *ibuf)
366 {
367         if (ibuf == NULL) return false;
368
369         if (!ibuf->tiles)
370                 if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles, "imb_tiles")))
371                         ibuf->mall |= IB_tiles;
372
373         return (ibuf->tiles != NULL);
374 }
375
376 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int flags)
377 {
378         ImBuf *ibuf;
379
380         ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
381
382         if (ibuf) {
383                 ibuf->x = x;
384                 ibuf->y = y;
385                 ibuf->planes = planes;
386                 ibuf->ftype = PNG | 15; /* the 15 means, set compression to low ratio but not time consuming */
387                 ibuf->channels = 4;  /* float option, is set to other values when buffers get assigned */
388                 ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */
389
390                 if (flags & IB_rect) {
391                         if (imb_addrectImBuf(ibuf) == false) {
392                                 IMB_freeImBuf(ibuf);
393                                 return NULL;
394                         }
395                 }
396                 
397                 if (flags & IB_rectfloat) {
398                         if (imb_addrectfloatImBuf(ibuf) == false) {
399                                 IMB_freeImBuf(ibuf);
400                                 return NULL;
401                         }
402                 }
403                 
404                 if (flags & IB_zbuf) {
405                         if (addzbufImBuf(ibuf) == false) {
406                                 IMB_freeImBuf(ibuf);
407                                 return NULL;
408                         }
409                 }
410                 
411                 if (flags & IB_zbuffloat) {
412                         if (addzbuffloatImBuf(ibuf) == false) {
413                                 IMB_freeImBuf(ibuf);
414                                 return NULL;
415                         }
416                 }
417
418                 /* assign default spaces */
419                 colormanage_imbuf_set_default_spaces(ibuf);
420         }
421         return (ibuf);
422 }
423
424 /* does no zbuffers? */
425 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
426 {
427         ImBuf *ibuf2, tbuf;
428         int flags = 0;
429         int a, x, y;
430         
431         if (ibuf1 == NULL) return NULL;
432
433         if (ibuf1->rect) flags |= IB_rect;
434         if (ibuf1->rect_float) flags |= IB_rectfloat;
435
436         x = ibuf1->x;
437         y = ibuf1->y;
438         if (ibuf1->flags & IB_fields) y *= 2;
439         
440         ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags);
441         if (ibuf2 == NULL) return NULL;
442
443         if (flags & IB_rect)
444                 memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
445         
446         if (flags & IB_rectfloat)
447                 memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float));
448
449         if (ibuf1->encodedbuffer) {
450                 ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
451                 if (imb_addencodedbufferImBuf(ibuf2) == false) {
452                         IMB_freeImBuf(ibuf2);
453                         return NULL;
454                 }
455
456                 memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
457         }
458
459         /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
460         tbuf = *ibuf1;
461         
462         /* fix pointers */
463         tbuf.rect          = ibuf2->rect;
464         tbuf.rect_float    = ibuf2->rect_float;
465         tbuf.encodedbuffer = ibuf2->encodedbuffer;
466         tbuf.zbuf          = NULL;
467         tbuf.zbuf_float    = NULL;
468         for (a = 0; a < IB_MIPMAP_LEVELS; a++)
469                 tbuf.mipmap[a] = NULL;
470         tbuf.dds_data.data = NULL;
471         
472         /* set malloc flag */
473         tbuf.mall               = ibuf2->mall;
474         tbuf.c_handle           = NULL;
475         tbuf.refcounter         = 0;
476
477         /* for now don't duplicate metadata */
478         tbuf.metadata = NULL;
479
480         tbuf.display_buffer_flags = NULL;
481         tbuf.colormanage_cache = NULL;
482
483         *ibuf2 = tbuf;
484
485         return(ibuf2);
486 }
487
488 #if 0 /* remove? - campbell */
489 /* support for cache limiting */
490
491 static void imbuf_cache_destructor(void *data)
492 {
493         ImBuf *ibuf = (ImBuf *) data;
494
495         imb_freerectImBuf(ibuf);
496         imb_freerectfloatImBuf(ibuf);
497         IMB_freezbufImBuf(ibuf);
498         IMB_freezbuffloatImBuf(ibuf);
499         freeencodedbufferImBuf(ibuf);
500
501         ibuf->c_handle = NULL;
502 }
503
504
505 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
506 {
507         static MEM_CacheLimiterC *c = NULL;
508
509         if (!c)
510                 c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
511
512         return &c;
513 }
514 #endif