move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_image_main.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include "config.h"  /* so that EAPI in Eet.h is correctly defined */
7 #endif
8
9 #ifdef BUILD_LOADER_EET
10 # include <Eet.h>
11 #endif
12
13 #include "evas_common.h"
14 #include "evas_private.h"
15 #include "evas_image_private.h"
16 #include "evas_convert_yuv.h"
17
18 #ifdef HAVE_VALGRIND
19 # include <memcheck.h>
20 #endif
21
22 static Evas_Cache_Image * eci = NULL;
23 static int                reference = 0;
24
25 /* static RGBA_Image *evas_rgba_line_buffer = NULL; */
26
27 #define  EVAS_RGBA_LINE_BUFFER_MIN_LEN  256
28 #define  EVAS_RGBA_LINE_BUFFER_MAX_LEN  2048
29
30 /* static RGBA_Image *evas_alpha_line_buffer = NULL; */
31
32 #define  EVAS_ALPHA_LINE_BUFFER_MIN_LEN  256
33 #define  EVAS_ALPHA_LINE_BUFFER_MAX_LEN  2048
34
35
36 static Image_Entry      *_evas_common_rgba_image_new(void);
37 static void              _evas_common_rgba_image_delete(Image_Entry *ie);
38
39 static int               _evas_common_rgba_image_surface_alloc(Image_Entry *ie, int w, int h);
40 static void              _evas_common_rgba_image_surface_delete(Image_Entry *ie);
41 static DATA32           *_evas_common_rgba_image_surface_pixels(Image_Entry *ie);
42
43 static void              _evas_common_rgba_image_unload(Image_Entry *im);
44
45 static void              _evas_common_rgba_image_dirty_region(Image_Entry *im, int x, int y, int w, int h);
46
47 static int               _evas_common_rgba_image_ram_usage(Image_Entry *ie);
48
49 /* Only called when references > 0. Need to provide a fresh copie of im. */
50 /* The destination surface does have a surface, but no allocated pixel data. */
51 static int               _evas_common_rgba_image_dirty(Image_Entry* dst, const Image_Entry* src);
52
53 static void
54 _evas_common_rgba_image_debug(const char* context, Image_Entry *eim)
55 {
56    fprintf(stderr, "%p = [%s] {%s,%s} %i [%i|%i]\n", eim, context, eim->file, eim->key, eim->references, eim->w, eim->h);
57 }
58
59 static const Evas_Cache_Image_Func      _evas_common_image_func =
60 {
61   _evas_common_rgba_image_new,
62   _evas_common_rgba_image_delete,
63   _evas_common_rgba_image_surface_alloc,
64   _evas_common_rgba_image_surface_delete,
65   _evas_common_rgba_image_surface_pixels,
66   evas_common_load_rgba_image_module_from_file,
67   _evas_common_rgba_image_unload,
68   _evas_common_rgba_image_dirty_region,
69   _evas_common_rgba_image_dirty,
70   evas_common_rgba_image_size_set,
71   evas_common_rgba_image_from_copied_data,
72   evas_common_rgba_image_from_data,
73   evas_common_rgba_image_colorspace_set,
74   evas_common_load_rgba_image_data_from_file,
75   _evas_common_rgba_image_ram_usage,
76 /*   _evas_common_rgba_image_debug */
77   NULL
78 };
79
80 EAPI void
81 evas_common_image_init(void)
82 {
83    if (!eci)
84      eci = evas_cache_image_init(&_evas_common_image_func);
85    reference++;
86 ////   printf("REF++=%i\n", reference);
87
88 #ifdef BUILD_LOADER_EET
89    eet_init();
90 #endif
91 }
92
93 EAPI void
94 evas_common_image_shutdown(void)
95 {
96    if (--reference == 0)
97      {
98 ////    printf("REF--=%i\n", reference);
99 // DISABLE for now - something wrong with cache shutdown freeing things
100 // still in use - rage_thumb segv's now.
101 //
102 // actually - i think i see it. cache ref goes to 0 (and thus gets freed)
103 // because in eng_setup() when a buffer changes size it is FIRST freed
104 // THEN allocated again - thus brignhjing ref to 0 then back to 1 immediately
105 // where it should stay at 1. - see evas_engine.c in the buffer enigne for
106 // example. eng_output_free() is called BEFORE _output_setup(). although this
107 // is only a SIGNE of the problem. we can patch this up with either freeing
108 // after the setup (so we just pt a ref of 2 then back to 1), or just
109 // evas_common_image_init() at the start and evas_common_image_shutdown()
110 // after it all. really ref 0 should only be reached when no more canvases
111 // with no more objects exist anywhere.
112 //        evas_cache_image_shutdown(eci);
113 //        eci = NULL;
114      }
115
116 #ifdef BUILD_LOADER_EET
117    eet_shutdown();
118 #endif
119 }
120
121 static Image_Entry *
122 _evas_common_rgba_image_new(void)
123 {
124    RGBA_Image *im;
125
126    im = calloc(1, sizeof(RGBA_Image));
127    if (!im) return NULL;
128    im->flags = RGBA_IMAGE_NOTHING;
129    im->ref = 1;
130    return &im->cache_entry;
131 }
132
133 static void
134 _evas_common_rgba_image_delete(Image_Entry *ie)
135 {
136    RGBA_Image   *im = (RGBA_Image *) ie;
137
138    evas_common_pipe_free(im);
139    if (ie->info.module) evas_module_unref((Evas_Module *)ie->info.module);
140    /* memset the image to 0x99 because i recently saw a segv where an
141     * seemed to be used BUT its contents were wrong - it looks like it was
142     * overwritten by something from efreet - as there was an execute command
143     * for a command there and some other signs - but to make sure, I am
144     * going to empty this struct out in case this happens again so i know
145     * that something else is overwritign this struct - or not */
146    memset(im, 0x99, sizeof(im));
147    free(im);
148 }
149
150 static int
151 _evas_common_rgba_image_surface_alloc(Image_Entry *ie, int w, int h)
152 {
153    RGBA_Image   *im = (RGBA_Image *) ie;
154    size_t        siz = 0;
155
156    if (im->image.no_free) return 0;
157
158    if (im->flags & RGBA_IMAGE_ALPHA_ONLY)
159      siz = w * h * sizeof(DATA8);
160    else
161      siz = w * h * sizeof(DATA32);
162
163    if (im->image.data) free(im->image.data);
164    im->image.data = malloc(siz);
165    if (im->image.data == NULL) return -1;
166
167 #ifdef HAVE_VALGRIND
168 # ifdef VALGRIND_MAKE_READABLE
169    VALGRIND_MAKE_READABLE(im->image.data, siz);
170 # else
171 #  ifdef VALGRIND_MAKE_MEM_DEFINED
172    VALGRIND_MAKE_MEM_DEFINED(im->image.data, siz);
173 #  endif
174 # endif
175 #endif
176
177    return 0;
178 }
179
180 static void
181 _evas_common_rgba_image_surface_delete(Image_Entry *ie)
182 {
183    RGBA_Image   *im = (RGBA_Image *) ie;
184
185    if ((im->cs.data) && (im->image.data))
186      {
187         if (im->cs.data != im->image.data)
188           {
189              if (!im->cs.no_free) free(im->cs.data);
190           }
191      }
192    else if (im->cs.data)
193      {
194         if (!im->cs.no_free) free(im->cs.data);
195      }
196    im->cs.data = NULL;
197
198    if (im->image.data && !im->image.no_free)
199      free(im->image.data);
200    im->image.data = NULL;
201 }
202
203 static void
204 _evas_common_rgba_image_unload(Image_Entry* im)
205 {
206 }
207
208 static void
209 _evas_common_rgba_image_dirty_region(Image_Entry* ie, int x, int y, int w, int h)
210 {
211    RGBA_Image   *im = (RGBA_Image *) ie;
212
213    im->flags |= RGBA_IMAGE_IS_DIRTY;
214 }
215
216 /* Only called when references > 0. Need to provide a fresh copie of im. */
217 static int
218 _evas_common_rgba_image_dirty(Image_Entry *ie_dst, const Image_Entry *ie_src)
219 {
220    RGBA_Image   *dst = (RGBA_Image *) ie_dst;
221    RGBA_Image   *src = (RGBA_Image *) ie_src;
222
223    evas_cache_image_load_data(&src->cache_entry);
224    if (_evas_common_rgba_image_surface_alloc(&dst->cache_entry,
225                                              src->cache_entry.w, src->cache_entry.h))
226      return 1;
227
228    evas_common_image_colorspace_normalize(src);
229    evas_common_image_colorspace_normalize(dst);
230 /*    evas_common_blit_rectangle(src, dst, 0, 0, src->cache_entry.w, src->cache_entry.h, 0, 0); */
231 /*    evas_common_cpu_end_opt(); */
232
233    return 0;
234 }
235
236 static int
237 _evas_common_rgba_image_ram_usage(Image_Entry *ie)
238 {
239    RGBA_Image   *im = (RGBA_Image *) ie;
240
241 //   ram += sizeof(struct _RGBA_Image);
242 //   if (im->info.real_file) ram += strlen(im->info.real_file);
243 //   if (im->info.comment) ram += strlen(im->info.comment);
244    if ((im->image.data) && (!im->image.no_free))
245      return im->cache_entry.w * im->cache_entry.h * sizeof(DATA32);
246    return 0;
247 }
248
249 static DATA32 *
250 _evas_common_rgba_image_surface_pixels(Image_Entry *ie)
251 {
252    RGBA_Image *im = (RGBA_Image *) ie;
253
254    return im->image.data;
255 }
256
257 #if 0
258 void
259 evas_common_image_surface_alpha_tiles_calc(RGBA_Surface *is, int tsize)
260 {
261    int x, y;
262    DATA32 *ptr;
263
264    if (is->spans) return;
265    if (!is->im->cache_entry.flags.alpha) return;
266    /* FIXME: dont handle alpha only images yet */
267    if ((is->im->flags & RGBA_IMAGE_ALPHA_ONLY)) return;
268    if (tsize < 0) tsize = 0;
269    is->spans = calloc(1, sizeof(RGBA_Image_Span *) * is->h);
270    if (!is->spans) return;
271    ptr = is->data;
272    for (y = 0; y < is->h; y++)
273      {
274         RGBA_Image_Span *sp;
275
276         sp = NULL;
277         for (x = 0; x < is->w; x++)
278           {
279              DATA8 a;
280
281              a = A_VAL(ptr);
282              if (sp)
283                {
284                   if (a == 0)
285                     {
286                        is->spans[y] = evas_object_list_append(is->spans[y], sp);
287                        sp = NULL;
288                     }
289                   else
290                     {
291                        sp->w++;
292                        if ((sp->v == 2) && (a != 255)) sp->v = 1;
293                     }
294                }
295              else
296                {
297                   if (a == 255)
298                     {
299                        sp = calloc(1, sizeof(RGBA_Image_Span));
300                        sp->x = x;
301                        sp->w = 1;
302                        sp->v = 2;
303                     }
304                   else if (a > 0)
305                     {
306                        sp = calloc(1, sizeof(RGBA_Image_Span));
307                        sp->x = x;
308                        sp->w = 1;
309                        sp->v = 1;
310                     }
311                }
312              ptr++;
313           }
314         if (sp)
315           {
316              is->spans[y] = evas_object_list_append(is->spans[y], sp);
317              sp = NULL;
318           }
319      }
320 }
321 #endif
322
323 /* EAPI void */
324 /* evas_common_image_surface_dealloc(RGBA_Surface *is) */
325 /* { */
326 /*    if ((is->data) && (!is->no_free)) */
327 /*      { */
328 /*      free(is->data); */
329 /*      is->data = NULL; */
330 /*      } */
331 /* } */
332
333 static RGBA_Image *
334 evas_common_image_create(int w, int h)
335 {
336    RGBA_Image *im;
337
338    im = (RGBA_Image *) _evas_common_rgba_image_new();
339    if (!im) return NULL;
340    im->cache_entry.w = w;
341    im->cache_entry.h = h;
342    if (_evas_common_rgba_image_surface_alloc(&im->cache_entry, w, h))
343      {
344         _evas_common_rgba_image_delete(&im->cache_entry);
345         return NULL;
346      }
347    im->cache_entry.flags.cached = 0;
348    return im;
349 }
350
351 EAPI RGBA_Image *
352 evas_common_image_alpha_create(int w, int h)
353 {
354    RGBA_Image   *im;
355
356    im = (RGBA_Image *) _evas_common_rgba_image_new();
357    if (!im) return NULL;
358    im->cache_entry.w = w;
359    im->cache_entry.h = h;
360    im->flags |= RGBA_IMAGE_ALPHA_ONLY;
361    if (_evas_common_rgba_image_surface_alloc(&im->cache_entry, w, h))
362      {
363         _evas_common_rgba_image_delete(&im->cache_entry);
364         return NULL;
365      }
366    im->cache_entry.flags.cached = 0;
367    return im;
368 }
369
370 void
371 evas_common_image_colorspace_normalize(RGBA_Image *im)
372 {
373    if ((!im->cs.data) ||
374        ((!im->cs.dirty) && (!(im->flags & RGBA_IMAGE_IS_DIRTY)))) return;
375    switch (im->cache_entry.space)
376      {
377       case EVAS_COLORSPACE_ARGB8888:
378         if (im->image.data != im->cs.data)
379           {
380              if (!im->image.no_free) free(im->image.data);
381              im->image.data = im->cs.data;
382              im->cs.no_free = im->image.no_free;
383           }
384         break;
385       case EVAS_COLORSPACE_YCBCR422P601_PL:
386 #ifdef BUILD_CONVERT_YUV
387         if ((im->image.data) && (*((unsigned char **)im->cs.data)))
388           evas_common_convert_yuv_420p_601_rgba(im->cs.data, (DATA8*) im->image.data,
389                                                 im->cache_entry.w, im->cache_entry.h);
390 #endif
391         break;
392       default:
393         break;
394      }
395    im->cs.dirty = 0;
396 }
397
398 EAPI void
399 evas_common_image_colorspace_dirty(RGBA_Image *im)
400 {
401    im->cs.dirty = 1;
402 }
403
404 EAPI void
405 evas_common_image_set_cache(int size)
406 {
407    if (eci != NULL)
408      evas_cache_image_set(eci, size);
409 }
410
411 EAPI int
412 evas_common_image_get_cache(void)
413 {
414    return evas_cache_image_get(eci);
415 }
416
417 EAPI RGBA_Image *
418 evas_common_load_image_from_file(const char *file, const char *key, RGBA_Image_Loadopts *lo)
419 {
420    int           error;
421
422    if (file == NULL) return NULL;
423    return (RGBA_Image *) evas_cache_image_request(eci, file, key, lo, &error);
424 }
425
426 EAPI void
427 evas_common_image_cache_free(void)
428 {
429    evas_common_image_set_cache(0);
430 }
431
432 EAPI Evas_Cache_Image*
433 evas_common_image_cache_get(void)
434 {
435    return eci;
436 }
437
438 EAPI RGBA_Image *
439 evas_common_image_line_buffer_obtain(int len)
440 {
441    if (len < 1) return NULL;
442    if (len < EVAS_RGBA_LINE_BUFFER_MIN_LEN)
443         len = EVAS_RGBA_LINE_BUFFER_MIN_LEN;
444    return evas_common_image_create(len, 1);
445 /*
446    if (evas_rgba_line_buffer)
447      {
448         if (evas_rgba_line_buffer->image->w >= len)
449            return evas_rgba_line_buffer;
450         evas_rgba_line_buffer->image->data = (DATA32 *)realloc(evas_rgba_line_buffer->image->data, len * sizeof(DATA32));
451         if (!evas_rgba_line_buffer->image->data)
452           {
453            evas_common_image_free(evas_rgba_line_buffer);
454            evas_rgba_line_buffer = NULL;
455            return NULL;
456           }
457         evas_rgba_line_buffer->image->w = len;
458         return evas_rgba_line_buffer;
459      }
460    evas_rgba_line_buffer = evas_common_image_create(len, 1);
461    if (!evas_rgba_line_buffer) return NULL;
462    return evas_rgba_line_buffer;
463  */
464 }
465
466 EAPI void
467 evas_common_image_line_buffer_release(RGBA_Image *im)
468 {
469     _evas_common_rgba_image_delete(&im->cache_entry);
470 /*
471    if (!evas_rgba_line_buffer) return;
472    if (EVAS_RGBA_LINE_BUFFER_MAX_LEN < evas_rgba_line_buffer->image->w)
473      {
474         evas_rgba_line_buffer->image->w = EVAS_RGBA_LINE_BUFFER_MAX_LEN;
475         evas_rgba_line_buffer->image->data = (DATA32 *)realloc(evas_rgba_line_buffer->image->data,
476                                  evas_rgba_line_buffer->image->w * sizeof(DATA32));
477         if (!evas_rgba_line_buffer->image->data)
478           {
479            evas_common_image_free(evas_rgba_line_buffer);
480            evas_rgba_line_buffer = NULL;
481           }
482      }
483  */
484 }
485
486 EAPI void
487 evas_common_image_line_buffer_free(RGBA_Image *im)
488 {
489     _evas_common_rgba_image_delete(&im->cache_entry);
490 /*
491    if (!evas_rgba_line_buffer) return;
492    evas_common_image_free(evas_rgba_line_buffer);
493    evas_rgba_line_buffer = NULL;
494  */
495 }
496
497 EAPI RGBA_Image *
498 evas_common_image_alpha_line_buffer_obtain(int len)
499 {
500    if (len < 1) return NULL;
501    if (len < EVAS_ALPHA_LINE_BUFFER_MIN_LEN)
502         len = EVAS_ALPHA_LINE_BUFFER_MIN_LEN;
503    return evas_common_image_alpha_create(len, 1);
504 /*
505    if (evas_alpha_line_buffer)
506      {
507         if (evas_alpha_line_buffer->image->w >= len)
508            return evas_alpha_line_buffer;
509         evas_alpha_line_buffer->image->data = realloc(evas_alpha_line_buffer->image->data, len * sizeof(DATA8));
510         if (!evas_alpha_line_buffer->image->data)
511           {
512            evas_common_image_free(evas_alpha_line_buffer);
513            evas_alpha_line_buffer = NULL;
514            return NULL;
515           }
516         evas_alpha_line_buffer->image->w = len;
517         return evas_alpha_line_buffer;
518      }
519    evas_alpha_line_buffer = evas_common_image_alpha_create(len, 1);
520    return evas_alpha_line_buffer;
521  */
522 }
523
524 EAPI void
525 evas_common_image_alpha_line_buffer_release(RGBA_Image *im)
526 {
527     _evas_common_rgba_image_delete(&im->cache_entry);
528 /*
529    if (!evas_alpha_line_buffer) return;
530    if (EVAS_ALPHA_LINE_BUFFER_MAX_LEN < evas_alpha_line_buffer->image->w)
531      {
532         evas_alpha_line_buffer->image->w = EVAS_ALPHA_LINE_BUFFER_MAX_LEN;
533         evas_alpha_line_buffer->image->data = realloc(evas_alpha_line_buffer->image->data,
534                                  evas_alpha_line_buffer->image->w * sizeof(DATA8));
535         if (!evas_alpha_line_buffer->image->data)
536           {
537            evas_common_image_free(evas_alpha_line_buffer);
538            evas_alpha_line_buffer = NULL;
539           }
540      }
541  */
542 }
543
544 EAPI void
545 evas_common_image_premul(Image_Entry *ie)
546 {
547    DATA32  *s, *se;
548    DATA32  nas = 0;
549
550    if (!ie) return ;
551    if (!evas_cache_image_pixels(ie)) return ;
552    if (!ie->flags.alpha) return;
553
554    s = evas_cache_image_pixels(ie);
555    se = s + (ie->w * ie->h);
556    while (s < se)
557      {
558         DATA32  a = 1 + (*s >> 24);
559
560         *s = (*s & 0xff000000) + (((((*s) >> 8) & 0xff) * a) & 0xff00) +
561                          (((((*s) & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
562         s++;
563         if ((a == 1) || (a == 256))
564            nas++;
565      }
566    if ((ALPHA_SPARSE_INV_FRACTION * nas) >= (ie->w * ie->h))
567      ie->flags.alpha_sparse = 1;
568 }
569
570 EAPI void
571 evas_common_image_set_alpha_sparse(Image_Entry *ie)
572 {
573    DATA32  *s, *se;
574    DATA32  nas = 0;
575
576    if (!ie) return;
577    if (!evas_cache_image_pixels(ie)) return ;
578    if (!ie->flags.alpha) return;
579
580    s = evas_cache_image_pixels(ie);
581    se = s + (ie->w * ie->h);
582    while (s < se)
583      {
584         DATA32  p = *s & 0xff000000;
585
586         if (!p || (p == 0xff000000))
587            nas++;
588         s++;
589      }
590    if ((ALPHA_SPARSE_INV_FRACTION * nas) >= (ie->w * ie->h))
591      ie->flags.alpha_sparse = 1;
592 }