2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
7 #include "evas_common.h"
8 #include "evas_private.h"
11 _evas_cache_engine_image_make_dirty(Evas_Cache_Engine_Image *cache,
12 Engine_Image_Entry *eim)
14 eim->flags.cached = 1;
16 eim->flags.loaded = 1;
18 cache->dirty = evas_object_list_prepend(cache->dirty, eim);
22 _evas_cache_engine_image_make_active(Evas_Cache_Engine_Image *cache,
23 Engine_Image_Entry *eim,
26 eim->flags.cached = 1;
29 cache->activ = evas_hash_add(cache->activ, key, eim);
33 _evas_cache_engine_image_make_inactive(Evas_Cache_Engine_Image *cache,
34 Engine_Image_Entry *eim,
37 eim->flags.cached = 1;
40 cache->inactiv = evas_hash_add(cache->inactiv, key, eim);
41 cache->lru = evas_object_list_prepend(cache->lru, eim);
42 cache->usage += cache->func.mem_size_get(eim);
46 _evas_cache_engine_image_remove_activ(Evas_Cache_Engine_Image *cache,
47 Engine_Image_Entry *eim)
49 if (eim->flags.cached)
53 cache->dirty = evas_object_list_remove(cache->dirty, eim);
58 cache->activ = evas_hash_del(cache->activ, eim->cache_key, eim);
62 cache->usage -= cache->func.mem_size_get(eim);
63 cache->inactiv = evas_hash_del(cache->inactiv, eim->cache_key, eim);
64 cache->lru = evas_object_list_remove(cache->lru, eim);
66 eim->flags.cached = 0;
72 static Engine_Image_Entry *
73 _evas_cache_engine_image_alloc(Evas_Cache_Engine_Image *cache,
77 Engine_Image_Entry *eim;
81 if (cache->func.alloc)
82 eim = cache->func.alloc();
84 eim = malloc(sizeof (Engine_Image_Entry));
86 if (!eim) goto on_error;
87 memset(eim, 0, sizeof (Engine_Image_Entry));
95 eim->flags.need_parent = 1;
101 eim->flags.need_parent = 0;
105 eim->flags.cached = 0;
107 eim->cache_key = hkey;
110 _evas_cache_engine_image_make_active(cache, eim, hkey);
112 _evas_cache_engine_image_make_dirty(cache, eim);
118 evas_cache_engine_image_drop(eim);
119 evas_stringshare_del(hkey);
120 evas_cache_image_drop(ie);
125 _evas_cache_engine_image_dealloc(Evas_Cache_Engine_Image *cache, Engine_Image_Entry *eim)
129 if (cache->func.debug) cache->func.debug("delete", eim);
131 _evas_cache_engine_image_remove_activ(cache, eim);
134 cache->func.destructor(eim);
135 if (im) evas_cache_image_drop(im);
137 if (cache->func.dealloc)
139 cache->func.dealloc(eim);
143 memset(eim, 0, sizeof (Engine_Image_Entry));
149 evas_cache_engine_image_usage_get(Evas_Cache_Engine_Image *cache)
151 assert(cache != NULL);
157 evas_cache_engine_image_get(Evas_Cache_Engine_Image *cache)
159 assert(cache != NULL);
165 evas_cache_engine_image_set(Evas_Cache_Engine_Image *cache, int limit)
167 assert(cache != NULL);
169 cache->limit = limit;
172 EAPI Evas_Cache_Engine_Image *
173 evas_cache_engine_image_init(const Evas_Cache_Engine_Image_Func *cb, Evas_Cache_Image *parent)
175 Evas_Cache_Engine_Image *new;
177 new = malloc(sizeof (Evas_Cache_Engine_Image));
191 new->parent = parent;
192 parent->references++;
199 EAPI Evas_Cache_Engine_Image *
200 evas_cache_engine_image_dup(const Evas_Cache_Engine_Image_Func *cb, Evas_Cache_Engine_Image *brother)
202 Evas_Cache_Engine_Image *new;
204 new = malloc(sizeof (Evas_Cache_Engine_Image));
208 new->func = brother->func;
210 #define ORD(Func) if (cb->Func) new->func.Func = cb->Func;
232 new->parent = brother->parent;
233 new->parent->references++;
235 new->brother = brother;
236 brother->references++;
242 _evas_cache_engine_image_free_cb(const Evas_Hash *hash, const char *key, void *data, void *fdata)
244 Evas_Cache_Engine_Image *cache = fdata;
245 Engine_Image_Entry *eim = data;
247 _evas_cache_engine_image_dealloc(cache, eim);
253 evas_cache_engine_image_flush(Evas_Cache_Engine_Image *cache)
255 assert(cache != NULL);
257 while ((cache->lru) && (cache->limit < cache->usage))
259 Engine_Image_Entry *eim;
261 eim = (Engine_Image_Entry *) cache->lru->last;
262 _evas_cache_engine_image_dealloc(cache, eim);
267 evas_cache_engine_image_shutdown(Evas_Cache_Engine_Image *cache)
269 Engine_Image_Entry *eim;
271 assert(cache != NULL);
273 if (cache->func.debug) cache->func.debug("shutdown-engine", NULL);
275 evas_hash_foreach(cache->inactiv, _evas_cache_engine_image_free_cb, cache);
276 evas_hash_free(cache->inactiv);
278 /* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
281 eim = (Engine_Image_Entry *) cache->dirty;
282 _evas_cache_engine_image_dealloc(cache, eim);
285 evas_hash_foreach(cache->activ, _evas_cache_engine_image_free_cb, cache);
286 evas_hash_free(cache->activ);
288 evas_cache_image_shutdown(cache->parent);
290 evas_cache_engine_image_shutdown(cache->brother);
294 EAPI Engine_Image_Entry *
295 evas_cache_engine_image_request(Evas_Cache_Engine_Image *cache,
296 const char *file, const char *key,
297 RGBA_Image_Loadopts *lo, void *data, int *error)
299 Engine_Image_Entry *eim;
303 assert(cache != NULL);
310 im = evas_cache_image_request(cache->parent, file, key, lo, error);
315 ekey = cache->func.key(im, file, key, lo, data);
317 ekey = evas_stringshare_add(im->cache_key);
321 eim = evas_hash_find(cache->activ, ekey);
324 evas_cache_image_drop(im);
328 eim = evas_hash_find(cache->inactiv, ekey);
331 _evas_cache_engine_image_remove_activ(cache, eim);
332 _evas_cache_engine_image_make_active(cache, eim, ekey);
333 evas_cache_image_drop(im);
337 eim = _evas_cache_engine_image_alloc(cache, im, ekey);
338 if (!eim) return NULL;
340 *error = cache->func.constructor(eim, data);
341 if (*error != 0) goto on_error;
342 if (cache->func.debug)
343 cache->func.debug("constructor-engine", eim);
352 if (im) evas_cache_image_drop(im);
353 if (ekey) evas_stringshare_del(ekey);
357 _evas_cache_engine_image_dealloc(cache, eim);
364 evas_cache_engine_image_drop(Engine_Image_Entry *eim)
366 Evas_Cache_Engine_Image *cache;
374 if (eim->flags.dirty)
376 _evas_cache_engine_image_dealloc(cache, eim);
380 if (eim->references == 0)
382 _evas_cache_engine_image_remove_activ(cache, eim);
383 _evas_cache_engine_image_make_inactive(cache, eim, eim->cache_key);
384 evas_cache_engine_image_flush(cache);
389 EAPI Engine_Image_Entry *
390 evas_cache_engine_image_dirty(Engine_Image_Entry *eim, int x, int y, int w, int h)
392 Engine_Image_Entry *eim_dirty = eim;
393 Image_Entry *im_dirty = NULL;
395 Evas_Cache_Engine_Image *cache;
396 unsigned char alloc_eim;
402 if (!(eim->flags.dirty))
406 if (eim->flags.need_parent == 1)
409 im_dirty = evas_cache_image_dirty(im, x, y, w, h);
411 /* If im == im_dirty, this meens that we have only one reference to the eim. */
414 if (eim->references == 1)
416 _evas_cache_engine_image_remove_activ(cache, eim);
417 _evas_cache_engine_image_make_dirty(cache, eim);
426 if (eim->references > 1)
432 _evas_cache_engine_image_remove_activ(cache, eim_dirty);
433 _evas_cache_engine_image_make_dirty(cache, eim_dirty);
440 eim_dirty = _evas_cache_engine_image_alloc(cache, im_dirty, NULL);
441 if (!eim_dirty) goto on_error;
443 eim_dirty->w = eim->w;
444 eim_dirty->h = eim->h;
445 eim_dirty->references = 1;
447 error = cache->func.dirty(eim_dirty, eim);
448 if (cache->func.debug)
449 cache->func.debug("dirty-engine", eim_dirty);
451 if (error != 0) goto on_error;
453 evas_cache_engine_image_drop(eim);
457 if (cache->func.dirty_region)
458 cache->func.dirty_region(eim_dirty, x, y, w, h);
459 if (cache->func.debug)
460 cache->func.debug("dirty-region-engine", eim_dirty);
465 if (eim) evas_cache_engine_image_drop(eim);
466 if (eim_dirty && eim_dirty != eim)
467 evas_cache_engine_image_drop(eim_dirty);
469 if (im_dirty) evas_cache_image_drop(im_dirty);
474 EAPI Engine_Image_Entry *
475 evas_cache_engine_image_alone(Engine_Image_Entry *eim, void *data)
477 Evas_Cache_Engine_Image *cache;
485 im = evas_cache_image_alone(eim->src);
488 eim = _evas_cache_engine_image_alloc(cache, im, NULL);
489 if (!eim) goto on_error;
493 if (cache->func.constructor(eim, data)) goto on_error;
499 evas_cache_image_drop(im);
503 static Engine_Image_Entry *
504 _evas_cache_engine_image_push_dirty(Evas_Cache_Engine_Image *cache, Image_Entry *im, void *engine_data)
506 Engine_Image_Entry *eim;
509 eim = _evas_cache_engine_image_alloc(cache, im, NULL);
510 if (!eim) goto on_error;
513 error = cache->func.update_data(eim, engine_data);
514 if (cache->func.debug)
515 cache->func.debug("dirty-update_data-engine", eim);
516 if (error != 0) goto on_error;
522 evas_cache_engine_image_drop(eim);
526 EAPI Engine_Image_Entry *
527 evas_cache_engine_image_copied_data(Evas_Cache_Engine_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace, void *engine_data)
533 im = evas_cache_image_copied_data(cache->parent, w, h, image_data, alpha, cspace);
535 return _evas_cache_engine_image_push_dirty(cache, im, engine_data);
538 EAPI Engine_Image_Entry *
539 evas_cache_engine_image_data(Evas_Cache_Engine_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace, void *engine_data)
545 im = evas_cache_image_data(cache->parent, w, h, image_data, alpha, cspace);
547 return _evas_cache_engine_image_push_dirty(cache, im, engine_data);
550 EAPI Engine_Image_Entry *
551 evas_cache_engine_image_size_set(Engine_Image_Entry *eim, int w, int h)
553 Evas_Cache_Engine_Image *cache;
554 Engine_Image_Entry *new;
561 assert(eim->references > 0);
566 if (eim->flags.need_parent == 1)
574 im = evas_cache_image_size_set(eim->src, w, h);
575 /* FIXME: Good idea to call update_data ? */
576 if (im == eim->src) return eim;
580 hkey = (eim->references > 1 ) ? evas_stringshare_add(eim->cache_key) : NULL;
582 new = _evas_cache_engine_image_alloc(cache, im, hkey);
583 if (!new) goto on_error;
589 error = cache->func.size_set(new, eim);
590 if (error) goto on_error;
592 evas_cache_engine_image_drop(eim);
597 evas_cache_engine_image_drop(new);
600 evas_cache_image_drop(im);
601 evas_cache_engine_image_drop(eim);
607 evas_cache_engine_image_load_data(Engine_Image_Entry *eim)
609 Evas_Cache_Engine_Image *cache;
616 if (eim->flags.loaded) return ;
619 evas_cache_image_load_data(eim->src);
622 if (cache->func.debug)
623 cache->func.debug("load-engine", eim);
625 if (eim->flags.dirty)
626 size = cache->func.mem_size_get(eim);
628 cache->func.load(eim, eim->src);
629 if (eim->flags.dirty)
630 cache->usage += cache->func.mem_size_get(eim) - size;
632 eim->flags.loaded = 1;
635 EAPI Engine_Image_Entry *
636 evas_cache_engine_image_engine(Evas_Cache_Engine_Image *cache, void *engine_data)
638 Engine_Image_Entry *eim;
642 ie = evas_cache_image_empty(cache->parent);
643 if (!ie) return NULL;
645 eim = _evas_cache_engine_image_alloc(cache, ie, NULL);
646 if (!eim) goto on_error;
649 error = cache->func.update_data(eim, engine_data);
650 if (cache->func.debug)
651 cache->func.debug("update_data-engine", eim);
653 if (error != 0) goto on_error;
661 evas_cache_image_drop(ie);
665 evas_cache_engine_image_drop(eim);
671 evas_cache_engine_image_colorspace(Engine_Image_Entry *eim, int cspace, void *engine_data)
673 Evas_Cache_Engine_Image *cache = eim->cache;
677 cache->func.destructor(eim);
678 evas_cache_image_colorspace(eim->src, cspace);
679 cache->func.constructor(eim, engine_data);
680 if (cache->func.debug)
681 cache->func.debug("cosntructor-colorspace-engine", eim);
685 evas_cache_engine_parent_not_needed(Engine_Image_Entry *eim)
690 eim->flags.need_parent = 0;
691 evas_cache_image_data_not_needed(eim->src);