This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/imbuf/intern/allocimbuf.c

569 lines
12 KiB
C
Raw Normal View History

2003-05-26 05:24:53 +00:00
/*
2002-10-12 11:37:38 +00:00
* allocimbuf.c
*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* It's become a bit messy... Basically, only the IMB_ prefixed files
* should remain. */
#include "IMB_imbuf_types.h"
#include "imbuf.h"
#include "imbuf_patch.h"
#include "IMB_imbuf.h"
#include "IMB_divers.h"
#include "IMB_allocimbuf.h"
#include "MEM_CacheLimiterC-Api.h"
2002-10-12 11:37:38 +00:00
static unsigned int dfltcmap[16] = {
0x00000000, 0xffffffff, 0x777777ff, 0xccccccff,
0xcc3344ff, 0xdd8844ff, 0xccdd44ff, 0x888833ff,
0x338844ff, 0x44dd44ff, 0x44ddccff, 0x3388ccff,
0x8888ddff, 0x4433ccff, 0xcc33ccff, 0xcc88ddff
};
void imb_freeplanesImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
2002-10-12 11:37:38 +00:00
if (ibuf->planes){
if (ibuf->mall & IB_planes) MEM_freeN(ibuf->planes);
2002-10-12 11:37:38 +00:00
}
ibuf->planes = 0;
ibuf->mall &= ~IB_planes;
}
void imb_freemipmapImBuf(struct ImBuf * ibuf)
{
int a;
for(a=0; a<IB_MIPMAP_LEVELS; a++) {
if(ibuf->mipmap[a]) IMB_freeImBuf(ibuf->mipmap[a]);
ibuf->mipmap[a]= NULL;
}
}
/* any free rect frees mipmaps to be sure, creation is in render on first request */
void imb_freerectfloatImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
if (ibuf->rect_float) {
if (ibuf->mall & IB_rectfloat) {
MEM_freeN(ibuf->rect_float);
ibuf->rect_float=NULL;
}
}
imb_freemipmapImBuf(ibuf);
ibuf->rect_float= NULL;
ibuf->mall &= ~IB_rectfloat;
}
2002-10-12 11:37:38 +00:00
/* any free rect frees mipmaps to be sure, creation is in render on first request */
2002-10-12 11:37:38 +00:00
void imb_freerectImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
if (ibuf->rect) {
if (ibuf->mall & IB_rect) {
MEM_freeN(ibuf->rect);
}
2002-10-12 11:37:38 +00:00
}
imb_freemipmapImBuf(ibuf);
ibuf->rect= NULL;
2002-10-12 11:37:38 +00:00
ibuf->mall &= ~IB_rect;
}
static void freeencodedbufferImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
2002-10-12 11:37:38 +00:00
if (ibuf->encodedbuffer){
if (ibuf->mall & IB_mem) MEM_freeN(ibuf->encodedbuffer);
2002-10-12 11:37:38 +00:00
}
ibuf->encodedbuffer = 0;
ibuf->encodedbuffersize = 0;
ibuf->encodedsize = 0;
ibuf->mall &= ~IB_mem;
}
void IMB_freezbufImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
2002-10-12 11:37:38 +00:00
if (ibuf->zbuf){
if (ibuf->mall & IB_zbuf) MEM_freeN(ibuf->zbuf);
2002-10-12 11:37:38 +00:00
}
ibuf->zbuf= NULL;
2002-10-12 11:37:38 +00:00
ibuf->mall &= ~IB_zbuf;
}
void IMB_freezbuffloatImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
if (ibuf->zbuf_float){
if (ibuf->mall & IB_zbuffloat) MEM_freeN(ibuf->zbuf_float);
}
ibuf->zbuf_float= NULL;
ibuf->mall &= ~IB_zbuffloat;
}
2002-10-12 11:37:38 +00:00
void IMB_freecmapImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return;
2002-10-12 11:37:38 +00:00
if (ibuf->cmap){
if (ibuf->mall & IB_cmap) MEM_freeN(ibuf->cmap);
2002-10-12 11:37:38 +00:00
}
ibuf->cmap = 0;
ibuf->mall &= ~IB_cmap;
}
void IMB_freeImBuf(struct ImBuf * ibuf)
{
if (ibuf){
if (ibuf->refcounter > 0) {
ibuf->refcounter--;
} else {
imb_freeplanesImBuf(ibuf);
imb_freerectImBuf(ibuf);
imb_freerectfloatImBuf(ibuf);
IMB_freezbufImBuf(ibuf);
IMB_freezbuffloatImBuf(ibuf);
IMB_freecmapImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
IMB_cache_limiter_unmanage(ibuf);
MEM_freeN(ibuf);
}
2002-10-12 11:37:38 +00:00
}
}
void IMB_refImBuf(struct ImBuf * ibuf)
{
ibuf->refcounter++;
}
short addzbufImBuf(struct ImBuf * ibuf)
2002-10-12 11:37:38 +00:00
{
int size;
if (ibuf==NULL) return(FALSE);
2002-10-12 11:37:38 +00:00
IMB_freezbufImBuf(ibuf);
2002-10-12 11:37:38 +00:00
size = ibuf->x * ibuf->y * sizeof(unsigned int);
Added new malloc type in our MEM module; using the unix feature 'mmap'. In Orange we've been fighting the past weeks with memory usage a lot... at the moment incredible huge scenes are being rendered, with multiple layers and all compositing, stressing limits of memory a lot. I had hoped that less frequently used blocks would be swapped away nicely, so fragmented memory could survive. Unfortunately (in OSX) the malloc range is limited to 2 GB only (upped half of address space). Other OS's have a limit too, but typically larger afaik. Now here's mmap to the rescue! It has a very nice feature to map to a virtual (non existing) file, allowing to allocate disk-mapped memory on the fly. For as long there's real memory it works nearly as fast as a regular malloc, and when you go to the swap boundary, it knows nicely what to swap first. The upcoming commit will use mmap for all large memory blocks, like the composit stack, render layers, lamp buffers and images. Tested here on my 1 GB system, and compositing huge images with a total of 2.5 gig still works acceptable here. :) http://www.blender.org/bf/memory.jpg This is a silly composit test, using 64 MB images with a load of nodes. Check the header print... the (2323.33M) is the mmap disk-cache in use. BTW: note that is still limited to the virtual address space of 4 GB. The new call is: MEM_mapalloc() Per definition, mmap() returns zero'ed memory, so a calloc isn't required. For Windows there's no mmap() available, but I'm pretty sure there's an equivalent. Windows gurus here are invited to insert that here in code! At the moment it's nicely ifdeffed, so for Windows the mmap defaults to a regular alloc.
2006-02-16 17:51:01 +00:00
if ( (ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf")) ){
2002-10-12 11:37:38 +00:00
ibuf->mall |= IB_zbuf;
ibuf->flags |= IB_zbuf;
2002-10-12 11:37:38 +00:00
return (TRUE);
}
return (FALSE);
}
2002-10-12 11:37:38 +00:00
short addzbuffloatImBuf(struct ImBuf * ibuf)
{
int size;
if (ibuf==NULL) return(FALSE);
IMB_freezbuffloatImBuf(ibuf);
size = ibuf->x * ibuf->y * sizeof(float);
Added new malloc type in our MEM module; using the unix feature 'mmap'. In Orange we've been fighting the past weeks with memory usage a lot... at the moment incredible huge scenes are being rendered, with multiple layers and all compositing, stressing limits of memory a lot. I had hoped that less frequently used blocks would be swapped away nicely, so fragmented memory could survive. Unfortunately (in OSX) the malloc range is limited to 2 GB only (upped half of address space). Other OS's have a limit too, but typically larger afaik. Now here's mmap to the rescue! It has a very nice feature to map to a virtual (non existing) file, allowing to allocate disk-mapped memory on the fly. For as long there's real memory it works nearly as fast as a regular malloc, and when you go to the swap boundary, it knows nicely what to swap first. The upcoming commit will use mmap for all large memory blocks, like the composit stack, render layers, lamp buffers and images. Tested here on my 1 GB system, and compositing huge images with a total of 2.5 gig still works acceptable here. :) http://www.blender.org/bf/memory.jpg This is a silly composit test, using 64 MB images with a load of nodes. Check the header print... the (2323.33M) is the mmap disk-cache in use. BTW: note that is still limited to the virtual address space of 4 GB. The new call is: MEM_mapalloc() Per definition, mmap() returns zero'ed memory, so a calloc isn't required. For Windows there's no mmap() available, but I'm pretty sure there's an equivalent. Windows gurus here are invited to insert that here in code! At the moment it's nicely ifdeffed, so for Windows the mmap defaults to a regular alloc.
2006-02-16 17:51:01 +00:00
if ( (ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf")) ){
ibuf->mall |= IB_zbuffloat;
ibuf->flags |= IB_zbuffloat;
return (TRUE);
}
2002-10-12 11:37:38 +00:00
return (FALSE);
}
short imb_addencodedbufferImBuf(struct ImBuf * ibuf)
{
if (ibuf==NULL) return(FALSE);
2002-10-12 11:37:38 +00:00
freeencodedbufferImBuf(ibuf);
if (ibuf->encodedbuffersize == 0)
ibuf->encodedbuffersize = 10000;
ibuf->encodedsize = 0;
if ( (ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf") )){
2002-10-12 11:37:38 +00:00
ibuf->mall |= IB_mem;
ibuf->flags |= IB_mem;
2002-10-12 11:37:38 +00:00
return (TRUE);
}
return (FALSE);
}
short imb_enlargeencodedbufferImBuf(struct ImBuf * ibuf)
{
unsigned int newsize, encodedsize;
void *newbuffer;
if (ibuf==NULL) return(FALSE);
2002-10-12 11:37:38 +00:00
if (ibuf->encodedbuffersize < ibuf->encodedsize) {
printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
return(FALSE);
}
newsize = 2 * ibuf->encodedbuffersize;
if (newsize < 10000) newsize = 10000;
newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
if (newbuffer == NULL) return(FALSE);
if (ibuf->encodedbuffer) {
memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
} else {
ibuf->encodedsize = 0;
}
encodedsize = ibuf->encodedsize;
freeencodedbufferImBuf(ibuf);
ibuf->encodedbuffersize = newsize;
ibuf->encodedsize = encodedsize;
ibuf->encodedbuffer = newbuffer;
ibuf->mall |= IB_mem;
ibuf->flags |= IB_mem;
2002-10-12 11:37:38 +00:00
return (TRUE);
}
short imb_addrectfloatImBuf(struct ImBuf * ibuf)
{
int size;
if (ibuf==NULL) return(FALSE);
imb_freerectfloatImBuf(ibuf);
size = ibuf->x * ibuf->y;
size = size * 4 * sizeof(float);
Added new malloc type in our MEM module; using the unix feature 'mmap'. In Orange we've been fighting the past weeks with memory usage a lot... at the moment incredible huge scenes are being rendered, with multiple layers and all compositing, stressing limits of memory a lot. I had hoped that less frequently used blocks would be swapped away nicely, so fragmented memory could survive. Unfortunately (in OSX) the malloc range is limited to 2 GB only (upped half of address space). Other OS's have a limit too, but typically larger afaik. Now here's mmap to the rescue! It has a very nice feature to map to a virtual (non existing) file, allowing to allocate disk-mapped memory on the fly. For as long there's real memory it works nearly as fast as a regular malloc, and when you go to the swap boundary, it knows nicely what to swap first. The upcoming commit will use mmap for all large memory blocks, like the composit stack, render layers, lamp buffers and images. Tested here on my 1 GB system, and compositing huge images with a total of 2.5 gig still works acceptable here. :) http://www.blender.org/bf/memory.jpg This is a silly composit test, using 64 MB images with a load of nodes. Check the header print... the (2323.33M) is the mmap disk-cache in use. BTW: note that is still limited to the virtual address space of 4 GB. The new call is: MEM_mapalloc() Per definition, mmap() returns zero'ed memory, so a calloc isn't required. For Windows there's no mmap() available, but I'm pretty sure there's an equivalent. Windows gurus here are invited to insert that here in code! At the moment it's nicely ifdeffed, so for Windows the mmap defaults to a regular alloc.
2006-02-16 17:51:01 +00:00
if ( (ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf")) ){
ibuf->mall |= IB_rectfloat;
ibuf->flags |= IB_rectfloat;
return (TRUE);
}
return (FALSE);
}
2002-10-12 11:37:38 +00:00
/* question; why also add zbuf? */
2002-10-12 11:37:38 +00:00
short imb_addrectImBuf(struct ImBuf * ibuf)
{
int size;
if (ibuf==NULL) return(FALSE);
2002-10-12 11:37:38 +00:00
imb_freerectImBuf(ibuf);
size = ibuf->x * ibuf->y;
size = size * sizeof(unsigned int);
Added new malloc type in our MEM module; using the unix feature 'mmap'. In Orange we've been fighting the past weeks with memory usage a lot... at the moment incredible huge scenes are being rendered, with multiple layers and all compositing, stressing limits of memory a lot. I had hoped that less frequently used blocks would be swapped away nicely, so fragmented memory could survive. Unfortunately (in OSX) the malloc range is limited to 2 GB only (upped half of address space). Other OS's have a limit too, but typically larger afaik. Now here's mmap to the rescue! It has a very nice feature to map to a virtual (non existing) file, allowing to allocate disk-mapped memory on the fly. For as long there's real memory it works nearly as fast as a regular malloc, and when you go to the swap boundary, it knows nicely what to swap first. The upcoming commit will use mmap for all large memory blocks, like the composit stack, render layers, lamp buffers and images. Tested here on my 1 GB system, and compositing huge images with a total of 2.5 gig still works acceptable here. :) http://www.blender.org/bf/memory.jpg This is a silly composit test, using 64 MB images with a load of nodes. Check the header print... the (2323.33M) is the mmap disk-cache in use. BTW: note that is still limited to the virtual address space of 4 GB. The new call is: MEM_mapalloc() Per definition, mmap() returns zero'ed memory, so a calloc isn't required. For Windows there's no mmap() available, but I'm pretty sure there's an equivalent. Windows gurus here are invited to insert that here in code! At the moment it's nicely ifdeffed, so for Windows the mmap defaults to a regular alloc.
2006-02-16 17:51:01 +00:00
if ( (ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf")) ){
2002-10-12 11:37:38 +00:00
ibuf->mall |= IB_rect;
ibuf->flags |= IB_rect;
2002-10-12 11:37:38 +00:00
if (ibuf->depth > 32) return (addzbufImBuf(ibuf));
else return (TRUE);
}
return (FALSE);
}
short imb_addcmapImBuf(struct ImBuf *ibuf)
{
int min;
if (ibuf==NULL) return(FALSE);
2002-10-12 11:37:38 +00:00
IMB_freecmapImBuf(ibuf);
imb_checkncols(ibuf);
if (ibuf->maxcol == 0) return (TRUE);
if ( (ibuf->cmap = MEM_callocN(sizeof(unsigned int) * ibuf->maxcol, "imb_addcmapImBuf") ) ){
2002-10-12 11:37:38 +00:00
min = ibuf->maxcol * sizeof(unsigned int);
if (min > sizeof(dfltcmap)) min = sizeof(dfltcmap);
memcpy(ibuf->cmap, dfltcmap, min);
ibuf->mall |= IB_cmap;
ibuf->flags |= IB_cmap;
2002-10-12 11:37:38 +00:00
return (TRUE);
}
return (FALSE);
}
short imb_addplanesImBuf(struct ImBuf *ibuf)
{
int size;
short skipx,d,y;
unsigned int **planes;
unsigned int *point2;
if (ibuf==NULL) return(FALSE);
2002-10-12 11:37:38 +00:00
imb_freeplanesImBuf(ibuf);
skipx = ((ibuf->x+31) >> 5);
ibuf->skipx=skipx;
y=ibuf->y;
d=ibuf->depth;
planes = MEM_mallocN( (d*skipx*y)*sizeof(int) + d*sizeof(int *), "imb_addplanesImBuf");
ibuf->planes = planes;
if (planes==0) return (FALSE);
point2 = (unsigned int *)(planes+d);
size = skipx*y;
for (;d>0;d--){
*(planes++) = point2;
point2 += size;
}
ibuf->mall |= IB_planes;
ibuf->flags |= IB_planes;
2002-10-12 11:37:38 +00:00
return (TRUE);
}
struct ImBuf *IMB_allocImBuf(short x, short y, uchar d, unsigned int flags, uchar bitmap)
2002-10-12 11:37:38 +00:00
{
struct ImBuf *ibuf;
ibuf = MEM_callocN(sizeof(struct ImBuf), "ImBuf_struct");
if (bitmap) flags |= IB_planes;
if (ibuf){
ibuf->x= x;
ibuf->y= y;
ibuf->depth= d;
ibuf->ftype= TGA;
ibuf->channels= 4; /* float option, is set to other values when buffers get assigned */
2002-10-12 11:37:38 +00:00
if (flags & IB_rect){
if (imb_addrectImBuf(ibuf)==FALSE){
IMB_freeImBuf(ibuf);
return NULL;
}
}
if (flags & IB_rectfloat){
if (imb_addrectfloatImBuf(ibuf)==FALSE){
IMB_freeImBuf(ibuf);
return NULL;
2002-10-12 11:37:38 +00:00
}
}
if (flags & IB_zbuf){
if (addzbufImBuf(ibuf)==FALSE){
IMB_freeImBuf(ibuf);
return NULL;
2002-10-12 11:37:38 +00:00
}
}
if (flags & IB_zbuffloat){
if (addzbuffloatImBuf(ibuf)==FALSE){
IMB_freeImBuf(ibuf);
return NULL;
}
}
2002-10-12 11:37:38 +00:00
if (flags & IB_planes){
if (imb_addplanesImBuf(ibuf)==FALSE){
IMB_freeImBuf(ibuf);
return NULL;
2002-10-12 11:37:38 +00:00
}
}
}
return (ibuf);
}
/* does no zbuffers? */
2002-10-12 11:37:38 +00:00
struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1)
{
struct ImBuf *ibuf2, tbuf;
int flags = 0;
int a, x, y;
2002-10-12 11:37:38 +00:00
if (ibuf1 == NULL) return NULL;
2002-10-12 11:37:38 +00:00
if (ibuf1->rect) flags |= IB_rect;
if (ibuf1->rect_float) flags |= IB_rectfloat;
2002-10-12 11:37:38 +00:00
if (ibuf1->planes) flags |= IB_planes;
x = ibuf1->x;
y = ibuf1->y;
if (ibuf1->flags & IB_fields) y *= 2;
ibuf2 = IMB_allocImBuf(x, y, ibuf1->depth, flags, 0);
if (ibuf2 == NULL) return NULL;
2002-10-12 11:37:38 +00:00
if (flags & IB_rect)
memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
if (flags & IB_rectfloat)
memcpy(ibuf2->rect_float, ibuf1->rect_float, 4 * x * y * sizeof(float));
if (flags & IB_planes)
memcpy(*(ibuf2->planes),*(ibuf1->planes),ibuf1->depth * ibuf1->skipx * y * sizeof(int));
2002-10-12 11:37:38 +00:00
if (ibuf1->encodedbuffer) {
ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
if (imb_addencodedbufferImBuf(ibuf2) == FALSE) {
IMB_freeImBuf(ibuf2);
return NULL;
2002-10-12 11:37:38 +00:00
}
memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
}
/* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
2002-10-12 11:37:38 +00:00
tbuf = *ibuf1;
// fix pointers
2002-10-12 11:37:38 +00:00
tbuf.rect = ibuf2->rect;
tbuf.rect_float = ibuf2->rect_float;
2002-10-12 11:37:38 +00:00
tbuf.planes = ibuf2->planes;
tbuf.cmap = ibuf2->cmap;
tbuf.encodedbuffer = ibuf2->encodedbuffer;
tbuf.zbuf= NULL;
tbuf.zbuf_float= NULL;
for(a=0; a<IB_MIPMAP_LEVELS; a++)
tbuf.mipmap[a]= NULL;
2002-10-12 11:37:38 +00:00
// set malloc flag
2002-10-12 11:37:38 +00:00
tbuf.mall = ibuf2->mall;
tbuf.c_handle = 0;
2002-10-12 11:37:38 +00:00
*ibuf2 = tbuf;
if (ibuf1->cmap){
imb_addcmapImBuf(ibuf2);
if (ibuf2->cmap) memcpy(ibuf2->cmap,ibuf1->cmap,ibuf2->maxcol * sizeof(int));
}
return(ibuf2);
}
/* support for cache limiting */
static void imbuf_cache_destructor(void * data)
{
struct ImBuf * ibuf = (struct ImBuf*) data;
imb_freeplanesImBuf(ibuf);
imb_freerectImBuf(ibuf);
imb_freerectfloatImBuf(ibuf);
IMB_freezbufImBuf(ibuf);
IMB_freezbuffloatImBuf(ibuf);
IMB_freecmapImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
ibuf->c_handle = 0;
}
static MEM_CacheLimiterC ** get_imbuf_cache_limiter()
{
static MEM_CacheLimiterC * c = 0;
if (!c) {
c = new_MEM_CacheLimiter(imbuf_cache_destructor);
}
return &c;
}
void IMB_free_cache_limiter()
{
delete_MEM_CacheLimiter(*get_imbuf_cache_limiter());
*get_imbuf_cache_limiter() = 0;
}
void IMB_cache_limiter_insert(struct ImBuf * i)
{
if (!i->c_handle) {
i->c_handle = MEM_CacheLimiter_insert(
*get_imbuf_cache_limiter(), i);
MEM_CacheLimiter_ref(i->c_handle);
MEM_CacheLimiter_enforce_limits(
*get_imbuf_cache_limiter());
MEM_CacheLimiter_unref(i->c_handle);
}
}
void IMB_cache_limiter_unmanage(struct ImBuf * i)
{
if (i->c_handle) {
MEM_CacheLimiter_unmanage(i->c_handle);
i->c_handle = 0;
}
}
void IMB_cache_limiter_touch(struct ImBuf * i)
{
if (i->c_handle) {
MEM_CacheLimiter_touch(i->c_handle);
}
}
void IMB_cache_limiter_ref(struct ImBuf * i)
{
if (i->c_handle) {
MEM_CacheLimiter_ref(i->c_handle);
}
}
void IMB_cache_limiter_unref(struct ImBuf * i)
{
if (i->c_handle) {
MEM_CacheLimiter_unref(i->c_handle);
}
}
int IMB_cache_limiter_get_refcount(struct ImBuf * i)
{
if (i->c_handle) {
return MEM_CacheLimiter_get_refcount(i->c_handle);
}
return 0;
}