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