Okay. imlib_free_image_and_decache() was leaking images. I hope I made the

right fix here. Basically, the imlib_free_image_and_decache() call in api.c
sets the flag F_INVALID then calls the internal __ImlibFreeImage(), this
checks if the flag F_UNCACHEABLE is set, and only frees it if so.

So the image never got free()d. I have changed the
imlib_free_image_and_decache() to set the F_UNCACHEABLE flag *as well* as
F_INVALID. I hope that's the correct fix. raster?


SVN revision: 3238
This commit is contained in:
Tom Gilbert 2000-08-23 00:11:39 +00:00
parent 54599eddb6
commit 5303cd3cf1
2 changed files with 722 additions and 708 deletions

View File

@ -492,6 +492,7 @@ imlib_free_image_and_decache(void)
CHECK_PARAM_POINTER("imlib_free_image_and_decache", "image", ctxt_image);
CAST_IMAGE(im, ctxt_image);
SET_FLAG(im->flags, F_INVALID);
SET_FLAG(im->flags, F_UNCACHEABLE);
__imlib_FreeImage(im);
ctxt_image = NULL;
}

View File

@ -23,7 +23,7 @@ static int cache_size = 4096 * 1024;
/* attach a string key'd data and/or int value to an image that cna be */
/* looked up later by its string key */
void
__imlib_AttachTag(ImlibImage *im, const char *key, int val, void *data,
__imlib_AttachTag(ImlibImage * im, const char *key, int val, void *data,
ImlibDataDestructorFunction destructor)
{
ImlibImageTag *t;
@ -49,7 +49,7 @@ __imlib_AttachTag(ImlibImage *im, const char *key, int val, void *data,
/* look up a tage by its key on the image it was attached to */
ImlibImageTag *
__imlib_GetTag(ImlibImage *im, const char *key)
__imlib_GetTag(ImlibImage * im, const char *key)
{
ImlibImageTag *t;
@ -67,7 +67,7 @@ __imlib_GetTag(ImlibImage *im, const char *key)
/* remove a tag by looking it up by its key and removing it from */
/* the list of keys */
ImlibImageTag *
__imlib_RemoveTag(ImlibImage *im, const char *key)
__imlib_RemoveTag(ImlibImage * im, const char *key)
{
ImlibImageTag *t, *tt;
@ -93,7 +93,7 @@ __imlib_RemoveTag(ImlibImage *im, const char *key)
/* free the data struct for the tag and if a destructor function was */
/* provided call it on the data member */
void
__imlib_FreeTag(ImlibImage *im, ImlibImageTag *t)
__imlib_FreeTag(ImlibImage * im, ImlibImageTag * t)
{
free(t->key);
if (t->destructor)
@ -103,7 +103,7 @@ __imlib_FreeTag(ImlibImage *im, ImlibImageTag *t)
/* free all the tags attached to an image */
void
__imlib_FreeAllTags(ImlibImage *im)
__imlib_FreeAllTags(ImlibImage * im)
{
ImlibImageTag *t, *tt;
@ -151,7 +151,7 @@ __imlib_ProduceImage(void)
/* free an image struct */
void
__imlib_ConsumeImage(ImlibImage *im)
__imlib_ConsumeImage(ImlibImage * im)
{
__imlib_FreeAllTags(im);
if (im->file)
@ -194,7 +194,7 @@ __imlib_FindCachedImage(const char *file)
/* add an image to the cache of images (at the start) */
void
__imlib_AddImageToCache(ImlibImage *im)
__imlib_AddImageToCache(ImlibImage * im)
{
im->next = images;
images = im;
@ -202,7 +202,7 @@ __imlib_AddImageToCache(ImlibImage *im)
/* remove (unlink) an image from the cache of images */
void
__imlib_RemoveImageFromCache(ImlibImage *im)
__imlib_RemoveImageFromCache(ImlibImage * im)
{
ImlibImage *current_im, *previous_im;
@ -234,7 +234,7 @@ __imlib_CurrentCacheSize(void)
/* go through the image cache */
im = images;
while(im)
while (im)
{
/* mayaswell clean out stuff thats invalid that we dont need anymore */
if (im->references == 0)
@ -256,7 +256,7 @@ __imlib_CurrentCacheSize(void)
}
/* go through the pixmaps */
ip = pixmaps;
while(ip)
while (ip)
{
/* if the pixmap has 0 references */
if (ip->references == 0)
@ -307,12 +307,11 @@ __imlib_CleanupImageCache(void)
im_last = NULL;
im = images;
/* remove 0 ref coutn invalid (dirty) images */
while(im)
while (im)
{
im_last = im;
im = im->next;
if ((im_last->references <= 0) &&
(!(IMAGE_IS_VALID(im_last))))
if ((im_last->references <= 0) && (!(IMAGE_IS_VALID(im_last))))
{
__imlib_RemoveImageFromCache(im_last);
__imlib_ConsumeImage(im_last);
@ -325,7 +324,7 @@ __imlib_CleanupImageCache(void)
im_last = NULL;
operation = 0;
im = images;
while(im)
while (im)
{
if (im->references <= 0)
im_last = im;
@ -358,10 +357,11 @@ __imlib_ProduceImagePixmap(void)
/* free a pixmap cache data struct and the pixmaps in it */
void
__imlib_ConsumeImagePixmap(ImlibImagePixmap *ip)
__imlib_ConsumeImagePixmap(ImlibImagePixmap * ip)
{
#ifdef DEBUG_CACHE
fprintf(stderr, "[Imlib2] Deleting pixmap. Reference count is %d, pixmap 0x%08x, mask 0x%08x\n",
fprintf(stderr,
"[Imlib2] Deleting pixmap. Reference count is %d, pixmap 0x%08x, mask 0x%08x\n",
ip->references, ip->pixmap, ip->mask);
#endif
if (ip->pixmap)
@ -372,10 +372,10 @@ __imlib_ConsumeImagePixmap(ImlibImagePixmap *ip)
}
ImlibImagePixmap *
__imlib_FindCachedImagePixmap(ImlibImage *im, int w, int h, Display *d, Visual *v,
int depth, int sx, int sy, int sw, int sh, Colormap cm,
char aa, char hiq, char dmask,
DATABIG modification_count)
__imlib_FindCachedImagePixmap(ImlibImage * im, int w, int h, Display * d,
Visual * v, int depth, int sx, int sy, int sw,
int sh, Colormap cm, char aa, char hiq,
char dmask, DATABIG modification_count)
{
ImlibImagePixmap *ip, *previous_ip;
@ -385,19 +385,17 @@ __imlib_FindCachedImagePixmap(ImlibImage *im, int w, int h, Display *d, Visual *
while (ip)
{
/* if all the pixmap attributes match */
if ((ip->w == w) && (ip->h == h) && (ip->depth == depth) &&
(!ip->dirty) && (ip->image == im) &&
(ip->visual == v) && (ip->display == d) &&
(ip->source_x == sx) && (ip->source_x == sy) &&
(ip->source_w == sw) && (ip->source_h == sh) &&
(ip->colormap == cm) && (ip->antialias == aa) &&
(ip->modification_count == modification_count) &&
(ip->dither_mask == dmask) &&
(ip->border.left == im->border.left) &&
(ip->border.right == im->border.right) &&
(ip->border.top == im->border.top) &&
(ip->border.bottom == im->border.bottom)
)
if ((ip->w == w) && (ip->h == h) && (ip->depth == depth) && (!ip->dirty)
&& (ip->image == im) && (ip->visual == v) && (ip->display == d)
&& (ip->source_x == sx) && (ip->source_x == sy)
&& (ip->source_w == sw) && (ip->source_h == sh)
&& (ip->colormap == cm) && (ip->antialias == aa)
&& (ip->modification_count == modification_count)
&& (ip->dither_mask == dmask)
&& (ip->border.left == im->border.left)
&& (ip->border.right == im->border.right)
&& (ip->border.top == im->border.top)
&& (ip->border.bottom == im->border.bottom))
{
/* move the pixmap to the head of the pixmap list */
if (previous_ip)
@ -416,7 +414,7 @@ __imlib_FindCachedImagePixmap(ImlibImage *im, int w, int h, Display *d, Visual *
}
ImlibImagePixmap *
__imlib_FindCachedImagePixmapByID(Display *d, Pixmap p)
__imlib_FindCachedImagePixmapByID(Display * d, Pixmap p)
{
ImlibImagePixmap *ip;
@ -434,7 +432,7 @@ __imlib_FindCachedImagePixmapByID(Display *d, Pixmap p)
/* add a pixmap cahce struct to the pixmap cache (at the start of course */
void
__imlib_AddImagePixmapToCache(ImlibImagePixmap *ip)
__imlib_AddImagePixmapToCache(ImlibImagePixmap * ip)
{
ip->next = pixmaps;
pixmaps = ip;
@ -442,7 +440,7 @@ __imlib_AddImagePixmapToCache(ImlibImagePixmap *ip)
/* remove a pixmap cache struct fromt he pixmap cache */
void
__imlib_RemoveImagePixmapFromCache(ImlibImagePixmap *ip)
__imlib_RemoveImagePixmapFromCache(ImlibImagePixmap * ip)
{
ImlibImagePixmap *current_ip, *previous_ip;
@ -474,12 +472,11 @@ __imlib_CleanupImagePixmapCache(void)
current_cache = __imlib_CurrentCacheSize();
ip_last = NULL;
ip = pixmaps;
while(ip)
while (ip)
{
ip_last = ip;
ip = ip->next;
if ((ip_last->references <= 0) &&
(ip_last->dirty))
if ((ip_last->references <= 0) && (ip_last->dirty))
{
__imlib_RemoveImagePixmapFromCache(ip_last);
__imlib_ConsumeImagePixmap(ip_last);
@ -490,7 +487,7 @@ __imlib_CleanupImagePixmapCache(void)
ip_last = NULL;
operation = 0;
ip = pixmaps;
while(ip)
while (ip)
{
if (ip->references <= 0)
ip_last = ip;
@ -528,6 +525,7 @@ LTDL_Init(void)
if (errors != 0)
{
const char *dlerror = lt_dlerror();
fprintf(stderr, "ERROR: failed to initialise ltdl: %s\n", dlerror);
exit(1);
}
@ -546,7 +544,7 @@ ImlibLoader *
__imlib_ProduceLoader(char *file)
{
ImlibLoader *l;
void (*l_formats)(ImlibLoader *l);
void (*l_formats) (ImlibLoader * l);
LTDL_Init();
@ -594,6 +592,7 @@ __imlib_ListLoaders(int *num_ret)
/* make a list of them */
*num_ret += num;
list = malloc(sizeof(char *) * *num_ret);
for (i = 0; i < num; i++)
{
sprintf(s, "%s/" USER_LOADERS_PATH "/image/%s", home, l[i]);
@ -609,6 +608,7 @@ __imlib_ListLoaders(int *num_ret)
{
*num_ret += num;
list = realloc(list, sizeof(char *) * *num_ret);
for (i = 0; i < num; i++)
{
sprintf(s, SYS_LOADERS_PATH "/image/%s", l[i]);
@ -627,14 +627,16 @@ __imlib_ListLoaders(int *num_ret)
return list;
}
char **__imlib_TrimLoaderList(char **list, int *num)
char **
__imlib_TrimLoaderList(char **list, int *num)
{
int i, n, size=0;
int i, n, size = 0;
char **ret = NULL;
if(!list)
if (!list)
return NULL;
if(*num == 0)
if (*num == 0)
return list;
n = *num;
@ -642,41 +644,45 @@ char **__imlib_TrimLoaderList(char **list, int *num)
for (i = 0; i < n; i++)
{
char *ext;
if(!list[i])
if (!list[i])
continue;
ext = strrchr(list[i], '.');
if(ext)
if (ext)
{
*ext = '\0';
/* Don't add the same loader multiple times... */
if(!__imlib_ItemInList(ret, size, list[i]))
if (!__imlib_ItemInList(ret, size, list[i]))
{
ret = realloc(ret, sizeof(char *) * (size + 1));
ret[size++] = strdup(list[i]);
}
}
if(list[i])
free (list[i]);
if (list[i])
free(list[i]);
}
if(list)
if (list)
free(list);
*num = size;
return ret;
}
int __imlib_ItemInList(char **list, int size, char *item)
int
__imlib_ItemInList(char **list, int size, char *item)
{
int i;
if(!size)
if (!size)
return 0;
if(!list)
if (!list)
return 0;
if(!item)
if (!item)
return 0;
for(i=0; i<size; i++)
for (i = 0; i < size; i++)
{
if(!strcmp(list[i], item))
if (!strcmp(list[i], item))
return 1;
}
return 0;
@ -684,7 +690,7 @@ int __imlib_ItemInList(char **list, int size, char *item)
/* fre the struct for a loader and close its dlopen'd handle */
void
__imlib_ConsumeLoader(ImlibLoader *l)
__imlib_ConsumeLoader(ImlibLoader * l)
{
if (l->file)
free(l->file);
@ -726,7 +732,8 @@ __imlib_RescanLoaders(void)
#ifndef __EMX__
current_time = __imlib_FileModDate(SYS_LOADERS_PATH "/image/");
#else
current_time = __imlib_FileModDate(__XOS2RedirRoot(SYS_LOADERS_PATH "/image/"));
current_time =
__imlib_FileModDate(__XOS2RedirRoot(SYS_LOADERS_PATH "/image/"));
#endif
if (current_time > last_modified_system_time)
{
@ -763,7 +770,7 @@ __imlib_RemoveAllLoaders(void)
ImlibLoader *l, *il;
l = loaders;
while(l)
while (l)
{
il = l;
l = l->next;
@ -822,7 +829,8 @@ __imlib_FindBestLoaderForFile(const char *file)
*lower = tolower(*lower);
lower++;
}
if (!extension) return NULL;
if (!extension)
return NULL;
/* go through the loaders - first loader that claims to handle that */
/* image type (extension wise) wins as a first guess to use - NOTE */
/* this is an OPTIMISATION - it is possible the file has no extension */
@ -883,7 +891,8 @@ __imlib_FindBestLoaderForFileFormat(const char *file, char *format)
lower++;
}
}
if (!extension) return NULL;
if (!extension)
return NULL;
/* look thought the loaders one by one to see if one matches that format */
l = loaders;
while (l)
@ -912,7 +921,7 @@ __imlib_FindBestLoaderForFileFormat(const char *file, char *format)
/* set or unset the alpha flag on the umage (alpha = 1 / 0 ) */
void
__imlib_SetImageAlphaFlag(ImlibImage *im, char alpha)
__imlib_SetImageAlphaFlag(ImlibImage * im, char alpha)
{
if (alpha)
SET_FLAG(im->flags, F_HAS_ALPHA);
@ -923,7 +932,7 @@ __imlib_SetImageAlphaFlag(ImlibImage *im, char alpha)
/* create a new image struct from data passed that is wize w x h then return */
/* a pointer to that image sturct */
ImlibImage *
__imlib_CreateImage(int w, int h, DATA32 *data)
__imlib_CreateImage(int w, int h, DATA32 * data)
{
ImlibImage *im;
@ -937,10 +946,9 @@ __imlib_CreateImage(int w, int h, DATA32 *data)
}
ImlibImage *
__imlib_LoadImage(const char *file,
ImlibProgressFunction progress,
char progress_granularity, char immediate_load, char dont_cache,
ImlibLoadError *er)
__imlib_LoadImage(const char *file, ImlibProgressFunction progress,
char progress_granularity, char immediate_load,
char dont_cache, ImlibLoadError * er)
{
ImlibImage *im;
ImlibLoader *best_loader;
@ -989,7 +997,9 @@ __imlib_LoadImage(const char *file,
best_loader = __imlib_FindBestLoaderForFile(file);
errno = 0;
if (best_loader)
loader_ret = best_loader->load(im, progress, progress_granularity, immediate_load);
loader_ret =
best_loader->load(im, progress, progress_granularity,
immediate_load);
/* if the caller wants error returns */
if (er)
{
@ -1032,13 +1042,15 @@ __imlib_LoadImage(const char *file,
if (im->w == 0)
{
ImlibLoader *l, *previous_l = NULL;
l = loaders;
/* run through all loaders and try load until one succeeds */
while ((l) && (im->w == 0))
{
/* if its not the best loader that alreayd failed - try load */
if (l != best_loader)
loader_ret = l->load(im, progress, progress_granularity, immediate_load);
loader_ret =
l->load(im, progress, progress_granularity, immediate_load);
/* if it failed - advance */
if (im->w == 0)
{
@ -1120,7 +1132,7 @@ __imlib_LoadImage(const char *file,
/* find an imagepixmap cache enctyr by the display and pixmap id */
ImlibImagePixmap *
__imlib_FindImlibImagePixmapByID(Display *d, Pixmap p)
__imlib_FindImlibImagePixmapByID(Display * d, Pixmap p)
{
ImlibImagePixmap *ip;
@ -1132,7 +1144,8 @@ __imlib_FindImlibImagePixmapByID(Display *d, Pixmap p)
if ((ip->pixmap == p) && (ip->display == d))
{
#ifdef DEBUG_CACHE
fprintf(stderr, "[Imlib2] Match found. Reference count is %d, pixmap 0x%08x, mask 0x%08x\n",
fprintf(stderr,
"[Imlib2] Match found. Reference count is %d, pixmap 0x%08x, mask 0x%08x\n",
ip->references, ip->pixmap, ip->mask);
#endif
return ip;
@ -1144,7 +1157,7 @@ __imlib_FindImlibImagePixmapByID(Display *d, Pixmap p)
/* free and image - if its uncachable and refcoutn is 0 - free it in reality */
void
__imlib_FreeImage(ImlibImage *im)
__imlib_FreeImage(ImlibImage * im)
{
/* if the refcount is positive */
if (im->references >= 0)
@ -1167,7 +1180,7 @@ __imlib_FreeImage(ImlibImage *im)
/* free a cached pixmap */
void
__imlib_FreePixmap(Display *d, Pixmap p)
__imlib_FreePixmap(Display * d, Pixmap p)
{
ImlibImagePixmap *ip;
@ -1181,7 +1194,8 @@ __imlib_FreePixmap(Display *d, Pixmap p)
/* dereference it by one */
ip->references--;
#ifdef DEBUG_CACHE
fprintf(stderr, "[Imlib2] Reference count is now %d for pixmap 0x%08x\n",
fprintf(stderr,
"[Imlib2] Reference count is now %d for pixmap 0x%08x\n",
ip->references, ip->pixmap);
#endif
/* if it becaume 0 reference count - clean the cache up */
@ -1202,7 +1216,7 @@ __imlib_FreePixmap(Display *d, Pixmap p)
/* wont pick up on them again sicne they are now invalid sicn ehte original */
/* data they were generated form has changed */
void
__imlib_DirtyPixmapsForImage(ImlibImage *im)
__imlib_DirtyPixmapsForImage(ImlibImage * im)
{
ImlibImagePixmap *ip;
@ -1220,7 +1234,7 @@ __imlib_DirtyPixmapsForImage(ImlibImage *im)
/* dirty and image by settings its invalid flag */
void
__imlib_DirtyImage(ImlibImage *im)
__imlib_DirtyImage(ImlibImage * im)
{
SET_FLAG(im->flags, F_INVALID);
/* and dirty all pixmaps generated from it */
@ -1228,10 +1242,9 @@ __imlib_DirtyImage(ImlibImage *im)
}
void
__imlib_SaveImage(ImlibImage *im, const char *file,
ImlibProgressFunction progress,
char progress_granularity,
ImlibLoadError *er)
__imlib_SaveImage(ImlibImage * im, const char *file,
ImlibProgressFunction progress, char progress_granularity,
ImlibLoadError * er)
{
ImlibLoader *l;
char e, *pfile;