2008-11-05 09:21:04 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
2008-11-05 09:21:04 -08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2009-12-22 15:11:57 -08:00
|
|
|
#include <errno.h>
|
2008-11-05 09:21:04 -08:00
|
|
|
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2013-06-20 03:53:29 -07:00
|
|
|
#include "evas_common_private.h"
|
2007-07-16 00:25:35 -07:00
|
|
|
#include "evas_private.h"
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
//#define CACHEDUMP 1
|
|
|
|
|
2009-01-19 06:06:09 -08:00
|
|
|
typedef struct _Evas_Cache_Preload Evas_Cache_Preload;
|
|
|
|
|
|
|
|
struct _Evas_Cache_Preload
|
2008-12-23 15:07:48 -08:00
|
|
|
{
|
|
|
|
EINA_INLIST;
|
|
|
|
Image_Entry *ie;
|
|
|
|
};
|
|
|
|
|
2011-05-02 04:28:47 -07:00
|
|
|
static LK(engine_lock);
|
|
|
|
static LK(wakeup);
|
|
|
|
static int _evas_cache_mutex_init = 0;
|
2008-09-16 07:52:57 -07:00
|
|
|
|
2011-05-09 03:33:21 -07:00
|
|
|
static Eina_Condition cond_wakeup;
|
2008-09-16 07:52:57 -07:00
|
|
|
|
2013-05-30 20:55:14 -07:00
|
|
|
static const Image_Entry_Task dummy_task = { NULL, NULL, NULL };
|
|
|
|
|
2013-06-12 23:50:01 -07:00
|
|
|
static void _evas_cache_image_entry_preload_remove(Image_Entry *ie, const Eo *target);
|
2008-09-16 07:52:57 -07:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
#define FREESTRC(Var) \
|
|
|
|
if (Var) \
|
2012-01-30 06:36:15 -08:00
|
|
|
{ \
|
|
|
|
eina_stringshare_del(Var); \
|
|
|
|
Var = NULL; \
|
|
|
|
}
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
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);
|
2008-05-09 12:04:49 -07:00
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
static void
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_dirty_add(Image_Entry *im)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
if (im->flags.dirty) return;
|
|
|
|
_evas_cache_image_activ_del(im);
|
|
|
|
_evas_cache_image_lru_del(im);
|
|
|
|
_evas_cache_image_lru_nodata_del(im);
|
2008-12-01 18:33:09 -08:00
|
|
|
im->flags.dirty = 1;
|
2011-04-20 23:24:27 -07:00
|
|
|
im->flags.cached = 1;
|
|
|
|
im->cache->dirty = eina_inlist_prepend(im->cache->dirty, EINA_INLIST_GET(im));
|
2008-12-01 18:33:09 -08:00
|
|
|
if (im->cache_key)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2008-12-01 18:33:09 -08:00
|
|
|
eina_stringshare_del(im->cache_key);
|
|
|
|
im->cache_key = NULL;
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_dirty_del(Image_Entry *im)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
if (!im->flags.dirty) return;
|
|
|
|
im->flags.dirty = 0;
|
|
|
|
im->flags.cached = 0;
|
2013-05-07 23:37:37 -07:00
|
|
|
im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_activ_add(Image_Entry *im)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
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;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
|
|
|
eina_hash_direct_add(im->cache->mmap_activ, im->cache_key, im);
|
|
|
|
else
|
|
|
|
eina_hash_direct_add(im->cache->activ, im->cache_key, im);
|
2011-04-20 23:24:27 -07:00
|
|
|
}
|
2008-04-11 17:32:30 -07:00
|
|
|
|
|
|
|
static void
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_activ_del(Image_Entry *im)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
if (!im->flags.activ) return;
|
|
|
|
if (!im->cache_key) return;
|
|
|
|
im->flags.activ = 0;
|
|
|
|
im->flags.cached = 0;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
|
|
|
eina_hash_del(im->cache->mmap_activ, im->cache_key, im);
|
|
|
|
else
|
|
|
|
eina_hash_del(im->cache->activ, im->cache_key, im);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_lru_add(Image_Entry *im)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
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;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
|
|
|
{
|
|
|
|
eina_hash_direct_add(im->cache->mmap_inactiv, im->cache_key, im);
|
|
|
|
im->cache->mmap_lru = eina_inlist_prepend(im->cache->mmap_lru, EINA_INLIST_GET(im));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
|
|
|
|
im->cache->lru = eina_inlist_prepend(im->cache->lru, EINA_INLIST_GET(im));
|
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
im->cache->usage += im->cache->func.mem_size_get(im);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_lru_del(Image_Entry *im)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
if (!im->flags.lru) return;
|
|
|
|
if (!im->cache_key) return;
|
|
|
|
im->flags.lru = 0;
|
|
|
|
im->flags.cached = 0;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
|
|
|
{
|
|
|
|
eina_hash_del(im->cache->mmap_inactiv, im->cache_key, im);
|
|
|
|
im->cache->mmap_lru = eina_inlist_remove(im->cache->mmap_lru, EINA_INLIST_GET(im));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eina_hash_del(im->cache->inactiv, im->cache_key, im);
|
|
|
|
im->cache->lru = eina_inlist_remove(im->cache->lru, EINA_INLIST_GET(im));
|
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
im->cache->usage -= im->cache->func.mem_size_get(im);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_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;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
|
|
|
im->cache->mmap_lru_nodata = eina_inlist_prepend(im->cache->mmap_lru_nodata, EINA_INLIST_GET(im));
|
|
|
|
else
|
|
|
|
im->cache->lru_nodata = eina_inlist_prepend(im->cache->lru_nodata, EINA_INLIST_GET(im));
|
2011-04-20 23:24:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
|
|
|
im->cache->mmap_lru_nodata = eina_inlist_remove(im->cache->mmap_lru_nodata, EINA_INLIST_GET(im));
|
|
|
|
else
|
|
|
|
im->cache->lru_nodata = eina_inlist_remove(im->cache->lru_nodata, EINA_INLIST_GET(im));
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
|
|
|
|
{
|
2013-05-30 20:55:14 -07:00
|
|
|
Image_Entry_Task *task;
|
|
|
|
|
2010-07-31 10:06:55 -07:00
|
|
|
if (!ie) return;
|
2013-06-07 00:15:29 -07:00
|
|
|
if ((cache) && (cache->func.debug)) cache->func.debug("deleting", ie);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (ie->flags.delete_me == 1) return;
|
2009-12-18 03:03:31 -08:00
|
|
|
if (ie->preload)
|
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
ie->flags.delete_me = 1;
|
|
|
|
_evas_cache_image_entry_preload_remove(ie, NULL);
|
|
|
|
return;
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2009-11-05 09:38:51 -08:00
|
|
|
|
2013-05-30 20:55:14 -07:00
|
|
|
EINA_LIST_FREE(ie->tasks, task)
|
|
|
|
if (task != &dummy_task) free(task);
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
_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);
|
2011-08-01 07:56:26 -07:00
|
|
|
|
2010-09-10 16:00:26 -07:00
|
|
|
cache->func.destructor(ie);
|
2011-04-20 23:24:27 -07:00
|
|
|
FREESTRC(ie->cache_key);
|
2008-04-11 17:32:30 -07:00
|
|
|
FREESTRC(ie->file);
|
|
|
|
FREESTRC(ie->key);
|
2009-11-30 05:26:46 -08:00
|
|
|
ie->cache = NULL;
|
2008-04-11 17:32:30 -07:00
|
|
|
cache->func.surface_delete(ie);
|
2008-12-23 15:07:48 -08:00
|
|
|
|
2009-03-13 22:08:08 -07:00
|
|
|
LKD(ie->lock);
|
2010-12-14 02:22:06 -08:00
|
|
|
LKD(ie->lock_cancel);
|
2013-05-30 20:55:14 -07:00
|
|
|
LKD(ie->lock_task);
|
2008-05-24 11:26:51 -07:00
|
|
|
cache->func.dealloc(ie);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
2011-03-19 00:08:59 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_timestamp_compare(Image_Timestamp *tstamp, struct stat *st)
|
|
|
|
{
|
|
|
|
if (tstamp->mtime != st->st_mtime) return EINA_FALSE;
|
|
|
|
if (tstamp->size != st->st_size) return EINA_FALSE;
|
|
|
|
if (tstamp->ino != st->st_ino) return EINA_FALSE;
|
|
|
|
#ifdef _STAT_VER_LINUX
|
2011-03-22 07:29:25 -07:00
|
|
|
#if (defined __USE_MISC && defined st_mtime)
|
2011-04-20 23:24:27 -07:00
|
|
|
if (tstamp->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec)
|
2012-01-30 06:36:15 -08:00
|
|
|
return EINA_FALSE;
|
2011-03-22 07:29:25 -07:00
|
|
|
#else
|
2011-04-20 23:24:27 -07:00
|
|
|
if (tstamp->mtime_nsec != (unsigned long int)st->st_mtimensec)
|
2012-01-30 06:36:15 -08:00
|
|
|
return EINA_FALSE;
|
2011-03-22 07:29:25 -07:00
|
|
|
#endif
|
2011-03-19 00:08:59 -07:00
|
|
|
#endif
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timestamp_build(Image_Timestamp *tstamp, struct stat *st)
|
|
|
|
{
|
|
|
|
tstamp->mtime = st->st_mtime;
|
|
|
|
tstamp->size = st->st_size;
|
|
|
|
tstamp->ino = st->st_ino;
|
|
|
|
#ifdef _STAT_VER_LINUX
|
2011-03-22 07:29:25 -07:00
|
|
|
#if (defined __USE_MISC && defined st_mtime)
|
2011-03-22 06:44:29 -07:00
|
|
|
tstamp->mtime_nsec = (unsigned long int)st->st_mtim.tv_nsec;
|
2011-03-22 07:29:25 -07:00
|
|
|
#else
|
2011-03-19 00:08:59 -07:00
|
|
|
tstamp->mtime_nsec = (unsigned long int)st->st_mtimensec;
|
|
|
|
#endif
|
2011-03-22 07:29:25 -07:00
|
|
|
#endif
|
2011-03-19 00:08:59 -07:00
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
static Image_Entry *
|
|
|
|
_evas_cache_image_entry_new(Evas_Cache_Image *cache,
|
|
|
|
const char *hkey,
|
2011-03-19 00:08:59 -07:00
|
|
|
Image_Timestamp *tstamp,
|
2013-05-07 23:37:37 -07:00
|
|
|
Eina_File *f,
|
2008-04-11 17:32:30 -07:00
|
|
|
const char *file,
|
|
|
|
const char *key,
|
2013-05-06 18:50:57 -07:00
|
|
|
Evas_Image_Load_Opts *lo,
|
2008-04-11 17:32:30 -07:00
|
|
|
int *error)
|
|
|
|
{
|
|
|
|
Image_Entry *ie;
|
|
|
|
|
|
|
|
ie = cache->func.alloc();
|
|
|
|
if (!ie)
|
2009-12-22 15:11:57 -08:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
return NULL;
|
2009-12-22 15:11:57 -08:00
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
ie->cache = cache;
|
|
|
|
if (hkey) ie->cache_key = eina_stringshare_add(hkey);
|
2008-04-11 17:32:30 -07:00
|
|
|
ie->flags.need_data = 1;
|
|
|
|
ie->space = EVAS_COLORSPACE_ARGB8888;
|
|
|
|
ie->w = -1;
|
|
|
|
ie->h = -1;
|
2011-04-20 23:24:27 -07:00
|
|
|
ie->scale = 1;
|
2013-05-07 23:37:37 -07:00
|
|
|
ie->f = f;
|
|
|
|
ie->loader_data = NULL;
|
|
|
|
if (ie->f) ie->flags.given_mmap = EINA_TRUE;
|
2011-04-20 23:24:27 -07:00
|
|
|
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));
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2009-03-13 22:08:08 -07:00
|
|
|
LKI(ie->lock);
|
2013-05-30 20:55:14 -07:00
|
|
|
LKI(ie->lock_cancel);
|
|
|
|
LKI(ie->lock_task);
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
if (lo) ie->load_opts = *lo;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (ie->file || ie->f)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
|
|
|
*error = cache->func.constructor(ie);
|
2009-12-22 15:11:57 -08:00
|
|
|
if (*error != EVAS_LOAD_ERROR_NONE)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
|
|
|
_evas_cache_image_entry_delete(cache, ie);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
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);
|
2008-04-11 17:32:30 -07:00
|
|
|
return ie;
|
|
|
|
}
|
|
|
|
|
2008-12-26 04:50:55 -08:00
|
|
|
static void
|
|
|
|
_evas_cache_image_entry_surface_alloc__locked(Evas_Cache_Image *cache,
|
2012-01-30 06:36:15 -08:00
|
|
|
Image_Entry *ie,
|
|
|
|
unsigned int wmin,
|
2010-09-18 16:16:25 -07:00
|
|
|
unsigned int hmin)
|
2008-12-26 04:50:55 -08:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
if ((ie->allocated.w == wmin) && (ie->allocated.h == hmin)) return;
|
2008-12-26 04:50:55 -08:00
|
|
|
if (cache->func.surface_alloc(ie, wmin, hmin))
|
|
|
|
{
|
|
|
|
wmin = 0;
|
|
|
|
hmin = 0;
|
|
|
|
}
|
|
|
|
ie->w = wmin;
|
|
|
|
ie->h = hmin;
|
|
|
|
ie->allocated.w = wmin;
|
|
|
|
ie->allocated.h = hmin;
|
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
static void
|
|
|
|
_evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
|
2010-07-31 10:06:55 -07:00
|
|
|
Image_Entry *ie, int w, int h)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
int wmin = w > 0 ? w : 1;
|
|
|
|
int hmin = h > 0 ? h : 1;
|
2009-12-18 03:03:31 -08:00
|
|
|
LKL(engine_lock);
|
2008-12-26 04:50:55 -08:00
|
|
|
_evas_cache_image_entry_surface_alloc__locked(cache, ie, wmin, hmin);
|
2009-12-18 03:03:31 -08:00
|
|
|
LKU(engine_lock);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
2009-01-20 06:56:37 -08:00
|
|
|
static void
|
2009-12-18 03:03:31 -08:00
|
|
|
_evas_cache_image_async_heavy(void *data)
|
|
|
|
{
|
|
|
|
Evas_Cache_Image *cache;
|
|
|
|
Image_Entry *current;
|
2013-05-30 20:55:14 -07:00
|
|
|
Image_Entry_Task *task;
|
2009-12-18 03:03:31 -08:00
|
|
|
int error;
|
|
|
|
int pchannel;
|
|
|
|
|
|
|
|
current = data;
|
|
|
|
|
|
|
|
LKL(current->lock);
|
|
|
|
pchannel = current->channel;
|
|
|
|
current->channel++;
|
|
|
|
cache = current->cache;
|
|
|
|
|
2013-06-03 19:17:21 -07:00
|
|
|
if ((!current->flags.loaded) &&
|
|
|
|
current->info.loader->threadable)
|
2009-12-18 03:03:31 -08:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
error = cache->func.load(current);
|
|
|
|
if (cache->func.debug) cache->func.debug("load", current);
|
2011-05-19 04:19:22 -07:00
|
|
|
current->load_error = error;
|
2012-01-30 06:36:15 -08:00
|
|
|
if (error != EVAS_LOAD_ERROR_NONE)
|
|
|
|
{
|
|
|
|
current->flags.loaded = 0;
|
|
|
|
_evas_cache_image_entry_surface_alloc(cache, current,
|
|
|
|
current->w, current->h);
|
|
|
|
}
|
|
|
|
else
|
2011-05-19 04:19:22 -07:00
|
|
|
{
|
|
|
|
current->flags.loaded = 1;
|
2013-05-30 20:55:14 -07:00
|
|
|
|
|
|
|
LKL(current->lock_task);
|
|
|
|
EINA_LIST_FREE(current->tasks, task)
|
|
|
|
{
|
|
|
|
if (task != &dummy_task)
|
|
|
|
{
|
|
|
|
task->cb((void *) task->engine_data, current, (void *) task->custom_data);
|
|
|
|
free(task);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LKU(current->lock_task);
|
2011-05-19 04:19:22 -07:00
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
|
|
|
current->channel = pchannel;
|
2010-12-14 02:22:06 -08:00
|
|
|
// check the unload cancel flag
|
|
|
|
LKL(current->lock_cancel);
|
2013-04-24 23:05:18 -07:00
|
|
|
if (current->flags.unload_cancel)
|
2010-12-14 02:22:06 -08:00
|
|
|
{
|
2013-04-24 23:05:18 -07:00
|
|
|
current->flags.unload_cancel = EINA_FALSE;
|
2010-12-14 02:22:06 -08:00
|
|
|
cache->func.surface_delete(current);
|
|
|
|
current->flags.loaded = 0;
|
|
|
|
current->flags.preload_done = 0;
|
|
|
|
}
|
|
|
|
LKU(current->lock_cancel);
|
2009-12-18 03:03:31 -08:00
|
|
|
LKU(current->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_cache_image_async_end(void *data)
|
2009-01-20 06:56:37 -08:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
Image_Entry *ie = (Image_Entry *)data;
|
2013-05-30 20:55:14 -07:00
|
|
|
Image_Entry_Task *task;
|
2009-12-18 03:03:31 -08:00
|
|
|
Evas_Cache_Target *tmp;
|
|
|
|
|
|
|
|
ie->cache->preload = eina_list_remove(ie->cache->preload, ie);
|
|
|
|
ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
|
|
|
|
ie->preload = NULL;
|
2009-12-24 05:15:34 -08:00
|
|
|
ie->flags.preload_done = ie->flags.loaded;
|
2011-04-20 23:24:27 -07:00
|
|
|
while ((tmp = ie->targets))
|
2009-01-20 06:56:37 -08:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
evas_object_inform_call_image_preloaded((Evas_Object*) tmp->target);
|
|
|
|
ie->targets = (Evas_Cache_Target *)
|
2011-04-20 23:24:27 -07:00
|
|
|
eina_inlist_remove(EINA_INLIST_GET(ie->targets),
|
|
|
|
EINA_INLIST_GET(ie->targets));
|
2012-01-30 06:36:15 -08:00
|
|
|
free(tmp);
|
2009-01-20 06:56:37 -08:00
|
|
|
}
|
2013-05-30 20:55:14 -07:00
|
|
|
|
|
|
|
EINA_LIST_FREE(ie->tasks, task)
|
|
|
|
if (task != &dummy_task) free(task);
|
2009-01-23 14:21:04 -08:00
|
|
|
}
|
|
|
|
|
2009-11-05 09:38:51 -08:00
|
|
|
static void
|
2009-12-18 03:03:31 -08:00
|
|
|
_evas_cache_image_async_cancel(void *data)
|
2009-11-05 09:38:51 -08:00
|
|
|
{
|
2010-05-21 00:44:07 -07:00
|
|
|
Evas_Cache_Image *cache = NULL;
|
2011-04-20 23:24:27 -07:00
|
|
|
Image_Entry *ie = (Image_Entry *)data;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
ie->preload = NULL;
|
|
|
|
ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
|
2011-04-20 23:24:27 -07:00
|
|
|
if ((ie->flags.delete_me) || (ie->flags.dirty))
|
2009-12-18 03:03:31 -08:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
ie->flags.delete_me = 0;
|
|
|
|
_evas_cache_image_entry_delete(ie->cache, ie);
|
|
|
|
return;
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
if (ie->flags.loaded) _evas_cache_image_async_end(ie);
|
2009-12-18 03:03:31 -08:00
|
|
|
if (ie->references == 0)
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_lru_add(ie);
|
2010-05-21 00:44:07 -07:00
|
|
|
cache = ie->cache;
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2010-05-21 00:44:07 -07:00
|
|
|
if (cache) evas_cache_image_flush(cache);
|
2009-01-20 06:56:37 -08:00
|
|
|
}
|
|
|
|
|
2011-05-02 20:20:02 -07:00
|
|
|
// note - preload_add assumes a target is ONLY added ONCE to the image
|
|
|
|
// entry. make sure you only add once, or remove first, then add
|
2008-09-16 07:52:57 -07:00
|
|
|
static int
|
2013-06-12 23:50:01 -07:00
|
|
|
_evas_cache_image_entry_preload_add(Image_Entry *ie, const Eo *target,
|
2013-05-30 20:55:14 -07:00
|
|
|
Evas_Engine_Thread_Task_Cb func, const void *engine_data, const void *custom_data)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2009-01-19 06:06:09 -08:00
|
|
|
Evas_Cache_Target *tg;
|
2013-05-30 20:55:14 -07:00
|
|
|
Image_Entry_Task *task;
|
2008-09-16 07:52:57 -07:00
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
if (ie->flags.preload_done) return 0;
|
2011-05-02 20:20:02 -07:00
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
tg = malloc(sizeof (Evas_Cache_Target));
|
|
|
|
if (!tg) return 0;
|
|
|
|
tg->target = target;
|
2013-05-30 20:55:14 -07:00
|
|
|
|
|
|
|
if (func == NULL && engine_data == NULL && custom_data == NULL)
|
|
|
|
{
|
|
|
|
task = (Image_Entry_Task*) &dummy_task;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
task = malloc(sizeof (Image_Entry_Task));
|
|
|
|
if (!task)
|
|
|
|
{
|
|
|
|
free(tg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
task->cb = func;
|
|
|
|
task->engine_data = engine_data;
|
|
|
|
task->custom_data = custom_data;
|
|
|
|
}
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
ie->targets = (Evas_Cache_Target *)
|
|
|
|
eina_inlist_append(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
|
2013-05-30 20:55:14 -07:00
|
|
|
LKL(ie->lock_task);
|
|
|
|
ie->tasks = eina_list_append(ie->tasks, task);
|
|
|
|
LKU(ie->lock_task);
|
|
|
|
|
2009-12-19 22:23:13 -08:00
|
|
|
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);
|
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
return 1;
|
2008-09-16 07:52:57 -07:00
|
|
|
}
|
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
static void
|
2013-06-12 23:50:01 -07:00
|
|
|
_evas_cache_image_entry_preload_remove(Image_Entry *ie, const Eo *target)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2013-05-30 20:55:14 -07:00
|
|
|
Evas_Cache_Target *tg;
|
|
|
|
Eina_List *l;
|
|
|
|
Image_Entry_Task *task;
|
|
|
|
|
2009-11-05 09:38:51 -08:00
|
|
|
if (target)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2013-05-30 20:55:14 -07:00
|
|
|
LKL(ie->lock_task);
|
|
|
|
l = ie->tasks;
|
2012-01-30 06:36:15 -08:00
|
|
|
EINA_INLIST_FOREACH(ie->targets, tg)
|
|
|
|
{
|
|
|
|
if (tg->target == target)
|
|
|
|
{
|
|
|
|
// FIXME: No callback when we cancel only for one target ?
|
|
|
|
ie->targets = (Evas_Cache_Target *)
|
2011-04-20 23:24:27 -07:00
|
|
|
eina_inlist_remove(EINA_INLIST_GET(ie->targets),
|
|
|
|
EINA_INLIST_GET(tg));
|
2013-05-30 20:55:14 -07:00
|
|
|
|
|
|
|
task = eina_list_data_get(l);
|
|
|
|
ie->tasks = eina_list_remove_list(ie->tasks, l);
|
|
|
|
if (task != &dummy_task) free(task);
|
|
|
|
LKU(ie->lock_task);
|
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
free(tg);
|
|
|
|
break;
|
|
|
|
}
|
2013-05-30 20:55:14 -07:00
|
|
|
|
|
|
|
l = eina_list_next(l);
|
2012-01-30 06:36:15 -08:00
|
|
|
}
|
2013-05-30 20:55:14 -07:00
|
|
|
LKU(ie->lock_task);
|
2009-11-05 09:38:51 -08:00
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
else
|
2009-09-22 00:02:14 -07:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
while (ie->targets)
|
|
|
|
{
|
|
|
|
tg = ie->targets;
|
|
|
|
ie->targets = (Evas_Cache_Target *)
|
2011-04-20 23:24:27 -07:00
|
|
|
eina_inlist_remove(EINA_INLIST_GET(ie->targets),
|
|
|
|
EINA_INLIST_GET(tg));
|
2012-01-30 06:36:15 -08:00
|
|
|
free(tg);
|
|
|
|
}
|
2013-05-30 20:55:14 -07:00
|
|
|
|
|
|
|
LKL(ie->lock_task);
|
|
|
|
EINA_LIST_FREE(ie->tasks, task)
|
|
|
|
if (task != &dummy_task) free(task);
|
|
|
|
LKU(ie->lock_task);
|
2009-09-22 00:02:14 -07:00
|
|
|
}
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
if ((!ie->targets) && (ie->preload) && (!ie->flags.pending))
|
2009-09-22 00:02:14 -07:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
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);
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2009-09-22 00:02:14 -07:00
|
|
|
}
|
2008-09-16 07:52:57 -07:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
EAPI int
|
|
|
|
evas_cache_image_usage_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
return cache->usage;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_cache_image_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
return cache->limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2010-09-18 16:16:25 -07:00
|
|
|
evas_cache_image_set(Evas_Cache_Image *cache, unsigned int limit)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-05-21 00:10:45 -07:00
|
|
|
if (cache->limit == limit)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
cache->limit = limit;
|
2011-05-09 05:55:57 -07:00
|
|
|
evas_cache_image_flush(cache);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2007-08-12 22:30:17 -07:00
|
|
|
EAPI Evas_Cache_Image *
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_init(const Evas_Cache_Image_Func *cb)
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
Evas_Cache_Image *cache;
|
2009-12-18 03:03:31 -08:00
|
|
|
|
2011-05-02 04:28:47 -07:00
|
|
|
if (_evas_cache_mutex_init++ == 0)
|
|
|
|
{
|
|
|
|
LKI(engine_lock);
|
|
|
|
LKI(wakeup);
|
2012-01-30 06:36:15 -08:00
|
|
|
eina_condition_new(&cond_wakeup, &wakeup);
|
2011-05-02 04:28:47 -07:00
|
|
|
}
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
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);
|
2013-05-07 23:37:37 -07:00
|
|
|
cache->mmap_activ = eina_hash_string_superfast_new(NULL);
|
|
|
|
cache->mmap_inactiv = eina_hash_string_superfast_new(NULL);
|
2011-04-20 23:24:27 -07:00
|
|
|
cache->references = 1;
|
|
|
|
return cache;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2009-06-17 03:01:52 -07:00
|
|
|
static Eina_Bool
|
2012-11-04 03:51:42 -08:00
|
|
|
_evas_cache_image_free_cb(EINA_UNUSED const Eina_Hash *hash, EINA_UNUSED const void *key, void *data, void *fdata)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2008-10-31 04:07:10 -07:00
|
|
|
Eina_List **delete_list = fdata;
|
|
|
|
*delete_list = eina_list_prepend(*delete_list, data);
|
2009-06-17 03:01:52 -07:00
|
|
|
return EINA_TRUE;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_shutdown(Evas_Cache_Image *cache)
|
|
|
|
{
|
2008-10-31 04:07:10 -07:00
|
|
|
Eina_List *delete_list;
|
2009-12-18 03:03:31 -08:00
|
|
|
Image_Entry *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
cache->references--;
|
2011-05-02 04:28:47 -07:00
|
|
|
if (cache->references != 0)
|
2010-05-21 00:10:45 -07:00
|
|
|
{
|
2011-04-18 09:31:12 -07:00
|
|
|
return;
|
2010-05-21 00:10:45 -07:00
|
|
|
}
|
2011-05-02 04:28:47 -07:00
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
EINA_LIST_FREE(cache->preload, im)
|
2009-01-22 16:09:10 -08:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
/* By doing that we are protecting us from destroying image when the cache is no longer available. */
|
|
|
|
im->flags.delete_me = 1;
|
|
|
|
_evas_cache_image_entry_preload_remove(im, NULL);
|
2009-01-22 16:09:10 -08:00
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
evas_async_events_process();
|
2013-05-08 17:57:37 -07:00
|
|
|
|
|
|
|
EINA_INLIST_FREE(cache->lru, im)
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
EINA_INLIST_FREE(cache->lru_nodata, im)
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
EINA_INLIST_FREE(cache->mmap_lru, im)
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
EINA_INLIST_FREE(cache->mmap_lru_nodata, im)
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
/* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
|
|
|
|
while (cache->dirty)
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
im = (Image_Entry *)cache->dirty;
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
2009-01-22 16:08:11 -08:00
|
|
|
delete_list = NULL;
|
2008-12-09 09:56:31 -08:00
|
|
|
eina_hash_foreach(cache->activ, _evas_cache_image_free_cb, &delete_list);
|
2013-05-07 23:37:37 -07:00
|
|
|
eina_hash_foreach(cache->mmap_activ, _evas_cache_image_free_cb, &delete_list);
|
2008-10-31 04:07:10 -07:00
|
|
|
while (delete_list)
|
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
_evas_cache_image_entry_delete(cache, eina_list_data_get(delete_list));
|
|
|
|
delete_list = eina_list_remove_list(delete_list, delete_list);
|
2008-10-31 04:07:10 -07:00
|
|
|
}
|
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
/* Now wait for all pending image to die */
|
|
|
|
while (cache->pending)
|
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
evas_async_events_process();
|
|
|
|
LKL(wakeup);
|
2011-05-01 06:25:23 -07:00
|
|
|
// the lazy bum who did eain threads and converted this code
|
2011-05-30 09:45:08 -07:00
|
|
|
// didn't bother to worry about Eina_Lock being a different type
|
2011-05-01 06:25:23 -07:00
|
|
|
// to a pthread mutex.
|
2012-01-30 06:36:15 -08:00
|
|
|
if (cache->pending) eina_condition_wait(&cond_wakeup);
|
|
|
|
LKU(wakeup);
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2008-12-09 09:56:31 -08:00
|
|
|
eina_hash_free(cache->activ);
|
|
|
|
eina_hash_free(cache->inactiv);
|
2013-05-07 23:37:37 -07:00
|
|
|
eina_hash_free(cache->mmap_activ);
|
|
|
|
eina_hash_free(cache->mmap_inactiv);
|
2007-07-16 00:25:35 -07:00
|
|
|
free(cache);
|
2011-05-02 04:28:47 -07:00
|
|
|
|
|
|
|
if (--_evas_cache_mutex_init == 0)
|
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
eina_condition_free(&cond_wakeup);
|
2011-05-02 04:28:47 -07:00
|
|
|
LKD(engine_lock);
|
|
|
|
LKD(wakeup);
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2013-05-07 23:37:37 -07:00
|
|
|
static const Evas_Image_Load_Opts prevent = {
|
|
|
|
{ 0, 0, 0, 0 },
|
|
|
|
{
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
},
|
|
|
|
0.0,
|
|
|
|
0, 0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
|
|
|
|
EINA_FALSE
|
|
|
|
};
|
|
|
|
|
|
|
|
static size_t
|
|
|
|
_evas_cache_image_loadopts_append(char *hkey, Evas_Image_Load_Opts **plo)
|
|
|
|
{
|
|
|
|
Evas_Image_Load_Opts *lo = *plo;
|
|
|
|
size_t offset = 0;
|
|
|
|
|
|
|
|
if ((!lo) ||
|
|
|
|
(lo &&
|
|
|
|
(lo->scale_down_by == 0) &&
|
|
|
|
(lo->dpi == 0.0) &&
|
|
|
|
((lo->w == 0) || (lo->h == 0)) &&
|
|
|
|
((lo->region.w == 0) || (lo->region.h == 0)) &&
|
|
|
|
(lo->orientation == 0)
|
|
|
|
))
|
|
|
|
{
|
|
|
|
*plo = (Evas_Image_Load_Opts*) &prevent;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(hkey, "//@/", 4);
|
|
|
|
offset += 4;
|
|
|
|
offset += eina_convert_xtoa(lo->scale_down_by, hkey + offset);
|
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_dtoa(lo->dpi, hkey + offset);
|
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_xtoa(lo->w, hkey + offset);
|
|
|
|
hkey[offset] = 'x';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_xtoa(lo->h, hkey + offset);
|
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_xtoa(lo->region.x, hkey + offset);
|
|
|
|
hkey[offset] = '+';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_xtoa(lo->region.y, hkey + offset);
|
|
|
|
hkey[offset] = '.';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_xtoa(lo->region.w, hkey + offset);
|
|
|
|
hkey[offset] = 'x';
|
|
|
|
offset += 1;
|
|
|
|
offset += eina_convert_xtoa(lo->region.h, hkey + offset);
|
|
|
|
|
|
|
|
if (lo->orientation)
|
|
|
|
{
|
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
|
|
|
hkey[offset] = 'o';
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hkey[offset] = '\0';
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Image_Entry *
|
|
|
|
evas_cache_image_mmap_request(Evas_Cache_Image *cache,
|
|
|
|
Eina_File *f, const char *key,
|
|
|
|
Evas_Image_Load_Opts *lo, int *error)
|
|
|
|
{
|
|
|
|
const char *hexcode = "0123456789abcdef";
|
|
|
|
const char *ckey = "(null)";
|
|
|
|
char *hkey;
|
|
|
|
char *pf;
|
|
|
|
Image_Entry *im;
|
|
|
|
size_t size;
|
|
|
|
size_t file_length;
|
|
|
|
size_t key_length;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
// FIXME: In the long term we should certainly merge both mmap and filename path
|
|
|
|
// by just using the mmap path. But for the time being, let's just have two path
|
|
|
|
// as it is unlikely to really have an impact on real world application
|
|
|
|
if ((!f) || (!f && !key))
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generate hkey from file+key+load opts */
|
|
|
|
file_length = sizeof (Eina_File*) * 2;
|
|
|
|
key_length = key ? strlen(key) : 6;
|
|
|
|
size = file_length + key_length + 132;
|
|
|
|
hkey = alloca(sizeof (char) * size);
|
|
|
|
pf = (char*) &f;
|
|
|
|
for (size = 0, i = 0; i < sizeof (Eina_File*); i++)
|
|
|
|
{
|
|
|
|
hkey[size++] = hexcode[(pf[i] & 0xF0) >> 4];
|
|
|
|
hkey[size++] = hexcode[(pf[i] & 0x0F)];
|
|
|
|
}
|
|
|
|
memcpy(hkey + size, "//://", 5);
|
|
|
|
size += 5;
|
|
|
|
if (key) ckey = key;
|
|
|
|
memcpy(hkey + size, ckey, key_length);
|
|
|
|
size += key_length;
|
|
|
|
size += _evas_cache_image_loadopts_append(hkey + size, &lo);
|
|
|
|
|
|
|
|
|
|
|
|
/* find image by key in active mmap hash */
|
|
|
|
im = eina_hash_find(cache->mmap_activ, hkey);
|
|
|
|
if (im) goto on_ok;
|
|
|
|
|
|
|
|
/* find image by key in inactive/lru hash */
|
|
|
|
im = eina_hash_find(cache->mmap_inactiv, hkey);
|
|
|
|
if (im) goto on_ok;
|
|
|
|
|
|
|
|
im = _evas_cache_image_entry_new(cache, hkey, NULL, f, NULL, key, lo, error);
|
|
|
|
if (!im) return NULL;
|
|
|
|
|
|
|
|
on_ok:
|
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
|
|
|
im->references++;
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI Image_Entry *
|
2011-04-20 23:24:27 -07:00
|
|
|
evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
|
2013-05-06 18:50:57 -07:00
|
|
|
const char *key, Evas_Image_Load_Opts *lo, int *error)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2008-10-17 04:59:49 -07:00
|
|
|
const char *ckey = "(null)";
|
2007-08-12 22:30:17 -07:00
|
|
|
char *hkey;
|
2008-04-11 17:32:30 -07:00
|
|
|
Image_Entry *im;
|
2009-09-22 23:45:39 -07:00
|
|
|
size_t size;
|
2011-04-15 02:32:28 -07:00
|
|
|
int stat_done = 0, stat_failed = 0;
|
2009-09-22 23:45:39 -07:00
|
|
|
size_t file_length;
|
|
|
|
size_t key_length;
|
2007-08-12 22:30:17 -07:00
|
|
|
struct stat st;
|
2011-03-19 00:08:59 -07:00
|
|
|
Image_Timestamp tstamp;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2009-12-22 15:11:57 -08:00
|
|
|
if ((!file) || ((!file) && (!key)))
|
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
|
|
|
return NULL;
|
2009-12-22 15:11:57 -08:00
|
|
|
}
|
2008-10-17 04:59:49 -07:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
/* generate hkey from file+key+load opts */
|
2008-10-17 04:59:49 -07:00
|
|
|
file_length = strlen(file);
|
|
|
|
key_length = key ? strlen(key) : 6;
|
2011-06-07 06:39:13 -07:00
|
|
|
size = file_length + key_length + 132;
|
2008-10-17 04:59:49 -07:00
|
|
|
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;
|
2013-05-07 23:37:37 -07:00
|
|
|
size += _evas_cache_image_loadopts_append(hkey + size, &lo);
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
/* find image by key in active hash */
|
2008-12-09 09:56:31 -08:00
|
|
|
im = eina_hash_find(cache->activ, hkey);
|
2007-07-16 00:25:35 -07:00
|
|
|
if (im)
|
2007-08-11 05:14:17 -07:00
|
|
|
{
|
2011-03-19 00:08:59 -07:00
|
|
|
int ok = 1;
|
2011-04-15 00:49:25 -07:00
|
|
|
|
2011-03-19 00:08:59 -07:00
|
|
|
stat_done = 1;
|
2011-04-15 02:32:28 -07:00
|
|
|
if (stat(file, &st) < 0)
|
2012-01-30 06:36:15 -08:00
|
|
|
{
|
|
|
|
stat_failed = 1;
|
|
|
|
ok = 0;
|
|
|
|
}
|
2011-04-15 00:49:25 -07:00
|
|
|
else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
|
2008-04-11 17:32:30 -07:00
|
|
|
if (ok) goto on_ok;
|
2011-04-20 23:24:27 -07:00
|
|
|
/* 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);
|
2011-04-15 00:49:25 -07:00
|
|
|
im = NULL;
|
2007-08-11 05:14:17 -07:00
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
/* find image by key in inactive/lru hash */
|
2008-12-09 09:56:31 -08:00
|
|
|
im = eina_hash_find(cache->inactiv, hkey);
|
2007-07-16 00:25:35 -07:00
|
|
|
if (im)
|
|
|
|
{
|
2011-03-19 00:08:59 -07:00
|
|
|
int ok = 1;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
if (!stat_done)
|
|
|
|
{
|
2011-03-19 00:08:59 -07:00
|
|
|
stat_done = 1;
|
2011-04-15 02:32:28 -07:00
|
|
|
if (stat(file, &st) < 0)
|
|
|
|
{
|
|
|
|
stat_failed = 1;
|
|
|
|
ok = 0;
|
|
|
|
}
|
2011-04-15 00:49:25 -07:00
|
|
|
else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
2011-04-15 00:49:25 -07:00
|
|
|
else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
|
2008-04-11 17:32:30 -07:00
|
|
|
|
|
|
|
if (ok)
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
/* remove from lru and make it active again */
|
|
|
|
_evas_cache_image_lru_del(im);
|
|
|
|
_evas_cache_image_activ_add(im);
|
2008-04-11 17:32:30 -07:00
|
|
|
goto on_ok;
|
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
/* as avtive cache find - if we match in lru and its invalid, dirty */
|
|
|
|
_evas_cache_image_dirty_add(im);
|
2012-01-30 06:36:15 -08:00
|
|
|
/* this image never used, so it have to be deleted */
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2011-04-15 00:49:25 -07:00
|
|
|
im = NULL;
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
2011-04-15 02:32:28 -07:00
|
|
|
if (stat_failed) goto on_stat_error;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
if (!stat_done)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2009-12-22 15:11:57 -08:00
|
|
|
if (stat(file, &st) < 0) goto on_stat_error;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
2011-03-19 00:08:59 -07:00
|
|
|
_timestamp_build(&tstamp, &st);
|
2013-05-07 23:37:37 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, hkey, &tstamp, NULL, file, key,
|
2011-04-20 23:24:27 -07:00
|
|
|
lo, error);
|
2011-08-01 07:56:26 -07:00
|
|
|
if (!im) goto on_stat_error;
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("request", im);
|
2011-08-01 07:56:26 -07:00
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
on_ok:
|
2009-12-22 15:11:57 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
2007-07-16 00:25:35 -07:00
|
|
|
im->references++;
|
|
|
|
return im;
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
on_stat_error:
|
2010-01-29 16:09:29 -08:00
|
|
|
#ifndef _WIN32
|
2009-12-22 15:11:57 -08:00
|
|
|
if ((errno == ENOENT) || (errno == ENOTDIR) ||
|
|
|
|
(errno == ENAMETOOLONG) || (errno == ELOOP))
|
2010-01-29 16:09:29 -08:00
|
|
|
#else
|
2012-01-30 06:36:15 -08:00
|
|
|
if (errno == ENOENT)
|
2010-01-29 16:09:29 -08:00
|
|
|
#endif
|
2012-01-30 06:36:15 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
2010-01-29 16:09:29 -08:00
|
|
|
#ifndef _WIN32
|
2012-01-30 06:36:15 -08:00
|
|
|
else if ((errno == ENOMEM) || (errno == EOVERFLOW))
|
2010-01-29 16:09:29 -08:00
|
|
|
#else
|
2012-01-30 06:36:15 -08:00
|
|
|
else if (errno == ENOMEM)
|
2010-01-29 16:09:29 -08:00
|
|
|
#endif
|
2012-01-30 06:36:15 -08:00
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
else if (errno == EACCES)
|
|
|
|
*error = EVAS_LOAD_ERROR_PERMISSION_DENIED;
|
|
|
|
else
|
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
2009-12-22 15:11:57 -08:00
|
|
|
|
|
|
|
if (im) _evas_cache_image_entry_delete(cache, im);
|
2008-04-11 17:32:30 -07:00
|
|
|
return NULL;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2012-12-18 08:22:47 -08:00
|
|
|
EAPI void
|
|
|
|
evas_cache_image_ref(Image_Entry *im)
|
|
|
|
{
|
|
|
|
im->references++;
|
|
|
|
}
|
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
EAPI void
|
2008-04-11 17:32:30 -07:00
|
|
|
evas_cache_image_drop(Image_Entry *im)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
Evas_Cache_Image *cache;
|
|
|
|
int references;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
im->references--;
|
2011-03-14 03:53:37 -07:00
|
|
|
if (im->references < 0) im->references = 0;
|
2010-05-21 00:10:45 -07:00
|
|
|
references = im->references;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
cache = im->cache;
|
|
|
|
|
2010-05-21 00:10:45 -07:00
|
|
|
if (references == 0)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
if (im->preload)
|
|
|
|
{
|
|
|
|
_evas_cache_image_entry_preload_remove(im, NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (im->flags.dirty)
|
|
|
|
{
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
return;
|
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_lru_add(im);
|
2012-01-30 06:36:15 -08:00
|
|
|
if (cache) evas_cache_image_flush(cache);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI void
|
|
|
|
evas_cache_image_data_not_needed(Image_Entry *im)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
int references;
|
|
|
|
|
2010-05-21 00:10:45 -07:00
|
|
|
references = im->references;
|
2011-04-18 09:31:12 -07:00
|
|
|
if (references > 1) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
if ((im->flags.dirty) || (!im->flags.need_data)) return;
|
|
|
|
_evas_cache_image_lru_nodata_add(im);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Image_Entry *
|
2010-09-18 16:16:25 -07:00
|
|
|
evas_cache_image_dirty(Image_Entry *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
Image_Entry *im_dirty = im;
|
|
|
|
Evas_Cache_Image *cache;
|
2008-04-11 17:32:30 -07:00
|
|
|
|
|
|
|
cache = im->cache;
|
|
|
|
if (!(im->flags.dirty))
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2012-10-16 01:57:18 -07:00
|
|
|
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);
|
|
|
|
cache->func.dirty(im_dirty, im);
|
|
|
|
if (cache->func.debug) cache->func.debug("dirty-out", im_dirty);
|
|
|
|
im_dirty->references = 1;
|
|
|
|
evas_cache_image_drop(im);
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_dirty_add(im_dirty);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("dirty-region", im_dirty);
|
2007-07-16 00:25:35 -07:00
|
|
|
if (cache->func.dirty_region)
|
2012-01-30 06:36:15 -08:00
|
|
|
cache->func.dirty_region(im_dirty, x, y, w, h);
|
2007-07-16 00:25:35 -07:00
|
|
|
return im_dirty;
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
on_error:
|
2008-04-11 17:32:30 -07:00
|
|
|
if (im_dirty) _evas_cache_image_entry_delete(cache, im_dirty);
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI Image_Entry *
|
|
|
|
evas_cache_image_alone(Image_Entry *im)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
Evas_Cache_Image *cache;
|
|
|
|
Image_Entry *im_dirty = im;
|
|
|
|
int references;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
cache = im->cache;
|
2010-05-21 00:10:45 -07:00
|
|
|
references = im->references;
|
|
|
|
|
2011-03-14 03:53:37 -07:00
|
|
|
if (references <= 1)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
if (!im->flags.dirty) _evas_cache_image_dirty_add(im);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
im_dirty = evas_cache_image_copied_data(cache, im->w, im->h,
|
|
|
|
evas_cache_image_pixels(im),
|
|
|
|
im->flags.alpha,
|
|
|
|
im->space);
|
2009-05-09 20:06:49 -07:00
|
|
|
if (!im_dirty) goto on_error;
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("dirty-src", im);
|
2012-01-18 15:33:33 -08:00
|
|
|
cache->func.dirty(im_dirty, im);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("dirty-out", im_dirty);
|
2007-07-16 00:25:35 -07:00
|
|
|
im_dirty->references = 1;
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
}
|
|
|
|
return im_dirty;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
on_error:
|
2008-04-11 17:32:30 -07:00
|
|
|
if (im_dirty) _evas_cache_image_entry_delete(cache, im_dirty);
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI Image_Entry *
|
2011-04-20 23:24:27 -07:00
|
|
|
evas_cache_image_copied_data(Evas_Cache_Image *cache,
|
|
|
|
unsigned int w, unsigned int h,
|
|
|
|
DATA32 *image_data, int alpha, int cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
Image_Entry *im;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2007-08-08 16:41:31 -07:00
|
|
|
if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
|
2011-07-21 03:36:05 -07:00
|
|
|
(cspace == EVAS_COLORSPACE_YCBCR422P709_PL) ||
|
|
|
|
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
|
2012-01-30 06:36:15 -08:00
|
|
|
w &= ~0x1;
|
|
|
|
|
2013-05-07 23:37:37 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
2007-07-16 00:25:35 -07:00
|
|
|
if (!im) return NULL;
|
2008-04-11 17:32:30 -07:00
|
|
|
im->space = cspace;
|
2008-06-03 02:09:39 -07:00
|
|
|
im->flags.alpha = alpha;
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_surface_alloc(cache, im, w, h);
|
2007-07-16 00:25:35 -07:00
|
|
|
if (cache->func.copied_data(im, w, h, image_data, alpha, cspace) != 0)
|
|
|
|
{
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2007-07-16 00:25:35 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-04-11 17:32:30 -07:00
|
|
|
im->references = 1;
|
2012-12-19 14:36:13 -08:00
|
|
|
im->flags.loaded = EINA_TRUE;
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("copied-data", im);
|
2008-04-11 17:32:30 -07:00
|
|
|
return im;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI Image_Entry *
|
2010-09-18 16:16:25 -07:00
|
|
|
evas_cache_image_data(Evas_Cache_Image *cache, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, int cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
Image_Entry *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2008-06-10 07:21:06 -07:00
|
|
|
if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
|
2011-07-21 03:36:05 -07:00
|
|
|
(cspace == EVAS_COLORSPACE_YCBCR422P709_PL) ||
|
|
|
|
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
|
2012-01-30 06:36:15 -08:00
|
|
|
w &= ~0x1;
|
|
|
|
|
2013-05-07 23:37:37 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (!im) return NULL;
|
2008-04-11 17:32:30 -07:00
|
|
|
im->w = w;
|
|
|
|
im->h = h;
|
2008-06-03 02:09:39 -07:00
|
|
|
im->flags.alpha = alpha;
|
2007-07-16 00:25:35 -07:00
|
|
|
if (cache->func.data(im, w, h, image_data, alpha, cspace) != 0)
|
|
|
|
{
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2007-07-16 00:25:35 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-04-11 17:32:30 -07:00
|
|
|
im->references = 1;
|
2013-01-09 13:36:03 -08:00
|
|
|
im->flags.loaded = EINA_TRUE;
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("data", im);
|
2008-04-11 17:32:30 -07:00
|
|
|
return im;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI void
|
2010-09-18 16:16:25 -07:00
|
|
|
evas_cache_image_surface_alloc(Image_Entry *im, unsigned int w, unsigned int h)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
Evas_Cache_Image *cache = im->cache;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2008-06-10 02:20:41 -07:00
|
|
|
if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
|
2011-07-21 03:36:05 -07:00
|
|
|
(im->space == EVAS_COLORSPACE_YCBCR422P709_PL) ||
|
|
|
|
(im->space == EVAS_COLORSPACE_YCBCR422601_PL))
|
2008-06-10 02:20:41 -07:00
|
|
|
w &= ~0x1;
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_surface_alloc(cache, im, w, h);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("surface-alloc", im);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Image_Entry *
|
2010-09-18 16:16:25 -07:00
|
|
|
evas_cache_image_size_set(Image_Entry *im, unsigned int w, unsigned int h)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
Evas_Cache_Image *cache;
|
2011-04-20 23:24:27 -07:00
|
|
|
Image_Entry *im2 = NULL;
|
2010-07-31 10:06:55 -07:00
|
|
|
int error;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2008-06-10 02:20:41 -07:00
|
|
|
if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
|
2011-07-21 03:36:05 -07:00
|
|
|
(im->space == EVAS_COLORSPACE_YCBCR422P709_PL) ||
|
|
|
|
(im->space == EVAS_COLORSPACE_YCBCR422601_PL))
|
2008-06-10 02:20:41 -07:00
|
|
|
w &= ~0x1;
|
2011-04-20 23:24:27 -07:00
|
|
|
if ((im->w == w) && (im->h == h)) return im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
cache = im->cache;
|
2013-05-07 23:37:37 -07:00
|
|
|
im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &error);
|
2011-04-20 23:24:27 -07:00
|
|
|
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);
|
2008-04-11 17:32:30 -07:00
|
|
|
if (error != 0) goto on_error;
|
2011-05-15 19:06:41 -07:00
|
|
|
im2->references = 1;
|
2013-01-09 13:36:03 -08:00
|
|
|
im2->flags.loaded = EINA_TRUE;
|
2011-05-15 19:06:41 -07:00
|
|
|
evas_cache_image_drop(im);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("size_set", im2);
|
|
|
|
return im2;
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
on_error:
|
2011-04-20 23:24:27 -07:00
|
|
|
if (im2) _evas_cache_image_entry_delete(cache, im2);
|
2007-07-16 00:25:35 -07:00
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-19 04:19:22 -07:00
|
|
|
EAPI int
|
2008-04-11 17:32:30 -07:00
|
|
|
evas_cache_image_load_data(Image_Entry *im)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2009-12-18 03:03:31 -08:00
|
|
|
Eina_Bool preload = EINA_FALSE;
|
2011-05-19 04:19:22 -07:00
|
|
|
int error = EVAS_LOAD_ERROR_NONE;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2013-04-24 23:05:18 -07:00
|
|
|
if ((im->flags.loaded) && (!im->animated.animated)) return error;
|
2009-12-18 03:03:31 -08:00
|
|
|
if (im->preload)
|
2009-09-22 00:02:14 -07:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
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();
|
2012-10-16 01:57:18 -07:00
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
LKL(wakeup);
|
|
|
|
while (im->preload)
|
|
|
|
{
|
2011-05-09 03:33:21 -07:00
|
|
|
eina_condition_wait(&cond_wakeup);
|
2012-01-30 06:36:15 -08:00
|
|
|
LKU(wakeup);
|
|
|
|
evas_async_events_process();
|
|
|
|
LKL(wakeup);
|
|
|
|
}
|
|
|
|
LKU(wakeup);
|
2009-09-22 00:02:14 -07:00
|
|
|
}
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2013-04-24 23:05:18 -07:00
|
|
|
if ((im->flags.loaded) && (!im->animated.animated)) return error;
|
2012-10-16 01:57:18 -07:00
|
|
|
|
2011-05-01 00:26:42 -07:00
|
|
|
LKL(im->lock);
|
2010-06-04 08:21:12 -07:00
|
|
|
im->flags.in_progress = EINA_TRUE;
|
2011-04-20 23:24:27 -07:00
|
|
|
error = im->cache->func.load(im);
|
2010-06-04 08:21:12 -07:00
|
|
|
im->flags.in_progress = EINA_FALSE;
|
2009-03-13 22:08:08 -07:00
|
|
|
LKU(im->lock);
|
2012-10-16 01:57:18 -07:00
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
im->flags.loaded = 1;
|
2011-04-20 23:24:27 -07:00
|
|
|
if (im->cache->func.debug) im->cache->func.debug("load", im);
|
2009-12-22 15:11:57 -08:00
|
|
|
if (error != EVAS_LOAD_ERROR_NONE)
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_entry_surface_alloc(im->cache, im, im->w, im->h);
|
2008-04-11 17:32:30 -07:00
|
|
|
im->flags.loaded = 0;
|
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
if (preload) _evas_cache_image_async_end(im);
|
2011-05-19 04:19:22 -07:00
|
|
|
return error;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2010-04-12 01:23:53 -07:00
|
|
|
EAPI void
|
|
|
|
evas_cache_image_unload_data(Image_Entry *im)
|
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
if (im->flags.in_progress) return;
|
2010-06-04 08:21:12 -07:00
|
|
|
evas_cache_image_preload_cancel(im, NULL);
|
2012-10-16 01:57:18 -07:00
|
|
|
|
2010-12-14 02:22:06 -08:00
|
|
|
LKL(im->lock_cancel);
|
2011-05-01 06:25:23 -07:00
|
|
|
if (LKT(im->lock) == EINA_FALSE) /* can't get image lock - busy async load */
|
2010-12-14 02:22:06 -08:00
|
|
|
{
|
2013-04-24 23:05:18 -07:00
|
|
|
im->flags.unload_cancel = EINA_TRUE;
|
2010-12-14 02:22:06 -08:00
|
|
|
LKU(im->lock_cancel);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
LKU(im->lock_cancel);
|
2012-10-16 01:57:18 -07:00
|
|
|
|
2013-05-07 23:37:37 -07:00
|
|
|
if ((!im->flags.loaded) || (!im->file && !im->f) || (!im->info.module) ||
|
2011-04-20 23:24:27 -07:00
|
|
|
(im->flags.dirty))
|
2010-04-12 01:23:53 -07:00
|
|
|
{
|
|
|
|
LKU(im->lock);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
2011-04-20 23:24:27 -07:00
|
|
|
im->cache->func.destructor(im);
|
2010-04-12 01:23:53 -07:00
|
|
|
LKU(im->lock);
|
2010-12-24 08:04:27 -08:00
|
|
|
//FIXME: imagedataunload - inform owners
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-11-04 03:51:42 -08:00
|
|
|
_evas_cache_image_unload_cb(EINA_UNUSED const Eina_Hash *hash, EINA_UNUSED const void *key, void *data, EINA_UNUSED void *fdata)
|
2010-04-12 01:23:53 -07:00
|
|
|
{
|
|
|
|
evas_cache_image_unload_data(data);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_unload_all(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
Image_Entry *im;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(cache->lru, im) evas_cache_image_unload_data(im);
|
|
|
|
EINA_INLIST_FOREACH(cache->lru_nodata, im) evas_cache_image_unload_data(im);
|
|
|
|
eina_hash_foreach(cache->activ, _evas_cache_image_unload_cb, NULL);
|
|
|
|
eina_hash_foreach(cache->inactiv, _evas_cache_image_unload_cb, NULL);
|
|
|
|
}
|
|
|
|
|
2010-03-24 12:07:59 -07:00
|
|
|
EAPI Eina_Bool
|
|
|
|
evas_cache_image_is_loaded(Image_Entry *im)
|
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
if (im->flags.loaded) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
2010-03-24 12:07:59 -07:00
|
|
|
}
|
|
|
|
|
2008-09-16 07:52:57 -07:00
|
|
|
EAPI void
|
2013-06-12 23:50:01 -07:00
|
|
|
evas_cache_image_preload_data(Image_Entry *im, const Eo *target,
|
2013-05-30 20:55:14 -07:00
|
|
|
Evas_Engine_Thread_Task_Cb func, const void *engine_data, const void *custom_data)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2010-12-14 02:22:06 -08:00
|
|
|
RGBA_Image *img = (RGBA_Image *)im;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2010-12-14 02:22:06 -08:00
|
|
|
if ((im->flags.loaded) && (img->image.data))
|
2008-12-20 05:39:15 -08:00
|
|
|
{
|
2013-06-12 23:50:01 -07:00
|
|
|
evas_object_inform_call_image_preloaded((Evas_Object*)target);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
2008-12-20 05:39:15 -08:00
|
|
|
}
|
2010-12-14 02:22:06 -08:00
|
|
|
im->flags.loaded = 0;
|
2013-05-30 20:55:14 -07:00
|
|
|
if (!_evas_cache_image_entry_preload_add(im, target, func, engine_data, custom_data))
|
2013-06-12 23:50:01 -07:00
|
|
|
evas_object_inform_call_image_preloaded((Evas_Object*) target);
|
2008-09-16 07:52:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2013-06-12 23:50:01 -07:00
|
|
|
evas_cache_image_preload_cancel(Image_Entry *im, const Eo *target)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2010-08-21 06:52:25 -07:00
|
|
|
if (!target) return;
|
2009-01-20 06:56:37 -08:00
|
|
|
_evas_cache_image_entry_preload_remove(im, target);
|
2008-09-16 07:52:57 -07:00
|
|
|
}
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
#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,
|
2013-05-07 23:37:37 -07:00
|
|
|
im->f ? eina_file_filename_get(im->f) : im->file, im->key);
|
2011-04-20 23:24:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-11-04 03:51:42 -08:00
|
|
|
_dump_cache_active(EINA_UNUSED const Eina_Hash *hash, EINA_UNUSED const void *key, void *data, void *fdata EINA_UNUSED)
|
2011-04-20 23:24:27 -07:00
|
|
|
{
|
|
|
|
Image_Entry *im = data;
|
|
|
|
_dump_img(im, "ACTIVE");
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_dump_cache(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
Image_Entry *im;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
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
|
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
EAPI int
|
|
|
|
evas_cache_image_flush(Evas_Cache_Image *cache)
|
|
|
|
{
|
2010-10-28 03:00:22 -07:00
|
|
|
#ifdef CACHEDUMP
|
2012-01-30 06:36:15 -08:00
|
|
|
_dump_cache(cache);
|
2010-10-28 03:00:22 -07:00
|
|
|
#endif
|
2010-09-18 16:16:25 -07:00
|
|
|
if (cache->limit == (unsigned int)-1) return -1;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2010-09-18 16:16:25 -07:00
|
|
|
while ((cache->lru) && (cache->limit < (unsigned int)cache->usage))
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2009-12-19 22:23:13 -08:00
|
|
|
Image_Entry *im;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2009-12-19 22:23:13 -08:00
|
|
|
im = (Image_Entry *)cache->lru->last;
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
}
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2010-09-18 16:16:25 -07:00
|
|
|
while ((cache->lru_nodata) && (cache->limit < (unsigned int)cache->usage))
|
2008-04-11 17:32:30 -07:00
|
|
|
{
|
2009-12-19 22:23:13 -08:00
|
|
|
Image_Entry *im;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
im = (Image_Entry *) cache->lru_nodata->last;
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_lru_nodata_del(im);
|
2008-04-11 17:32:30 -07:00
|
|
|
cache->func.surface_delete(im);
|
|
|
|
im->flags.loaded = 0;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
return cache->usage;
|
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
EAPI Image_Entry *
|
2007-08-12 22:30:17 -07:00
|
|
|
evas_cache_image_empty(Evas_Cache_Image *cache)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2009-12-19 22:23:13 -08:00
|
|
|
Image_Entry *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2013-05-07 23:37:37 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
2009-12-19 22:23:13 -08:00
|
|
|
if (!im) return NULL;
|
|
|
|
im->references = 1;
|
|
|
|
return im;
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2008-04-11 17:32:30 -07:00
|
|
|
evas_cache_image_colorspace(Image_Entry *im, int cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2009-12-19 22:23:13 -08:00
|
|
|
if (im->space == cspace) return;
|
2008-04-11 17:32:30 -07:00
|
|
|
im->space = cspace;
|
2011-04-20 23:24:27 -07:00
|
|
|
im->cache->func.color_space(im, cspace);
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
2008-05-30 06:33:40 -07:00
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
evas_cache_private_from_image_entry_get(Image_Entry *im)
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
return (void *)im->cache->data;
|
2008-05-30 06:33:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
evas_cache_private_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
|
|
|
return cache->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_private_set(Evas_Cache_Image *cache, const void *data)
|
|
|
|
{
|
2008-12-23 10:14:16 -08:00
|
|
|
cache->data = (void *)data;
|
2008-05-30 06:33:40 -07:00
|
|
|
}
|
2008-06-03 02:09:39 -07:00
|
|
|
|
|
|
|
EAPI DATA32 *
|
|
|
|
evas_cache_image_pixels(Image_Entry *im)
|
|
|
|
{
|
2011-04-20 23:24:27 -07:00
|
|
|
return im->cache->func.surface_pixels(im);
|
2008-06-03 02:09:39 -07:00
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_image_wakeup(void)
|
|
|
|
{
|
2011-05-09 07:42:12 -07:00
|
|
|
if (_evas_cache_mutex_init > 0)
|
|
|
|
eina_condition_broadcast(&cond_wakeup);
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|