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
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
static SLK(engine_lock);
|
2011-05-02 04:28:47 -07:00
|
|
|
static int _evas_cache_mutex_init = 0;
|
2008-09-16 07:52:57 -07:00
|
|
|
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
static void _evas_cache_image_entry_preload_remove(Image_Entry *ie, const Eo *target, Eina_Bool force);
|
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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
_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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
im->flags.dirty = 0;
|
|
|
|
im->flags.cached = 0;
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
_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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_dirty_del(im);
|
|
|
|
_evas_cache_image_activ_del(im);
|
2017-03-08 18:18:32 -08:00
|
|
|
_evas_cache_image_lru_nodata_del(im);
|
2011-04-20 23:24:27 -07:00
|
|
|
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)
|
2017-03-08 18:18:32 -08:00
|
|
|
eina_hash_direct_add(im->cache->mmap_inactiv, im->cache_key, im);
|
2013-05-07 23:37:37 -07:00
|
|
|
else
|
2017-03-08 18:18:32 -08:00
|
|
|
eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
|
2013-06-24 19:42:14 -07:00
|
|
|
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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
im->flags.lru = 0;
|
|
|
|
im->flags.cached = 0;
|
2013-05-07 23:37:37 -07:00
|
|
|
if (im->flags.given_mmap)
|
2017-03-08 18:18:32 -08:00
|
|
|
eina_hash_del(im->cache->mmap_inactiv, im->cache_key, im);
|
2013-05-07 23:37:37 -07:00
|
|
|
else
|
2017-03-08 18:18:32 -08:00
|
|
|
eina_hash_del(im->cache->inactiv, im->cache_key, im);
|
2013-06-24 19:42:14 -07:00
|
|
|
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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
_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-06-24 19:42:14 -07:00
|
|
|
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;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
im->flags.lru = 0;
|
|
|
|
im->flags.cached = 0;
|
2013-06-24 19:42:14 -07:00
|
|
|
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)
|
|
|
|
{
|
2010-07-31 10:06:55 -07:00
|
|
|
if (!ie) return;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!ie->cache) 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 image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
_evas_cache_image_entry_preload_remove(ie, NULL, EINA_TRUE);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
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
|
|
|
|
2018-09-21 00:32:07 -07:00
|
|
|
if ((cache) && (cache->func.destructor)) 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);
|
2019-08-05 10:51:36 -07:00
|
|
|
if (ie->f && ie->flags.given_mmap)
|
|
|
|
{
|
|
|
|
eina_file_close(ie->f);
|
|
|
|
ie->f = NULL;
|
|
|
|
}
|
2009-11-30 05:26:46 -08:00
|
|
|
ie->cache = NULL;
|
2018-09-21 00:32:07 -07:00
|
|
|
if ((cache) && (cache->func.surface_delete)) cache->func.surface_delete(ie);
|
2008-12-23 15:07:48 -08:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKD(ie->lock);
|
|
|
|
SLKD(ie->lock_cancel);
|
2018-09-21 00:32:07 -07:00
|
|
|
if ((cache) && (cache->func.dealloc)) cache->func.dealloc(ie);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
2017-10-11 06:17:35 -07:00
|
|
|
#if 0
|
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
|
|
|
}
|
2017-10-11 06:17:35 -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;
|
|
|
|
|
2016-08-31 19:17:08 -07:00
|
|
|
if (!cache)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-04-11 17:32:30 -07:00
|
|
|
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-06-24 19:42:14 -07:00
|
|
|
ie->f = eina_file_dup(f);
|
2013-05-07 23:37:37 -07:00
|
|
|
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
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKI(ie->lock);
|
|
|
|
SLKI(ie->lock_cancel);
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2017-01-01 05:15:24 -08: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;
|
2017-01-05 16:37:40 -08:00
|
|
|
if ((cache->func.surface_alloc(ie, wmin, hmin)) || (ie->load_failed))
|
2008-12-26 04:50:55 -08:00
|
|
|
{
|
|
|
|
wmin = 0;
|
|
|
|
hmin = 0;
|
|
|
|
}
|
|
|
|
ie->w = wmin;
|
|
|
|
ie->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;
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKL(engine_lock);
|
2008-12-26 04:50:55 -08:00
|
|
|
_evas_cache_image_entry_surface_alloc__locked(cache, ie, wmin, hmin);
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKU(engine_lock);
|
2008-04-11 17:32:30 -07:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:44:05 -08:00
|
|
|
static Eina_Bool
|
|
|
|
evas_cache_image_cancelled(void *data)
|
|
|
|
{
|
|
|
|
Image_Entry *current = data;
|
2017-03-08 18:18:32 -08:00
|
|
|
Eina_Bool ret;
|
2016-12-06 11:44:05 -08:00
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(current);
|
|
|
|
ret = evas_preload_thread_cancelled_is(current->preload);
|
|
|
|
evas_cache_image_drop(current);
|
|
|
|
return ret;
|
2016-12-06 11:44:05 -08: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;
|
|
|
|
int error;
|
|
|
|
int pchannel;
|
|
|
|
|
2017-03-07 02:42:20 -08:00
|
|
|
eina_thread_name_set(eina_thread_self(), "Evas-preload");
|
|
|
|
|
2009-12-18 03:03:31 -08:00
|
|
|
current = data;
|
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!current->cache) return;
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKL(current->lock);
|
2009-12-18 03:03:31 -08:00
|
|
|
pchannel = current->channel;
|
|
|
|
current->channel++;
|
|
|
|
cache = current->cache;
|
|
|
|
|
2013-06-03 19:17:21 -07:00
|
|
|
if ((!current->flags.loaded) &&
|
2018-10-09 05:00:01 -07:00
|
|
|
(current->info.loader) &&
|
|
|
|
(current->info.loader->threadable))
|
2009-12-18 03:03:31 -08:00
|
|
|
{
|
2016-12-06 11:44:05 -08:00
|
|
|
evas_module_task_register(evas_cache_image_cancelled, current);
|
2012-01-30 06:36:15 -08:00
|
|
|
error = cache->func.load(current);
|
2016-12-06 11:44:05 -08:00
|
|
|
evas_module_task_unregister();
|
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
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);
|
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
|
|
|
current->channel = pchannel;
|
2010-12-14 02:22:06 -08:00
|
|
|
// check the unload cancel flag
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKL(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;
|
|
|
|
}
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKU(current->lock_cancel);
|
|
|
|
SLKU(current->lock);
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-08-23 11:24:11 -07:00
|
|
|
_evas_cache_image_preloaded_notify(Image_Entry *ie)
|
2009-01-20 06:56:37 -08:00
|
|
|
{
|
2009-12-18 03:03:31 -08:00
|
|
|
Evas_Cache_Target *tmp;
|
|
|
|
|
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
|
|
|
ie->targets = (Evas_Cache_Target *)
|
2017-01-01 05:15:24 -08:00
|
|
|
eina_inlist_remove(EINA_INLIST_GET(ie->targets),
|
|
|
|
EINA_INLIST_GET(ie->targets));
|
2018-08-29 21:26:06 -07:00
|
|
|
if (!tmp->delete_me && tmp->preloaded_cb)
|
|
|
|
tmp->preloaded_cb(tmp->preloaded_data);
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
if (!tmp->preload_cancel)
|
|
|
|
evas_object_inform_call_image_preloaded((Eo*) tmp->target);
|
2012-01-30 06:36:15 -08:00
|
|
|
free(tmp);
|
2009-01-20 06:56:37 -08:00
|
|
|
}
|
2017-08-23 11:24:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_cache_image_async_end(void *data)
|
|
|
|
{
|
|
|
|
Image_Entry *ie = (Image_Entry *)data;
|
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!ie->cache) return;
|
2017-08-23 11:24:11 -07:00
|
|
|
evas_cache_image_ref(ie);
|
|
|
|
ie->cache->preload = eina_list_remove(ie->cache->preload, ie);
|
|
|
|
ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
|
|
|
|
ie->preload = NULL;
|
|
|
|
ie->flags.preload_done = ie->flags.loaded;
|
|
|
|
ie->flags.updated_data = 1;
|
|
|
|
ie->flags.preload_pending = 0;
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
ie->flags.loaded = EINA_TRUE;
|
2017-08-23 11:24:11 -07:00
|
|
|
|
|
|
|
_evas_cache_image_preloaded_notify(ie);
|
2017-01-05 16:37:40 -08:00
|
|
|
evas_cache_image_drop(ie);
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!ie->cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(ie);
|
2009-12-18 03:03:31 -08:00
|
|
|
ie->preload = NULL;
|
|
|
|
ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
|
2016-03-15 11:57:19 -07:00
|
|
|
|
|
|
|
ie->flags.preload_pending = 0;
|
|
|
|
|
2011-04-20 23:24:27 -07:00
|
|
|
if ((ie->flags.delete_me) || (ie->flags.dirty))
|
2009-12-18 03:03:31 -08:00
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2017-04-09 18:40:52 -07:00
|
|
|
ie->flags.delete_me = 0;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2017-04-09 18:40:52 -07:00
|
|
|
evas_cache_image_drop(ie);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2017-01-30 21:47:36 -08:00
|
|
|
if (ie->references == 0)
|
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2017-01-30 21:47:36 -08:00
|
|
|
_evas_cache_image_lru_add(ie);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2017-01-30 21:47:36 -08:00
|
|
|
cache = ie->cache;
|
|
|
|
}
|
|
|
|
if (ie->flags.loaded) _evas_cache_image_async_end(ie);
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
//On Cancelling, they need to draw image directly.
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (ie->targets)
|
|
|
|
{
|
|
|
|
Evas_Cache_Target *tg = ie->targets;
|
|
|
|
ie->targets = (Evas_Cache_Target *)
|
|
|
|
eina_inlist_remove(EINA_INLIST_GET(ie->targets),
|
|
|
|
EINA_INLIST_GET(tg));
|
|
|
|
//FIXME: What/When they properly get a notification? Call in advance for compatibility.
|
|
|
|
evas_object_inform_call_image_preloaded((Eo*) tg->target);
|
|
|
|
free(tg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(ie);
|
2017-01-30 21:47:36 -08: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
|
2018-08-29 21:26:06 -07:00
|
|
|
_evas_cache_image_entry_preload_add(Image_Entry *ie, const Eo *target, void (*preloaded_cb)(void *), void *preloaded_data)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2009-01-19 06:06:09 -08:00
|
|
|
Evas_Cache_Target *tg;
|
2008-09-16 07:52:57 -07:00
|
|
|
|
2018-03-05 06:29:37 -08:00
|
|
|
if (!ie->cache) return 0;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(ie);
|
|
|
|
if (ie->flags.preload_done)
|
|
|
|
{
|
|
|
|
evas_cache_image_drop(ie);
|
|
|
|
return 0;
|
|
|
|
}
|
2011-05-02 20:20:02 -07:00
|
|
|
|
2017-01-01 05:15:24 -08:00
|
|
|
tg = calloc(1, sizeof(Evas_Cache_Target));
|
2018-10-10 21:54:40 -07:00
|
|
|
if (!tg)
|
|
|
|
{
|
|
|
|
evas_cache_image_drop(ie);
|
|
|
|
return 0;
|
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
tg->target = target;
|
2018-08-29 21:26:06 -07:00
|
|
|
tg->preloaded_cb = preloaded_cb;
|
|
|
|
tg->preloaded_data = preloaded_data;
|
2013-05-30 20:55:14 -07:00
|
|
|
|
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
|
|
|
|
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;
|
2016-03-15 11:57:19 -07:00
|
|
|
ie->flags.preload_pending = 1;
|
2009-12-19 22:23:13 -08:00
|
|
|
ie->preload = evas_preload_thread_run(_evas_cache_image_async_heavy,
|
|
|
|
_evas_cache_image_async_end,
|
|
|
|
_evas_cache_image_async_cancel,
|
|
|
|
ie);
|
|
|
|
}
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(ie);
|
2009-12-18 03:03:31 -08:00
|
|
|
return 1;
|
2008-09-16 07:52:57 -07:00
|
|
|
}
|
|
|
|
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
/* force: remove preload forcely. If one object cancel preload and draw image direcltly,
|
|
|
|
* all other targets of that preload will be affected this as well. */
|
2009-12-18 03:03:31 -08:00
|
|
|
static void
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
_evas_cache_image_entry_preload_remove(Image_Entry *ie, const Eo *target, Eina_Bool force)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2013-05-30 20:55:14 -07:00
|
|
|
Evas_Cache_Target *tg;
|
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!ie->cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
// evas_cache_image_ref(ie);
|
2009-11-05 09:38:51 -08:00
|
|
|
if (target)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2012-01-30 06:36:15 -08:00
|
|
|
EINA_INLIST_FOREACH(ie->targets, tg)
|
|
|
|
{
|
|
|
|
if (tg->target == target)
|
|
|
|
{
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
tg->preload_cancel = EINA_TRUE;
|
2012-01-30 06:36:15 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
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);
|
|
|
|
}
|
2009-09-22 00:02:14 -07:00
|
|
|
}
|
|
|
|
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
if ((!ie->targets || force) && (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
|
|
|
}
|
2017-03-08 18:18:32 -08:00
|
|
|
// evas_cache_image_drop(ie);
|
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)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return 0;
|
2007-07-16 00:25:35 -07:00
|
|
|
return cache->usage;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_cache_image_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return 0;
|
2007-07-16 00:25:35 -07:00
|
|
|
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
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return;
|
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)
|
|
|
|
{
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKI(engine_lock);
|
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 image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
_evas_cache_image_entry_preload_remove(im, NULL, EINA_TRUE);
|
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
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
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);
|
|
|
|
|
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;
|
2017-03-08 18:18:32 -08:00
|
|
|
|
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
|
|
|
}
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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)
|
|
|
|
{
|
2017-02-02 10:29:59 -08:00
|
|
|
im = eina_list_data_get(cache->pending);
|
|
|
|
evas_preload_thread_cancel(im->preload);
|
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
evas_async_events_process();
|
2017-02-02 10:29:59 -08:00
|
|
|
if (!evas_preload_pthread_wait(im->preload, 1.0))
|
|
|
|
{
|
|
|
|
// We have waited long enough without reaction from that said
|
|
|
|
// thread, remove it from pending list and silently continue
|
|
|
|
// in the hope of an ok shutdown (but something is wrong).
|
|
|
|
cache->pending = eina_list_remove_list(cache->pending, cache->pending);
|
|
|
|
ERR("Could not stop decoding '%s' during shutdown.\n", im->file);
|
|
|
|
}
|
2009-12-18 03:03:31 -08:00
|
|
|
}
|
2017-02-02 10:29:59 -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)
|
|
|
|
{
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKD(engine_lock);
|
2011-05-02 04:28:47 -07:00
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
}
|
|
|
|
|
2013-05-07 23:37:37 -07:00
|
|
|
static const Evas_Image_Load_Opts prevent = {
|
2017-01-01 05:15:24 -08:00
|
|
|
{
|
|
|
|
{ 0, 0, 0, 0 },
|
|
|
|
{
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
},
|
|
|
|
0.0,
|
|
|
|
0, 0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
|
|
|
|
EINA_FALSE
|
|
|
|
},
|
|
|
|
EINA_FALSE
|
2013-05-07 23:37:37 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
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 &&
|
2017-01-01 05:15:24 -08:00
|
|
|
(lo->emile.scale_down_by == 0) &&
|
2017-01-06 09:57:46 -08:00
|
|
|
(EINA_DBL_EQ(lo->emile.dpi, 0.0)) &&
|
2017-01-01 05:15:24 -08:00
|
|
|
((lo->emile.w == 0) || (lo->emile.h == 0)) &&
|
|
|
|
((lo->emile.region.w == 0) || (lo->emile.region.h == 0)) &&
|
|
|
|
(lo->emile.orientation == 0)
|
2013-05-07 23:37:37 -07:00
|
|
|
))
|
|
|
|
{
|
|
|
|
*plo = (Evas_Image_Load_Opts*) &prevent;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(hkey, "//@/", 4);
|
|
|
|
offset += 4;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.scale_down_by, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_dtoa(lo->emile.dpi, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.w, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = 'x';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.h, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = '/';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.region.x, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = '+';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.region.y, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = '.';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.region.w, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
hkey[offset] = 'x';
|
|
|
|
offset += 1;
|
2017-01-01 05:15:24 -08:00
|
|
|
offset += eina_convert_xtoa(lo->emile.region.h, hkey + offset);
|
2013-05-07 23:37:37 -07:00
|
|
|
|
2017-01-01 05:15:24 -08:00
|
|
|
if (lo->emile.orientation)
|
2013-05-07 23:37:37 -07:00
|
|
|
{
|
|
|
|
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
|
2014-08-14 02:44:46 -07:00
|
|
|
if (!f)
|
2013-05-07 23:37:37 -07:00
|
|
|
{
|
|
|
|
*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 */
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2013-05-07 23:37:37 -07:00
|
|
|
im = eina_hash_find(cache->mmap_activ, hkey);
|
2018-08-22 22:56:58 -07:00
|
|
|
if (im)
|
2017-01-05 16:37:40 -08:00
|
|
|
{
|
2018-08-22 22:56:58 -07:00
|
|
|
if (im->f != f)
|
|
|
|
{
|
|
|
|
/* as active cache find - if we match in lru and its invalid, dirty */
|
|
|
|
_evas_cache_image_dirty_add(im);
|
|
|
|
/* this image never used, so it have to be deleted */
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
im = NULL;
|
|
|
|
}
|
|
|
|
else if (!im->load_failed) goto on_ok;
|
|
|
|
else if (im->load_failed)
|
|
|
|
{
|
|
|
|
_evas_cache_image_dirty_add(im);
|
|
|
|
im = NULL;
|
|
|
|
}
|
2017-01-05 16:37:40 -08:00
|
|
|
}
|
2013-05-07 23:37:37 -07:00
|
|
|
|
|
|
|
/* find image by key in inactive/lru hash */
|
|
|
|
im = eina_hash_find(cache->mmap_inactiv, hkey);
|
2018-08-22 22:56:58 -07:00
|
|
|
if (im)
|
2017-01-05 16:37:40 -08:00
|
|
|
{
|
2018-08-22 22:56:58 -07:00
|
|
|
if (im->f != f)
|
|
|
|
{
|
|
|
|
/* as active cache find - if we match in lru and its invalid, dirty */
|
|
|
|
_evas_cache_image_dirty_add(im);
|
|
|
|
/* this image never used, so it have to be deleted */
|
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
|
|
|
im = NULL;
|
|
|
|
}
|
|
|
|
else if (!im->load_failed)
|
|
|
|
{
|
|
|
|
_evas_cache_image_lru_del(im);
|
|
|
|
_evas_cache_image_activ_add(im);
|
|
|
|
goto on_ok;
|
|
|
|
}
|
2017-01-05 16:37:40 -08:00
|
|
|
}
|
2013-05-07 23:37:37 -07:00
|
|
|
|
|
|
|
im = _evas_cache_image_entry_new(cache, hkey, NULL, f, NULL, key, lo, error);
|
2017-03-08 18:18:32 -08:00
|
|
|
if (!im)
|
|
|
|
{
|
|
|
|
SLKU(engine_lock);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-05-07 23:37:37 -07:00
|
|
|
|
|
|
|
on_ok:
|
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
|
|
|
im->references++;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2013-05-07 23:37:37 -07:00
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:22:47 -08:00
|
|
|
EAPI void
|
|
|
|
evas_cache_image_ref(Image_Entry *im)
|
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2012-12-18 08:22:47 -08:00
|
|
|
im->references++;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2012-12-18 08:22:47 -08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
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;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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)
|
|
|
|
{
|
2018-10-10 21:54:40 -07:00
|
|
|
SLKL(engine_lock);
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
_evas_cache_image_entry_preload_remove(im, NULL, EINA_TRUE);
|
2018-10-10 21:54:40 -07:00
|
|
|
SLKU(engine_lock);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
|
|
|
}
|
2017-01-05 16:37:40 -08:00
|
|
|
if ((im->flags.dirty) || (im->load_failed))
|
2012-01-30 06:36:15 -08:00
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2012-01-30 06:36:15 -08:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
|
|
|
}
|
2016-07-02 23:43:04 -07:00
|
|
|
if (cache)
|
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2016-07-02 23:43:04 -07:00
|
|
|
_evas_cache_image_lru_add(im);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2016-07-02 23:43:04 -07:00
|
|
|
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;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_lru_nodata_add(im);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return NULL;
|
2008-04-11 17:32:30 -07:00
|
|
|
cache = im->cache;
|
|
|
|
if (!(im->flags.dirty))
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2015-11-10 18:35:49 -08:00
|
|
|
if (im->references == 1) im_dirty = im;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2011-04-20 23:24:27 -07:00
|
|
|
_evas_cache_image_dirty_add(im_dirty);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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:
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return NULL;
|
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
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (!im->flags.dirty) _evas_cache_image_dirty_add(im);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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:
|
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,
|
2014-04-08 01:19:38 -07:00
|
|
|
DATA32 *image_data, int alpha,
|
|
|
|
Evas_Colorspace cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2016-09-22 04:45:04 -07:00
|
|
|
int err;
|
2010-07-31 10:06:55 -07:00
|
|
|
Image_Entry *im;
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return NULL;
|
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;
|
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2016-09-22 04:45:04 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &err);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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)
|
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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 *
|
2014-04-08 01:19:38 -07:00
|
|
|
evas_cache_image_data(Evas_Cache_Image *cache, unsigned int w, unsigned int h,
|
|
|
|
DATA32 *image_data, int alpha, Evas_Colorspace cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2016-09-22 04:45:04 -07:00
|
|
|
int err;
|
2010-07-31 10:06:55 -07:00
|
|
|
Image_Entry *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return NULL;
|
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;
|
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2016-09-22 04:45:04 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &err);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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)
|
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2008-04-11 17:32:30 -07:00
|
|
|
_evas_cache_image_entry_delete(cache, im);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return im;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
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;
|
2017-03-08 18:18:32 -08:00
|
|
|
if ((im->w == w) && (im->h == h))
|
|
|
|
{
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return im;
|
|
|
|
}
|
2007-07-16 00:25:35 -07:00
|
|
|
|
|
|
|
cache = im->cache;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2013-05-07 23:37:37 -07:00
|
|
|
im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &error);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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-04-20 23:24:27 -07:00
|
|
|
if (cache->func.debug) cache->func.debug("size_set", im2);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
2011-04-20 23:24:27 -07:00
|
|
|
return im2;
|
2008-04-11 17:32:30 -07:00
|
|
|
|
2012-01-30 06:36:15 -08:00
|
|
|
on_error:
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2011-04-20 23:24:27 -07:00
|
|
|
if (im2) _evas_cache_image_entry_delete(cache, im2);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
|
|
|
evas_cache_image_drop(im);
|
2007-07-16 00:25:35 -07:00
|
|
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return error;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
|
|
|
if ((im->flags.loaded) && (!im->animated.animated))
|
|
|
|
{
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return error;
|
|
|
|
}
|
2015-07-07 05:29:31 -07:00
|
|
|
evas_common_rgba_pending_unloads_remove(im);
|
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();
|
2016-12-07 11:17:01 -08:00
|
|
|
evas_preload_pthread_wait(im->preload, 0.01);
|
|
|
|
|
2016-03-15 11:57:19 -07:00
|
|
|
while (im->flags.preload_pending)
|
2012-01-30 06:36:15 -08:00
|
|
|
{
|
|
|
|
evas_async_events_process();
|
2017-02-02 10:29:59 -08:00
|
|
|
evas_preload_pthread_wait(im->preload, 0.1);
|
2012-01-30 06:36:15 -08:00
|
|
|
}
|
2009-09-22 00:02:14 -07:00
|
|
|
}
|
2012-01-30 06:36:15 -08:00
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
if ((im->flags.loaded) && (!im->animated.animated))
|
|
|
|
{
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return error;
|
|
|
|
}
|
2017-02-02 10:29:59 -08:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKL(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;
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKU(im->lock);
|
2017-02-02 10:29:59 -08: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);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(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)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
|
|
|
if (im->flags.in_progress)
|
|
|
|
{
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return;
|
|
|
|
}
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
evas_cache_image_preload_cancel(im, NULL, EINA_TRUE);
|
2017-03-08 18:18:32 -08:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
if (SLKT(im->lock) == EINA_FALSE) /* can't get image lock - busy async load */
|
2010-12-14 02:22:06 -08:00
|
|
|
{
|
2014-08-14 02:03:07 -07:00
|
|
|
SLKL(im->lock_cancel);
|
2013-04-24 23:05:18 -07:00
|
|
|
im->flags.unload_cancel = EINA_TRUE;
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKU(im->lock_cancel);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
2010-12-14 02:22:06 -08:00
|
|
|
return;
|
|
|
|
}
|
2012-10-16 01:57:18 -07:00
|
|
|
|
2014-08-14 02:03:07 -07:00
|
|
|
SLKL(im->lock_cancel);
|
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
|
|
|
{
|
2014-08-14 02:03:07 -07:00
|
|
|
SLKU(im->lock_cancel);
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKU(im->lock);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
2012-01-30 06:36:15 -08:00
|
|
|
return;
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
2014-08-14 02:03:07 -07:00
|
|
|
SLKU(im->lock_cancel);
|
2011-04-20 23:24:27 -07:00
|
|
|
im->cache->func.destructor(im);
|
2013-10-10 01:44:24 -07:00
|
|
|
SLKU(im->lock);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
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;
|
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
// _evas_cache_image_unload_cb -> evas_cache_image_unload_data -> evas_cache_image_ref
|
|
|
|
// deadlock
|
|
|
|
////// SLKL(engine_lock);
|
2010-04-12 01:23:53 -07:00
|
|
|
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);
|
2017-03-08 18:18:32 -08:00
|
|
|
////// SLKU(engine_lock);
|
2010-04-12 01:23:53 -07:00
|
|
|
}
|
|
|
|
|
2013-08-28 00:43:58 -07:00
|
|
|
static int async_frozen = 0;
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_cache_async_frozen_get(void)
|
|
|
|
{
|
|
|
|
return async_frozen;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_async_freeze(void)
|
|
|
|
{
|
|
|
|
async_frozen++;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_async_thaw(void)
|
|
|
|
{
|
|
|
|
async_frozen--;
|
|
|
|
}
|
|
|
|
|
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
|
2018-08-29 21:26:06 -07:00
|
|
|
evas_cache_image_preload_data(Image_Entry *im, const Eo *target, void (*preloaded_cb)(void *), void *preloaded_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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
2017-01-05 23:35:09 -08:00
|
|
|
if (((int)im->w > 0) && ((int)im->h > 0) &&
|
|
|
|
(((im->flags.loaded) && (img->image.data)) ||
|
|
|
|
(im->flags.textured && !im->flags.updated_data)))
|
2008-12-20 05:39:15 -08:00
|
|
|
{
|
2017-08-23 11:24:11 -07:00
|
|
|
_evas_cache_image_preloaded_notify(im);
|
2013-06-12 23:50:01 -07:00
|
|
|
evas_object_inform_call_image_preloaded((Evas_Object*)target);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
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;
|
2018-08-29 21:26:06 -07:00
|
|
|
if (!_evas_cache_image_entry_preload_add(im, target, preloaded_cb, preloaded_data))
|
2013-06-12 23:50:01 -07:00
|
|
|
evas_object_inform_call_image_preloaded((Evas_Object*) target);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
2008-09-16 07:52:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
evas_cache_image_preload_cancel(Image_Entry *im, const Eo *target, Eina_Bool force)
|
2008-09-16 07:52:57 -07:00
|
|
|
{
|
2010-08-21 06:52:25 -07:00
|
|
|
if (!target) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
evas image: fix a bug in image preloading.
Summary:
Current preloading is too buggy since it's on thread-based.
This is a fundamental improvement to fix a bug.
The critical issue here is,
When preloading img object suddenly cancel its preloading,
the object possibly cannot render image next then because
renderer doesn't have any idea when async cancelling is
finished. Renderer just tries to render regardless of
image loading status, and this could occur no-texture(in gl case)
image object.
So, here improvement is, adding a notification for async cancelled
so that putting img objects to redraw images properly after their preloading is
cancelled.
The best scenario to reproduce this bug is this one.
Evas_Object *img2 = evas_object_image_filled_add(evas);
evas_object_image_file_set(img2, "test.jpg", NULL);
evas_object_image_preload(img2, EINA_FALSE);
evas_object_resize(img2, 200, 200);
evas_object_show(img2);
Evas_Object *img = evas_object_image_filled_add(evas);
evas_object_image_file_set(img, "test.jpg", NULL);
evas_object_image_preload(img, EINA_FALSE);
evas_object_move(img, 200, 200);
evas_object_resize(img, 200, 200);
evas_object_show(img);
evas_object_image_preload(img2, EINA_TRUE);
If you run this on gl backend, occasionally happens rendering fail.
Yet there other bugs on preloading feature....
@fix
Reviewers: #committers, raster
Subscribers: cedric, #reviewers, #committers, zmike
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6919
2018-09-02 23:19:02 -07:00
|
|
|
_evas_cache_image_entry_preload_remove(im, target, force);
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_drop(im);
|
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)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2011-04-20 23:24:27 -07:00
|
|
|
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
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return;
|
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;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2011-04-20 23:24:27 -07:00
|
|
|
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);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
2011-04-20 23:24:27 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-07-16 00:25:35 -07:00
|
|
|
EAPI int
|
|
|
|
evas_cache_image_flush(Evas_Cache_Image *cache)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return 0;
|
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
|
|
|
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
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;
|
2017-01-05 16:37:40 -08:00
|
|
|
if (!im) im = (Image_Entry *)cache->lru;
|
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
|
|
|
|
2017-01-05 16:37:40 -08:00
|
|
|
im = (Image_Entry *)cache->lru_nodata->last;
|
|
|
|
if (!im) im = (Image_Entry *)cache->lru_nodata;
|
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
|
|
|
}
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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
|
|
|
{
|
2016-09-22 04:45:04 -07:00
|
|
|
int err;
|
2009-12-19 22:23:13 -08:00
|
|
|
Image_Entry *im;
|
2007-07-16 00:25:35 -07:00
|
|
|
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return NULL;
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKL(engine_lock);
|
2016-09-22 04:45:04 -07:00
|
|
|
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL, &err);
|
2017-03-08 18:18:32 -08:00
|
|
|
SLKU(engine_lock);
|
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
|
2014-03-16 22:52:47 -07:00
|
|
|
evas_cache_image_colorspace(Image_Entry *im, Evas_Colorspace cspace)
|
2007-07-16 00:25:35 -07:00
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
|
|
|
if (im->space == cspace) goto done;
|
2008-04-11 17:32:30 -07:00
|
|
|
im->space = cspace;
|
2017-03-08 18:18:32 -08:00
|
|
|
if (!im->cache) goto done;
|
2011-04-20 23:24:27 -07:00
|
|
|
im->cache->func.color_space(im, cspace);
|
2017-03-08 18:18:32 -08:00
|
|
|
done:
|
|
|
|
evas_cache_image_drop(im);
|
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)
|
|
|
|
{
|
2017-03-08 18:18:32 -08:00
|
|
|
void *data;
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!im->cache) return NULL;
|
2017-03-08 18:18:32 -08:00
|
|
|
evas_cache_image_ref(im);
|
|
|
|
data = (void *)im->cache->data;
|
|
|
|
evas_cache_image_drop(im);
|
|
|
|
return data;
|
2008-05-30 06:33:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
evas_cache_private_get(Evas_Cache_Image *cache)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return NULL;
|
2008-05-30 06:33:40 -07:00
|
|
|
return cache->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
evas_cache_private_set(Evas_Cache_Image *cache, const void *data)
|
|
|
|
{
|
2018-03-05 02:04:42 -08:00
|
|
|
if (!cache) return;
|
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)
|
|
|
|
{
|
2014-01-12 15:50:52 -08:00
|
|
|
if (!im->cache) return NULL;
|
2011-04-20 23:24:27 -07:00
|
|
|
return im->cache->func.surface_pixels(im);
|
2008-06-03 02:09:39 -07:00
|
|
|
}
|