Blender V4.5
allocimbuf.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9/* It's become a bit messy... Basically, only the IMB_ prefixed files
10 * should remain. */
11
12#include <algorithm>
13#include <cstddef>
14
15#include "IMB_imbuf.hh"
16#include "IMB_imbuf_types.hh"
17
18#include "IMB_allocimbuf.hh"
20#include "IMB_filetype.hh"
21#include "IMB_metadata.hh"
22
23#include "imbuf.hh"
24
25#include "MEM_guardedalloc.h"
26
27#include "BLI_threads.h"
28
29#include "GPU_texture.hh"
30
31#include "atomic_ops.h"
32
33#ifndef WIN32
35
40
45
50
55#endif
56
57/* Free the specified buffer storage, freeing memory when needed and restoring the state of the
58 * buffer to its defaults. */
59template<class BufferType> static void imb_free_buffer(BufferType &buffer)
60{
61 if (buffer.data) {
62 switch (buffer.ownership) {
64 break;
65
67 MEM_freeN(buffer.data);
68 break;
69 }
70 }
71
72 /* Reset buffer to defaults. */
73 buffer.data = nullptr;
74 buffer.ownership = IB_DO_NOT_TAKE_OWNERSHIP;
75}
76
77/* Free the specified DDS buffer storage, freeing memory when needed and restoring the state of the
78 * buffer to its defaults. */
79static void imb_free_dds_buffer(DDSData &dds_data)
80{
81 if (dds_data.data) {
82 switch (dds_data.ownership) {
84 break;
85
87 /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
88 free(dds_data.data);
89 break;
90 }
91 }
92
93 /* Reset buffer to defaults. */
94 dds_data.data = nullptr;
96}
97
98/* Allocate pixel storage of the given buffer. The buffer owns the allocated memory.
99 * Returns true of allocation succeeded, false otherwise. */
100template<class BufferType>
101bool imb_alloc_buffer(BufferType &buffer,
102 const uint x,
103 const uint y,
104 const uint channels,
105 const size_t type_size,
106 bool initialize_pixels)
107{
108 buffer.data = static_cast<decltype(BufferType::data)>(
109 imb_alloc_pixels(x, y, channels, type_size, initialize_pixels, __func__));
110 if (!buffer.data) {
111 return false;
112 }
113
114 buffer.ownership = IB_TAKE_OWNERSHIP;
115
116 return true;
117}
118
119/* Make the buffer available for modification.
120 * Is achieved by ensuring that the buffer is the only owner of its data. */
121template<class BufferType> void imb_make_writeable_buffer(BufferType &buffer)
122{
123 if (!buffer.data) {
124 return;
125 }
126
127 switch (buffer.ownership) {
129 buffer.data = static_cast<decltype(BufferType::data)>(MEM_dupallocN(buffer.data));
130 buffer.ownership = IB_TAKE_OWNERSHIP;
131
133 break;
134 }
135}
136
137template<class BufferType>
138auto imb_steal_buffer_data(BufferType &buffer) -> decltype(BufferType::data)
139{
140 if (!buffer.data) {
141 return nullptr;
142 }
143
144 switch (buffer.ownership) {
146 BLI_assert_msg(false, "Unexpected behavior: stealing non-owned data pointer");
147 return nullptr;
148
149 case IB_TAKE_OWNERSHIP: {
150 decltype(BufferType::data) data = buffer.data;
151
152 buffer.data = nullptr;
153 buffer.ownership = IB_DO_NOT_TAKE_OWNERSHIP;
154
155 return data;
156 }
157 }
158
160
161 return nullptr;
162}
163
165{
166 int a;
167
168 /* Do not trust ibuf->miptot, in some cases IMB_remakemipmap can leave unfreed unused levels,
169 * leading to memory leaks... */
170 for (a = 0; a < IMB_MIPMAP_LEVELS; a++) {
171 if (ibuf->mipmap[a] != nullptr) {
172 IMB_freeImBuf(ibuf->mipmap[a]);
173 ibuf->mipmap[a] = nullptr;
174 }
175 }
176
177 ibuf->miptot = 0;
178}
179
181{
182 if (ibuf == nullptr) {
183 return;
184 }
185
187
188 IMB_free_mipmaps(ibuf);
189
190 ibuf->flags &= ~IB_float_data;
191}
192
194{
195 if (ibuf == nullptr) {
196 return;
197 }
198
200
201 IMB_free_mipmaps(ibuf);
202
203 ibuf->flags &= ~IB_byte_data;
204}
205
206static void free_encoded_data(ImBuf *ibuf)
207{
208 if (ibuf == nullptr) {
209 return;
210 }
211
213
214 ibuf->encoded_buffer_size = 0;
215 ibuf->encoded_size = 0;
216
217 ibuf->flags &= ~IB_mem;
218}
219
221{
224 free_encoded_data(ibuf);
225}
226
228{
229 if (!ibuf || !ibuf->gpu.texture) {
230 return;
231 }
232
234 ibuf->gpu.texture = nullptr;
235}
236
238{
239 if (ibuf == nullptr) {
240 return;
241 }
242
243 bool needs_free = atomic_sub_and_fetch_int32(&ibuf->refcounter, 1) < 0;
244 if (needs_free) {
245 /* Include this check here as the path may be manipulated after creation. */
246 BLI_assert_msg(!(ibuf->filepath[0] == '/' && ibuf->filepath[1] == '/'),
247 "'.blend' relative \"//\" must not be used in ImBuf!");
248
249 IMB_free_all_data(ibuf);
254 MEM_freeN(ibuf);
255 }
256}
257
259{
261}
262
264{
265 if (ibuf == nullptr) {
266 return nullptr;
267 }
268
269 const bool is_single = (atomic_load_int32(&ibuf->refcounter) == 0);
270 if (is_single) {
271 return ibuf;
272 }
273
274 ImBuf *rval = IMB_dupImBuf(ibuf);
275
276 IMB_metadata_copy(rval, ibuf);
277
278 IMB_freeImBuf(ibuf);
279
280 return rval;
281}
282
284{
285 if (ibuf == nullptr) {
286 return false;
287 }
288
289 free_encoded_data(ibuf);
290
291 if (ibuf->encoded_buffer_size == 0) {
292 ibuf->encoded_buffer_size = 10000;
293 }
294
295 ibuf->encoded_size = 0;
296
297 if (!imb_alloc_buffer(
298 ibuf->encoded_buffer, ibuf->encoded_buffer_size, 1, 1, sizeof(uint8_t), true))
299 {
300 return false;
301 }
302
303 ibuf->flags |= IB_mem;
304
305 return true;
306}
307
309{
310 if (ibuf == nullptr) {
311 return false;
312 }
313
314 if (ibuf->encoded_buffer_size < ibuf->encoded_size) {
315 printf("%s: error in parameters\n", __func__);
316 return false;
317 }
318
319 uint newsize = 2 * ibuf->encoded_buffer_size;
320 newsize = std::max<uint>(newsize, 10000);
321
322 ImBufByteBuffer new_buffer;
323 if (!imb_alloc_buffer(new_buffer, newsize, 1, 1, sizeof(uint8_t), true)) {
324 return false;
325 }
326
327 if (ibuf->encoded_buffer.data) {
328 memcpy(new_buffer.data, ibuf->encoded_buffer.data, ibuf->encoded_size);
329 }
330 else {
331 ibuf->encoded_size = 0;
332 }
333
335
336 ibuf->encoded_buffer = new_buffer;
337 ibuf->encoded_buffer_size = newsize;
338 ibuf->flags |= IB_mem;
339
340 return true;
341}
342
344 uint x, uint y, uint channels, size_t typesize, bool initialize_pixels, const char *alloc_name)
345{
346 /* Protect against buffer overflow vulnerabilities from files specifying
347 * a width and height that overflow and alloc too little memory. */
348 if (!(uint64_t(x) * uint64_t(y) < (SIZE_MAX / (channels * typesize)))) {
349 return nullptr;
350 }
351
352 size_t size = size_t(x) * size_t(y) * size_t(channels) * typesize;
353 return initialize_pixels ? MEM_callocN(size, alloc_name) : MEM_mallocN(size, alloc_name);
354}
355
356bool IMB_alloc_float_pixels(ImBuf *ibuf, const uint channels, bool initialize_pixels)
357{
358 if (ibuf == nullptr) {
359 return false;
360 }
361
362 /* NOTE: Follows the historical code.
363 * Is unclear if it is desired or not to free mipmaps. If mipmaps are to be preserved a simple
364 * `imb_free_buffer(ibuf->float_buffer)` can be used instead. */
365 if (ibuf->float_buffer.data) {
366 IMB_free_float_pixels(ibuf); /* frees mipmap too, hrm */
367 }
368
369 if (!imb_alloc_buffer(
370 ibuf->float_buffer, ibuf->x, ibuf->y, channels, sizeof(float), initialize_pixels))
371 {
372 return false;
373 }
374
375 ibuf->channels = channels;
376 ibuf->flags |= IB_float_data;
377
378 return true;
379}
380
381bool IMB_alloc_byte_pixels(ImBuf *ibuf, bool initialize_pixels)
382{
383 /* Question; why also add ZBUF (when `planes > 32`)? */
384
385 if (ibuf == nullptr) {
386 return false;
387 }
388
389 /* Don't call IMB_free_byte_pixels, it frees mipmaps,
390 * this call is used only too give float buffers display. */
392
393 if (!imb_alloc_buffer(
394 ibuf->byte_buffer, ibuf->x, ibuf->y, 4, sizeof(uint8_t), initialize_pixels))
395 {
396 return false;
397 }
398
399 ibuf->flags |= IB_byte_data;
400
401 return true;
402}
403
405{
406 uint8_t *data = imb_steal_buffer_data(ibuf->byte_buffer);
407 ibuf->flags &= ~IB_byte_data;
408 return data;
409}
410
412{
414 ibuf->flags &= ~IB_float_data;
415 return data;
416}
417
419{
420 uint8_t *data = imb_steal_buffer_data(ibuf->encoded_buffer);
421
422 ibuf->encoded_size = 0;
423 ibuf->encoded_buffer_size = 0;
424
425 ibuf->flags &= ~IB_mem;
426
427 return data;
428}
429
434
439
440void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, const ImBufOwnership ownership)
441{
443 ibuf->flags &= ~IB_byte_data;
444
445 if (buffer_data) {
446 ibuf->byte_buffer.data = buffer_data;
447 ibuf->byte_buffer.ownership = ownership;
448
449 ibuf->flags |= IB_byte_data;
450 }
451}
452
453void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, const ImBufOwnership ownership)
454{
456 ibuf->flags &= ~IB_float_data;
457
458 if (buffer_data) {
459 ibuf->float_buffer.data = buffer_data;
460 ibuf->float_buffer.ownership = ownership;
461
462 ibuf->flags |= IB_float_data;
463 }
464}
465
467 const ImBufByteBuffer &buffer,
468 const ImBufOwnership ownership)
469{
470 IMB_assign_byte_buffer(ibuf, buffer.data, ownership);
471 ibuf->byte_buffer.colorspace = buffer.colorspace;
472}
473
475 const ImBufFloatBuffer &buffer,
476 const ImBufOwnership ownership)
477{
478 IMB_assign_float_buffer(ibuf, buffer.data, ownership);
479 ibuf->float_buffer.colorspace = buffer.colorspace;
480}
481
482void IMB_assign_dds_data(ImBuf *ibuf, const DDSData &data, const ImBufOwnership ownership)
483{
485
487
488 ibuf->dds_data = data;
489 ibuf->dds_data.ownership = ownership;
490}
491
493 uint8_t *byte_buffer, float *float_buffer, uint w, uint h, uint channels)
494{
495 if (!(byte_buffer || float_buffer)) {
496 return nullptr;
497 }
498
499 ImBuf *ibuf = IMB_allocImBuf(w, h, 32, 0);
500
501 ibuf->channels = channels;
502
503 if (float_buffer) {
504 /* TODO(sergey): The 4 channels is the historical code. Should probably be `channels`, but
505 * needs a dedicated investigation. */
506 BLI_assert(MEM_allocN_len(float_buffer) == sizeof(float[4]) * w * h);
507 IMB_assign_float_buffer(ibuf, float_buffer, IB_TAKE_OWNERSHIP);
508 }
509
510 if (byte_buffer) {
511 BLI_assert(MEM_allocN_len(byte_buffer) == sizeof(uint8_t[4]) * w * h);
512 IMB_assign_byte_buffer(ibuf, byte_buffer, IB_TAKE_OWNERSHIP);
513 }
514
515 return ibuf;
516}
517
519 const uint8_t *byte_buffer, const float *float_buffer, uint w, uint h, uint channels)
520{
521 ImBuf *ibuf = nullptr;
522
523 if (!(byte_buffer || float_buffer)) {
524 return nullptr;
525 }
526
527 ibuf = IMB_allocImBuf(w, h, 32, 0);
528
529 ibuf->channels = channels;
530
531 /* NOTE: Avoid #MEM_dupallocN since the buffers might not be allocated using guarded-allocation.
532 */
533 if (float_buffer) {
534 /* TODO(sergey): The 4 channels is the historical code. Should probably be `channels`, but
535 * needs a dedicated investigation. */
536 imb_alloc_buffer(ibuf->float_buffer, w, h, 4, sizeof(float), false);
537
538 memcpy(ibuf->float_buffer.data, float_buffer, sizeof(float[4]) * w * h);
539 }
540
541 if (byte_buffer) {
542 imb_alloc_buffer(ibuf->byte_buffer, w, h, 4, sizeof(uint8_t), false);
543
544 memcpy(ibuf->byte_buffer.data, byte_buffer, sizeof(uint8_t[4]) * w * h);
545 }
546
547 return ibuf;
548}
549
551{
552 ImBuf *ibuf = MEM_callocN<ImBuf>("ImBuf_struct");
553
554 if (ibuf) {
555 if (!IMB_initImBuf(ibuf, x, y, planes, flags)) {
556 IMB_freeImBuf(ibuf);
557 return nullptr;
558 }
559 }
560
561 return ibuf;
562}
563
564bool IMB_initImBuf(ImBuf *ibuf, uint x, uint y, uchar planes, uint flags)
565{
566 *ibuf = ImBuf{};
567
568 ibuf->x = x;
569 ibuf->y = y;
570 ibuf->planes = planes;
571 ibuf->ftype = IMB_FTYPE_PNG;
572 /* The '15' means, set compression to low ratio but not time consuming. */
573 ibuf->foptions.quality = 15;
574 /* float option, is set to other values when buffers get assigned. */
575 ibuf->channels = 4;
576 /* IMB_DPI_DEFAULT -> pixels-per-meter. */
577 ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254;
578
579 const bool init_pixels = (flags & IB_uninitialized_pixels) == 0;
580
581 if (flags & IB_byte_data) {
582 if (IMB_alloc_byte_pixels(ibuf, init_pixels) == false) {
583 return false;
584 }
585 }
586
587 if (flags & IB_float_data) {
588 if (IMB_alloc_float_pixels(ibuf, ibuf->channels, init_pixels) == false) {
589 return false;
590 }
591 }
592
593 /* assign default spaces */
595
596 return true;
597}
598
600{
601 ImBuf *ibuf2, tbuf;
602 int flags = IB_uninitialized_pixels;
603 int a, x, y;
604
605 if (ibuf1 == nullptr) {
606 return nullptr;
607 }
608
609 if (ibuf1->byte_buffer.data) {
610 flags |= IB_byte_data;
611 }
612
613 x = ibuf1->x;
614 y = ibuf1->y;
615
616 ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags);
617 if (ibuf2 == nullptr) {
618 return nullptr;
619 }
620
621 if (flags & IB_byte_data) {
622 memcpy(ibuf2->byte_buffer.data, ibuf1->byte_buffer.data, size_t(x) * y * 4 * sizeof(uint8_t));
623 }
624
625 if (ibuf1->float_buffer.data) {
626 /* Ensure the correct number of channels are being allocated for the new #ImBuf. Some
627 * compositing scenarios might end up with >4 channels and we want to duplicate them properly.
628 */
629 if (IMB_alloc_float_pixels(ibuf2, ibuf1->channels, false) == false) {
630 IMB_freeImBuf(ibuf2);
631 return nullptr;
632 }
633
634 memcpy(ibuf2->float_buffer.data,
635 ibuf1->float_buffer.data,
636 size_t(ibuf2->channels) * x * y * sizeof(float));
637 }
638
639 if (ibuf1->encoded_buffer.data) {
641 if (imb_addencodedbufferImBuf(ibuf2) == false) {
642 IMB_freeImBuf(ibuf2);
643 return nullptr;
644 }
645
646 memcpy(ibuf2->encoded_buffer.data, ibuf1->encoded_buffer.data, ibuf1->encoded_size);
647 }
648
651
652 /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
653 tbuf = *ibuf1;
654
655 /* fix pointers */
656 tbuf.byte_buffer = ibuf2->byte_buffer;
657 tbuf.float_buffer = ibuf2->float_buffer;
658 tbuf.encoded_buffer = ibuf2->encoded_buffer;
659 for (a = 0; a < IMB_MIPMAP_LEVELS; a++) {
660 tbuf.mipmap[a] = nullptr;
661 }
662 tbuf.dds_data.data = nullptr;
663
664 /* Set `malloc` flag. */
665 tbuf.refcounter = 0;
666
667 /* for now don't duplicate metadata */
668 tbuf.metadata = nullptr;
669
670 tbuf.display_buffer_flags = nullptr;
671 tbuf.colormanage_cache = nullptr;
672
673 /* GPU textures can not be easily copied, as it is not guaranteed that this function is called
674 * from within an active GPU context. */
675 tbuf.gpu.texture = nullptr;
676
677 *ibuf2 = tbuf;
678
679 return ibuf2;
680}
681
682size_t IMB_get_pixel_count(const ImBuf *ibuf)
683{
684 return size_t(ibuf->x) * size_t(ibuf->y);
685}
686
687size_t IMB_get_size_in_memory(const ImBuf *ibuf)
688{
689 int a;
690 size_t size = 0, channel_size = 0;
691
692 size += sizeof(ImBuf);
693
694 if (ibuf->byte_buffer.data) {
695 channel_size += sizeof(char);
696 }
697
698 if (ibuf->float_buffer.data) {
699 channel_size += sizeof(float);
700 }
701
702 size += channel_size * IMB_get_pixel_count(ibuf) * size_t(ibuf->channels);
703
704 if (ibuf->miptot) {
705 for (a = 0; a < ibuf->miptot; a++) {
706 if (ibuf->mipmap[a]) {
708 }
709 }
710 }
711
712 return size;
713}
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void BLI_kdtree_nd_ free(KDTree *tree)
unsigned char uchar
unsigned int uint
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_unlock(SpinLock *spin)
Definition threads.cc:430
void BLI_spin_lock(SpinLock *spin)
Definition threads.cc:405
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
void GPU_texture_free(GPUTexture *texture)
@ IMB_FTYPE_DDS
@ IMB_FTYPE_PNG
#define IMB_MIPMAP_LEVELS
ImBufOwnership
@ IB_DO_NOT_TAKE_OWNERSHIP
@ IB_TAKE_OWNERSHIP
@ IB_float_data
@ IB_byte_data
@ IB_uninitialized_pixels
@ IB_mem
void IMB_metadata_free(IDProperty *metadata)
Definition metadata.cc:32
void IMB_metadata_copy(ImBuf *ibuf_dst, const ImBuf *ibuf_src)
Definition metadata.cc:59
Read Guarded memory(de)allocation.
void IMB_free_gpu_textures(ImBuf *ibuf)
void imb_mmap_lock_exit()
Definition allocimbuf.cc:41
bool IMB_alloc_byte_pixels(ImBuf *ibuf, bool initialize_pixels)
float * IMB_steal_float_buffer(ImBuf *ibuf)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_make_writable_byte_buffer(ImBuf *ibuf)
uint8_t * IMB_steal_byte_buffer(ImBuf *ibuf)
static SpinLock mmap_spin
Definition allocimbuf.cc:34
bool IMB_alloc_float_pixels(ImBuf *ibuf, const uint channels, bool initialize_pixels)
void imb_mmap_lock()
Definition allocimbuf.cc:46
bool IMB_initImBuf(ImBuf *ibuf, uint x, uint y, uchar planes, uint flags)
ImBuf * IMB_makeSingleUser(ImBuf *ibuf)
void imb_mmap_lock_init()
Definition allocimbuf.cc:36
void * imb_alloc_pixels(uint x, uint y, uint channels, size_t typesize, bool initialize_pixels, const char *alloc_name)
static void imb_free_dds_buffer(DDSData &dds_data)
Definition allocimbuf.cc:79
void IMB_free_all_data(ImBuf *ibuf)
void IMB_make_writable_float_buffer(ImBuf *ibuf)
bool imb_alloc_buffer(BufferType &buffer, const uint x, const uint y, const uint channels, const size_t type_size, bool initialize_pixels)
ImBuf * IMB_allocImBuf(uint x, uint y, uchar planes, uint flags)
ImBuf * IMB_allocFromBufferOwn(uint8_t *byte_buffer, float *float_buffer, uint w, uint h, uint channels)
bool imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
static void free_encoded_data(ImBuf *ibuf)
void IMB_freeImBuf(ImBuf *ibuf)
size_t IMB_get_pixel_count(const ImBuf *ibuf)
Get the length of the data of the given image buffer in pixels.
void imb_make_writeable_buffer(BufferType &buffer)
void IMB_free_float_pixels(ImBuf *ibuf)
void IMB_refImBuf(ImBuf *ibuf)
void IMB_free_byte_pixels(ImBuf *ibuf)
uint8_t * IMB_steal_encoded_buffer(ImBuf *ibuf)
void IMB_assign_dds_data(ImBuf *ibuf, const DDSData &data, const ImBufOwnership ownership)
auto imb_steal_buffer_data(BufferType &buffer) -> decltype(BufferType::data)
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, const ImBufOwnership ownership)
void imb_mmap_unlock()
Definition allocimbuf.cc:51
ImBuf * IMB_allocFromBuffer(const uint8_t *byte_buffer, const float *float_buffer, uint w, uint h, uint channels)
static void imb_free_buffer(BufferType &buffer)
Definition allocimbuf.cc:59
void IMB_free_mipmaps(ImBuf *ibuf)
bool imb_addencodedbufferImBuf(ImBuf *ibuf)
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, const ImBufOwnership ownership)
size_t IMB_get_size_in_memory(const ImBuf *ibuf)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x)
ATOMIC_INLINE int32_t atomic_load_int32(const int32_t *v)
ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x)
BMesh const char void * data
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
void colormanage_cache_free(ImBuf *ibuf)
void colormanage_imbuf_set_default_spaces(ImBuf *ibuf)
#define SIZE_MAX
#define printf(...)
#define IMB_DPI_DEFAULT
Definition imbuf.hh:26
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ImBufOwnership ownership
unsigned char * data
const ColorSpace * colorspace
ImBufOwnership ownership
const ColorSpace * colorspace
ImBufOwnership ownership
GPUTexture * texture
ImBufGPU gpu
char filepath[IMB_FILEPATH_SIZE]
DDSData dds_data
ImBufFloatBuffer float_buffer
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
unsigned char planes
enum eImbFileType ftype
ImBuf * mipmap[IMB_MIPMAP_LEVELS]
unsigned int encoded_buffer_size
unsigned int * display_buffer_flags
IDProperty * metadata
ColormanageCache * colormanage_cache
ImBufByteBuffer encoded_buffer
int32_t refcounter
double ppm[2]
unsigned int encoded_size