#include "evas_common.h"
#include "evas_private.h"
+//#define CACHEDUMP 1
+
#ifdef EVAS_CSERVE
// FIXME: cache server and threaded preload clash badly atm - disable
//#undef BUILD_ASYNC_PRELOAD
eina_stringshare_del(Var); \
Var = NULL; \
}
-//#define CACHEDUMP 1
-
-#ifdef CACHEDUMP
-static void
-_dump_img(Image_Entry *im, const char *type)
-{
- printf("%s: %4i: %4ikb, %4ix%4i alloc[%4ix%4i] [%s] [%s]\n",
- type,
- im->references,
- (im->allocated.w * im->allocated.h * 4) / 1024,
- im->w, im->h, im->allocated.w, im->allocated.h,
- im->file, im->key);
-}
-
-static Eina_Bool
-_dump_cache_active(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, void *fdata __UNUSED__)
-{
- Image_Entry *im = data;
-
- _dump_img(im, "ACTIVE");
- return EINA_TRUE;
-}
-
-static void
-_dump_cache(Evas_Cache_Image *cache)
-{
- Image_Entry *im;
- printf("--CACHE DUMP----------------------------------------------------\n");
- printf("%cache: %ikb / %ikb\n",
- cache->usage / 1024,
- cache->limit / 1024);
- printf("................................................................\n");
- EINA_INLIST_FOREACH(cache->lru_nodata, im)
- _dump_img(im, "NODATA");
- EINA_INLIST_FOREACH(cache->lru, im)
- _dump_img(im, "DATA ");
- eina_hash_foreach(cache->activ, _dump_cache_active, NULL);
-}
-#endif
-
-static void _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie);
+static void _evas_cache_image_dirty_add(Image_Entry *im);
+static void _evas_cache_image_dirty_del(Image_Entry *im);
+static void _evas_cache_image_activ_add(Image_Entry *im);
+static void _evas_cache_image_activ_del(Image_Entry *im);
+static void _evas_cache_image_lru_add(Image_Entry *im);
+static void _evas_cache_image_lru_del(Image_Entry *im);
+static void _evas_cache_image_lru_nodata_add(Image_Entry *im);
+static void _evas_cache_image_lru_nodata_del(Image_Entry *im);
static void
-_evas_cache_image_make_dirty(Evas_Cache_Image *cache, Image_Entry *im)
+_evas_cache_image_dirty_add(Image_Entry *im)
{
if (im->flags.dirty) return;
- im->flags.cached = 1;
+ _evas_cache_image_activ_del(im);
+ _evas_cache_image_lru_del(im);
+ _evas_cache_image_lru_nodata_del(im);
im->flags.dirty = 1;
- im->flags.activ = 0;
- im->flags.lru_nodata = 0;
+ im->flags.cached = 1;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(im));
+ im->cache->dirty = eina_inlist_prepend(im->cache->dirty, EINA_INLIST_GET(im));
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
-
if (im->cache_key)
{
eina_stringshare_del(im->cache_key);
}
static void
-_evas_cache_image_make_activ(Evas_Cache_Image *cache,
- Image_Entry *im, const char *key)
+_evas_cache_image_dirty_del(Image_Entry *im)
{
- /* FIXME: Handle case when image is being processed anyway and don't do a double decode. */
- if (im->flags.activ) return;
- im->cache_key = key;
- if (key)
- {
- im->flags.cached = 1;
- im->flags.activ = 1;
- im->flags.lru_nodata = 0;
+ if (!im->flags.dirty) return;
im->flags.dirty = 0;
+ im->flags.cached = 0;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- eina_hash_direct_add(cache->activ, key, im);
+ im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
}
- else
+
+static void
+_evas_cache_image_activ_add(Image_Entry *im)
{
- _evas_cache_image_make_dirty(cache, im);
- }
+ if (im->flags.activ) return;
+ _evas_cache_image_dirty_del(im);
+ _evas_cache_image_lru_del(im);
+ _evas_cache_image_lru_nodata_del(im);
+ if (!im->cache_key) return;
+ im->flags.activ = 1;
+ im->flags.cached = 1;
+#ifdef EVAS_FRAME_QUEUING
+ LKL(im->cache->lock);
+#endif
+ eina_hash_direct_add(im->cache->activ, im->cache_key, im);
+#ifdef EVAS_FRAME_QUEUING
+ LKU(im->cache->lock);
+#endif
}
static void
-_evas_cache_image_make_inactiv(Evas_Cache_Image *cache,
- Image_Entry *im, const char *key)
+_evas_cache_image_activ_del(Image_Entry *im)
{
if (!im->flags.activ) return;
- if (im->cache_key)
- {
+ if (!im->cache_key) return;
im->flags.activ = 0;
- im->flags.dirty = 0;
- im->flags.cached = 1;
+ im->flags.cached = 0;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- eina_hash_direct_add(cache->inactiv, key, im);
- cache->lru = eina_inlist_prepend(cache->lru, EINA_INLIST_GET(im));
- cache->usage += cache->func.mem_size_get(im);
+ eina_hash_del(im->cache->activ, im->cache_key, im);
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
}
- else
- {
- _evas_cache_image_entry_delete(cache, im);
- }
- }
static void
-_evas_cache_image_remove_lru_nodata(Evas_Cache_Image *cache, Image_Entry *im)
+_evas_cache_image_lru_add(Image_Entry *im)
{
- if (im->flags.lru_nodata)
- {
- im->flags.lru_nodata = 0;
+ if (im->flags.lru) return;
+ _evas_cache_image_dirty_del(im);
+ _evas_cache_image_activ_del(im);
+ _evas_cache_image_lru_nodata_del(im);
+ if (!im->cache_key) return;
+ im->flags.lru = 1;
+ im->flags.cached = 1;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- cache->lru_nodata = eina_inlist_remove(cache->lru_nodata, EINA_INLIST_GET(im));
- cache->usage -= cache->func.mem_size_get(im);
+ eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
+ im->cache->lru = eina_inlist_prepend(im->cache->lru, EINA_INLIST_GET(im));
+ im->cache->usage += im->cache->func.mem_size_get(im);
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
}
-}
static void
-_evas_cache_image_activ_lru_nodata(Evas_Cache_Image *cache, Image_Entry *im)
+_evas_cache_image_lru_del(Image_Entry *im)
{
- if (!im->flags.lru_nodata) return;
- im->flags.need_data = 0;
- im->flags.lru_nodata = 1;
+ if (!im->flags.lru) return;
+ if (!im->cache_key) return;
+ im->flags.lru = 0;
+ im->flags.cached = 0;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- cache->lru_nodata = eina_inlist_prepend(cache->lru_nodata, EINA_INLIST_GET(im));
- cache->usage += cache->func.mem_size_get(im);
+ eina_hash_del(im->cache->inactiv, im->cache_key, im);
+ im->cache->lru = eina_inlist_remove(im->cache->lru, EINA_INLIST_GET(im));
+ im->cache->usage -= im->cache->func.mem_size_get(im);
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
}
static void
-_evas_cache_image_remove_activ(Evas_Cache_Image *cache, Image_Entry *ie)
-{
- if (ie->flags.cached)
- {
- if (ie->flags.activ)
+_evas_cache_image_lru_nodata_add(Image_Entry *im)
{
+ if (im->flags.lru_nodata) return;
+ _evas_cache_image_dirty_del(im);
+ _evas_cache_image_activ_del(im);
+ _evas_cache_image_lru_del(im);
+ im->flags.lru = 1;
+ im->flags.cached = 1;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- eina_hash_del(cache->activ, ie->cache_key, ie);
+ im->cache->lru_nodata = eina_inlist_prepend(im->cache->lru_nodata, EINA_INLIST_GET(im));
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
- _evas_cache_image_remove_lru_nodata(cache, ie);
}
- else
+
+static void
+_evas_cache_image_lru_nodata_del(Image_Entry *im)
{
+ if (!im->flags.lru_nodata) return;
+ im->flags.lru = 0;
+ im->flags.cached = 0;
#ifdef EVAS_FRAME_QUEUING
- LKL(cache->lock);
+ LKL(im->cache->lock);
#endif
- if (ie->flags.dirty)
- {
- cache->dirty = eina_inlist_remove(cache->dirty, EINA_INLIST_GET(ie));
- }
- else
- {
- eina_hash_del(cache->inactiv, ie->cache_key, ie);
- cache->lru = eina_inlist_remove(cache->lru, EINA_INLIST_GET(ie));
- cache->usage -= cache->func.mem_size_get(ie);
- }
+ im->cache->lru_nodata = eina_inlist_remove(im->cache->lru_nodata, EINA_INLIST_GET(im));
#ifdef EVAS_FRAME_QUEUING
- LKU(cache->lock);
+ LKU(im->cache->lock);
#endif
}
- ie->flags.cached = 0;
- ie->flags.dirty = 0;
- ie->flags.activ = 0;
- }
-}
static void
_evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
{
if (!ie) return;
-
- if (cache->func.debug)
- cache->func.debug("deleting", ie);
-
+ if (cache->func.debug) cache->func.debug("deleting", ie);
#ifdef BUILD_ASYNC_PRELOAD
- if (ie->flags.delete_me == 1)
- return ;
-
+ if (ie->flags.delete_me == 1) return;
if (ie->preload)
{
ie->flags.delete_me = 1;
-
_evas_cache_image_entry_preload_remove(ie, NULL);
return ;
}
#endif
- _evas_cache_image_remove_activ(cache, ie);
+ _evas_cache_image_dirty_del(ie);
+ _evas_cache_image_activ_del(ie);
+ _evas_cache_image_lru_del(ie);
+ _evas_cache_image_lru_nodata_del(ie);
cache->func.destructor(ie);
-
- if (ie->cache_key)
- {
- eina_stringshare_del(ie->cache_key);
- ie->cache_key = NULL;
- }
-
+ FREESTRC(ie->cache_key);
FREESTRC(ie->file);
FREESTRC(ie->key);
-
ie->cache = NULL;
-
cache->func.surface_delete(ie);
#ifdef BUILD_ASYNC_PRELOAD
#ifdef EVAS_FRAME_QUEUING
LKD(ie->lock_references);
#endif
-
cache->func.dealloc(ie);
}
if (tstamp->ino != st->st_ino) return EINA_FALSE;
#ifdef _STAT_VER_LINUX
#if (defined __USE_MISC && defined st_mtime)
- if (tstamp->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec) return EINA_FALSE;
+ if (tstamp->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec)
+ return EINA_FALSE;
#else
- if (tstamp->mtime_nsec != (unsigned long int)st->st_mtimensec) return EINA_FALSE;
+ if (tstamp->mtime_nsec != (unsigned long int)st->st_mtimensec)
+ return EINA_FALSE;
#endif
#endif
return EINA_TRUE;
int *error)
{
Image_Entry *ie;
- const char *cache_key;
ie = cache->func.alloc();
if (!ie)
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
return NULL;
}
-
- cache_key = hkey ? eina_stringshare_add(hkey) : NULL;
-
- ie->flags.loaded = 0;
+ ie->cache = cache;
+ if (hkey) ie->cache_key = eina_stringshare_add(hkey);
ie->flags.need_data = 1;
-
- _evas_cache_image_make_activ(cache, ie, cache_key);
-
ie->space = EVAS_COLORSPACE_ARGB8888;
ie->w = -1;
ie->h = -1;
- ie->allocated.w = 0;
- ie->allocated.h = 0;
+ ie->scale = 1;
+ if (file) ie->file = eina_stringshare_add(file);
+ if (key) ie->key = eina_stringshare_add(key);
+ if (tstamp) ie->tstamp = *tstamp;
+ else memset(&ie->tstamp, 0, sizeof(Image_Timestamp));
#ifdef EVAS_FRAME_QUEUING
LKI(ie->lock_references);
#endif
- ie->references = 0;
- ie->cache = cache;
-
- ie->file = file ? eina_stringshare_add(file) : NULL;
- ie->key = key ? eina_stringshare_add(key) : NULL;
-
- if (tstamp) ie->tstamp = *tstamp;
- else memset(&ie->tstamp, 0, sizeof(Image_Timestamp));
-
- ie->load_opts.scale_down_by = 0;
- ie->load_opts.dpi = 0;
- ie->load_opts.w = 0;
- ie->load_opts.h = 0;
- ie->load_opts.region.x = 0;
- ie->load_opts.region.y = 0;
- ie->load_opts.region.w = 0;
- ie->load_opts.region.h = 0;
- ie->scale = 1;
-
#ifdef BUILD_ASYNC_PRELOAD
LKI(ie->lock);
LKI(ie->lock_cancel);
- ie->targets = NULL;
- ie->preload = NULL;
- ie->flags.delete_me = 0;
#endif
- if (lo)
- ie->load_opts = *lo;
-
- if (file)
+ if (lo) ie->load_opts = *lo;
+ if (ie->file)
{
*error = cache->func.constructor(ie);
if (*error != EVAS_LOAD_ERROR_NONE)
return NULL;
}
}
- if (cache->func.debug)
- cache->func.debug("build", ie);
-
+ if (cache->func.debug) cache->func.debug("build", ie);
+ if (ie->cache_key) _evas_cache_image_activ_add(ie);
+ else _evas_cache_image_dirty_add(ie);
return ie;
}
unsigned int wmin,
unsigned int hmin)
{
- if (ie->allocated.w == wmin && ie->allocated.h == hmin)
- return ;
-
+ if ((ie->allocated.w == wmin) && (ie->allocated.h == hmin)) return;
if (cache->func.surface_alloc(ie, wmin, hmin))
{
wmin = 0;
hmin = 0;
}
-
ie->w = wmin;
ie->h = hmin;
ie->allocated.w = wmin;
_evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
Image_Entry *ie, int w, int h)
{
- int wmin;
- int hmin;
-
- wmin = w > 0 ? w : 1;
- hmin = h > 0 ? h : 1;
-
+ int wmin = w > 0 ? w : 1;
+ int hmin = h > 0 ? h : 1;
#ifdef BUILD_ASYNC_PRELOAD
LKL(engine_lock);
#endif
current->channel++;
cache = current->cache;
- if (!current->flags.loaded && ((Evas_Image_Load_Func*) current->info.module)->threadable)
+ if ((!current->flags.loaded) &&
+ ((Evas_Image_Load_Func*) current->info.module)->threadable)
{
error = cache->func.load(current);
- if (cache->func.debug)
- cache->func.debug("load", current);
+ if (cache->func.debug) cache->func.debug("load", current);
if (error != EVAS_LOAD_ERROR_NONE)
{
current->flags.loaded = 0;
_evas_cache_image_entry_surface_alloc(cache, current,
current->w, current->h);
}
- else
- current->flags.loaded = 1;
+ else current->flags.loaded = 1;
}
-
current->channel = pchannel;
-
// check the unload cancel flag
LKL(current->lock_cancel);
if (current->unload_cancel)
current->flags.preload_done = 0;
}
LKU(current->lock_cancel);
-
LKU(current->lock);
}
ie->cache->preload = eina_list_remove(ie->cache->preload, ie);
ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
-
ie->preload = NULL;
ie->flags.preload_done = ie->flags.loaded;
- while (ie->targets)
+ while ((tmp = ie->targets))
{
- tmp = ie->targets;
-
evas_object_inform_call_image_preloaded((Evas_Object*) tmp->target);
- ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(ie->targets));
+ ie->targets = (Evas_Cache_Target *)
+ eina_inlist_remove(EINA_INLIST_GET(ie->targets),
+ EINA_INLIST_GET(ie->targets));
free(tmp);
}
}
ie->preload = NULL;
ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
-
- if (ie->flags.delete_me || ie->flags.dirty)
+ if ((ie->flags.delete_me) || (ie->flags.dirty))
{
ie->flags.delete_me = 0;
_evas_cache_image_entry_delete(ie->cache, ie);
-
return ;
}
-
- if (ie->flags.loaded)
- {
- _evas_cache_image_async_end(ie);
- }
-
+ if (ie->flags.loaded) _evas_cache_image_async_end(ie);
#ifdef EVAS_FRAME_QUEUING
LKL(ie->lock_references);
#endif
if (ie->references == 0)
{
- _evas_cache_image_remove_activ(ie->cache, ie);
- _evas_cache_image_make_inactiv(ie->cache, ie, ie->cache_key);
+ _evas_cache_image_lru_add(ie);
cache = ie->cache;
}
#ifdef EVAS_FRAME_QUEUING
Evas_Cache_Target *tg;
if (ie->flags.preload_done) return 0;
-
tg = malloc(sizeof (Evas_Cache_Target));
if (!tg) return 0;
tg->target = target;
-
- ie->targets = (Evas_Cache_Target*) eina_inlist_append(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
-
+ ie->targets = (Evas_Cache_Target *)
+ eina_inlist_append(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
if (!ie->preload)
{
ie->cache->preload = eina_list_append(ie->cache->preload, ie);
ie->flags.pending = 0;
-
ie->preload = evas_preload_thread_run(_evas_cache_image_async_heavy,
_evas_cache_image_async_end,
_evas_cache_image_async_cancel,
ie);
}
-
return 1;
}
if (tg->target == target)
{
// FIXME: No callback when we cancel only for one target ?
- ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
+ ie->targets = (Evas_Cache_Target *)
+ eina_inlist_remove(EINA_INLIST_GET(ie->targets),
+ EINA_INLIST_GET(tg));
free(tg);
break;
}
while (ie->targets)
{
tg = ie->targets;
-
- ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
+ ie->targets = (Evas_Cache_Target *)
+ eina_inlist_remove(EINA_INLIST_GET(ie->targets),
+ EINA_INLIST_GET(tg));
free(tg);
}
}
- if (!ie->targets && ie->preload && !ie->flags.pending)
+ if ((!ie->targets) && (ie->preload) && (!ie->flags.pending))
{
ie->cache->preload = eina_list_remove(ie->cache->preload, ie);
ie->cache->pending = eina_list_append(ie->cache->pending, ie);
-
ie->flags.pending = 1;
-
evas_preload_thread_cancel(ie->preload);
}
}
EAPI int
evas_cache_image_usage_get(Evas_Cache_Image *cache)
{
- assert(cache != NULL);
-
return cache->usage;
}
EAPI int
evas_cache_image_get(Evas_Cache_Image *cache)
{
- assert(cache != NULL);
-
return cache->limit;
}
EAPI void
evas_cache_image_set(Evas_Cache_Image *cache, unsigned int limit)
{
- assert(cache != NULL);
#ifdef EVAS_FRAME_QUEUING
LKL(cache->lock);
#endif
EAPI Evas_Cache_Image *
evas_cache_image_init(const Evas_Cache_Image_Func *cb)
-{
- Evas_Cache_Image *new;
-
- new = malloc(sizeof (Evas_Cache_Image));
- if (!new) return NULL;
-
- new->func = *cb;
-
- new->limit = 0;
- new->usage = 0;
-
- new->dirty = NULL;
- new->lru = NULL;
- new->lru_nodata = NULL;
- new->inactiv = eina_hash_string_superfast_new(NULL);
- new->activ = eina_hash_string_superfast_new(NULL);
-
- new->references = 1;
-
- new->preload = NULL;
- new->pending = NULL;
+{printf("[%s][%d]\n",__FUNCTION__,__LINE__);
+ Evas_Cache_Image *cache;
+ cache = calloc(1, sizeof(Evas_Cache_Image));
+ if (!cache) return NULL;
+ cache->func = *cb;
+ cache->inactiv = eina_hash_string_superfast_new(NULL);
+ cache->activ = eina_hash_string_superfast_new(NULL);
+ cache->references = 1;
#ifdef EVAS_FRAME_QUEUING
- LKI(new->lock);
+ LKI(cache->lock);
#endif
-
- return new;
+ return cache;
}
static Eina_Bool
_evas_cache_image_free_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, void *fdata)
{
Eina_List **delete_list = fdata;
-
*delete_list = eina_list_prepend(*delete_list, data);
-
return EINA_TRUE;
}
Eina_List *delete_list;
Image_Entry *im;
- assert(cache != NULL);
#ifdef EVAS_FRAME_QUEUING
LKL(cache->lock);
#endif
cache->references--;
-
if (cache->references > 0)
{
#ifdef EVAS_FRAME_QUEUING
#endif
return ;
}
-
#ifdef BUILD_ASYNC_PRELOAD
EINA_LIST_FREE(cache->preload, im)
{
im->flags.delete_me = 1;
_evas_cache_image_entry_preload_remove(im, NULL);
}
-
evas_async_events_process();
#endif
-
while (cache->lru)
{
im = (Image_Entry *) cache->lru;
_evas_cache_image_entry_delete(cache, im);
}
-
while (cache->lru_nodata)
{
im = (Image_Entry *) cache->lru_nodata;
_evas_cache_image_entry_delete(cache, im);
}
-
/* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
while (cache->dirty)
{
im = (Image_Entry *) cache->dirty;
_evas_cache_image_entry_delete(cache, im);
}
-
delete_list = NULL;
eina_hash_foreach(cache->activ, _evas_cache_image_free_cb, &delete_list);
-
while (delete_list)
{
_evas_cache_image_entry_delete(cache, eina_list_data_get(delete_list));
while (cache->pending)
{
evas_async_events_process();
-
LKL(wakeup);
- if (cache->pending)
- pthread_cond_wait(&cond_wakeup, &wakeup);
+ if (cache->pending) pthread_cond_wait(&cond_wakeup, &wakeup);
LKU(wakeup);
}
#endif
-
eina_hash_free(cache->activ);
eina_hash_free(cache->inactiv);
-
#ifdef EVAS_FRAME_QUEUING
LKU(cache->lock);
LKD(cache->lock);
#endif
-
free(cache);
}
EAPI Image_Entry *
-evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, RGBA_Image_Loadopts *lo, int *error)
+evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
+ const char *key, RGBA_Image_Loadopts *lo, int *error)
{
const char *ckey = "(null)";
char *hkey;
struct stat st;
Image_Timestamp tstamp;
- assert(cache != NULL);
-
if ((!file) || ((!file) && (!key)))
{
*error = EVAS_LOAD_ERROR_GENERIC;
return NULL;
}
+ /* generate hkey from file+key+load opts */
file_length = strlen(file);
key_length = key ? strlen(key) : 6;
-
size = file_length + key_length + 128;
hkey = alloca(sizeof (char) * size);
-
memcpy(hkey, file, file_length);
size = file_length;
-
memcpy(hkey + size, "//://", 5);
size += 5;
-
if (key) ckey = key;
memcpy(hkey + size, ckey, key_length);
size += key_length;
-
if ((!lo) ||
(lo &&
(lo->scale_down_by == 0) &&
))
{
lo = &prevent;
-// if (key)
-// format = "%s//://%s";
-// else
-// format = "%s//://%p";
}
else
{
memcpy(hkey + size, "//@/", 4);
size += 4;
-
size += eina_convert_xtoa(lo->scale_down_by, hkey + size);
-
hkey[size] = '/';
size += 1;
-
size += eina_convert_dtoa(lo->dpi, hkey + size);
-
hkey[size] = '/';
size += 1;
-
size += eina_convert_xtoa(lo->w, hkey + size);
-
hkey[size] = 'x';
size += 1;
-
size += eina_convert_xtoa(lo->h, hkey + size);
-
hkey[size] = '/';
size += 1;
-
size += eina_convert_xtoa(lo->region.x, hkey + size);
-
hkey[size] = '+';
size += 1;
-
size += eina_convert_xtoa(lo->region.y, hkey + size);
-
hkey[size] = '.';
size += 1;
-
size += eina_convert_xtoa(lo->region.w, hkey + size);
-
hkey[size] = 'x';
size += 1;
-
size += eina_convert_xtoa(lo->region.h, hkey + size);
}
-
hkey[size] = '\0';
+ /* find image by key in active hash */
#ifdef EVAS_FRAME_QUEUING
LKL(cache->lock);
#endif
}
else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
if (ok) goto on_ok;
-
- _evas_cache_image_remove_activ(cache, im);
- _evas_cache_image_make_dirty(cache, im);
+ /* image we found doesn't match what's on disk (stat info wise)
+ * so dirty the active cache entry so we never find it again. this
+ * also implicitly guarantees that we only have 1 active copy
+ * of an image at a given key. we wither find it and keep re-reffing
+ * it or we dirty it and get it out */
+ _evas_cache_image_dirty_add(im);
im = NULL;
}
+ /* find image by key in inactive/lru hash */
#ifdef EVAS_FRAME_QUEUING
LKL(cache->lock);
#endif
if (ok)
{
- _evas_cache_image_remove_activ(cache, im);
- _evas_cache_image_make_activ(cache, im, im->cache_key);
+ /* remove from lru and make it active again */
+ _evas_cache_image_lru_del(im);
+ _evas_cache_image_activ_add(im);
goto on_ok;
}
- _evas_cache_image_make_dirty(cache, im);
+ /* as avtive cache find - if we match in lru and its invalid, dirty */
+ _evas_cache_image_dirty_add(im);
im = NULL;
}
if (stat_failed) goto on_stat_error;
if (stat(file, &st) < 0) goto on_stat_error;
}
_timestamp_build(&tstamp, &st);
- im = _evas_cache_image_entry_new(cache, hkey, &tstamp, file, key, lo, error);
+ im = _evas_cache_image_entry_new(cache, hkey, &tstamp, file, key,
+ lo, error);
if (!im) return NULL;
-
- if (cache->func.debug)
- cache->func.debug("request", im);
+ if (cache->func.debug) cache->func.debug("request", im);
on_ok:
*error = EVAS_LOAD_ERROR_NONE;
LKL(im->lock_references);
#endif
im->references++;
- if (im->references > 1 && im->flags.lru_nodata)
- _evas_cache_image_remove_lru_nodata(cache, im);
#ifdef EVAS_FRAME_QUEUING
LKU(im->lock_references);
#endif
-
return im;
on_stat_error:
Evas_Cache_Image *cache;
int references;
- assert(im);
- assert(im->cache);
-
#ifdef EVAS_FRAME_QUEUING
LKL(im->lock_references);
#endif
_evas_cache_image_entry_delete(cache, im);
return;
}
-
- _evas_cache_image_remove_activ(cache, im);
- _evas_cache_image_make_inactiv(cache, im, im->cache_key);
+ _evas_cache_image_lru_add(im);
evas_cache_image_flush(cache);
}
}
Evas_Cache_Image *cache;
int references;
- assert(im);
- assert(im->cache);
-
+ /* FIXME: no one uses this api... well evas_cache_engine_parent_not_needed()
+ * does, but nothing uses that! */
cache = im->cache;
-
#ifdef EVAS_FRAME_QUEUING
LKL(im->lock_references);
#endif
#ifdef EVAS_FRAME_QUEUING
LKU(im->lock_references);
#endif
-
if (references > 1) return ;
- if (im->flags.dirty || !im->flags.need_data) return ;
-
- _evas_cache_image_activ_lru_nodata(cache, im);
+ if ((im->flags.dirty) || (!im->flags.need_data)) return;
+ _evas_cache_image_lru_nodata_add(im);
}
EAPI Image_Entry *
Evas_Cache_Image *cache;
int references;
- assert(im);
- assert(im->cache);
-
cache = im->cache;
if (!(im->flags.dirty))
{
#ifdef EVAS_FRAME_QUEUING
LKU(im->lock_references);
#endif
-
#ifndef EVAS_CSERVE
// if ref 1 also copy if using shared cache as its read-only
if (references == 1) im_dirty = im;
evas_cache_image_pixels(im),
im->flags.alpha, im->space);
if (!im_dirty) goto on_error;
- if (cache->func.debug)
- cache->func.debug("dirty-src", im);
+ if (cache->func.debug) cache->func.debug("dirty-src", im);
error = cache->func.dirty(im_dirty, im);
- if (cache->func.debug)
- cache->func.debug("dirty-out", im_dirty);
+ if (cache->func.debug) cache->func.debug("dirty-out", im_dirty);
#ifdef EVAS_FRAME_QUEUING
LKL(im_dirty->lock_references);
#endif
#ifdef EVAS_FRAME_QUEUING
LKU(im_dirty->lock_references);
#endif
-
evas_cache_image_drop(im);
}
-
- _evas_cache_image_remove_activ(cache, im_dirty);
- _evas_cache_image_make_dirty(cache, im_dirty);
+ _evas_cache_image_dirty_add(im_dirty);
}
- if (cache->func.debug)
- cache->func.debug("dirty-region", im_dirty);
+ if (cache->func.debug) cache->func.debug("dirty-region", im_dirty);
if (cache->func.dirty_region)
cache->func.dirty_region(im_dirty, x, y, w, h);
-
return im_dirty;
on_error:
Image_Entry *im_dirty = im;
int references;
- assert(im);
- assert(im->cache);
-
cache = im->cache;
#ifdef EVAS_FRAME_QUEUING
LKL(im->lock_references);
if (references <= 1)
{
- if (!(im->flags.dirty))
- {
- _evas_cache_image_remove_activ(cache, im);
- _evas_cache_image_make_dirty(cache, im);
- }
+ if (!im->flags.dirty) _evas_cache_image_dirty_add(im);
}
else
{
int error;
- im_dirty = evas_cache_image_copied_data
- (cache, im->w, im->h,
+ im_dirty = evas_cache_image_copied_data(cache, im->w, im->h,
evas_cache_image_pixels(im),
im->flags.alpha,
im->space);
if (!im_dirty) goto on_error;
- if (cache->func.debug)
- cache->func.debug("dirty-src", im);
+ if (cache->func.debug) cache->func.debug("dirty-src", im);
error = cache->func.dirty(im_dirty, im);
- if (cache->func.debug)
- cache->func.debug("dirty-out", im_dirty);
+ if (cache->func.debug) cache->func.debug("dirty-out", im_dirty);
#ifdef EVAS_FRAME_QUEUING
LKL(im_dirty->lock_references);
#endif
#ifdef EVAS_FRAME_QUEUING
LKU(im_dirty->lock_references);
#endif
-
evas_cache_image_drop(im);
}
-
return im_dirty;
on_error:
}
EAPI Image_Entry *
-evas_cache_image_copied_data(Evas_Cache_Image *cache, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, int cspace)
+evas_cache_image_copied_data(Evas_Cache_Image *cache,
+ unsigned int w, unsigned int h,
+ DATA32 *image_data, int alpha, int cspace)
{
Image_Entry *im;
- assert(cache);
-
if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(cspace == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
-
im->space = cspace;
im->flags.alpha = alpha;
-
_evas_cache_image_entry_surface_alloc(cache, im, w, h);
-
if (cache->func.copied_data(im, w, h, image_data, alpha, cspace) != 0)
{
_evas_cache_image_entry_delete(cache, im);
#ifdef EVAS_FRAME_QUEUING
LKU(im->lock_references);
#endif
-
- if (cache->func.debug)
- cache->func.debug("copied-data", im);
+ if (cache->func.debug) cache->func.debug("copied-data", im);
return im;
}
{
Image_Entry *im;
- assert(cache);
-
if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(cspace == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (!im) return NULL;
im->w = w;
im->h = h;
im->flags.alpha = alpha;
-
if (cache->func.data(im, w, h, image_data, alpha, cspace) != 0)
{
_evas_cache_image_entry_delete(cache, im);
#ifdef EVAS_FRAME_QUEUING
LKU(im->lock_references);
#endif
-
- if (cache->func.debug)
- cache->func.debug("data", im);
+ if (cache->func.debug) cache->func.debug("data", im);
return im;
}
EAPI void
evas_cache_image_surface_alloc(Image_Entry *im, unsigned int w, unsigned int h)
{
- Evas_Cache_Image *cache;
-
- assert(im);
- assert(im->cache);
-
- cache = im->cache;
+ Evas_Cache_Image *cache = im->cache;
if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(im->space == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
_evas_cache_image_entry_surface_alloc(cache, im, w, h);
-
- if (cache->func.debug)
- cache->func.debug("surface-alloc", im);
+ if (cache->func.debug) cache->func.debug("surface-alloc", im);
}
EAPI Image_Entry *
evas_cache_image_size_set(Image_Entry *im, unsigned int w, unsigned int h)
{
Evas_Cache_Image *cache;
- Image_Entry *new;
+ Image_Entry *im2 = NULL;
int error;
- assert(im);
- assert(im->cache);
#ifdef EVAS_FRAME_QUEUING
LKL(im->lock_references);
#endif
- assert(im->references > 0);
#ifdef EVAS_FRAME_QUEUING
LKU(im->lock_references);
#endif
-
if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
(im->space == EVAS_COLORSPACE_YCBCR422P709_PL))
w &= ~0x1;
-
- if ((im->w == w) && (im->h == h))
- return im;
+ if ((im->w == w) && (im->h == h)) return im;
cache = im->cache;
-
- new = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, &error);
- if (!new) goto on_error;
-
- new->flags.alpha = im->flags.alpha;
- new->space = im->space;
- new->load_opts = im->load_opts;
-
- _evas_cache_image_entry_surface_alloc(cache, new, w, h);
-
- error = cache->func.size_set(new, im, w, h);
+ im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, &error);
+ if (!im2) goto on_error;
+
+ im2->flags.alpha = im->flags.alpha;
+ im2->space = im->space;
+ im2->load_opts = im->load_opts;
+ _evas_cache_image_entry_surface_alloc(cache, im2, w, h);
+ error = cache->func.size_set(im2, im, w, h);
if (error != 0) goto on_error;
-
#ifdef EVAS_FRAME_QUEUING
- LKL(new->lock_references);
+ LKL(im2->lock_references);
#endif
- new->references = 1;
+ im->references = 1;
#ifdef EVAS_FRAME_QUEUING
- LKU(new->lock_references);
+ LKU(im2->lock_references);
#endif
-
- evas_cache_image_drop(im);
-
- if (cache->func.debug)
- cache->func.debug("size_set", new);
-
- return new;
+ _evas_cache_image_dirty_add(im);
+ if (cache->func.debug) cache->func.debug("size_set", im2);
+ return im2;
on_error:
- if (new) _evas_cache_image_entry_delete(cache, new);
+ if (im2) _evas_cache_image_entry_delete(cache, im2);
evas_cache_image_drop(im);
return NULL;
}
#ifdef BUILD_ASYNC_PRELOAD
Eina_Bool preload = EINA_FALSE;
#endif
- Evas_Cache_Image *cache;
int error;
- assert(im);
- assert(im->cache);
- cache = im->cache;
-
if (im->flags.loaded) return;
-
#ifdef BUILD_ASYNC_PRELOAD
if (im->preload)
{
preload = EINA_TRUE;
-
if (!im->flags.pending)
{
im->cache->preload = eina_list_remove(im->cache->preload, im);
im->cache->pending = eina_list_append(im->cache->pending, im);
im->flags.pending = 1;
-
evas_preload_thread_cancel(im->preload);
}
-
evas_async_events_process();
-
LKL(wakeup);
while (im->preload)
{
pthread_cond_wait(&cond_wakeup, &wakeup);
LKU(wakeup);
-
evas_async_events_process();
-
LKL(wakeup);
}
LKU(wakeup);
if (im->flags.loaded) return ;
LKL(im->lock);
#endif
-
im->flags.in_progress = EINA_TRUE;
- error = cache->func.load(im);
+ error = im->cache->func.load(im);
im->flags.in_progress = EINA_FALSE;
-
#ifdef BUILD_ASYNC_PRELOAD
LKU(im->lock);
#endif
-
im->flags.loaded = 1;
-
- if (cache->func.debug)
- cache->func.debug("load", im);
-
+ if (im->cache->func.debug) im->cache->func.debug("load", im);
if (error != EVAS_LOAD_ERROR_NONE)
{
- _evas_cache_image_entry_surface_alloc(cache, im, im->w, im->h);
+ _evas_cache_image_entry_surface_alloc(im->cache, im, im->w, im->h);
im->flags.loaded = 0;
}
-
#ifdef BUILD_ASYNC_PRELOAD
- if (preload)
- _evas_cache_image_async_end(im);
+ if (preload) _evas_cache_image_async_end(im);
#endif
}
EAPI void
evas_cache_image_unload_data(Image_Entry *im)
{
- Evas_Cache_Image *cache;
-
- assert(im);
- assert(im->cache);
- cache = im->cache;
-
if (im->flags.in_progress) return;
-
evas_cache_image_preload_cancel(im, NULL);
-
#ifdef BUILD_ASYNC_PRELOAD
LKL(im->lock_cancel);
if (LKT(im->lock) != 0) /* can't get image lock - busy async load */
return;
}
LKU(im->lock_cancel);
-// LKL(im->lock);
#endif
- if ((!im->flags.loaded) || (!im->file) ||
- (!im->info.module) || (im->flags.dirty))
+ if ((!im->flags.loaded) || (!im->file) || (!im->info.module) ||
+ (im->flags.dirty))
{
#ifdef BUILD_ASYNC_PRELOAD
LKU(im->lock);
#endif
return;
}
- cache->func.destructor(im);
-
+ im->cache->func.destructor(im);
#ifdef BUILD_ASYNC_PRELOAD
LKU(im->lock);
#endif
EAPI Eina_Bool
evas_cache_image_is_loaded(Image_Entry *im)
{
- assert(im);
if (im->flags.loaded) return EINA_TRUE;
return EINA_FALSE;
}
#ifdef BUILD_ASYNC_PRELOAD
RGBA_Image *img = (RGBA_Image *)im;
- assert(im);
- assert(im->cache);
-
if ((im->flags.loaded) && (img->image.data))
{
evas_object_inform_call_image_preloaded((Evas_Object *)target);
return;
}
im->flags.loaded = 0;
-
if (!_evas_cache_image_entry_preload_add(im, target))
- {
evas_object_inform_call_image_preloaded((Evas_Object *)target);
- }
#else
evas_cache_image_load_data(im);
evas_object_inform_call_image_preloaded((Evas_Object *)target);
evas_cache_image_preload_cancel(Image_Entry *im, const void *target)
{
#ifdef BUILD_ASYNC_PRELOAD
- assert(im);
- assert(im->cache);
-
if (!target) return;
_evas_cache_image_entry_preload_remove(im, target);
#else
#endif
}
+#ifdef CACHEDUMP
+static int total = 0;
+
+static void
+_dump_img(Image_Entry *im, const char *type)
+{
+ total += im->cache->func.mem_size_get(im);
+ printf("%s: %4i: %4ib, %4ix%4i alloc[%4ix%4i] [%s] [%s]\n",
+ type,
+ im->references,
+ im->cache->func.mem_size_get(im),
+ im->w, im->h, im->allocated.w, im->allocated.h,
+ im->file, im->key);
+}
+
+static Eina_Bool
+_dump_cache_active(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, void *fdata __UNUSED__)
+{
+ Image_Entry *im = data;
+ _dump_img(im, "ACTIVE");
+ return EINA_TRUE;
+}
+
+static void
+_dump_cache(Evas_Cache_Image *cache)
+{
+ Image_Entry *im;
+
+ printf("--CACHE DUMP----------------------------------------------------\n");
+ printf("cache: %ikb / %ikb\n",
+ cache->usage / 1024,
+ cache->limit / 1024);
+ printf("................................................................\n");
+ total = 0;
+ EINA_INLIST_FOREACH(cache->lru_nodata, im)
+ _dump_img(im, "NODATA");
+ EINA_INLIST_FOREACH(cache->lru, im)
+ _dump_img(im, "DATA ");
+ printf("tot: %i\n"
+ "usg: %i\n",
+ total,
+ cache->usage);
+ eina_hash_foreach(cache->activ, _dump_cache_active, NULL);
+}
+#endif
+
EAPI int
evas_cache_image_flush(Evas_Cache_Image *cache)
{
- assert(cache);
- assert(cache->usage >= 0);
-
#ifdef CACHEDUMP
_dump_cache(cache);
#endif
Image_Entry *im;
im = (Image_Entry *) cache->lru_nodata->last;
- _evas_cache_image_remove_lru_nodata(cache, im);
-
+ _evas_cache_image_lru_nodata_del(im);
cache->func.surface_delete(im);
-
im->flags.loaded = 0;
}
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
-
#ifdef EVAS_FRAME_QUEUING
LKL(im->lock_references);
#endif
EAPI void
evas_cache_image_colorspace(Image_Entry *im, int cspace)
{
- Evas_Cache_Image *cache;
-
- assert(im);
- assert(im->cache);
-
- cache = im->cache;
-
if (im->space == cspace) return;
-
im->space = cspace;
- cache->func.color_space(im, cspace);
+ im->cache->func.color_space(im, cspace);
}
EAPI void *
evas_cache_private_from_image_entry_get(Image_Entry *im)
{
- Evas_Cache_Image *cache;
-
- assert(im);
- assert(im->cache);
-
- cache = im->cache;
-
- return (void*) cache->data;
+ return (void *)im->cache->data;
}
EAPI void *
evas_cache_private_get(Evas_Cache_Image *cache)
{
- assert(cache);
-
return cache->data;
}
EAPI void
evas_cache_private_set(Evas_Cache_Image *cache, const void *data)
{
- assert(cache);
-
cache->data = (void *)data;
}
EAPI DATA32 *
evas_cache_image_pixels(Image_Entry *im)
{
- Evas_Cache_Image *cache;
-
- assert(im);
- assert(im->cache);
-
- cache = im->cache;
-
- return cache->func.surface_pixels(im);
+ return im->cache->func.surface_pixels(im);
}
EAPI void