{
EVAS_OBJ_IMAGE_SUB_ID_MEMFILE_SET,
EVAS_OBJ_IMAGE_SUB_ID_FILE_SET,
+ EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET,
EVAS_OBJ_IMAGE_SUB_ID_FILE_GET,
EVAS_OBJ_IMAGE_SUB_ID_SOURCE_SET,
EVAS_OBJ_IMAGE_SUB_ID_SOURCE_GET,
#define evas_obj_image_file_set(file, key) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_FILE_SET), EO_TYPECHECK(const char *, file), EO_TYPECHECK(const char*, key)
/**
+ * @def evas_obj_image_mmap_set
+ * @since 1.8
+ *
+ * Set the source mmaped file from where an image object must fetch the real
+ * image data (it may be any Eina_File).
+ *
+ * @param[in] file in
+ * @param[in] key in
+ *
+ * @see evas_obj_image_file_set
+ */
+#define evas_obj_image_mmap_set(f, key) EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET), EO_TYPECHECK(Eina_File *, f), EO_TYPECHECK(const char*, key)
+
+/**
* @def evas_obj_image_file_get
* @since 1.8
*
EAPI void evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key) EINA_ARG_NONNULL(1);
/**
+ * Set the source mmaped file from where an image object must fetch the real
+ * image data (it must be an Eina_File).
+ *
+ * @param obj The given image object.
+ * @param f The mmaped file
+ * @param key The image key in @p file (if its an Eet one), or @c
+ * NULL, otherwise.
+ *
+ * If the file supports multiple data stored in it (as Eet files do),
+ * you can specify the key to be used as the index of the image in
+ * this file.
+ *
+ * @since 1.8
+ */
+EAPI void evas_object_image_mmap_set(Evas_Object *eo_obj, Eina_File *f, const char *key);
+
+/**
* Retrieve the source file from where an image object is to fetch the
* real image data (it may be an Eet file, besides pure image ones).
*
Eina_Inlist *lru_nodata;
Eina_Hash *inactiv;
Eina_Hash *activ;
+
+ Eina_Hash *mmap_activ;
+ Eina_Hash *mmap_inactiv;
+ Eina_Inlist *mmap_lru;
+ Eina_Inlist *mmap_lru_nodata;
+
void *data;
int usage;
{
Evas_Cache_Engine_Image_Func func;
- Eina_Inlist* dirty;
+ Eina_Inlist *dirty;
- Eina_Hash* activ;
- Eina_Hash* inactiv;
- Eina_Inlist* lru;
+ Eina_Hash *activ;
+ Eina_Hash *inactiv;
+ Eina_Inlist *lru;
- Evas_Cache_Image* parent;
- Evas_Cache_Engine_Image* brother;
+ Evas_Cache_Image *parent;
+ Evas_Cache_Engine_Image *brother;
int usage;
int limit;
EAPI Evas_Cache_Image* evas_cache_image_init(const Evas_Cache_Image_Func *cb);
EAPI void evas_cache_image_shutdown(Evas_Cache_Image *cache);
EAPI Image_Entry* evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
+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);
EAPI void evas_cache_image_ref(Image_Entry *im);
EAPI void evas_cache_image_drop(Image_Entry *im);
EAPI void evas_cache_image_data_not_needed(Image_Entry *im);
if (!im->flags.dirty) return;
im->flags.dirty = 0;
im->flags.cached = 0;
- im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
+ im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
}
static void
if (!im->cache_key) return;
im->flags.activ = 1;
im->flags.cached = 1;
- eina_hash_direct_add(im->cache->activ, im->cache_key, im);
+ 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);
}
static void
if (!im->cache_key) return;
im->flags.activ = 0;
im->flags.cached = 0;
- eina_hash_del(im->cache->activ, im->cache_key, im);
+ 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);
}
static void
if (!im->cache_key) return;
im->flags.lru = 1;
im->flags.cached = 1;
- eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
- im->cache->lru = eina_inlist_prepend(im->cache->lru, EINA_INLIST_GET(im));
+ 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));
+ }
im->cache->usage += im->cache->func.mem_size_get(im);
}
if (!im->cache_key) return;
im->flags.lru = 0;
im->flags.cached = 0;
- eina_hash_del(im->cache->inactiv, im->cache_key, im);
- im->cache->lru = eina_inlist_remove(im->cache->lru, EINA_INLIST_GET(im));
+ 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));
+ }
im->cache->usage -= im->cache->func.mem_size_get(im);
}
_evas_cache_image_lru_del(im);
im->flags.lru = 1;
im->flags.cached = 1;
- im->cache->lru_nodata = eina_inlist_prepend(im->cache->lru_nodata, EINA_INLIST_GET(im));
+ 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));
}
static void
if (!im->flags.lru_nodata) return;
im->flags.lru = 0;
im->flags.cached = 0;
- im->cache->lru_nodata = eina_inlist_remove(im->cache->lru_nodata, EINA_INLIST_GET(im));
+ 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));
}
static void
_evas_cache_image_entry_new(Evas_Cache_Image *cache,
const char *hkey,
Image_Timestamp *tstamp,
+ Eina_File *f,
const char *file,
const char *key,
Evas_Image_Load_Opts *lo,
ie->w = -1;
ie->h = -1;
ie->scale = 1;
+ ie->f = f;
+ ie->loader_data = NULL;
+ if (ie->f) ie->flags.given_mmap = EINA_TRUE;
if (file) ie->file = eina_stringshare_add(file);
if (key) ie->key = eina_stringshare_add(key);
if (tstamp) ie->tstamp = *tstamp;
LKI(ie->lock_cancel);
if (lo) ie->load_opts = *lo;
- if (ie->file)
+ if (ie->file || ie->f)
{
*error = cache->func.constructor(ie);
if (*error != EVAS_LOAD_ERROR_NONE)
cache->func = *cb;
cache->inactiv = eina_hash_string_superfast_new(NULL);
cache->activ = eina_hash_string_superfast_new(NULL);
+ cache->mmap_activ = eina_hash_string_superfast_new(NULL);
+ cache->mmap_inactiv = eina_hash_string_superfast_new(NULL);
cache->references = 1;
return cache;
}
}
delete_list = NULL;
eina_hash_foreach(cache->activ, _evas_cache_image_free_cb, &delete_list);
+ eina_hash_foreach(cache->mmap_activ, _evas_cache_image_free_cb, &delete_list);
+ eina_hash_foreach(cache->inactiv, _evas_cache_image_free_cb, &delete_list);
+ eina_hash_foreach(cache->mmap_inactiv, _evas_cache_image_free_cb, &delete_list);
while (delete_list)
{
_evas_cache_image_entry_delete(cache, eina_list_data_get(delete_list));
}
eina_hash_free(cache->activ);
eina_hash_free(cache->inactiv);
+ eina_hash_free(cache->mmap_activ);
+ eina_hash_free(cache->mmap_inactiv);
free(cache);
if (--_evas_cache_mutex_init == 0)
}
}
+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;
+}
+
+
EAPI Image_Entry *
evas_cache_image_request(Evas_Cache_Image *cache, const char *file,
const char *key, Evas_Image_Load_Opts *lo, int *error)
const char *ckey = "(null)";
char *hkey;
Image_Entry *im;
- Evas_Image_Load_Opts prevent;
size_t size;
int stat_done = 0, stat_failed = 0;
size_t file_length;
return NULL;
}
- memset(&prevent, 0, sizeof prevent);
-
/* generate hkey from file+key+load opts */
file_length = strlen(file);
key_length = key ? strlen(key) : 6;
if (key) ckey = key;
memcpy(hkey + size, ckey, key_length);
size += key_length;
- 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)
- ))
- {
- lo = &prevent;
- }
- 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);
-
- if (lo->orientation)
- {
- hkey[size] = '/';
- size += 1;
- hkey[size] = 'o';
- size += 1;
- }
- }
- hkey[size] = '\0';
+ size += _evas_cache_image_loadopts_append(hkey + size, &lo);
/* find image by key in active hash */
im = eina_hash_find(cache->activ, hkey);
if (stat(file, &st) < 0) goto on_stat_error;
}
_timestamp_build(&tstamp, &st);
- im = _evas_cache_image_entry_new(cache, hkey, &tstamp, file, key,
+ im = _evas_cache_image_entry_new(cache, hkey, &tstamp, NULL, file, key,
lo, error);
if (!im) goto on_stat_error;
if (cache->func.debug) cache->func.debug("request", im);
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
w &= ~0x1;
- im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
+ im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->space = cspace;
im->flags.alpha = alpha;
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
w &= ~0x1;
- im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
+ im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->w = w;
im->h = h;
if ((im->w == w) && (im->h == h)) return im;
cache = im->cache;
- im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, &error);
+ im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &error);
if (!im2) goto on_error;
im2->flags.alpha = im->flags.alpha;
}
LKU(im->lock_cancel);
- if ((!im->flags.loaded) || (!im->file) || (!im->info.module) ||
+ if ((!im->flags.loaded) || (!im->file && !im->f) || (!im->info.module) ||
(im->flags.dirty))
{
LKU(im->lock);
im->references,
im->cache->func.mem_size_get(im),
im->w, im->h, im->allocated.w, im->allocated.h,
- im->file, im->key);
+ im->f ? eina_file_filename_get(im->f) : im->file, im->key);
}
static Eina_Bool
{
Image_Entry *im;
- im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
+ im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->references = 1;
return im;
Evas_Map *defmap;
const char *file;
const char *key;
+ Eina_File *f;
int frame;
int spread;
{ 0, 0, 0 }, // image
{ 1.0, 0, 0, 0, 0, 1 }, // border
- NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
0,
EVAS_TEXTURE_REPEAT,
EVAS_COLORSPACE_ARGB8888,
}
}
-EAPI void
-evas_object_image_file_set(Evas_Object *eo_obj, const char *file, const char *key)
-{
- MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
- return;
- MAGIC_CHECK_END();
- eo_do(eo_obj, evas_obj_image_file_set(file, key));
-}
-
static void
-_image_file_set(Eo *eo_obj, void *_pd, va_list *list)
+_image_init_set(Eina_File *f, const char *file, const char *key,
+ Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object_Image *o,
+ Evas_Image_Load_Opts *lo)
{
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
- Evas_Object_Image *o = _pd;
- Evas_Image_Load_Opts lo;
- Eina_Bool resize_call = EINA_FALSE;
-
- const char *file = va_arg(*list, const char*);
- const char *key = va_arg(*list, const char*);
-
- if ((o->pixels->tmpf) && (file != o->pixels->tmpf)) _cleanup_tmpf(eo_obj);
- if ((o->cur->file) && (file) && (!strcmp(o->cur->file, file)))
- {
- if ((!o->cur->key) && (!key))
- return;
- if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
- return;
- }
- /*
- * WTF? why cancel a null image preload? this is just silly (tm)
- if (!o->engine_data)
- obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
- o->engine_data,
- eo_obj);
- */
if (o->cur->source) _proxy_unset(eo_obj, obj, o);
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
{
- if (o->cur->file) eina_stringshare_del(state_write->file);
- if (o->cur->key) eina_stringshare_del(o->cur->key);
- if (file) state_write->file = eina_stringshare_add(file);
- else state_write->file = NULL;
- if (key) state_write->key = eina_stringshare_add(key);
- else state_write->key = NULL;
+ eina_stringshare_replace(&state_write->file, file);
+ eina_stringshare_replace(&state_write->key, key);
+ state_write->f = f;
}
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
{
state_write->file = NULL;
state_write->key = NULL;
+ state_write->f = NULL;
}
EINA_COW_WRITE_END(evas_object_image_state_cow, o->prev, state_write);
-
+
if (o->engine_data)
{
if (o->preloading)
obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output, o->engine_data);
}
o->load_error = EVAS_LOAD_ERROR_NONE;
- lo.scale_down_by = o->load_opts->scale_down_by;
- lo.dpi = o->load_opts->dpi;
- lo.w = o->load_opts->w;
- lo.h = o->load_opts->h;
- lo.region.x = o->load_opts->region.x;
- lo.region.y = o->load_opts->region.y;
- lo.region.w = o->load_opts->region.w;
- lo.region.h = o->load_opts->region.h;
- lo.scale_load.src_x = o->load_opts->scale_load.src_x;
- lo.scale_load.src_y = o->load_opts->scale_load.src_y;
- lo.scale_load.src_w = o->load_opts->scale_load.src_w;
- lo.scale_load.src_h = o->load_opts->scale_load.src_h;
- lo.scale_load.dst_w = o->load_opts->scale_load.dst_w;
- lo.scale_load.dst_h = o->load_opts->scale_load.dst_h;
- lo.scale_load.smooth = o->load_opts->scale_load.smooth;
- lo.scale_load.scale_hint = o->load_opts->scale_load.scale_hint;
- lo.orientation = o->load_opts->orientation;
- o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
- o->cur->file,
- o->cur->key,
- &o->load_error,
- &lo);
+ lo->scale_down_by = o->load_opts->scale_down_by;
+ lo->dpi = o->load_opts->dpi;
+ lo->w = o->load_opts->w;
+ lo->h = o->load_opts->h;
+ lo->region.x = o->load_opts->region.x;
+ lo->region.y = o->load_opts->region.y;
+ lo->region.w = o->load_opts->region.w;
+ lo->region.h = o->load_opts->region.h;
+ lo->scale_load.src_x = o->load_opts->scale_load.src_x;
+ lo->scale_load.src_y = o->load_opts->scale_load.src_y;
+ lo->scale_load.src_w = o->load_opts->scale_load.src_w;
+ lo->scale_load.src_h = o->load_opts->scale_load.src_h;
+ lo->scale_load.dst_w = o->load_opts->scale_load.dst_w;
+ lo->scale_load.dst_h = o->load_opts->scale_load.dst_h;
+ lo->scale_load.smooth = o->load_opts->scale_load.smooth;
+ lo->scale_load.scale_hint = o->load_opts->scale_load.scale_hint;
+ lo->orientation = o->load_opts->orientation;
+}
+
+static void
+_image_done_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object_Image *o)
+{
+ Eina_Bool resize_call = EINA_FALSE;
+
if (o->engine_data)
{
int w, h;
}
EAPI void
+evas_object_image_mmap_set(Evas_Object *eo_obj, Eina_File *f, const char *key)
+{
+ eo_do(eo_obj, evas_obj_image_mmap_set(f, key));
+}
+
+static void
+_image_mmap_set(Eo *eo_obj, void *_pd, va_list *list)
+{
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
+ Evas_Object_Image *o = _pd;
+ Evas_Image_Load_Opts lo;
+
+ Eina_File *f = va_arg(*list, Eina_File *);
+ const char *key = va_arg(*list, const char*);
+
+ if (o->pixels->tmpf) _cleanup_tmpf(eo_obj);
+ if (o->cur->f == f)
+ {
+ if ((!o->cur->key) && (!key))
+ return;
+ if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
+ return;
+ }
+
+ _image_init_set(f, NULL, key, eo_obj, obj, o, &lo);
+ o->engine_data = obj->layer->evas->engine.func->image_mmap(obj->layer->evas->engine.data.output,
+ o->cur->f,
+ o->cur->key,
+ &o->load_error,
+ &lo);
+ _image_done_set(eo_obj, obj, o);
+}
+
+EAPI void
+evas_object_image_file_set(Evas_Object *eo_obj, const char *file, const char *key)
+{
+ MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
+ return;
+ MAGIC_CHECK_END();
+ eo_do(eo_obj, evas_obj_image_file_set(file, key));
+}
+
+static void
+_image_file_set(Eo *eo_obj, void *_pd, va_list *list)
+{
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
+ Evas_Object_Image *o = _pd;
+ Evas_Image_Load_Opts lo;
+
+ const char *file = va_arg(*list, const char*);
+ const char *key = va_arg(*list, const char*);
+
+ if ((o->pixels->tmpf) && (file != o->pixels->tmpf)) _cleanup_tmpf(eo_obj);
+ if ((o->cur->file) && (file) && (!strcmp(o->cur->file, file)))
+ {
+ if ((!o->cur->key) && (!key))
+ return;
+ if ((o->cur->key) && (key) && (!strcmp(o->cur->key, key)))
+ return;
+ }
+ /*
+ * WTF? why cancel a null image preload? this is just silly (tm)
+ if (!o->engine_data)
+ obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+ o->engine_data,
+ eo_obj);
+ */
+ _image_init_set(NULL, file, key, eo_obj, obj, o, &lo);
+ o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
+ o->cur->file,
+ o->cur->key,
+ &o->load_error,
+ &lo);
+ _image_done_set(eo_obj, obj, o);
+}
+
+EAPI void
evas_object_image_file_get(const Evas_Object *eo_obj, const char **file, const char **key)
{
MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DBG_INFO_GET), _dbg_info_get),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_MEMFILE_SET), _image_memfile_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_FILE_SET), _image_file_set),
+ EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET), _image_mmap_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_FILE_GET), _image_file_get),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_SET), _image_source_set),
EO_OP_FUNC(EVAS_OBJ_IMAGE_ID(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_GET), _image_source_get),
static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_MEMFILE_SET, "Sets the data for an image from memory to be loaded"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_FILE_SET, "Set the source file from where an image object must fetch the real"),
+ EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_MMAP_SET, "Set the source mmaped file from where an image object must fetch the real"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_FILE_GET, "Retrieve the source file from where an image object is to fetch the"),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_SET, "Set the source object on an image object to used as a @b proxy."),
EO_OP_DESCRIPTION(EVAS_OBJ_IMAGE_SUB_ID_SOURCE_GET, "Get the current source object of an image object."),
EAPI void evas_common_image_alpha_line_buffer_free (RGBA_Image *im);
EAPI RGBA_Image *evas_common_load_image_from_file (const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
+EAPI RGBA_Image *evas_common_load_image_from_mmap (Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error);
EAPI int evas_common_save_image_to_file (RGBA_Image *im, const char *file, const char *key, int quality, int compress);
EAPI void evas_common_rgba_image_scalecache_init(Image_Entry *ie);
if (evas_image_load_func)
{
Evas_Image_Property property;
+ const char *file;
- if (!ie->f) ie->f = eina_file_open(ie->file, EINA_FALSE);
+ if (!ie->f)
+ {
+ ie->f = eina_file_open(ie->file, EINA_FALSE);
+ file = ie->file;
+ }
+ else
+ {
+ file = eina_file_filename_get(ie->f);
+ }
if (!ie->f)
{
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
(*error == EVAS_LOAD_ERROR_NONE))
{
DBG("loaded file head using module '%s' (%p): %s",
- em->definition->name, em, ie->file);
+ em->definition->name, em, file);
ie->w = property.w;
ie->h = property.h;
evas_module_unload(em);
INF("failed to load file head using module '%s' (%p): "
"%s (%s)",
- em->definition->name, em, ie->file, evas_load_error_str(*error));
+ em->definition->name, em, file, evas_load_error_str(*error));
}
}
else
evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
{
const char *loader = NULL, *end;
+ const char *file;
Evas_Module *em;
- struct stat st;
unsigned int i;
int len, ret = EVAS_LOAD_ERROR_NONE;
struct evas_image_foreach_loader_data fdata;
// }
}
#endif
- if (stat(ie->file, &st) != 0 || S_ISDIR(st.st_mode))
+ if (ie->f)
{
- DBG("trying to open directory '%s' !", ie->file);
- return EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+ len = strlen(eina_file_filename_get(ie->f));
+ end = eina_file_filename_get(ie->f) + len;
+ file = eina_file_filename_get(ie->f);
+ }
+ else
+ {
+ struct stat st;
+
+ if (stat(ie->file, &st) != 0 || S_ISDIR(st.st_mode))
+ {
+ DBG("trying to open directory '%s' !", ie->file);
+ return EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+ }
+
+ len = strlen(ie->file);
+ end = ie->file + len;
+ file = ie->file;
}
- len = strlen(ie->file);
- end = ie->file + len;
for (i = 0; i < (sizeof (loaders) / sizeof(struct ext_loader_s)); i++)
{
int len2 = strlen(loaders[i].extension);
{
loader = loaders[i].loader;
DBG("known loader '%s' handles extension '%s' of file '%s'",
- loader, end - len2, ie->file);
+ loader, end - len2, file);
break;
}
}
DBG("could not find module '%s'", loaders_name[i]);
}
- INF("exhausted all means to load image '%s'", ie->file);
+ INF("exhausted all means to load image '%s'", file);
return EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
- end:
+ end:
if (ret != EVAS_LOAD_ERROR_NONE)
{
WRN("loader '%s' (version %d) "
"handled file '%s', key '%s' with errors: %s",
modname ? modname : "<UNKNOWN>", modversion,
- ie->file, ie->key ? ie->key : "",
+ file, ie->key ? ie->key : "",
evas_load_error_str(ret));
goto end;
}
DBG("loader '%s' used for file %s",
(em && em->definition && em->definition->name) ?
em->definition->name : "<UNKNOWN>",
- ie->file);
+ file);
ie->info.module = (void*) em;
ie->info.loader = (void*) em ? em->functions : NULL;
#ifdef BUILD_PIPE_RENDER
evas_common_pipe_free(im);
#endif
+ if (ie->loader_data)
+ {
+ Evas_Image_Load_Func *evas_image_load_func = NULL;
+
+ evas_image_load_func = ie->info.loader;
+ if (evas_image_load_func)
+ evas_image_load_func->file_close(ie->loader_data);
+ ie->loader_data = NULL;
+ }
evas_common_rgba_image_scalecache_shutdown(&im->cache_entry);
if (ie->info.module) evas_module_unref((Evas_Module *)ie->info.module);
/* memset the image to 0x99 because i recently saw a segv where an
}
}
}
- if (ie->loader_data)
- {
- Evas_Image_Load_Func *evas_image_load_func = NULL;
-
- evas_image_load_func = ie->info.loader;
- if (evas_image_load_func)
- evas_image_load_func->file_close(ie->loader_data);
- }
- if (ie->f) eina_file_close(ie->f);
+ if (ie->f && !ie->flags.given_mmap) eina_file_close(ie->f);
free(im);
}
if (!ie->flags.loaded) return;
if ((!ie->info.module) && (!ie->data1)) return;
- if (!ie->file) return;
+ if (!ie->file && !ie->f) return;
if (ie->references > 0) return;
ie->flags.loaded = 0;
return (RGBA_Image *) evas_cache_image_request(eci, file, key, lo, error);
}
+EAPI RGBA_Image *
+evas_common_load_image_from_mmap(Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error)
+{
+ if (!f)
+ {
+ *error = EVAS_LOAD_ERROR_GENERIC;
+ return NULL;
+ }
+ return (RGBA_Image *) evas_cache_image_mmap_request(eci, f, key, lo, error);
+}
+
EAPI void
evas_common_image_cache_free(void)
{
Eina_Bool pending : 1;
Eina_Bool rotated : 1;
Eina_Bool unload_cancel : 1;
+ Eina_Bool given_mmap : 1;
};
struct _Image_Entry_Frame
void (*polygon_draw) (void *data, void *context, void *surface, void *polygon, int x, int y, Eina_Bool do_async);
void *(*image_load) (void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo);
+ void *(*image_mmap) (void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo);
void *(*image_new_from_data) (void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
void *(*image_new_from_copied_data) (void *data, int w, int h, DATA32 *image_data, int alpha, int cspace);
void (*image_free) (void *data, void *image);
}
static void *
+eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
+{
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+ *error = EVAS_LOAD_ERROR_NONE;
+ eng_window_use(re->win);
+ return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error);
+}
+
+static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
Render_Engine *re;
ORD(polygon_draw);
ORD(image_load);
+ ORD(image_mmap);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);
void evas_gl_common_image_ref(Evas_GL_Image *im);
void evas_gl_common_image_unref(Evas_GL_Image *im);
Evas_GL_Image *evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error);
+Evas_GL_Image *evas_gl_common_image_mmap(Evas_Engine_GL_Context *gc, Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error);
Evas_GL_Image *evas_gl_common_image_new_from_data(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, int cspace);
Evas_GL_Image *evas_gl_common_image_new_from_copied_data(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, int cspace);
Evas_GL_Image *evas_gl_common_image_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha, int cspace);
}
}
-Evas_GL_Image *
-evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error)
+static Evas_GL_Image *
+_evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_Load_Opts *lo, int *error)
{
- Evas_GL_Image *im;
- RGBA_Image *im_im;
- Eina_List *l;
-
- im_im = evas_common_load_image_from_file(file, key, lo, error);
- if (!im_im) return NULL;
+ Evas_GL_Image *im;
+ Eina_List *l;
/* i'd LOVe to do this, but we can't because we load to load header
* to get image size to know if its too big or not! so this disallows
im->h = im->im->cache_entry.h;
if (lo) im->load_opts = *lo;
gc->shared->images = eina_list_prepend(gc->shared->images, im);
- return im;
+ return im;
+}
+
+Evas_GL_Image *
+evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const char *key, Evas_Image_Load_Opts *lo, int *error)
+{
+ RGBA_Image *im_im;
+
+ im_im = evas_common_load_image_from_file(file, key, lo, error);
+ if (!im_im) return NULL;
+
+ return _evas_gl_common_image(gc, im_im, lo, error);
+}
+
+Evas_GL_Image *
+evas_gl_common_image_mmap(Evas_Engine_GL_Context *gc, Eina_File *f, const char *key, Evas_Image_Load_Opts *lo, int *error)
+{
+ RGBA_Image *im_im;
+
+ im_im = evas_common_load_image_from_mmap(f, key, lo, error);
+ if (!im_im) return NULL;
+
+ return _evas_gl_common_image(gc, im_im, lo, error);
}
Evas_GL_Image *
}
static void *
+eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
+{
+ Render_Engine *re = data;
+
+ *error = EVAS_LOAD_ERROR_NONE;
+ return evas_gl_common_image_mmap(re->gl_context, f, key, lo, error);
+}
+
+static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
Render_Engine *re = data;
ORD(polygon_draw);
ORD(image_load);
+ ORD(image_mmap);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);
}
static void *
+eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
+{
+ Render_Engine *re;
+
+ re = (Render_Engine *)data;
+ *error = EVAS_LOAD_ERROR_NONE;
+ eng_window_use(re->win);
+ return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error);
+}
+
+static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
Render_Engine *re;
ORD(polygon_draw);
ORD(image_load);
+ ORD(image_mmap);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);
}
static void *
+eng_image_mmap(void *data EINA_UNUSED, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo)
+{
+ *error = EVAS_LOAD_ERROR_NONE;
+#ifdef EVAS_CSERVE2
+ // FIXME: Need to pass fd to make that useful, so just get the filename for now.
+ if (evas_cserve2_use_get())
+ {
+ Image_Entry *ie;
+ ie = evas_cache2_image_open(evas_common_image_cache2_get(),
+ eina_file_filename_get(f), key, lo, error);
+ if (ie)
+ evas_cache2_image_open_wait(ie);
+
+ return ie;
+ }
+#endif
+ return evas_common_load_image_from_mmap(f, key, lo, error);
+}
+
+static void *
eng_image_new_from_data(void *data EINA_UNUSED, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
#ifdef EVAS_CSERVE2
eng_polygon_draw,
/* image draw funcs */
eng_image_load,
+ eng_image_mmap,
eng_image_new_from_data,
eng_image_new_from_copied_data,
eng_image_free,