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