static void
_evas_cache_image_make_dirty(Evas_Cache_Image *cache,
- Image_Entry *im)
+ Image_Entry *ie)
{
- im->flags.cached = 1;
- im->flags.dirty = 1;
- im->flags.activ = 0;
- im->flags.lru_nodata = 0;
- cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(im));
+ ie->flags.cached = 1;
+ ie->flags.dirty = 1;
+ ie->flags.activ = 0;
+ ie->flags.lru_nodata = 0;
+ cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(ie));
- if (im->cache_key)
+ if (ie->cache_key)
{
- eina_stringshare_del(im->cache_key);
- im->cache_key = NULL;
+ eina_stringshare_del(ie->cache_key);
+ ie->cache_key = NULL;
}
+
+ while (ie->scalecache.others)
+ {
+ Image_Entry *ie2;
+
+ ie2 = ie->scalecache.others->data;
+ cache->usage -= cache->func.mem_size_get(ie2);
+ if (ie2->scalecache.usage >= 6)
+ {
+ ie->scalecache.mem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+ ie->cache->scaledmem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+ ie->cache->scaled =
+ eina_list_remove(ie->cache->scaled, ie2);
+ }
+ ie->scalecache.others = eina_list_remove_list(ie->scalecache.others, ie->scalecache.others);
+ ie2->scalecache.parent = NULL;
+ evas_cache_image_drop(ie2);
+ }
+
}
static void
im->flags.cached = 1;
cache->inactiv = evas_hash_direct_add(cache->inactiv, key, im);
cache->lru = eina_inlist_prepend(cache->lru, EINA_INLIST_GET(im));
- cache->usage += cache->func.mem_size_get(im);
}
else
{
{
im->flags.lru_nodata = 0;
cache->lru_nodata = eina_inlist_remove(cache->lru_nodata, EINA_INLIST_GET(im));
- cache->usage -= cache->func.mem_size_get(im);
}
}
if (cache->func.debug)
cache->func.debug("deleting", ie);
+ while (ie->scalecache.others)
+ {
+ Image_Entry *ie2;
+
+ ie2 = ie->scalecache.others->data;
+ cache->usage -= cache->func.mem_size_get(ie2);
+ if (ie2->scalecache.usage >= 6)
+ {
+ ie->scalecache.mem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+ ie->cache->scaledmem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+ ie->cache->scaled =
+ eina_list_remove(ie->cache->scaled, ie2);
+ }
+ ie->scalecache.others = eina_list_remove_list(ie->scalecache.others, ie->scalecache.others);
+ ie2->scalecache.parent = NULL;
+ evas_cache_image_drop(ie2);
+ }
+
cache->func.destructor(ie);
_evas_cache_image_remove_activ(cache, ie);
wmin = w > 0 ? w : 1;
hmin = h > 0 ? h : 1;
if (ie->allocated.w == wmin && ie->allocated.h == hmin)
- return ;
+ return;
#ifdef BUILD_ASYNC_PRELOAD
pthread_mutex_lock(&mutex_surface_alloc);
new->references = 1;
+ new->scaled = NULL;
+ new->scaledmem = 0;
+
return new;
}
assert(im);
assert(im->cache);
+ if (im->scalecache.parent)
+ {
+ im->scalecache.parent->cache->usage -= im->scalecache.parent->cache->func.mem_size_get(im);
+ if (im->scalecache.usage >= 6)
+ {
+ im->scalecache.parent->scalecache.mem -= im->scalecache.dst_w * im->scalecache.dst_h;
+ im->scalecache.parent->cache->scaledmem -= im->scalecache.dst_w * im->scalecache.dst_h;
+ im->scalecache.parent->cache->scaled =
+ eina_list_remove(im->scalecache.parent->cache->scaled, im);
+ }
+ im->scalecache.parent->scalecache.others =
+ eina_list_remove(im->scalecache.parent->scalecache.others, im);
+ }
+
im->references--;
cache = im->cache;
EAPI Image_Entry *
evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
{
- Image_Entry *im_dirty = im;
+ Image_Entry *im_dirty = im, *ie = im;
Evas_Cache_Image *cache;
assert(im);
assert(im->cache);
cache = im->cache;
+ while (ie->scalecache.others)
+ {
+ Image_Entry *ie2;
+
+ ie2 = ie->scalecache.others->data;
+ cache->usage -= cache->func.mem_size_get(ie2);
+ if (ie2->scalecache.usage >= 6)
+ {
+ ie->scalecache.mem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+ ie->cache->scaledmem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+ ie->cache->scaled =
+ eina_list_remove(ie->cache->scaled, ie2);
+ }
+ ie->scalecache.others = eina_list_remove_list(ie->scalecache.others, ie->scalecache.others);
+ ie2->scalecache.parent = NULL;
+ evas_cache_image_drop(ie2);
+ }
+
if (!(im->flags.dirty))
{
if (im->references == 1) im_dirty = im;
cache->func.debug("surface-alloc", im);
}
+EAPI void
+evas_cache_image_surface_dealloc(Image_Entry *im)
+{
+ Evas_Cache_Image *cache;
+
+ assert(im);
+ assert(im->cache);
+
+ cache = im->cache;
+
+ if (!((RGBA_Image *)im)->image.data) return;
+ if (!im->info.loader) return;
+ if (!im->info.module) return;
+ if (!im->flags.loaded) return;
+
+ im->flags.loaded = 0;
+
+#ifdef BUILD_ASYNC_PRELOAD
+ pthread_mutex_lock(&mutex_surface_alloc);
+#endif
+
+ printf("-------- actual dealloc %p\n", im);
+ _evas_cache_image_remove_lru_nodata(cache, im);
+ cache->func.surface_delete(im);
+ im->allocated.w = 0;
+ im->allocated.h = 0;
+
+#ifdef BUILD_ASYNC_PRELOAD
+ pthread_mutex_unlock(&mutex_surface_alloc);
+#endif
+
+ if (cache->func.debug)
+ cache->func.debug("surface-dealloc", im);
+}
+
EAPI Image_Entry *
evas_cache_image_size_set(Image_Entry *im, int w, int h)
{
{
_evas_cache_image_entry_surface_alloc(cache, im, im->w, im->h);
im->flags.loaded = 0;
-
return ;
}
evas_cache_image_preload_cancel(&im->cache_entry);
}
+#define SCALECACHE 1
+
+#ifdef SCALECACHE
+static Image_Entry *
+_sc_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth)
+{
+ Eina_List *l;
+ Image_Entry *ie = NULL;
+
+ for (l = im->scalecache.others; l; l = l->next)
+ {
+ ie = l->data;
+ if ((ie->scalecache.dst_w == dst_w) &&
+ (ie->scalecache.dst_h == dst_h) &&
+ (ie->scalecache.src_w == src_w) &&
+ (ie->scalecache.src_h == src_h) &&
+ (ie->scalecache.src_x == src_x) &&
+ (ie->scalecache.src_y == src_y) &&
+ (ie->scalecache.smooth == smooth))
+ {
+ if (l != ie->scalecache.others)
+ {
+ im->scalecache.others = eina_list_remove_list(im->scalecache.others, l);
+ im->scalecache.others = eina_list_prepend(im->scalecache.others, ie);
+ }
+ ie->scalecache.usage++;
+ return ie;
+ }
+ }
+ return NULL;
+}
+
+static void
+_sc_clean(Image_Entry *im)
+{
+ while ((im->scalecache.mem > (im->cache->limit >> 2)) ||
+ (eina_list_count(im->scalecache.others) > 40))
+ {
+ Eina_List *l;
+ Image_Entry *ie;
+
+ printf("clean %i > %i\n", im->cache->scaledmem, im->cache->limit >> 2);
+ l = eina_list_last(im->scalecache.others);
+ ie = l->data;
+ if (ie->scalecache.usage >= 6)
+ {
+ im->scalecache.mem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+ im->cache->scaledmem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+ im->cache->scaled =
+ eina_list_remove(im->cache->scaled, ie);
+ }
+ im->scalecache.others = eina_list_remove_list(im->scalecache.others, l);
+ ie->scalecache.parent = NULL;
+ evas_cache_image_drop(ie);
+ }
+}
+
+static Image_Entry *
+_sc_new(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth)
+{
+ Image_Entry *ie;
+
+ ie = evas_cache_image_empty(im->cache);
+ evas_cache_image_colorspace(ie, EVAS_COLORSPACE_ARGB8888);
+ im->scalecache.usage++;
+ im->scalecache.others = eina_list_prepend(im->scalecache.others, ie);
+ ie->scalecache.src_x = src_x;
+ ie->scalecache.src_y = src_y;
+ ie->scalecache.src_w = src_w;
+ ie->scalecache.src_h = src_h;
+ ie->scalecache.dst_w = dst_w;
+ ie->scalecache.dst_h = dst_h;
+ ie->scalecache.smooth = smooth;
+ ie->scalecache.parent = im;
+ return ie;
+}
+
+static int
+_sc_fill(Image_Entry *im, Image_Entry *ie)
+{
+ RGBA_Draw_Context *tctx;
+
+ ie->scalecache.usage++;
+ if (ie->scalecache.usage < 5) return 0;
+ if (ie->scalecache.usage >= 6)
+ {
+ ie->scalecache.parent->scalecache.usage--;
+ if (ie->scalecache.parent->scalecache.usage <= 0)
+ {
+ ie->scalecache.parent->scalecache.usage = 0;
+ if ((im->info.loader) &&
+ (im->flags.loaded) &&
+ (im->info.module) &&
+ (im->file) &&
+ (((RGBA_Image*)im)->image.data));
+ {
+ evas_cache_image_surface_dealloc(im);
+ }
+ }
+ im->cache->scaled =
+ eina_list_remove(im->cache->scaled, ie);
+ im->cache->scaled =
+ eina_list_prepend(im->cache->scaled, ie);
+ return 1;
+ }
+ im->scalecache.usage += 10;
+ im->cache->func.load(im);
+ ie->scalecache.usage = 6;
+ im->scalecache.mem += ie->scalecache.dst_w * ie->scalecache.dst_h;
+ im->cache->scaledmem += ie->scalecache.dst_w * ie->scalecache.dst_h;
+ im->cache->scaled =
+ eina_list_prepend(im->cache->scaled, ie);
+ ie->flags.alpha = im->flags.alpha;
+ ie->w = ie->scalecache.dst_w;
+ ie->h = ie->scalecache.dst_h;
+ evas_cache_image_surface_alloc(ie, ie->w, ie->h);
+ tctx = evas_common_draw_context_new();
+ evas_common_draw_context_set_render_op(tctx, _EVAS_RENDER_COPY);
+ if (ie->scalecache.smooth)
+ evas_common_scale_rgba_in_to_out_clip_smooth
+ ((RGBA_Image *)im, (RGBA_Image *)ie, tctx,
+ ie->scalecache.src_x, ie->scalecache.src_y,
+ ie->scalecache.src_w, ie->scalecache.src_h,
+ 0, 0,
+ ie->scalecache.dst_w, ie->scalecache.dst_h);
+ else
+ evas_common_scale_rgba_in_to_out_clip_sample
+ ((RGBA_Image *)im, (RGBA_Image *)ie, tctx,
+ ie->scalecache.src_x, ie->scalecache.src_y,
+ ie->scalecache.src_w, ie->scalecache.src_h,
+ 0, 0,
+ ie->scalecache.dst_w, ie->scalecache.dst_h);
+ evas_common_draw_context_free(tctx);
+ return 1;
+}
+
+static void
+_sc_flush(Evas_Cache_Image *cache)
+{
+ while (cache->scaledmem > (cache->limit >> 2))
+ {
+ Eina_List *l;
+ Image_Entry *ie;
+
+ printf("flush %i > %i\n", cache->scaledmem, cache->limit >> 2);
+ l = eina_list_last(cache->scaled);
+ while (l)
+ {
+ ie = l->data;
+ if (ie->scalecache.parent) break;
+ l = l->prev;
+ }
+ if (!l)
+ {
+ break;
+ }
+ ie->scalecache.parent->scalecache.mem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+ cache->scaledmem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+ cache->scaled =
+ eina_list_remove_list(cache->scaled, l);
+ ie->scalecache.parent->scalecache.others =
+ eina_list_remove(ie->scalecache.parent->scalecache.others, ie);
+ ie->scalecache.parent = NULL;
+ evas_cache_image_drop(ie);
+ }
+}
+
+#endif
+
static void
eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
{
evas_common_image_colorspace_normalize(im);
#ifdef BUILD_PTHREAD
if (cpunum > 1)
- evas_common_pipe_image_draw(im, surface, context, smooth,
- src_x, src_y, src_w, src_h,
- dst_x, dst_y, dst_w, dst_h);
+ {
+ if (im->image.data)
+ {
+ evas_common_pipe_image_draw(im, surface,
+ context, smooth,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h);
+ }
+ }
else
#endif
{
- if (smooth)
- evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context,
- src_x, src_y, src_w, src_h,
- dst_x, dst_y, dst_w, dst_h);
- else
- evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context,
- src_x, src_y, src_w, src_h,
- dst_x, dst_y, dst_w, dst_h);
+#ifdef SCALECACHE
+ Image_Entry *ie, *ie2;
+ int ok;
+
+ ie = (Image_Entry *)im;
+ if ((src_w == dst_w) && (src_h == dst_h))
+ {
+ ie->scalecache.usage++;
+ if (smooth)
+ evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h);
+ else
+ evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h);
+ }
+ else
+ {
+ ok = 0;
+ _sc_clean(ie);
+ ie2 = _sc_find(ie, src_x, src_y, src_w, src_h, dst_w, dst_h, smooth);
+ if (ie2) ok = _sc_fill(ie, ie2);
+ else
+ {
+ ie2 = _sc_new(ie, src_x, src_y, src_w, src_h, dst_w, dst_h, smooth);
+ if (ie2) ok = _sc_fill(ie, ie2);
+ }
+ if ((ie2) && (ok))
+ evas_common_scale_rgba_in_to_out_clip_sample((RGBA_Image *)ie2,
+ surface, context,
+ 0, 0, dst_w, dst_h,
+ dst_x, dst_y, dst_w, dst_h);
+ else
+ {
+ ie->scalecache.usage++;
+ evas_cache_image_load_data(ie);
+#endif
+ if (im->image.data)
+ {
+ if (smooth)
+ evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h);
+ else
+ evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context,
+ src_x, src_y, src_w, src_h,
+ dst_x, dst_y, dst_w, dst_h);
+ }
+#ifdef SCALECACHE
+ }
+ }
+ _sc_flush(ie->cache);
+#endif
evas_common_cpu_end_opt();
}
}