aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/cache/evas_cache_engine_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/cache/evas_cache_engine_image.c')
-rw-r--r--libraries/evas/src/lib/cache/evas_cache_engine_image.c703
1 files changed, 0 insertions, 703 deletions
diff --git a/libraries/evas/src/lib/cache/evas_cache_engine_image.c b/libraries/evas/src/lib/cache/evas_cache_engine_image.c
deleted file mode 100644
index 5ec1af2..0000000
--- a/libraries/evas/src/lib/cache/evas_cache_engine_image.c
+++ /dev/null
@@ -1,703 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <assert.h>
6
7#include "evas_common.h"
8#include "evas_private.h"
9
10static void
11_evas_cache_engine_image_make_dirty(Evas_Cache_Engine_Image *cache,
12 Engine_Image_Entry *eim)
13{
14 eim->flags.cached = 1;
15 eim->flags.dirty = 1;
16 eim->flags.loaded = 1;
17 eim->flags.activ = 0;
18 cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(eim));
19}
20
21static void
22_evas_cache_engine_image_make_active(Evas_Cache_Engine_Image *cache,
23 Engine_Image_Entry *eim,
24 const char *key)
25{
26 eim->flags.cached = 1;
27 eim->flags.activ = 1;
28 eim->flags.dirty = 0;
29 eina_hash_add(cache->activ, key, eim);
30}
31
32static void
33_evas_cache_engine_image_make_inactive(Evas_Cache_Engine_Image *cache,
34 Engine_Image_Entry *eim,
35 const char *key)
36{
37 eim->flags.cached = 1;
38 eim->flags.dirty = 0;
39 eim->flags.activ = 0;
40 eina_hash_add(cache->inactiv, key, eim);
41 cache->lru = eina_inlist_prepend(cache->lru, EINA_INLIST_GET(eim));
42 cache->usage += cache->func.mem_size_get(eim);
43}
44
45static void
46_evas_cache_engine_image_remove_activ(Evas_Cache_Engine_Image *cache,
47 Engine_Image_Entry *eim)
48{
49 if (eim->flags.cached)
50 {
51 if (eim->flags.dirty)
52 {
53 cache->dirty = eina_inlist_remove(cache->dirty, EINA_INLIST_GET(eim));
54 }
55 else
56 if (eim->flags.activ)
57 {
58 eina_hash_del(cache->activ, eim->cache_key, eim);
59 }
60 else
61 {
62 cache->usage -= cache->func.mem_size_get(eim);
63 eina_hash_del(cache->inactiv, eim->cache_key, eim);
64 cache->lru = eina_inlist_remove(cache->lru, EINA_INLIST_GET(eim));
65 }
66 eim->flags.cached = 0;
67 eim->flags.dirty = 0;
68 eim->flags.activ = 0;
69 }
70}
71
72static Engine_Image_Entry *
73_evas_cache_engine_image_alloc(Evas_Cache_Engine_Image *cache,
74 Image_Entry *ie,
75 const char *hkey)
76{
77 Engine_Image_Entry *eim;
78
79 assert(cache);
80
81 if (cache->func.alloc)
82 eim = cache->func.alloc();
83 else
84 eim = malloc(sizeof (Engine_Image_Entry));
85
86 if (!eim) goto on_error;
87 memset(eim, 0, sizeof (Engine_Image_Entry));
88
89 eim->cache = cache;
90 if (ie)
91 {
92 eim->w = ie->w;
93 eim->h = ie->h;
94 eim->src = ie;
95 eim->flags.need_parent = 1;
96 }
97 else
98 {
99 eim->w = -1;
100 eim->h = -1;
101 eim->flags.need_parent = 0;
102 eim->src = NULL;
103 }
104
105 eim->flags.cached = 0;
106 eim->references = 0;
107 eim->cache_key = hkey;
108
109 if (hkey)
110 _evas_cache_engine_image_make_active(cache, eim, hkey);
111 else
112 _evas_cache_engine_image_make_dirty(cache, eim);
113
114 return eim;
115
116 on_error:
117 if (eim)
118 evas_cache_engine_image_drop(eim);
119 eina_stringshare_del(hkey);
120 evas_cache_image_drop(ie);
121 return NULL;
122}
123
124static void
125_evas_cache_engine_image_dealloc(Evas_Cache_Engine_Image *cache, Engine_Image_Entry *eim)
126{
127 Image_Entry *im;
128
129 if (cache->func.debug) cache->func.debug("delete", eim);
130
131 _evas_cache_engine_image_remove_activ(cache, eim);
132
133 im = eim->src;
134 cache->func.destructor(eim);
135 if (im) evas_cache_image_drop(im);
136
137 if (cache->func.dealloc)
138 {
139 cache->func.dealloc(eim);
140 }
141 else
142 {
143 memset(eim, 0, sizeof (Engine_Image_Entry));
144 free(eim);
145 }
146}
147
148EAPI int
149evas_cache_engine_image_usage_get(Evas_Cache_Engine_Image *cache)
150{
151 assert(cache != NULL);
152
153 return cache->usage;
154}
155
156EAPI int
157evas_cache_engine_image_get(Evas_Cache_Engine_Image *cache)
158{
159 assert(cache != NULL);
160
161 return cache->limit;
162}
163
164EAPI void
165evas_cache_engine_image_set(Evas_Cache_Engine_Image *cache, int limit)
166{
167 assert(cache != NULL);
168
169 cache->limit = limit;
170}
171
172EAPI Evas_Cache_Engine_Image *
173evas_cache_engine_image_init(const Evas_Cache_Engine_Image_Func *cb, Evas_Cache_Image *parent)
174{
175 Evas_Cache_Engine_Image *new;
176
177 new = malloc(sizeof (Evas_Cache_Engine_Image));
178 if (!new)
179 return NULL;
180
181 new->func = *cb;
182
183 new->limit = 0;
184 new->usage = 0;
185
186 new->dirty = NULL;
187 new->lru = NULL;
188 new->activ = eina_hash_string_superfast_new(NULL);
189 new->inactiv = eina_hash_string_superfast_new(NULL);
190
191 new->parent = parent;
192 parent->references++;
193
194 new->brother = NULL;
195
196 return new;
197}
198
199EAPI Evas_Cache_Engine_Image *
200evas_cache_engine_image_dup(const Evas_Cache_Engine_Image_Func *cb, Evas_Cache_Engine_Image *brother)
201{
202 Evas_Cache_Engine_Image *new;
203
204 new = calloc(1, sizeof (Evas_Cache_Engine_Image));
205 if (!new)
206 return NULL;
207
208 new->func = brother->func;
209
210#define ORD(Func) if (cb->Func) new->func.Func = cb->Func;
211
212 ORD(key);
213 ORD(constructor);
214 ORD(destructor);
215 ORD(dirty_region);
216 ORD(dirty);
217 ORD(size_set);
218 ORD(update_data);
219 ORD(load);
220 ORD(mem_size_get);
221 ORD(debug);
222
223#undef ORD
224
225 new->limit = -1;
226 new->usage = 0;
227 new->references = 1;
228
229 new->dirty = NULL;
230 new->activ = NULL;
231
232 new->parent = brother->parent;
233 new->parent->references++;
234
235 new->brother = brother;
236 brother->references++;
237
238 return new;
239}
240
241static Eina_Bool
242_evas_cache_engine_image_free_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, void *fdata)
243{
244 Eina_List **delete_list = fdata;
245
246 *delete_list = eina_list_prepend(*delete_list, data);
247
248 return EINA_TRUE;
249}
250
251EAPI void
252evas_cache_engine_image_flush(Evas_Cache_Engine_Image *cache)
253{
254 assert(cache != NULL);
255
256 while ((cache->lru) && (cache->limit < cache->usage))
257 {
258 Engine_Image_Entry *eim;
259
260 eim = (Engine_Image_Entry *) cache->lru->last;
261 _evas_cache_engine_image_dealloc(cache, eim);
262 }
263}
264
265EAPI void
266evas_cache_engine_image_shutdown(Evas_Cache_Engine_Image *cache)
267{
268 Engine_Image_Entry *eim;
269 Eina_List *delete_list = NULL;
270
271 assert(cache != NULL);
272
273 if (cache->func.debug) cache->func.debug("shutdown-engine", NULL);
274
275 eina_hash_foreach(cache->inactiv, _evas_cache_engine_image_free_cb, &delete_list);
276 eina_hash_foreach(cache->activ, _evas_cache_engine_image_free_cb, &delete_list);
277
278 while (delete_list)
279 {
280 _evas_cache_engine_image_dealloc(cache, eina_list_data_get(delete_list));
281 delete_list = eina_list_remove_list(delete_list, delete_list);
282 }
283
284 eina_hash_free(cache->inactiv);
285 eina_hash_free(cache->activ);
286
287 /* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
288 while (cache->dirty)
289 {
290 eim = (Engine_Image_Entry *) cache->dirty;
291 _evas_cache_engine_image_dealloc(cache, eim);
292 }
293
294
295 evas_cache_image_shutdown(cache->parent);
296 if (cache->brother)
297 evas_cache_engine_image_shutdown(cache->brother);
298 free(cache);
299}
300
301EAPI Engine_Image_Entry *
302evas_cache_engine_image_request(Evas_Cache_Engine_Image *cache,
303 const char *file, const char *key,
304 RGBA_Image_Loadopts *lo, void *data, int *error)
305{
306 Engine_Image_Entry *eim;
307 Image_Entry *im;
308 const char *ekey;
309
310 assert(cache != NULL);
311
312 *error = EVAS_LOAD_ERROR_NONE;
313
314 ekey = NULL;
315 eim = NULL;
316
317 im = evas_cache_image_request(cache->parent, file, key, lo, error);
318 if (!im)
319 goto on_error;
320
321 if (cache->func.key)
322 ekey = cache->func.key(im, file, key, lo, data);
323 else
324 ekey = eina_stringshare_add(im->cache_key);
325 if (!ekey)
326 {
327 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
328 goto on_error;
329 }
330
331 eim = eina_hash_find(cache->activ, ekey);
332 if (eim)
333 {
334 evas_cache_image_drop(im);
335 goto on_ok;
336 }
337
338 eim = eina_hash_find(cache->inactiv, ekey);
339 if (eim)
340 {
341 _evas_cache_engine_image_remove_activ(cache, eim);
342 _evas_cache_engine_image_make_active(cache, eim, ekey);
343 evas_cache_image_drop(im);
344 goto on_ok;
345 }
346
347 eim = _evas_cache_engine_image_alloc(cache, im, ekey);
348 if (!eim)
349 {
350 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
351 return NULL;
352 }
353
354 *error = cache->func.constructor(eim, data);
355 if (*error != EVAS_LOAD_ERROR_NONE) goto on_error;
356 if (cache->func.debug)
357 cache->func.debug("constructor-engine", eim);
358
359 on_ok:
360 eim->references++;
361 return eim;
362
363 on_error:
364 if (!eim)
365 {
366 if (im) evas_cache_image_drop(im);
367 if (ekey) eina_stringshare_del(ekey);
368 }
369 else
370 {
371 _evas_cache_engine_image_dealloc(cache, eim);
372 }
373
374 return NULL;
375}
376
377EAPI void
378evas_cache_engine_image_drop(Engine_Image_Entry *eim)
379{
380 Evas_Cache_Engine_Image *cache;
381
382 assert(eim);
383 assert(eim->cache);
384
385 eim->references--;
386 cache = eim->cache;
387
388 if (eim->flags.dirty)
389 {
390 _evas_cache_engine_image_dealloc(cache, eim);
391 return ;
392 }
393
394 if (eim->references == 0)
395 {
396 _evas_cache_engine_image_remove_activ(cache, eim);
397 _evas_cache_engine_image_make_inactive(cache, eim, eim->cache_key);
398 evas_cache_engine_image_flush(cache);
399 return ;
400 }
401}
402
403EAPI Engine_Image_Entry *
404evas_cache_engine_image_dirty(Engine_Image_Entry *eim, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
405{
406 Engine_Image_Entry *eim_dirty = eim;
407 Image_Entry *im_dirty = NULL;
408 Image_Entry *im;
409 Evas_Cache_Engine_Image *cache;
410 unsigned char alloc_eim;
411
412 assert(eim);
413 assert(eim->cache);
414
415 cache = eim->cache;
416 if (!(eim->flags.dirty))
417 {
418 alloc_eim = 0;
419
420 if (eim->flags.need_parent == 1)
421 {
422 im = eim->src;
423 im_dirty = evas_cache_image_dirty(im, x, y, w, h);
424
425 /* If im == im_dirty, this meens that we have only one reference to the eim. */
426 if (im != im_dirty)
427 {
428 if (eim->references == 1)
429 {
430 _evas_cache_engine_image_remove_activ(cache, eim);
431 _evas_cache_engine_image_make_dirty(cache, eim);
432
433 eim->src = im_dirty;
434 }
435 else
436 alloc_eim = 1;
437 }
438 }
439 else
440 if (eim->references > 1)
441 {
442 alloc_eim = 1;
443 }
444 else
445 {
446 _evas_cache_engine_image_remove_activ(cache, eim_dirty);
447 _evas_cache_engine_image_make_dirty(cache, eim_dirty);
448 }
449
450 if (alloc_eim == 1)
451 {
452 int error;
453
454 eim_dirty = _evas_cache_engine_image_alloc(cache, im_dirty, NULL);
455 if (!eim_dirty) goto on_error;
456
457 eim_dirty->w = eim->w;
458 eim_dirty->h = eim->h;
459 eim_dirty->references = 1;
460
461 error = cache->func.dirty(eim_dirty, eim);
462 if (cache->func.debug)
463 cache->func.debug("dirty-engine", eim_dirty);
464
465 if (error != 0) goto on_error;
466
467 evas_cache_engine_image_drop(eim);
468 }
469 }
470
471 if (cache->func.dirty_region)
472 cache->func.dirty_region(eim_dirty, x, y, w, h);
473 if (cache->func.debug)
474 cache->func.debug("dirty-region-engine", eim_dirty);
475
476 return eim_dirty;
477
478 on_error:
479 if (eim) evas_cache_engine_image_drop(eim);
480 if (eim_dirty && eim_dirty != eim)
481 evas_cache_engine_image_drop(eim_dirty);
482 else
483 if (im_dirty) evas_cache_image_drop(im_dirty);
484
485 return NULL;
486}
487
488EAPI Engine_Image_Entry *
489evas_cache_engine_image_alone(Engine_Image_Entry *eim, void *data)
490{
491 Evas_Cache_Engine_Image *cache;
492 Image_Entry *im;
493
494
495 assert(eim);
496 assert(eim->cache);
497
498 cache = eim->cache;
499 im = evas_cache_image_alone(eim->src);
500 if (im != eim->src)
501 {
502 eim = _evas_cache_engine_image_alloc(cache, im, NULL);
503 if (!eim) goto on_error;
504
505 eim->references = 1;
506
507 if (cache->func.constructor(eim, data) != EVAS_LOAD_ERROR_NONE)
508 goto on_error;
509 }
510 /* FIXME */
511 return eim;
512
513 on_error:
514 evas_cache_image_drop(im);
515 return NULL;
516}
517
518static Engine_Image_Entry *
519_evas_cache_engine_image_push_dirty(Evas_Cache_Engine_Image *cache, Image_Entry *im, void *engine_data)
520{
521 Engine_Image_Entry *eim;
522 int error;
523
524 eim = _evas_cache_engine_image_alloc(cache, im, NULL);
525 if (!eim) goto on_error;
526 eim->references = 1;
527
528 error = cache->func.update_data(eim, engine_data);
529 if (cache->func.debug)
530 cache->func.debug("dirty-update_data-engine", eim);
531 if (error != 0) goto on_error;
532
533 return eim;
534
535 on_error:
536 if (eim)
537 evas_cache_engine_image_drop(eim);
538 return NULL;
539}
540
541EAPI Engine_Image_Entry *
542evas_cache_engine_image_copied_data(Evas_Cache_Engine_Image *cache, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, int cspace, void *engine_data)
543{
544 Image_Entry *im;
545
546 assert(cache);
547
548 im = evas_cache_image_copied_data(cache->parent, w, h, image_data, alpha, cspace);
549
550 return _evas_cache_engine_image_push_dirty(cache, im, engine_data);
551}
552
553EAPI Engine_Image_Entry *
554evas_cache_engine_image_data(Evas_Cache_Engine_Image *cache, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, int cspace, void *engine_data)
555{
556 Image_Entry *im;
557
558 assert(cache);
559
560 im = evas_cache_image_data(cache->parent, w, h, image_data, alpha, cspace);
561
562 return _evas_cache_engine_image_push_dirty(cache, im, engine_data);
563}
564
565EAPI Engine_Image_Entry *
566evas_cache_engine_image_size_set(Engine_Image_Entry *eim, unsigned int w, unsigned int h)
567{
568 Evas_Cache_Engine_Image *cache;
569 Engine_Image_Entry *new;
570 Image_Entry *im;
571 const char *hkey;
572 int error;
573
574 assert(eim);
575 assert(eim->cache);
576 assert(eim->references > 0);
577
578 im = NULL;
579 cache = eim->cache;
580
581 if (eim->flags.need_parent == 1)
582 {
583 assert(eim->src);
584
585 if (eim->src->w == w
586 && eim->src->h == h)
587 return eim;
588
589 im = evas_cache_image_size_set(eim->src, w, h);
590 /* FIXME: Good idea to call update_data ? */
591 if (im == eim->src) return eim;
592 eim->src = NULL;
593 }
594
595 hkey = (eim->references > 1 ) ? eina_stringshare_add(eim->cache_key) : NULL;
596
597 new = _evas_cache_engine_image_alloc(cache, im, hkey);
598 if (!new) goto on_error;
599
600 new->w = w;
601 new->h = h;
602 new->references = 1;
603
604 error = cache->func.size_set(new, eim);
605 if (error) goto on_error;
606
607 evas_cache_engine_image_drop(eim);
608 return new;
609
610 on_error:
611 if (new)
612 evas_cache_engine_image_drop(new);
613 else
614 if (im)
615 evas_cache_image_drop(im);
616 evas_cache_engine_image_drop(eim);
617
618 return NULL;
619}
620
621EAPI void
622evas_cache_engine_image_load_data(Engine_Image_Entry *eim)
623{
624 Evas_Cache_Engine_Image *cache;
625 int size = 0;
626
627 assert(eim);
628 assert(eim->src);
629 assert(eim->cache);
630
631 if (eim->flags.loaded) return;
632
633 if (eim->src)
634 evas_cache_image_load_data(eim->src);
635
636 cache = eim->cache;
637 if (cache->func.debug)
638 cache->func.debug("load-engine", eim);
639
640 if (eim->flags.dirty)
641 size = cache->func.mem_size_get(eim);
642 cache = eim->cache;
643 cache->func.load(eim, eim->src);
644 if (eim->flags.dirty)
645 cache->usage += cache->func.mem_size_get(eim) - size;
646
647 eim->flags.loaded = 1;
648}
649
650EAPI Engine_Image_Entry *
651evas_cache_engine_image_engine(Evas_Cache_Engine_Image *cache, void *engine_data)
652{
653 Engine_Image_Entry *eim;
654 Image_Entry *ie;
655 int error;
656
657 ie = evas_cache_image_empty(cache->parent);
658 if (!ie) return NULL;
659
660 eim = _evas_cache_engine_image_alloc(cache, ie, NULL);
661 if (!eim) goto on_error;
662 eim->references = 1;
663
664 error = cache->func.update_data(eim, engine_data);
665 if (cache->func.debug)
666 cache->func.debug("update_data-engine", eim);
667
668 if (error != 0) goto on_error;
669
670 return eim;
671
672 on_error:
673 if (!eim)
674 evas_cache_image_drop(ie);
675 else
676 evas_cache_engine_image_drop(eim);
677
678 return NULL;
679}
680
681EAPI void
682evas_cache_engine_image_colorspace(Engine_Image_Entry *eim, int cspace, void *engine_data)
683{
684 Evas_Cache_Engine_Image *cache = eim->cache;
685
686 assert(cache);
687
688 cache->func.destructor(eim);
689 evas_cache_image_colorspace(eim->src, cspace);
690 cache->func.constructor(eim, engine_data);
691 if (cache->func.debug)
692 cache->func.debug("cosntructor-colorspace-engine", eim);
693}
694
695EAPI void
696evas_cache_engine_parent_not_needed(Engine_Image_Entry *eim)
697{
698 assert(eim);
699 assert(eim->cache);
700
701 eim->flags.need_parent = 0;
702 evas_cache_image_data_not_needed(eim->src);
703}