Blender V2.61 - r43446

allocimbuf.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 /* It's become a bit messy... Basically, only the IMB_ prefixed files
00034  * should remain. */
00035 
00036 #include <stddef.h>
00037 
00038 #include "IMB_imbuf.h"
00039 #include "IMB_imbuf_types.h"
00040 
00041 #include "IMB_allocimbuf.h"
00042 #include "IMB_filetype.h"
00043 #include "IMB_metadata.h"
00044 
00045 #include "imbuf.h"
00046 
00047 #include "MEM_guardedalloc.h"
00048 #include "MEM_CacheLimiterC-Api.h"
00049 
00050 void imb_freemipmapImBuf(ImBuf *ibuf)
00051 {
00052     int a;
00053     
00054     for(a=1; a<ibuf->miptot; a++) {
00055         if(ibuf->mipmap[a-1])
00056             IMB_freeImBuf(ibuf->mipmap[a-1]);
00057         ibuf->mipmap[a-1]= NULL;
00058     }
00059 
00060     ibuf->miptot= 0;
00061 }
00062 
00063 /* any free rect frees mipmaps to be sure, creation is in render on first request */
00064 void imb_freerectfloatImBuf(ImBuf *ibuf)
00065 {
00066     if(ibuf==NULL) return;
00067     
00068     if(ibuf->rect_float && (ibuf->mall & IB_rectfloat)) {
00069         MEM_freeN(ibuf->rect_float);
00070         ibuf->rect_float=NULL;
00071     }
00072 
00073     imb_freemipmapImBuf(ibuf);
00074     
00075     ibuf->rect_float= NULL;
00076     ibuf->mall &= ~IB_rectfloat;
00077 }
00078 
00079 /* any free rect frees mipmaps to be sure, creation is in render on first request */
00080 void imb_freerectImBuf(ImBuf *ibuf)
00081 {
00082     if(ibuf==NULL) return;
00083 
00084     if(ibuf->rect && (ibuf->mall & IB_rect))
00085         MEM_freeN(ibuf->rect);
00086     ibuf->rect= NULL;
00087     
00088     imb_freemipmapImBuf(ibuf);
00089 
00090     ibuf->mall &= ~IB_rect;
00091 }
00092 
00093 void imb_freetilesImBuf(ImBuf *ibuf)
00094 {
00095     int tx, ty;
00096 
00097     if(ibuf==NULL) return;
00098 
00099     if(ibuf->tiles && (ibuf->mall & IB_tiles)) {
00100         for(ty=0; ty<ibuf->ytiles; ty++) {
00101             for(tx=0; tx<ibuf->xtiles; tx++) {
00102                 if(ibuf->tiles[ibuf->xtiles*ty + tx]) {
00103                     imb_tile_cache_tile_free(ibuf, tx, ty);
00104                     MEM_freeN(ibuf->tiles[ibuf->xtiles*ty + tx]);
00105                 }
00106             }
00107         }
00108 
00109         MEM_freeN(ibuf->tiles);
00110     }
00111 
00112     ibuf->tiles= NULL;
00113     ibuf->mall &= ~IB_tiles;
00114 }
00115 
00116 static void freeencodedbufferImBuf(ImBuf *ibuf)
00117 {
00118     if(ibuf==NULL) return;
00119 
00120     if(ibuf->encodedbuffer && (ibuf->mall & IB_mem))
00121         MEM_freeN(ibuf->encodedbuffer);
00122 
00123     ibuf->encodedbuffer = NULL;
00124     ibuf->encodedbuffersize = 0;
00125     ibuf->encodedsize = 0;
00126     ibuf->mall &= ~IB_mem;
00127 }
00128 
00129 void IMB_freezbufImBuf(ImBuf *ibuf)
00130 {
00131     if(ibuf==NULL) return;
00132 
00133     if(ibuf->zbuf && (ibuf->mall & IB_zbuf))
00134         MEM_freeN(ibuf->zbuf);
00135 
00136     ibuf->zbuf= NULL;
00137     ibuf->mall &= ~IB_zbuf;
00138 }
00139 
00140 void IMB_freezbuffloatImBuf(ImBuf *ibuf)
00141 {
00142     if(ibuf==NULL) return;
00143 
00144     if(ibuf->zbuf_float && (ibuf->mall & IB_zbuffloat))
00145         MEM_freeN(ibuf->zbuf_float);
00146 
00147     ibuf->zbuf_float= NULL;
00148     ibuf->mall &= ~IB_zbuffloat;
00149 }
00150 
00151 void IMB_freeImBuf(ImBuf *ibuf)
00152 {
00153     if(ibuf) {
00154         if(ibuf->refcounter > 0) {
00155             ibuf->refcounter--;
00156         }
00157         else {
00158             imb_freerectImBuf(ibuf);
00159             imb_freerectfloatImBuf(ibuf);
00160             imb_freetilesImBuf(ibuf);
00161             IMB_freezbufImBuf(ibuf);
00162             IMB_freezbuffloatImBuf(ibuf);
00163             freeencodedbufferImBuf(ibuf);
00164             IMB_metadata_free(ibuf);
00165             MEM_freeN(ibuf);
00166         }
00167     }
00168 }
00169 
00170 void IMB_refImBuf(ImBuf *ibuf)
00171 {
00172     ibuf->refcounter++;
00173 }
00174 
00175 ImBuf * IMB_makeSingleUser(ImBuf *ibuf)
00176 {
00177     ImBuf * rval;
00178 
00179     if (!ibuf || ibuf->refcounter == 0) { return ibuf; }
00180 
00181     rval = IMB_dupImBuf(ibuf);
00182 
00183     IMB_freeImBuf(ibuf);
00184 
00185     return rval;
00186 }
00187 
00188 short addzbufImBuf(ImBuf *ibuf)
00189 {
00190     int size;
00191     
00192     if(ibuf==NULL) return FALSE;
00193     
00194     IMB_freezbufImBuf(ibuf);
00195     
00196     size = ibuf->x *ibuf->y *sizeof(unsigned int);
00197     if((ibuf->zbuf = MEM_mapallocN(size, "addzbufImBuf"))) {
00198         ibuf->mall |= IB_zbuf;
00199         ibuf->flags |= IB_zbuf;
00200         return TRUE;
00201     }
00202     
00203     return FALSE;
00204 }
00205 
00206 short addzbuffloatImBuf(ImBuf *ibuf)
00207 {
00208     int size;
00209     
00210     if(ibuf==NULL) return FALSE;
00211     
00212     IMB_freezbuffloatImBuf(ibuf);
00213     
00214     size = ibuf->x *ibuf->y *sizeof(float);
00215     if((ibuf->zbuf_float = MEM_mapallocN(size, "addzbuffloatImBuf"))) {
00216         ibuf->mall |= IB_zbuffloat;
00217         ibuf->flags |= IB_zbuffloat;
00218         return TRUE;
00219     }
00220     
00221     return FALSE;
00222 }
00223 
00224 
00225 short imb_addencodedbufferImBuf(ImBuf *ibuf)
00226 {
00227     if(ibuf==NULL) return FALSE;
00228 
00229     freeencodedbufferImBuf(ibuf);
00230 
00231     if(ibuf->encodedbuffersize == 0) 
00232         ibuf->encodedbuffersize = 10000;
00233 
00234     ibuf->encodedsize = 0;
00235 
00236     if((ibuf->encodedbuffer = MEM_mallocN(ibuf->encodedbuffersize, "addencodedbufferImBuf"))) {
00237         ibuf->mall |= IB_mem;
00238         ibuf->flags |= IB_mem;
00239         return TRUE;
00240     }
00241 
00242     return FALSE;
00243 }
00244 
00245 
00246 short imb_enlargeencodedbufferImBuf(ImBuf *ibuf)
00247 {
00248     unsigned int newsize, encodedsize;
00249     void *newbuffer;
00250 
00251     if(ibuf==NULL) return FALSE;
00252 
00253     if(ibuf->encodedbuffersize < ibuf->encodedsize) {
00254         printf("imb_enlargeencodedbufferImBuf: error in parameters\n");
00255         return FALSE;
00256     }
00257 
00258     newsize = 2 *ibuf->encodedbuffersize;
00259     if(newsize < 10000) newsize = 10000;
00260 
00261     newbuffer = MEM_mallocN(newsize, "enlargeencodedbufferImBuf");
00262     if(newbuffer == NULL) return FALSE;
00263 
00264     if(ibuf->encodedbuffer) {
00265         memcpy(newbuffer, ibuf->encodedbuffer, ibuf->encodedsize);
00266     } else {
00267         ibuf->encodedsize = 0;
00268     }
00269 
00270     encodedsize = ibuf->encodedsize;
00271 
00272     freeencodedbufferImBuf(ibuf);
00273 
00274     ibuf->encodedbuffersize = newsize;
00275     ibuf->encodedsize = encodedsize;
00276     ibuf->encodedbuffer = newbuffer;
00277     ibuf->mall |= IB_mem;
00278     ibuf->flags |= IB_mem;
00279 
00280     return TRUE;
00281 }
00282 
00283 short imb_addrectfloatImBuf(ImBuf *ibuf)
00284 {
00285     int size;
00286     
00287     if(ibuf==NULL) return FALSE;
00288     
00289     if(ibuf->rect_float)
00290         imb_freerectfloatImBuf(ibuf); /* frees mipmap too, hrm */
00291     
00292     size = ibuf->x *ibuf->y;
00293     size = size *4 *sizeof(float);
00294     ibuf->channels= 4;
00295     
00296     if((ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf"))) {
00297         ibuf->mall |= IB_rectfloat;
00298         ibuf->flags |= IB_rectfloat;
00299         return TRUE;
00300     }
00301     
00302     return FALSE;
00303 }
00304 
00305 /* question; why also add zbuf? */
00306 short imb_addrectImBuf(ImBuf *ibuf)
00307 {
00308     int size;
00309 
00310     if(ibuf==NULL) return FALSE;
00311     
00312     /* don't call imb_freerectImBuf, it frees mipmaps, this call is used only too give float buffers display */
00313     if(ibuf->rect && (ibuf->mall & IB_rect))
00314         MEM_freeN(ibuf->rect);
00315     ibuf->rect= NULL;
00316     
00317     size = ibuf->x*ibuf->y;
00318     size = size*sizeof(unsigned int);
00319 
00320     if((ibuf->rect = MEM_mapallocN(size, "imb_addrectImBuf"))) {
00321         ibuf->mall |= IB_rect;
00322         ibuf->flags |= IB_rect;
00323         if(ibuf->planes > 32) return (addzbufImBuf(ibuf));
00324         else return TRUE;
00325     }
00326 
00327     return FALSE;
00328 }
00329 
00330 short imb_addtilesImBuf(ImBuf *ibuf)
00331 {
00332     if(ibuf==NULL) return FALSE;
00333 
00334     if(!ibuf->tiles)
00335         if((ibuf->tiles = MEM_callocN(sizeof(unsigned int*)*ibuf->xtiles*ibuf->ytiles, "imb_tiles")))
00336             ibuf->mall |= IB_tiles;
00337 
00338     return (ibuf->tiles != NULL);
00339 }
00340 
00341 ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int flags)
00342 {
00343     ImBuf *ibuf;
00344 
00345     ibuf = MEM_callocN(sizeof(ImBuf), "ImBuf_struct");
00346 
00347     if(ibuf) {
00348         ibuf->x= x;
00349         ibuf->y= y;
00350         ibuf->planes= planes;
00351         ibuf->ftype= TGA;
00352         ibuf->channels= 4;  /* float option, is set to other values when buffers get assigned */
00353         ibuf->ppm[0]= ibuf->ppm[1]= 150.0 / 0.0254; /* 150dpi -> pixels-per-meter */
00354         
00355         if(flags & IB_rect) {
00356             if(imb_addrectImBuf(ibuf)==FALSE) {
00357                 IMB_freeImBuf(ibuf);
00358                 return NULL;
00359             }
00360         }
00361         
00362         if(flags & IB_rectfloat) {
00363             if(imb_addrectfloatImBuf(ibuf)==FALSE) {
00364                 IMB_freeImBuf(ibuf);
00365                 return NULL;
00366             }
00367         }
00368         
00369         if(flags & IB_zbuf) {
00370             if(addzbufImBuf(ibuf)==FALSE) {
00371                 IMB_freeImBuf(ibuf);
00372                 return NULL;
00373             }
00374         }
00375         
00376         if(flags & IB_zbuffloat) {
00377             if(addzbuffloatImBuf(ibuf)==FALSE) {
00378                 IMB_freeImBuf(ibuf);
00379                 return NULL;
00380             }
00381         }
00382     }
00383     return (ibuf);
00384 }
00385 
00386 /* does no zbuffers? */
00387 ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
00388 {
00389     ImBuf *ibuf2, tbuf;
00390     int flags = 0;
00391     int a, x, y;
00392     
00393     if(ibuf1 == NULL) return NULL;
00394 
00395     if(ibuf1->rect) flags |= IB_rect;
00396     if(ibuf1->rect_float) flags |= IB_rectfloat;
00397 
00398     x = ibuf1->x;
00399     y = ibuf1->y;
00400     if(ibuf1->flags & IB_fields) y *= 2;
00401     
00402     ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags);
00403     if(ibuf2 == NULL) return NULL;
00404 
00405     if(flags & IB_rect)
00406         memcpy(ibuf2->rect, ibuf1->rect, x *y *sizeof(int));
00407     
00408     if(flags & IB_rectfloat)
00409         memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels *x *y *sizeof(float));
00410 
00411     if(ibuf1->encodedbuffer) {
00412         ibuf2->encodedbuffersize = ibuf1->encodedbuffersize;
00413         if(imb_addencodedbufferImBuf(ibuf2) == FALSE) {
00414             IMB_freeImBuf(ibuf2);
00415             return NULL;
00416         }
00417 
00418         memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize);
00419     }
00420 
00421     /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */
00422     tbuf = *ibuf1;
00423     
00424     // fix pointers 
00425     tbuf.rect       = ibuf2->rect;
00426     tbuf.rect_float = ibuf2->rect_float;
00427     tbuf.encodedbuffer = ibuf2->encodedbuffer;
00428     tbuf.zbuf= NULL;
00429     tbuf.zbuf_float= NULL;
00430     for(a=0; a<IB_MIPMAP_LEVELS; a++)
00431         tbuf.mipmap[a]= NULL;
00432     
00433     // set malloc flag
00434     tbuf.mall       = ibuf2->mall;
00435     tbuf.c_handle           = NULL;
00436     tbuf.refcounter         = 0;
00437 
00438     // for now don't duplicate metadata
00439     tbuf.metadata = NULL;
00440 
00441     *ibuf2 = tbuf;
00442     
00443     return(ibuf2);
00444 }
00445 
00446 #if 0 /* remove? - campbell */
00447 /* support for cache limiting */
00448 
00449 static void imbuf_cache_destructor(void *data)
00450 {
00451     ImBuf *ibuf = (ImBuf*) data;
00452 
00453     imb_freerectImBuf(ibuf);
00454     imb_freerectfloatImBuf(ibuf);
00455     IMB_freezbufImBuf(ibuf);
00456     IMB_freezbuffloatImBuf(ibuf);
00457     freeencodedbufferImBuf(ibuf);
00458 
00459     ibuf->c_handle = NULL;
00460 }
00461 
00462 
00463 static MEM_CacheLimiterC **get_imbuf_cache_limiter(void)
00464 {
00465     static MEM_CacheLimiterC *c = NULL;
00466 
00467     if(!c)
00468         c = new_MEM_CacheLimiter(imbuf_cache_destructor, NULL);
00469 
00470     return &c;
00471 }
00472 #endif