1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup imbuf
22  */
23 
24 /* It's become a bit messy... Basically, only the IMB_ prefixed files
25  * should remain. */
26 
27 #include <stddef.h>
28 
29 #include "IMB_imbuf.h"
30 #include "IMB_imbuf_types.h"
31 
32 #include "IMB_allocimbuf.h"
33 #include "IMB_colormanagement_intern.h"
34 #include "IMB_filetype.h"
35 #include "IMB_metadata.h"
36 
37 #include "imbuf.h"
38 
39 #include "MEM_guardedalloc.h"
40 
41 #include "BLI_threads.h"
42 #include "BLI_utildefines.h"
43 
44 static SpinLock refcounter_spin;
45 
imb_refcounter_lock_init(void)46 void imb_refcounter_lock_init(void)
47 {
48   BLI_spin_init(&refcounter_spin);
49 }
50 
imb_refcounter_lock_exit(void)51 void imb_refcounter_lock_exit(void)
52 {
53   BLI_spin_end(&refcounter_spin);
54 }
55 
56 #ifdef WIN32
57 static SpinLock mmap_spin;
58 
imb_mmap_lock_init(void)59 void imb_mmap_lock_init(void)
60 {
61   BLI_spin_init(&mmap_spin);
62 }
63 
imb_mmap_lock_exit(void)64 void imb_mmap_lock_exit(void)
65 {
66   BLI_spin_end(&mmap_spin);
67 }
68 
imb_mmap_lock(void)69 void imb_mmap_lock(void)
70 {
71   BLI_spin_lock(&mmap_spin);
72 }
73 
imb_mmap_unlock(void)74 void imb_mmap_unlock(void)
75 {
76   BLI_spin_unlock(&mmap_spin);
77 }
78 #endif
79 
imb_freemipmapImBuf(ImBuf * ibuf)80 void imb_freemipmapImBuf(ImBuf *ibuf)
81 {
82   int a;
83 
84   /* Do not trust ibuf->miptot, in some cases IMB_remakemipmap can leave unfreed unused levels,
85    * leading to memory leaks... */
86   for (a = 0; a < IMB_MIPMAP_LEVELS; a++) {
87     if (ibuf->mipmap[a] != NULL) {
88       IMB_freeImBuf(ibuf->mipmap[a]);
89       ibuf->mipmap[a] = NULL;
90     }
91   }
92 
93   ibuf->miptot = 0;
94 }
95 
96 /* any free rect frees mipmaps to be sure, creation is in render on first request */
imb_freerectfloatImBuf(ImBuf * ibuf)97 void imb_freerectfloatImBuf(ImBuf *ibuf)
98 {
99   if (ibuf == NULL) {
100     return;
101   }
102 
103   if (ibuf->rect_float && (ibuf->mall & IB_rectfloat)) {
104     MEM_freeN(ibuf->rect_float);
105     ibuf->rect_float = NULL;
106   }
107 
108   imb_freemipmapImBuf(ibuf);
109 
110   ibuf->rect_float = NULL;
111   ibuf->mall &= ~IB_rectfloat;
112 }
113 
114 /* any free rect frees mipmaps to be sure, creation is in render on first request */
imb_freerectImBuf(ImBuf * ibuf)115 void imb_freerectImBuf(ImBuf *ibuf)
116 {
117   if (ibuf == NULL) {
118     return;
119   }
120 
121   if (ibuf->rect && (ibuf->mall & IB_rect)) {
122     MEM_freeN(ibuf->rect);
123   }
124   ibuf->rect = NULL;
125 
126   imb_freemipmapImBuf(ibuf);
127 
128   ibuf->mall &= ~IB_rect;
129 }
130 
imb_freetilesImBuf(ImBuf * ibuf)131 void imb_freetilesImBuf(ImBuf *ibuf)
132 {
133   int tx, ty;
134 
135   if (ibuf == NULL) {
136     return;
137   }
138 
139   if (ibuf->tiles && (ibuf->mall & IB_tiles)) {
140     for (ty = 0; ty < ibuf->ytiles; ty++) {
141       for (tx = 0; tx < ibuf->xtiles; tx++) {
142         if (ibuf->tiles[ibuf->xtiles * ty + tx]) {
143           imb_tile_cache_tile_free(ibuf, tx, ty);
144           MEM_freeN(ibuf->tiles[ibuf->xtiles * ty + tx]);
145         }
146       }
147     }
148 
149     MEM_freeN(ibuf->tiles);
150   }
151 
152   ibuf->tiles = NULL;
153   ibuf->mall &= ~IB_tiles;
154 }
155 
freeencodedbufferImBuf(ImBuf * ibuf)156 static void freeencodedbufferImBuf(ImBuf *ibuf)
157 {
158   if (ibuf == NULL) {
159     return;
160   }
161 
162   if (ibuf->encodedbuffer && (ibuf->mall & IB_mem)) {
163     MEM_freeN(ibuf->encodedbuffer);
164   }
165 
166   ibuf->encodedbuffer = NULL;
167   ibuf->encodedbuffersize = 0;
168   ibuf->encodedsize = 0;
169   ibuf->mall &= ~IB_mem;
170 }
171 
IMB_freezbufImBuf(ImBuf * ibuf)172 void IMB_freezbufImBuf(ImBuf *ibuf)
173 {
174   if (ibuf == NULL) {
175     return;
176   }
177 
178   if (ibuf->zbuf && (ibuf->mall & IB_zbuf)) {
179     MEM_freeN(ibuf->zbuf);
180   }
181 
182   ibuf->zbuf = NULL;
183   ibuf->mall &= ~IB_zbuf;
184 }
185 
IMB_freezbuffloatImBuf(ImBuf * ibuf)186 void IMB_freezbuffloatImBuf(ImBuf *ibuf)
187 {
188   if (ibuf == NULL) {
189     return;
190   }
191 
192   if (ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat)) {
193     MEM_freeN(ibuf->zbuf_float);
194   }
195 
196   ibuf->zbuf_float = NULL;
197   ibuf->mall &= ~IB_zbuffloat;
198 }
199 
200 /** Free all pixel data (assosiated with image size). */
imb_freerectImbuf_all(ImBuf * ibuf)201 void imb_freerectImbuf_all(ImBuf *ibuf)
202 {
203   imb_freerectImBuf(ibuf);
204   imb_freerectfloatImBuf(ibuf);
205   imb_freetilesImBuf(ibuf);
206   IMB_freezbufImBuf(ibuf);
207   IMB_freezbuffloatImBuf(ibuf);
208   freeencodedbufferImBuf(ibuf);
209 }
210 
IMB_freeImBuf(ImBuf * ibuf)211 void IMB_freeImBuf(ImBuf *ibuf)
212 {
213   if (ibuf) {
214     bool needs_free = false;
215 
216     BLI_spin_lock(&refcounter_spin);
217     if (ibuf->refcounter > 0) {
218       ibuf->refcounter--;
219     }
220     else {
221       needs_free = true;
222     }
223     BLI_spin_unlock(&refcounter_spin);
224 
225     if (needs_free) {
226       imb_freerectImbuf_all(ibuf);
227       IMB_metadata_free(ibuf->metadata);
228       colormanage_cache_free(ibuf);
229 
230       if (ibuf->dds_data.data != NULL) {
231         /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
232         free(ibuf->dds_data.data);
233       }
234       MEM_freeN(ibuf);
235     }
236   }
237 }
238 
IMB_refImBuf(ImBuf * ibuf)239 void IMB_refImBuf(ImBuf *ibuf)
240 {
241   BLI_spin_lock(&refcounter_spin);
242   ibuf->refcounter++;
243   BLI_spin_unlock(&refcounter_spin);
244 }
245 
IMB_makeSingleUser(ImBuf * ibuf)246 ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
247 {
248   ImBuf *rval;
249 
250   if (ibuf) {
251     bool is_single;
252     BLI_spin_lock(&refcounter_spin);
253     is_single = (ibuf->refcounter == 0);
254     BLI_spin_unlock(&refcounter_spin);
255     if (is_single) {
256       return ibuf;
257     }
258   }
259   else {
260     return NULL;
261   }
262 
263   rval = IMB_dupImBuf(ibuf);
264 
265   IMB_metadata_copy(rval, ibuf);
266 
267   IMB_freeImBuf(ibuf);
268 
269   return rval;
270 }
271 
addzbufImBuf(ImBuf * ibuf)272 bool addzbufImBuf(ImBuf *ibuf)
273 {
274   if (ibuf == NULL) {
275     return false;
276   }
277 
278   IMB_freezbufImBuf(ibuf);
279 
280   if ((ibuf->zbuf = imb_alloc_pixels(ibuf->x, ibuf->y, 1, sizeof(unsigned int), __func__))) {
281     ibuf->mall |= IB_zbuf;
282     ibuf->flags |= IB_zbuf;
283     return true;
284   }
285 
286   return false;
287 }
288 
addzbuffloatImBuf(ImBuf * ibuf)289 bool addzbuffloatImBuf(ImBuf *ibuf)
290 {
291   if (ibuf == NULL) {
292     return false;
293   }
294 
295   IMB_freezbuffloatImBuf(ibuf);
296 
297   if ((ibuf->zbuf_float = imb_alloc_pixels(ibuf->x, ibuf->y, 1, sizeof(float), __func__))) {
298     ibuf->mall |= IB_zbuffloat;
299     ibuf->flags |= IB_zbuffloat;
300     return true;
301   }
302 
303   return false;
304 }
305 
imb_addencodedbufferImBuf(ImBuf * ibuf)306 bool imb_addencodedbufferImBuf(ImBuf *ibuf)
307 {
308   if (ibuf == NULL) {
309     return false;
310   }
311 
312   freeencodedbufferImBuf(ibuf);
313 
314   if (ibuf->encodedbuffersize == 0) {
315     ibuf->encodedbuffersize = 10000;
316   }
317 
318   ibuf->encodedsize = 0;
319 
320   if ((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, __func__))) {
321     ibuf->mall |= IB_mem;
322     ibuf->flags |= IB_mem;
323     return true;
324   }
325 
326   return false;
327 }
328 
imb_enlargeencodedbufferImBuf(ImBuf * ibuf)329 bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
330 {
331   unsigned int newsize, encodedsize;
332   void *newbuffer;
333 
334   if (ibuf == NULL) {
335     return false;
336   }
337 
338   if (ibuf->encodedbuffersize < ibuf->encodedsize) {
339     printf("%s: error in parameters\n", __func__);
340     return false;
341   }
342 
343   newsize = 2 * ibuf->encodedbuffersize;
344   if (newsize < 10000) {
345     newsize = 10000;
346   }
347 
348   newbuffer = MEM_mallocN(newsize, __func__);
349   if (newbuffer == NULL) {
350     return false;
351   }
352 
353   if (ibuf->encodedbuffer) {
354     memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
355   }
356   else {
357     ibuf->encodedsize = 0;
358   }
359 
360   encodedsize = ibuf->encodedsize;
361 
362   freeencodedbufferImBuf(ibuf);
363 
364   ibuf->encodedbuffersize = newsize;
365   ibuf->encodedsize = encodedsize;
366   ibuf->encodedbuffer = newbuffer;
367   ibuf->mall |= IB_mem;
368   ibuf->flags |= IB_mem;
369 
370   return true;
371 }
372 
imb_alloc_pixels(unsigned int x,unsigned int y,unsigned int channels,size_t typesize,const char * name)373 void *imb_alloc_pixels(
374     unsigned int x, unsigned int y, unsigned int channels, size_t typesize, const char *name)
375 {
376   /* Protect against buffer overflow vulnerabilities from files specifying
377    * a width and height that overflow and alloc too little memory. */
378   if (!((uint64_t)x * (uint64_t)y < (SIZE_MAX / (channels * typesize)))) {
379     return NULL;
380   }
381 
382   size_t size = (size_t)x * (size_t)y * (size_t)channels * typesize;
383   return MEM_callocN(size, name);
384 }
385 
imb_addrectfloatImBuf(ImBuf * ibuf)386 bool imb_addrectfloatImBuf(ImBuf *ibuf)
387 {
388   if (ibuf == NULL) {
389     return false;
390   }
391 
392   if (ibuf->rect_float) {
393     imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */
394   }
395 
396   ibuf->channels = 4;
397   if ((ibuf->rect_float = imb_alloc_pixels(ibuf->x, ibuf->y, 4, sizeof(float), __func__))) {
398     ibuf->mall |= IB_rectfloat;
399     ibuf->flags |= IB_rectfloat;
400     return true;
401   }
402 
403   return false;
404 }
405 
406 /* question; why also add zbuf? */
imb_addrectImBuf(ImBuf * ibuf)407 bool imb_addrectImBuf(ImBuf *ibuf)
408 {
409   if (ibuf == NULL) {
410     return false;
411   }
412 
413   /* Don't call imb_freerectImBuf, it frees mipmaps,
414    * this call is used only too give float buffers display. */
415   if (ibuf->rect && (ibuf->mall & IB_rect)) {
416     MEM_freeN(ibuf->rect);
417   }
418   ibuf->rect = NULL;
419 
420   if ((ibuf->rect = imb_alloc_pixels(ibuf->x, ibuf->y, 4, sizeof(unsigned char), __func__))) {
421     ibuf->mall |= IB_rect;
422     ibuf->flags |= IB_rect;
423     if (ibuf->planes > 32) {
424       return (addzbufImBuf(ibuf));
425     }
426 
427     return true;
428   }
429 
430   return false;
431 }
432 
IMB_allocFromBuffer(const unsigned int * rect,const float * rectf,unsigned int w,unsigned int h,unsigned int channels)433 struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
434                                   const float *rectf,
435                                   unsigned int w,
436                                   unsigned int h,
437                                   unsigned int channels)
438 {
439   ImBuf *ibuf = NULL;
440 
441   if (!(rect || rectf)) {
442     return NULL;
443   }
444 
445   ibuf = IMB_allocImBuf(w, h, 32, 0);
446 
447   ibuf->channels = channels;
448   if (rectf) {
449     ibuf->rect_float = MEM_dupallocN(rectf);
450     ibuf->flags |= IB_rectfloat;
451     ibuf->mall |= IB_rectfloat;
452   }
453   if (rect) {
454     ibuf->rect = MEM_dupallocN(rect);
455     ibuf->flags |= IB_rect;
456     ibuf->mall |= IB_rect;
457   }
458 
459   return ibuf;
460 }
461 
imb_addtilesImBuf(ImBuf * ibuf)462 bool imb_addtilesImBuf(ImBuf *ibuf)
463 {
464   if (ibuf == NULL) {
465     return false;
466   }
467 
468   if (!ibuf->tiles) {
469     if ((ibuf->tiles = MEM_callocN(sizeof(unsigned int *) * ibuf->xtiles * ibuf->ytiles,
470                                    "imb_tiles"))) {
471       ibuf->mall |= IB_tiles;
472     }
473   }
474 
475   return (ibuf->tiles != NULL);
476 }
477 
IMB_allocImBuf(unsigned int x,unsigned int y,uchar planes,unsigned int flags)478 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int flags)
479 {
480   ImBuf *ibuf;
481 
482   ibuf = MEM_mallocN(sizeof(ImBuf), "ImBuf_struct");
483 
484   if (ibuf) {
485     if (!IMB_initImBuf(ibuf, x, y, planes, flags)) {
486       IMB_freeImBuf(ibuf);
487       return NULL;
488     }
489   }
490 
491   return ibuf;
492 }
493 
IMB_initImBuf(struct ImBuf * ibuf,unsigned int x,unsigned int y,unsigned char planes,unsigned int flags)494 bool IMB_initImBuf(
495     struct ImBuf *ibuf, unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
496 {
497   memset(ibuf, 0, sizeof(ImBuf));
498 
499   ibuf->x = x;
500   ibuf->y = y;
501   ibuf->planes = planes;
502   ibuf->ftype = IMB_FTYPE_PNG;
503   /* The '15' means, set compression to low ratio but not time consuming. */
504   ibuf->foptions.quality = 15;
505   /* float option, is set to other values when buffers get assigned. */
506   ibuf->channels = 4;
507   /* IMB_DPI_DEFAULT -> pixels-per-meter. */
508   ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f;
509 
510   if (flags & IB_rect) {
511     if (imb_addrectImBuf(ibuf) == false) {
512       return false;
513     }
514   }
515 
516   if (flags & IB_rectfloat) {
517     if (imb_addrectfloatImBuf(ibuf) == false) {
518       return false;
519     }
520   }
521 
522   if (flags & IB_zbuf) {
523     if (addzbufImBuf(ibuf) == false) {
524       return false;
525     }
526   }
527 
528   if (flags & IB_zbuffloat) {
529     if (addzbuffloatImBuf(ibuf) == false) {
530       return false;
531     }
532   }
533 
534   /* assign default spaces */
535   colormanage_imbuf_set_default_spaces(ibuf);
536 
537   return true;
538 }
539 
540 /* does no zbuffers? */
IMB_dupImBuf(const ImBuf * ibuf1)541 ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
542 {
543   ImBuf *ibuf2, tbuf;
544   int flags = 0;
545   int a, x, y;
546 
547   if (ibuf1 == NULL) {
548     return NULL;
549   }
550 
551   if (ibuf1->rect) {
552     flags |= IB_rect;
553   }
554   if (ibuf1->rect_float) {
555     flags |= IB_rectfloat;
556   }
557   if (ibuf1->zbuf) {
558     flags |= IB_zbuf;
559   }
560   if (ibuf1->zbuf_float) {
561     flags |= IB_zbuffloat;
562   }
563 
564   x = ibuf1->x;
565   y = ibuf1->y;
566 
567   ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags);
568   if (ibuf2 == NULL) {
569     return NULL;
570   }
571 
572   if (flags & IB_rect) {
573     memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int));
574   }
575 
576   if (flags & IB_rectfloat) {
577     memcpy(
578         ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float));
579   }
580 
581   if (flags & IB_zbuf) {
582     memcpy(ibuf2->zbuf, ibuf1->zbuf, ((size_t)x) * y * sizeof(int));
583   }
584 
585   if (flags & IB_zbuffloat) {
586     memcpy(ibuf2->zbuf_float, ibuf1->zbuf_float, ((size_t)x) * y * sizeof(float));
587   }
588 
589   if (ibuf1->encodedbuffer) {
590     ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
591     if (imb_addencodedbufferImBuf(ibuf2) == false) {
592       IMB_freeImBuf(ibuf2);
593       return NULL;
594     }
595 
596     memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
597   }
598 
599   /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
600   tbuf = *ibuf1;
601 
602   /* fix pointers */
603   tbuf.rect = ibuf2->rect;
604   tbuf.rect_float = ibuf2->rect_float;
605   tbuf.encodedbuffer = ibuf2->encodedbuffer;
606   tbuf.zbuf = ibuf2->zbuf;
607   tbuf.zbuf_float = ibuf2->zbuf_float;
608   for (a = 0; a < IMB_MIPMAP_LEVELS; a++) {
609     tbuf.mipmap[a] = NULL;
610   }
611   tbuf.dds_data.data = NULL;
612 
613   /* set malloc flag */
614   tbuf.mall = ibuf2->mall;
615   tbuf.c_handle = NULL;
616   tbuf.refcounter = 0;
617 
618   /* for now don't duplicate metadata */
619   tbuf.metadata = NULL;
620 
621   tbuf.display_buffer_flags = NULL;
622   tbuf.colormanage_cache = NULL;
623 
624   *ibuf2 = tbuf;
625 
626   return ibuf2;
627 }
628 
IMB_get_size_in_memory(ImBuf * ibuf)629 size_t IMB_get_size_in_memory(ImBuf *ibuf)
630 {
631   int a;
632   size_t size = 0, channel_size = 0;
633 
634   size += sizeof(ImBuf);
635 
636   if (ibuf->rect) {
637     channel_size += sizeof(char);
638   }
639 
640   if (ibuf->rect_float) {
641     channel_size += sizeof(float);
642   }
643 
644   size += channel_size * ibuf->x * ibuf->y * ibuf->channels;
645 
646   if (ibuf->miptot) {
647     for (a = 0; a < ibuf->miptot; a++) {
648       if (ibuf->mipmap[a]) {
649         size += IMB_get_size_in_memory(ibuf->mipmap[a]);
650       }
651     }
652   }
653 
654   if (ibuf->tiles) {
655     size += sizeof(unsigned int) * ibuf->ytiles * ibuf->xtiles;
656   }
657 
658   return size;
659 }
660 
661 #if 0 /* remove? - campbell */
662 /* support for cache limiting */
663 
664 static void imbuf_cache_destructor(void *data)
665 {
666   ImBuf *ibuf = (ImBuf *)data;
667 
668   imb_freerectImBuf(ibuf);
669   imb_freerectfloatImBuf(ibuf);
670   IMB_freezbufImBuf(ibuf);
671   IMB_freezbuffloatImBuf(ibuf);
672   freeencodedbufferImBuf(ibuf);
673 
674   ibuf->c_handle = NULL;
675 }
676 
677 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
678 {
679   static MEM_CacheLimiterC *c = NULL;
680 
681   if (!c) {
682     c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
683   }
684 
685   return &c;
686 }
687 #endif
688