c6ab7bbafdebb51bc6a7c6eaafb34dca52e4bfd1
[framework/uifw/evas.git] / src / lib / cache / evas_cache_image.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <assert.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <errno.h>
10
11 #ifdef HAVE_EVIL
12 # include <Evil.h>
13 #endif
14
15 #include "evas_common.h"
16 #include "evas_private.h"
17
18 //#define CACHEDUMP 1
19
20 #ifdef EVAS_CSERVE
21 // FIXME: cache server and threaded preload clash badly atm - disable
22 //#undef BUILD_ASYNC_PRELOAD
23 #endif
24
25 #ifdef BUILD_ASYNC_PRELOAD
26 typedef struct _Evas_Cache_Preload Evas_Cache_Preload;
27
28 struct _Evas_Cache_Preload
29 {
30    EINA_INLIST;
31    Image_Entry *ie;
32 };
33
34 static LK(engine_lock);
35 static LK(wakeup);
36 static int _evas_cache_mutex_init = 0;
37
38 static Eina_Condition cond_wakeup;
39
40 static void _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target);
41 #endif
42
43 #define FREESTRC(Var)             \
44    if (Var)                       \
45    {                              \
46       eina_stringshare_del(Var);  \
47       Var = NULL;                 \
48    }
49
50 static void _evas_cache_image_dirty_add(Image_Entry *im);
51 static void _evas_cache_image_dirty_del(Image_Entry *im);
52 static void _evas_cache_image_activ_add(Image_Entry *im);
53 static void _evas_cache_image_activ_del(Image_Entry *im);
54 static void _evas_cache_image_lru_add(Image_Entry *im);
55 static void _evas_cache_image_lru_del(Image_Entry *im);
56 static void _evas_cache_image_lru_nodata_add(Image_Entry *im);
57 static void _evas_cache_image_lru_nodata_del(Image_Entry *im);
58
59 static void
60 _evas_cache_image_dirty_add(Image_Entry *im)
61 {
62    if (im->flags.dirty) return;
63    _evas_cache_image_activ_del(im);
64    _evas_cache_image_lru_del(im);
65    _evas_cache_image_lru_nodata_del(im);
66    im->flags.dirty = 1;
67    im->flags.cached = 1;
68 #ifdef EVAS_FRAME_QUEUING
69    LKL(im->cache->lock);
70 #endif
71    im->cache->dirty = eina_inlist_prepend(im->cache->dirty, EINA_INLIST_GET(im));
72 #ifdef EVAS_FRAME_QUEUING
73    LKU(im->cache->lock);
74 #endif
75    if (im->cache_key)
76      {
77         eina_stringshare_del(im->cache_key);
78         im->cache_key = NULL;
79      }
80 }
81
82 static void
83 _evas_cache_image_dirty_del(Image_Entry *im)
84 {
85    if (!im->flags.dirty) return;
86    im->flags.dirty = 0;
87    im->flags.cached = 0;
88 #ifdef EVAS_FRAME_QUEUING
89    LKL(im->cache->lock);
90 #endif
91    im->cache->dirty = eina_inlist_remove(im->cache->dirty, EINA_INLIST_GET(im));
92 #ifdef EVAS_FRAME_QUEUING
93    LKU(im->cache->lock);
94 #endif
95 }
96
97 static void
98 _evas_cache_image_activ_add(Image_Entry *im)
99 {
100    if (im->flags.activ) return;
101    _evas_cache_image_dirty_del(im);
102    _evas_cache_image_lru_del(im);
103    _evas_cache_image_lru_nodata_del(im);
104    if (!im->cache_key) return;
105    im->flags.activ = 1;
106    im->flags.cached = 1;
107 #ifdef EVAS_FRAME_QUEUING
108    LKL(im->cache->lock);
109 #endif
110    eina_hash_direct_add(im->cache->activ, im->cache_key, im);
111 #ifdef EVAS_FRAME_QUEUING
112    LKU(im->cache->lock);
113 #endif
114 }
115
116 static void
117 _evas_cache_image_activ_del(Image_Entry *im)
118 {
119    if (!im->flags.activ) return;
120    if (!im->cache_key) return;
121    im->flags.activ = 0;
122    im->flags.cached = 0;
123 #ifdef EVAS_FRAME_QUEUING
124    LKL(im->cache->lock);
125 #endif
126    eina_hash_del(im->cache->activ, im->cache_key, im);
127 #ifdef EVAS_FRAME_QUEUING
128    LKU(im->cache->lock);
129 #endif
130 }
131
132 static void
133 _evas_cache_image_lru_add(Image_Entry *im)
134 {
135    if (im->flags.lru) return;
136    _evas_cache_image_dirty_del(im);
137    _evas_cache_image_activ_del(im);
138    _evas_cache_image_lru_nodata_del(im); 
139    if (!im->cache_key) return;
140    im->flags.lru = 1;
141    im->flags.cached = 1;
142 #ifdef EVAS_FRAME_QUEUING
143    LKL(im->cache->lock);
144 #endif
145    eina_hash_direct_add(im->cache->inactiv, im->cache_key, im);
146    im->cache->lru = eina_inlist_prepend(im->cache->lru, EINA_INLIST_GET(im));
147    im->cache->usage += im->cache->func.mem_size_get(im);
148 #ifdef EVAS_FRAME_QUEUING
149    LKU(im->cache->lock);
150 #endif
151 }
152
153 static void
154 _evas_cache_image_lru_del(Image_Entry *im)
155 {
156    if (!im->flags.lru) return;
157    if (!im->cache_key) return;
158    im->flags.lru = 0;
159    im->flags.cached = 0;
160 #ifdef EVAS_FRAME_QUEUING
161    LKL(im->cache->lock);
162 #endif
163    eina_hash_del(im->cache->inactiv, im->cache_key, im);
164    im->cache->lru = eina_inlist_remove(im->cache->lru, EINA_INLIST_GET(im));
165    im->cache->usage -= im->cache->func.mem_size_get(im);
166 #ifdef EVAS_FRAME_QUEUING
167    LKU(im->cache->lock);
168 #endif
169 }
170
171 static void
172 _evas_cache_image_lru_nodata_add(Image_Entry *im)
173 {
174    if (im->flags.lru_nodata) return;
175    _evas_cache_image_dirty_del(im);
176    _evas_cache_image_activ_del(im);
177    _evas_cache_image_lru_del(im);
178    im->flags.lru = 1;
179    im->flags.cached = 1;
180 #ifdef EVAS_FRAME_QUEUING
181    LKL(im->cache->lock);
182 #endif
183    im->cache->lru_nodata = eina_inlist_prepend(im->cache->lru_nodata, EINA_INLIST_GET(im));
184 #ifdef EVAS_FRAME_QUEUING
185    LKU(im->cache->lock);
186 #endif
187 }
188
189 static void
190 _evas_cache_image_lru_nodata_del(Image_Entry *im)
191 {
192    if (!im->flags.lru_nodata) return;
193    im->flags.lru = 0;
194    im->flags.cached = 0;
195 #ifdef EVAS_FRAME_QUEUING
196    LKL(im->cache->lock);
197 #endif
198    im->cache->lru_nodata = eina_inlist_remove(im->cache->lru_nodata, EINA_INLIST_GET(im));
199 #ifdef EVAS_FRAME_QUEUING
200    LKU(im->cache->lock);
201 #endif
202 }
203
204 static void
205 _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
206 {
207    if (!ie) return;
208    if (cache->func.debug) cache->func.debug("deleting", ie);
209 #ifdef BUILD_ASYNC_PRELOAD
210    if (ie->flags.delete_me == 1) return;
211    if (ie->preload)
212      {
213         ie->flags.delete_me = 1;
214         _evas_cache_image_entry_preload_remove(ie, NULL);
215         return;
216      }
217 #endif
218
219    _evas_cache_image_dirty_del(ie);
220    _evas_cache_image_activ_del(ie);
221    _evas_cache_image_lru_del(ie);
222    _evas_cache_image_lru_nodata_del(ie);
223
224    cache->func.destructor(ie);
225    FREESTRC(ie->cache_key);
226    FREESTRC(ie->file);
227    FREESTRC(ie->key);
228    ie->cache = NULL;
229    cache->func.surface_delete(ie);
230
231 #ifdef BUILD_ASYNC_PRELOAD
232    LKD(ie->lock);
233    LKD(ie->lock_cancel);
234 #endif
235 #ifdef EVAS_FRAME_QUEUING
236    LKD(ie->lock_references);
237 #endif
238    cache->func.dealloc(ie);
239 }
240
241 static Eina_Bool
242 _timestamp_compare(Image_Timestamp *tstamp, struct stat *st)
243 {
244    if (tstamp->mtime != st->st_mtime) return EINA_FALSE;
245    if (tstamp->size != st->st_size) return EINA_FALSE;
246    if (tstamp->ino != st->st_ino) return EINA_FALSE;
247 #ifdef _STAT_VER_LINUX
248 #if (defined __USE_MISC && defined st_mtime)
249    if (tstamp->mtime_nsec != (unsigned long int)st->st_mtim.tv_nsec)
250       return EINA_FALSE;
251 #else
252    if (tstamp->mtime_nsec != (unsigned long int)st->st_mtimensec)
253       return EINA_FALSE;
254 #endif
255 #endif
256    return EINA_TRUE;
257 }
258
259 static void
260 _timestamp_build(Image_Timestamp *tstamp, struct stat *st)
261 {
262    tstamp->mtime = st->st_mtime;
263    tstamp->size = st->st_size;
264    tstamp->ino = st->st_ino;
265 #ifdef _STAT_VER_LINUX
266 #if (defined __USE_MISC && defined st_mtime)
267    tstamp->mtime_nsec = (unsigned long int)st->st_mtim.tv_nsec;
268 #else
269    tstamp->mtime_nsec = (unsigned long int)st->st_mtimensec;
270 #endif
271 #endif
272 }
273
274 static Image_Entry *
275 _evas_cache_image_entry_new(Evas_Cache_Image *cache,
276                             const char *hkey,
277                             Image_Timestamp *tstamp,
278                             const char *file,
279                             const char *key,
280                             RGBA_Image_Loadopts *lo,
281                             int *error)
282 {
283    Image_Entry  *ie;
284
285    ie = cache->func.alloc();
286    if (!ie)
287      {
288         *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
289         return NULL;
290      }
291    ie->cache = cache;
292    if (hkey) ie->cache_key = eina_stringshare_add(hkey);
293    ie->flags.need_data = 1;
294    ie->space = EVAS_COLORSPACE_ARGB8888;
295    ie->w = -1;
296    ie->h = -1;
297    ie->scale = 1;
298    if (file) ie->file = eina_stringshare_add(file);
299    if (key) ie->key = eina_stringshare_add(key);
300    if (tstamp) ie->tstamp = *tstamp;
301    else memset(&ie->tstamp, 0, sizeof(Image_Timestamp));
302
303 #ifdef EVAS_FRAME_QUEUING
304    LKI(ie->lock_references);
305 #endif
306 #ifdef BUILD_ASYNC_PRELOAD
307    LKI(ie->lock);
308    LKI(ie->lock_cancel); 
309 #endif
310    
311    if (lo) ie->load_opts = *lo;
312    if (ie->file)
313      {
314         *error = cache->func.constructor(ie);
315         if (*error != EVAS_LOAD_ERROR_NONE)
316           {
317              _evas_cache_image_entry_delete(cache, ie);
318              return NULL;
319           }
320      }
321    if (cache->func.debug) cache->func.debug("build", ie);
322    if (ie->cache_key) _evas_cache_image_activ_add(ie);
323    else _evas_cache_image_dirty_add(ie);
324    return ie;
325 }
326
327 static void
328 _evas_cache_image_entry_surface_alloc__locked(Evas_Cache_Image *cache,
329                                               Image_Entry *ie,
330                                               unsigned int wmin,
331                                               unsigned int hmin)
332 {
333    if ((ie->allocated.w == wmin) && (ie->allocated.h == hmin)) return;
334    if (cache->func.surface_alloc(ie, wmin, hmin))
335      {
336         wmin = 0;
337         hmin = 0;
338      }
339    ie->w = wmin;
340    ie->h = hmin;
341    ie->allocated.w = wmin;
342    ie->allocated.h = hmin;
343 }
344
345 static void
346 _evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
347                                       Image_Entry *ie, int w, int h)
348 {
349    int wmin = w > 0 ? w : 1;
350    int hmin = h > 0 ? h : 1;
351 #ifdef BUILD_ASYNC_PRELOAD
352    LKL(engine_lock);
353 #endif
354    _evas_cache_image_entry_surface_alloc__locked(cache, ie, wmin, hmin);
355 #ifdef BUILD_ASYNC_PRELOAD
356    LKU(engine_lock);
357 #endif
358 }
359
360 #ifdef BUILD_ASYNC_PRELOAD
361 static void
362 _evas_cache_image_async_heavy(void *data)
363 {
364    Evas_Cache_Image *cache;
365    Image_Entry *current;
366    int error;
367    int pchannel;
368
369    current = data;
370
371    LKL(current->lock);
372    pchannel = current->channel;
373    current->channel++;
374    cache = current->cache;
375
376    if ((!current->flags.loaded) && 
377        ((Evas_Image_Load_Func*) current->info.module)->threadable)
378      {
379         error = cache->func.load(current);
380         if (cache->func.debug) cache->func.debug("load", current);
381         current->load_error = error;
382         if (error != EVAS_LOAD_ERROR_NONE)
383           {
384              current->flags.loaded = 0;
385              _evas_cache_image_entry_surface_alloc(cache, current,
386                                                    current->w, current->h);
387           }
388         else
389           {
390              current->flags.loaded = 1;
391           }
392      }
393    current->channel = pchannel;
394    // check the unload cancel flag
395    LKL(current->lock_cancel);
396    if (current->unload_cancel)
397      {
398         current->unload_cancel = EINA_FALSE;
399         cache->func.surface_delete(current);
400         current->flags.loaded = 0;
401         current->flags.preload_done = 0;
402      }
403    LKU(current->lock_cancel);
404    LKU(current->lock);
405 }
406
407 static void
408 _evas_cache_image_async_end(void *data)
409 {
410    Image_Entry *ie = (Image_Entry *)data;
411    Evas_Cache_Target *tmp;
412
413    ie->cache->preload = eina_list_remove(ie->cache->preload, ie);
414    ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
415    ie->preload = NULL;
416    ie->flags.preload_done = ie->flags.loaded;
417    while ((tmp = ie->targets))
418      {
419         evas_object_inform_call_image_preloaded((Evas_Object*) tmp->target);
420         ie->targets = (Evas_Cache_Target *)
421            eina_inlist_remove(EINA_INLIST_GET(ie->targets), 
422                               EINA_INLIST_GET(ie->targets));
423         free(tmp);
424      }
425 }
426
427 static void
428 _evas_cache_image_async_cancel(void *data)
429 {
430    Evas_Cache_Image *cache = NULL;
431    Image_Entry *ie = (Image_Entry *)data;
432    
433    ie->preload = NULL;
434    ie->cache->pending = eina_list_remove(ie->cache->pending, ie);
435    if ((ie->flags.delete_me) || (ie->flags.dirty))
436      {
437         ie->flags.delete_me = 0;
438         _evas_cache_image_entry_delete(ie->cache, ie);
439         return;
440      }
441    if (ie->flags.loaded) _evas_cache_image_async_end(ie);
442 #ifdef EVAS_FRAME_QUEUING
443    LKL(ie->lock_references);
444 #endif
445    if (ie->references == 0)
446      {
447         _evas_cache_image_lru_add(ie);
448         cache = ie->cache;
449      }
450 #ifdef EVAS_FRAME_QUEUING
451    LKU(ie->lock_references);
452 #endif
453    if (cache) evas_cache_image_flush(cache);
454 }
455
456 // note - preload_add assumes a target is ONLY added ONCE to the image
457 // entry. make sure you only add once, or remove first, then add
458 static int
459 _evas_cache_image_entry_preload_add(Image_Entry *ie, const void *target)
460 {
461    Evas_Cache_Target *tg;
462
463    if (ie->flags.preload_done) return 0;
464    tg = malloc(sizeof (Evas_Cache_Target));
465    if (!tg) return 0;
466
467    tg->target = target;
468    ie->targets = (Evas_Cache_Target *)
469       eina_inlist_append(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
470    if (!ie->preload)
471      {
472         ie->cache->preload = eina_list_append(ie->cache->preload, ie);
473         ie->flags.pending = 0;
474         ie->preload = evas_preload_thread_run(_evas_cache_image_async_heavy,
475                                               _evas_cache_image_async_end,
476                                               _evas_cache_image_async_cancel,
477                                               ie);
478      }
479    return 1;
480 }
481
482 static void
483 _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target)
484 {
485    if (target)
486      {
487         Evas_Cache_Target *tg;
488
489         EINA_INLIST_FOREACH(ie->targets, tg)
490           {
491              if (tg->target == target)
492                {
493                   // FIXME: No callback when we cancel only for one target ?
494                   ie->targets = (Evas_Cache_Target *)
495                      eina_inlist_remove(EINA_INLIST_GET(ie->targets),
496                                         EINA_INLIST_GET(tg));
497                   free(tg);
498                   break;
499                }
500           }
501      }
502    else
503      {
504         Evas_Cache_Target *tg;
505
506         while (ie->targets)
507           {
508              tg = ie->targets;
509              ie->targets = (Evas_Cache_Target *)
510                 eina_inlist_remove(EINA_INLIST_GET(ie->targets),
511                                    EINA_INLIST_GET(tg));
512              free(tg);
513           }
514      }
515
516    if ((!ie->targets) && (ie->preload) && (!ie->flags.pending))
517      {
518         ie->cache->preload = eina_list_remove(ie->cache->preload, ie);
519         ie->cache->pending = eina_list_append(ie->cache->pending, ie);
520         ie->flags.pending = 1;
521         evas_preload_thread_cancel(ie->preload);
522      }
523 }
524 #endif
525
526 EAPI int
527 evas_cache_image_usage_get(Evas_Cache_Image *cache)
528 {
529    return cache->usage;
530 }
531
532 EAPI int
533 evas_cache_image_get(Evas_Cache_Image *cache)
534 {
535    return cache->limit;
536 }
537
538 EAPI void
539 evas_cache_image_set(Evas_Cache_Image *cache, unsigned int limit)
540 {
541 #ifdef EVAS_FRAME_QUEUING
542    LKL(cache->lock);
543 #endif
544    if (cache->limit == limit)
545      {
546 #ifdef EVAS_FRAME_QUEUING
547         LKU(cache->lock);
548 #endif
549         return;
550      }
551    cache->limit = limit;
552 #ifdef EVAS_FRAME_QUEUING
553    LKU(cache->lock);
554 #endif
555    evas_cache_image_flush(cache);
556 }
557
558 EAPI Evas_Cache_Image *
559 evas_cache_image_init(const Evas_Cache_Image_Func *cb)
560 {
561    Evas_Cache_Image *cache;
562
563 #ifdef BUILD_ASYNC_PRELOAD
564    if (_evas_cache_mutex_init++ == 0)
565      {
566         LKI(engine_lock);
567         LKI(wakeup);
568         eina_condition_new(&cond_wakeup, &wakeup);
569      }
570 #endif
571
572    cache = calloc(1, sizeof(Evas_Cache_Image));
573    if (!cache) return NULL;
574    cache->func = *cb;
575    cache->inactiv = eina_hash_string_superfast_new(NULL);
576    cache->activ = eina_hash_string_superfast_new(NULL);
577    cache->references = 1;
578 #ifdef EVAS_FRAME_QUEUING
579    LKI(cache->lock);
580 #endif
581    return cache;
582 }
583
584 static Eina_Bool
585 _evas_cache_image_free_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, void *fdata)
586 {
587    Eina_List **delete_list = fdata;
588    *delete_list = eina_list_prepend(*delete_list, data);
589    return EINA_TRUE;
590 }
591
592 EAPI void
593 evas_cache_image_shutdown(Evas_Cache_Image *cache)
594 {
595    Eina_List *delete_list;
596    Image_Entry  *im;
597
598 #ifdef EVAS_FRAME_QUEUING
599    LKL(cache->lock);
600 #endif
601    cache->references--;
602    if (cache->references != 0)
603      {
604 #ifdef EVAS_FRAME_QUEUING
605         LKU(cache->lock);
606 #endif
607         return;
608      }
609 #ifdef EVAS_FRAME_QUEUING
610    /* Release and destroy lock early ! */
611    LKU(cache->lock);
612    LKD(cache->lock);
613 #endif
614
615 #ifdef BUILD_ASYNC_PRELOAD
616    EINA_LIST_FREE(cache->preload, im)
617      {
618         /* By doing that we are protecting us from destroying image when the cache is no longer available. */
619         im->flags.delete_me = 1;
620         _evas_cache_image_entry_preload_remove(im, NULL);
621      }
622    evas_async_events_process();
623 #endif
624    while (cache->lru)
625      {
626         im = (Image_Entry *)cache->lru;
627         _evas_cache_image_entry_delete(cache, im);
628      }
629    while (cache->lru_nodata)
630      {
631         im = (Image_Entry *)cache->lru_nodata;
632         _evas_cache_image_entry_delete(cache, im);
633      }
634    /* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
635    while (cache->dirty)
636      {
637         im = (Image_Entry *)cache->dirty;
638         _evas_cache_image_entry_delete(cache, im);
639      }
640    delete_list = NULL;
641    eina_hash_foreach(cache->activ, _evas_cache_image_free_cb, &delete_list);
642    while (delete_list)
643      {
644         _evas_cache_image_entry_delete(cache, eina_list_data_get(delete_list));
645         delete_list = eina_list_remove_list(delete_list, delete_list);
646      }
647
648 #ifdef BUILD_ASYNC_PRELOAD
649    /* Now wait for all pending image to die */
650    while (cache->pending)
651      {
652         evas_async_events_process();
653         LKL(wakeup);
654         // the lazy bum who did eain threads and converted this code
655         // didn't bother to worry about Eina_Lock being a different type
656         // to a pthread mutex.
657         if (cache->pending) eina_condition_wait(&cond_wakeup);
658         LKU(wakeup);
659      }
660 #endif
661    eina_hash_free(cache->activ);
662    eina_hash_free(cache->inactiv);
663    free(cache);
664
665 #ifdef BUILD_ASYNC_PRELOAD
666    if (--_evas_cache_mutex_init == 0)
667      {
668         eina_condition_free(&cond_wakeup);
669         LKD(engine_lock);
670         LKD(wakeup);
671      }
672 #endif
673 }
674
675 EAPI Image_Entry *
676 evas_cache_image_request(Evas_Cache_Image *cache, const char *file, 
677                          const char *key, RGBA_Image_Loadopts *lo, int *error)
678 {
679    const char           *ckey = "(null)";
680    char                 *hkey;
681    Image_Entry          *im;
682    Evas_Image_Load_Opts  prevent = { 0, 0, 0, 0, { 0, 0, 0, 0 }, 0 };
683    size_t                size;
684    int                   stat_done = 0, stat_failed = 0;
685    size_t                file_length;
686    size_t                key_length;
687    struct stat           st;
688    Image_Timestamp       tstamp;
689
690    if ((!file) || ((!file) && (!key)))
691      {
692         *error = EVAS_LOAD_ERROR_GENERIC;
693         return NULL;
694      }
695
696    /* generate hkey from file+key+load opts */
697    file_length = strlen(file);
698    key_length = key ? strlen(key) : 6;
699    size = file_length + key_length + 132;
700    hkey = alloca(sizeof (char) * size);
701    memcpy(hkey, file, file_length);
702    size = file_length;
703    memcpy(hkey + size, "//://", 5);
704    size += 5;
705    if (key) ckey = key;
706    memcpy(hkey + size, ckey, key_length);
707    size += key_length;
708    if ((!lo) ||
709        (lo &&
710         (lo->scale_down_by == 0) &&
711         (lo->dpi == 0.0) &&
712         ((lo->w == 0) || (lo->h == 0)) &&
713         ((lo->region.w == 0) || (lo->region.h == 0)) &&
714         (lo->orientation == 0)
715         ))
716      {
717         lo = &prevent;
718      }
719    else
720      {
721         memcpy(hkey + size, "//@/", 4);
722         size += 4;
723         size += eina_convert_xtoa(lo->scale_down_by, hkey + size);
724         hkey[size] = '/';
725         size += 1;
726         size += eina_convert_dtoa(lo->dpi, hkey + size);
727         hkey[size] = '/';
728         size += 1;
729         size += eina_convert_xtoa(lo->w, hkey + size);
730         hkey[size] = 'x';
731         size += 1;
732         size += eina_convert_xtoa(lo->h, hkey + size);
733         hkey[size] = '/';
734         size += 1;
735         size += eina_convert_xtoa(lo->region.x, hkey + size);
736         hkey[size] = '+';
737         size += 1;
738         size += eina_convert_xtoa(lo->region.y, hkey + size);
739         hkey[size] = '.';
740         size += 1;
741         size += eina_convert_xtoa(lo->region.w, hkey + size);
742         hkey[size] = 'x';
743         size += 1;
744         size += eina_convert_xtoa(lo->region.h, hkey + size);
745
746         if (lo->orientation)
747           {
748              hkey[size] = '/';
749              hkey[size] = 'o';
750              size += 2;
751           }
752      }
753    hkey[size] = '\0';
754
755    /* find image by key in active hash */
756 #ifdef EVAS_FRAME_QUEUING
757    LKL(cache->lock);
758 #endif
759    im = eina_hash_find(cache->activ, hkey);
760 #ifdef EVAS_FRAME_QUEUING
761    LKU(cache->lock);
762 #endif
763    if (im)
764      {
765         int ok = 1;
766
767         stat_done = 1;
768         if (stat(file, &st) < 0)
769            {
770               stat_failed = 1;
771               ok = 0;
772            }
773         else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
774         if (ok) goto on_ok;
775         /* image we found doesn't match what's on disk (stat info wise)
776          * so dirty the active cache entry so we never find it again. this
777          * also implicitly guarantees that we only have 1 active copy
778          * of an image at a given key. we wither find it and keep re-reffing
779          * it or we dirty it and get it out */
780         _evas_cache_image_dirty_add(im);
781         im = NULL;
782      }
783
784    /* find image by key in inactive/lru hash */
785 #ifdef EVAS_FRAME_QUEUING
786    LKL(cache->lock);
787 #endif
788    im = eina_hash_find(cache->inactiv, hkey);
789 #ifdef EVAS_FRAME_QUEUING
790    LKU(cache->lock);
791 #endif
792    if (im)
793      {
794         int ok = 1;
795
796         if (!stat_done)
797           {
798              stat_done = 1;
799              if (stat(file, &st) < 0)
800                {
801                   stat_failed = 1;
802                   ok = 0;
803                }
804              else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
805           }
806         else if (!_timestamp_compare(&(im->tstamp), &st)) ok = 0;
807
808         if (ok)
809           {
810              /* remove from lru and make it active again */
811              _evas_cache_image_lru_del(im);
812              _evas_cache_image_activ_add(im);
813              goto on_ok;
814           }
815         /* as avtive cache find - if we match in lru and its invalid, dirty */
816         _evas_cache_image_dirty_add(im);
817         im = NULL;
818      }
819    if (stat_failed) goto on_stat_error;
820    
821    if (!stat_done)
822      {
823         if (stat(file, &st) < 0) goto on_stat_error;
824      }
825    _timestamp_build(&tstamp, &st);
826    im = _evas_cache_image_entry_new(cache, hkey, &tstamp, file, key, 
827                                     lo, error);
828    if (!im) goto on_stat_error;
829    if (cache->func.debug) cache->func.debug("request", im);
830
831  on_ok:
832    *error = EVAS_LOAD_ERROR_NONE;
833 #ifdef EVAS_FRAME_QUEUING
834    LKL(im->lock_references);
835 #endif
836    im->references++;
837 #ifdef EVAS_FRAME_QUEUING
838    LKU(im->lock_references);
839 #endif
840    return im;
841
842  on_stat_error:
843 #ifndef _WIN32
844    if ((errno == ENOENT) || (errno == ENOTDIR) ||
845        (errno == ENAMETOOLONG) || (errno == ELOOP))
846 #else
847    if (errno == ENOENT)
848 #endif
849      *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
850 #ifndef _WIN32
851    else if ((errno == ENOMEM) || (errno == EOVERFLOW))
852 #else
853    else if (errno == ENOMEM)
854 #endif
855      *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
856    else if (errno == EACCES)
857      *error = EVAS_LOAD_ERROR_PERMISSION_DENIED;
858    else
859      *error = EVAS_LOAD_ERROR_GENERIC;
860
861    if (im) _evas_cache_image_entry_delete(cache, im);
862    return NULL;
863 }
864
865 EAPI void
866 evas_cache_image_drop(Image_Entry *im)
867 {
868    Evas_Cache_Image *cache;
869    int references;
870
871 #ifdef EVAS_FRAME_QUEUING
872    LKL(im->lock_references);
873 #endif
874    im->references--;
875    if (im->references < 0) im->references = 0;
876    references = im->references;
877 #ifdef EVAS_FRAME_QUEUING
878    LKU(im->lock_references);
879 #endif
880
881    cache = im->cache;
882
883    if (references == 0)
884      {
885 #ifdef EVAS_FRAME_QUEUING
886         LKL(im->ref_fq_add);
887         LKL(im->ref_fq_del);
888         if (im->ref_fq[0] != im->ref_fq[1])
889           {
890              LKU(im->ref_fq_add);
891              LKU(im->ref_fq_del);
892              return;
893           }
894         LKU(im->ref_fq_add);
895         LKU(im->ref_fq_del);
896 #endif
897
898 #ifdef BUILD_ASYNC_PRELOAD
899         if (im->preload)
900           {
901              _evas_cache_image_entry_preload_remove(im, NULL);
902              return;
903           }
904 #endif
905
906         if (im->flags.dirty)
907           {
908              _evas_cache_image_entry_delete(cache, im);
909              return;
910           }
911         _evas_cache_image_lru_add(im);
912         if (cache) evas_cache_image_flush(cache);
913      }
914 }
915
916 EAPI void
917 evas_cache_image_data_not_needed(Image_Entry *im)
918 {
919    Evas_Cache_Image *cache;
920    int references;
921
922    /* FIXME: no one uses this api... well evas_cache_engine_parent_not_needed()
923     * does, but nothing uses that! */
924    cache = im->cache;
925 #ifdef EVAS_FRAME_QUEUING
926    LKL(im->lock_references);
927 #endif
928    references = im->references;
929 #ifdef EVAS_FRAME_QUEUING
930    LKU(im->lock_references);
931 #endif
932    if (references > 1) return;
933    if ((im->flags.dirty) || (!im->flags.need_data)) return;
934    _evas_cache_image_lru_nodata_add(im);
935 }
936
937 EAPI Image_Entry *
938 evas_cache_image_dirty(Image_Entry *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
939 {
940    Image_Entry *im_dirty = im;
941    Evas_Cache_Image *cache;
942    int references;
943
944    cache = im->cache;
945    if (!(im->flags.dirty))
946      {
947 #ifdef EVAS_FRAME_QUEUING
948         LKL(im->lock_references);
949 #endif
950         references = im->references;
951 #ifdef EVAS_FRAME_QUEUING
952         LKU(im->lock_references);
953 #endif
954 #ifndef EVAS_CSERVE
955         // if ref 1 also copy if using shared cache as its read-only
956         if (references == 1) im_dirty = im;
957         else
958 #endif
959           {
960              int error;
961              
962              im_dirty = 
963                 evas_cache_image_copied_data(cache, im->w, im->h, 
964                                              evas_cache_image_pixels(im), 
965                                              im->flags.alpha, im->space);
966              if (!im_dirty) goto on_error;
967              if (cache->func.debug) cache->func.debug("dirty-src", im);
968              error = cache->func.dirty(im_dirty, im);
969              if (cache->func.debug) cache->func.debug("dirty-out", im_dirty);
970 #ifdef EVAS_FRAME_QUEUING
971              LKL(im_dirty->lock_references);
972 #endif
973              im_dirty->references = 1;
974 #ifdef EVAS_FRAME_QUEUING
975              LKU(im_dirty->lock_references);
976 #endif
977              evas_cache_image_drop(im);
978           }
979         _evas_cache_image_dirty_add(im_dirty);
980      }
981    
982    if (cache->func.debug) cache->func.debug("dirty-region", im_dirty);
983    if (cache->func.dirty_region)
984       cache->func.dirty_region(im_dirty, x, y, w, h);
985    return im_dirty;
986
987 on_error:
988    if (im_dirty) _evas_cache_image_entry_delete(cache, im_dirty);
989    evas_cache_image_drop(im);
990    return NULL;
991 }
992
993 EAPI Image_Entry *
994 evas_cache_image_alone(Image_Entry *im)
995 {
996    Evas_Cache_Image *cache;
997    Image_Entry *im_dirty = im;
998    int references;
999
1000    cache = im->cache;
1001 #ifdef EVAS_FRAME_QUEUING
1002    LKL(im->lock_references);
1003 #endif
1004    references = im->references;
1005 #ifdef EVAS_FRAME_QUEUING
1006    LKU(im->lock_references);
1007 #endif
1008
1009    if (references <= 1)
1010      {
1011         if (!im->flags.dirty) _evas_cache_image_dirty_add(im);
1012      }
1013    else
1014      {
1015         int error;
1016
1017         im_dirty = evas_cache_image_copied_data(cache, im->w, im->h, 
1018                                                 evas_cache_image_pixels(im), 
1019                                                 im->flags.alpha, 
1020                                                 im->space);
1021         if (!im_dirty) goto on_error;
1022         if (cache->func.debug) cache->func.debug("dirty-src", im);
1023         error = cache->func.dirty(im_dirty, im);
1024         if (cache->func.debug) cache->func.debug("dirty-out", im_dirty);
1025 #ifdef EVAS_FRAME_QUEUING
1026         LKL(im_dirty->lock_references);
1027 #endif
1028         im_dirty->references = 1;
1029 #ifdef EVAS_FRAME_QUEUING
1030         LKU(im_dirty->lock_references);
1031 #endif
1032         evas_cache_image_drop(im);
1033      }
1034    return im_dirty;
1035    
1036 on_error:
1037    if (im_dirty) _evas_cache_image_entry_delete(cache, im_dirty);
1038    evas_cache_image_drop(im);
1039    return NULL;
1040 }
1041
1042 EAPI Image_Entry *
1043 evas_cache_image_copied_data(Evas_Cache_Image *cache, 
1044                              unsigned int w, unsigned int h, 
1045                              DATA32 *image_data, int alpha, int cspace)
1046 {
1047    Image_Entry *im;
1048    
1049    if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
1050        (cspace == EVAS_COLORSPACE_YCBCR422P709_PL) ||
1051        (cspace == EVAS_COLORSPACE_YCBCR422601_PL))
1052       w &= ~0x1;
1053    
1054    im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
1055    if (!im) return NULL;
1056    im->space = cspace;
1057    im->flags.alpha = alpha;
1058    _evas_cache_image_entry_surface_alloc(cache, im, w, h);
1059    if (cache->func.copied_data(im, w, h, image_data, alpha, cspace) != 0)
1060      {
1061         _evas_cache_image_entry_delete(cache, im);
1062         return NULL;
1063      }
1064 #ifdef EVAS_FRAME_QUEUING
1065    LKL(im->lock_references);
1066 #endif
1067    im->references = 1;
1068 #ifdef EVAS_FRAME_QUEUING
1069    LKU(im->lock_references);
1070 #endif
1071    if (cache->func.debug) cache->func.debug("copied-data", im);
1072    return im;
1073 }
1074
1075 EAPI Image_Entry *
1076 evas_cache_image_data(Evas_Cache_Image *cache, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, int cspace)
1077 {
1078    Image_Entry *im;
1079
1080    if ((cspace == EVAS_COLORSPACE_YCBCR422P601_PL) ||
1081        (cspace == EVAS_COLORSPACE_YCBCR422P709_PL) ||
1082        (cspace == EVAS_COLORSPACE_YCBCR422601_PL))
1083       w &= ~0x1;
1084    
1085    im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
1086    if (!im) return NULL;
1087    im->w = w;
1088    im->h = h;
1089    im->flags.alpha = alpha;
1090    if (cache->func.data(im, w, h, image_data, alpha, cspace) != 0)
1091      {
1092         _evas_cache_image_entry_delete(cache, im);
1093         return NULL;
1094      }
1095 #ifdef EVAS_FRAME_QUEUING
1096    LKL(im->lock_references);
1097 #endif
1098    im->references = 1;
1099 #ifdef EVAS_FRAME_QUEUING
1100    LKU(im->lock_references);
1101 #endif
1102    if (cache->func.debug) cache->func.debug("data", im);
1103    return im;
1104 }
1105
1106 EAPI void
1107 evas_cache_image_surface_alloc(Image_Entry *im, unsigned int w, unsigned int h)
1108 {
1109    Evas_Cache_Image *cache = im->cache;
1110    
1111    if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
1112        (im->space == EVAS_COLORSPACE_YCBCR422P709_PL) ||
1113        (im->space == EVAS_COLORSPACE_YCBCR422601_PL))
1114      w &= ~0x1;
1115
1116    _evas_cache_image_entry_surface_alloc(cache, im, w, h);
1117    if (cache->func.debug) cache->func.debug("surface-alloc", im);
1118 }
1119
1120 EAPI Image_Entry *
1121 evas_cache_image_size_set(Image_Entry *im, unsigned int w, unsigned int h)
1122 {
1123    Evas_Cache_Image *cache;
1124    Image_Entry *im2 = NULL;
1125    int error;
1126
1127    if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
1128        (im->space == EVAS_COLORSPACE_YCBCR422P709_PL) ||
1129        (im->space == EVAS_COLORSPACE_YCBCR422601_PL))
1130      w &= ~0x1;
1131    if ((im->w == w) && (im->h == h)) return im;
1132
1133    cache = im->cache;
1134    im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, &error);
1135    if (!im2) goto on_error;
1136
1137    im2->flags.alpha = im->flags.alpha;
1138    im2->space = im->space;
1139    im2->load_opts = im->load_opts;
1140    _evas_cache_image_entry_surface_alloc(cache, im2, w, h);
1141    error = cache->func.size_set(im2, im, w, h);
1142    if (error != 0) goto on_error;
1143 #ifdef EVAS_FRAME_QUEUING
1144    LKL(im2->lock_references);
1145 #endif
1146    im2->references = 1;
1147 #ifdef EVAS_FRAME_QUEUING
1148    LKU(im2->lock_references);
1149 #endif
1150    evas_cache_image_drop(im);
1151    if (cache->func.debug) cache->func.debug("size_set", im2);
1152    return im2;
1153
1154  on_error:
1155    if (im2) _evas_cache_image_entry_delete(cache, im2);
1156    evas_cache_image_drop(im);
1157    return NULL;
1158 }
1159
1160 EAPI int
1161 evas_cache_image_load_data(Image_Entry *im)
1162 {
1163 #ifdef BUILD_ASYNC_PRELOAD
1164    Eina_Bool preload = EINA_FALSE;
1165 #endif
1166    int error = EVAS_LOAD_ERROR_NONE;
1167
1168    if ((im->flags.loaded) && (!im->flags.animated)) return error;
1169 #ifdef BUILD_ASYNC_PRELOAD
1170    if (im->preload)
1171      {
1172         preload = EINA_TRUE;
1173         if (!im->flags.pending)
1174           {
1175              im->cache->preload = eina_list_remove(im->cache->preload, im);
1176              im->cache->pending = eina_list_append(im->cache->pending, im);
1177              im->flags.pending = 1;
1178              evas_preload_thread_cancel(im->preload);
1179           }
1180         evas_async_events_process();
1181         LKL(wakeup);
1182         while (im->preload)
1183           {
1184              eina_condition_wait(&cond_wakeup);
1185              LKU(wakeup);
1186              evas_async_events_process();
1187              LKL(wakeup);
1188           }
1189         LKU(wakeup);
1190      }
1191    
1192    if ((im->flags.loaded) && (!im->flags.animated)) return error;
1193    LKL(im->lock);
1194 #endif
1195    im->flags.in_progress = EINA_TRUE;
1196    error = im->cache->func.load(im);
1197    im->flags.in_progress = EINA_FALSE;
1198 #ifdef BUILD_ASYNC_PRELOAD
1199    LKU(im->lock);
1200 #endif
1201    im->flags.loaded = 1;
1202    if (im->cache->func.debug) im->cache->func.debug("load", im);
1203    if (error != EVAS_LOAD_ERROR_NONE)
1204      {
1205         _evas_cache_image_entry_surface_alloc(im->cache, im, im->w, im->h);
1206         im->flags.loaded = 0;
1207      }
1208 #ifdef BUILD_ASYNC_PRELOAD
1209    if (preload) _evas_cache_image_async_end(im);
1210 #endif
1211    return error;
1212 }
1213
1214 EAPI void
1215 evas_cache_image_unload_data(Image_Entry *im)
1216 {
1217    if (im->flags.in_progress) return;
1218    evas_cache_image_preload_cancel(im, NULL);
1219 #ifdef BUILD_ASYNC_PRELOAD
1220    LKL(im->lock_cancel);
1221    if (LKT(im->lock) == EINA_FALSE) /* can't get image lock - busy async load */
1222      {
1223         im->unload_cancel = EINA_TRUE;
1224         LKU(im->lock_cancel);
1225         return;
1226      }
1227    LKU(im->lock_cancel);
1228 #endif
1229    if ((!im->flags.loaded) || (!im->file) || (!im->info.module) || 
1230        (im->flags.dirty))
1231      {
1232 #ifdef BUILD_ASYNC_PRELOAD
1233         LKU(im->lock);
1234 #endif
1235         return;
1236      }
1237    im->cache->func.destructor(im);
1238 #ifdef BUILD_ASYNC_PRELOAD
1239    LKU(im->lock);
1240 #endif
1241    //FIXME: imagedataunload - inform owners
1242 }
1243
1244 static Eina_Bool
1245 _evas_cache_image_unload_cb(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, __UNUSED__ void *fdata)
1246 {
1247    evas_cache_image_unload_data(data);
1248    return EINA_TRUE;
1249 }
1250
1251 EAPI void
1252 evas_cache_image_unload_all(Evas_Cache_Image *cache)
1253 {
1254    Image_Entry *im;
1255
1256    EINA_INLIST_FOREACH(cache->lru, im) evas_cache_image_unload_data(im);
1257    EINA_INLIST_FOREACH(cache->lru_nodata, im) evas_cache_image_unload_data(im);
1258    eina_hash_foreach(cache->activ, _evas_cache_image_unload_cb, NULL);
1259    eina_hash_foreach(cache->inactiv, _evas_cache_image_unload_cb, NULL);
1260 }
1261
1262 EAPI Eina_Bool
1263 evas_cache_image_is_loaded(Image_Entry *im)
1264 {
1265   if (im->flags.loaded) return EINA_TRUE;
1266   return EINA_FALSE;
1267 }
1268
1269 EAPI void
1270 evas_cache_image_preload_data(Image_Entry *im, const void *target)
1271 {
1272 #ifdef BUILD_ASYNC_PRELOAD
1273    RGBA_Image *img = (RGBA_Image *)im;
1274    
1275    if ((im->flags.loaded) && (img->image.data))
1276      {
1277         evas_object_inform_call_image_preloaded((Evas_Object *)target);
1278         return;
1279      }
1280    im->flags.loaded = 0;
1281    if (!_evas_cache_image_entry_preload_add(im, target))
1282       evas_object_inform_call_image_preloaded((Evas_Object *)target);
1283 #else
1284    evas_cache_image_load_data(im);
1285    evas_object_inform_call_image_preloaded((Evas_Object *)target);
1286 #endif
1287 }
1288
1289 EAPI void
1290 evas_cache_image_preload_cancel(Image_Entry *im, const void *target)
1291 {
1292 #ifdef BUILD_ASYNC_PRELOAD
1293    if (!target) return;
1294    _evas_cache_image_entry_preload_remove(im, target);
1295 #else
1296    (void)im;
1297 #endif
1298 }
1299
1300 #ifdef CACHEDUMP
1301 static int total = 0;
1302
1303 static void
1304 _dump_img(Image_Entry *im, const char *type)
1305 {
1306    total += im->cache->func.mem_size_get(im);
1307    printf("%s: %4i: %4ib, %4ix%4i alloc[%4ix%4i] [%s] [%s]\n",
1308           type,
1309           im->references,
1310           im->cache->func.mem_size_get(im),
1311           im->w, im->h, im->allocated.w, im->allocated.h,
1312           im->file, im->key);
1313 }
1314
1315 static Eina_Bool
1316 _dump_cache_active(__UNUSED__ const Eina_Hash *hash, __UNUSED__ const void *key, void *data, void *fdata __UNUSED__)
1317 {
1318    Image_Entry *im = data;
1319    _dump_img(im, "ACTIVE");
1320    return EINA_TRUE;
1321 }
1322
1323 static void
1324 _dump_cache(Evas_Cache_Image *cache)
1325 {
1326    Image_Entry *im;
1327    
1328    printf("--CACHE DUMP----------------------------------------------------\n");
1329    printf("cache: %ikb / %ikb\n",
1330           cache->usage / 1024,
1331           cache->limit / 1024);
1332    printf("................................................................\n");
1333    total = 0;
1334    EINA_INLIST_FOREACH(cache->lru_nodata, im)
1335       _dump_img(im, "NODATA");
1336    EINA_INLIST_FOREACH(cache->lru, im)
1337       _dump_img(im, "DATA  ");
1338    printf("tot: %i\n"
1339           "usg: %i\n",
1340           total,
1341           cache->usage);
1342    eina_hash_foreach(cache->activ, _dump_cache_active, NULL);
1343 }
1344 #endif
1345
1346 EAPI int
1347 evas_cache_image_flush(Evas_Cache_Image *cache)
1348 {
1349 #ifdef CACHEDUMP
1350   _dump_cache(cache);
1351 #endif
1352    if (cache->limit == (unsigned int)-1) return -1;
1353
1354    while ((cache->lru) && (cache->limit < (unsigned int)cache->usage))
1355      {
1356         Image_Entry *im;
1357         
1358         im = (Image_Entry *)cache->lru->last;
1359         _evas_cache_image_entry_delete(cache, im);
1360      }
1361    
1362    while ((cache->lru_nodata) && (cache->limit < (unsigned int)cache->usage))
1363      {
1364         Image_Entry *im;
1365         
1366         im = (Image_Entry *) cache->lru_nodata->last;
1367         _evas_cache_image_lru_nodata_del(im);
1368         cache->func.surface_delete(im);
1369         im->flags.loaded = 0;
1370      }
1371
1372    return cache->usage;
1373 }
1374
1375 EAPI Image_Entry *
1376 evas_cache_image_empty(Evas_Cache_Image *cache)
1377 {
1378    Image_Entry *im;
1379
1380    im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
1381    if (!im) return NULL;
1382 #ifdef EVAS_FRAME_QUEUING
1383    LKL(im->lock_references);
1384 #endif
1385    im->references = 1;
1386 #ifdef EVAS_FRAME_QUEUING
1387    LKU(im->lock_references);
1388 #endif
1389    return im;
1390 }
1391
1392 EAPI void
1393 evas_cache_image_colorspace(Image_Entry *im, int cspace)
1394 {
1395    if (im->space == cspace) return;
1396    im->space = cspace;
1397    im->cache->func.color_space(im, cspace);
1398 }
1399
1400 EAPI void *
1401 evas_cache_private_from_image_entry_get(Image_Entry *im)
1402 {
1403    return (void *)im->cache->data;
1404 }
1405
1406 EAPI void *
1407 evas_cache_private_get(Evas_Cache_Image *cache)
1408 {
1409    return cache->data;
1410 }
1411
1412 EAPI void
1413 evas_cache_private_set(Evas_Cache_Image *cache, const void *data)
1414 {
1415    cache->data = (void *)data;
1416 }
1417
1418 EAPI DATA32 *
1419 evas_cache_image_pixels(Image_Entry *im)
1420 {
1421    return im->cache->func.surface_pixels(im);
1422 }
1423
1424 EAPI void
1425 evas_cache_image_wakeup(void)
1426 {
1427 #ifdef BUILD_ASYNC_PRELOAD
1428    if (_evas_cache_mutex_init > 0)
1429      eina_condition_broadcast(&cond_wakeup);
1430 #endif
1431 }