1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include "evas_engine.h"
4 #include "Evas_Engine_XRender_X11.h"
6 static Evas_Hash *_xr_image_hash = NULL;
7 static int _xr_image_cache_size = 0;
8 static int _xr_image_cache_usage = 0;
9 static Evas_List *_xr_image_cache = NULL;
10 static Evas_Hash *_xr_image_dirty_hash = NULL;
13 __xre_image_dirty_hash_add(XR_Image *im)
17 if (!im->data) return;
18 snprintf(buf, sizeof(buf), "%p", im->data);
19 _xr_image_dirty_hash = evas_hash_add(_xr_image_dirty_hash, buf, im);
23 __xre_image_dirty_hash_del(XR_Image *im)
27 if (!im->data) return;
28 snprintf(buf, sizeof(buf), "%p", im->data);
29 _xr_image_dirty_hash = evas_hash_del(_xr_image_dirty_hash, buf, im);
33 __xre_image_dirty_hash_find(void *data)
37 snprintf(buf, sizeof(buf), "%p", data);
38 return evas_hash_find(_xr_image_dirty_hash, buf);
42 __xre_image_find(char *fkey)
46 im = evas_hash_find(_xr_image_hash, fkey);
51 for (l = _xr_image_cache; l; l = l->next)
54 if (!strcmp(im->fkey, fkey))
56 _xr_image_cache = evas_list_remove_list(_xr_image_cache, l);
57 _xr_image_hash = evas_hash_add(_xr_image_hash, im->fkey, im);
58 _xr_image_cache_usage -= (im->w * im->h * 4);
64 if (im) im->references++;
69 _xre_image_load(Ximage_Info *xinf, const char *file, const char *key, Evas_Image_Load_Opts *lo)
74 if (!file) return NULL;
78 snprintf(buf, sizeof(buf), "/@%p@%lx@/%s//://%s", xinf->disp, xinf->root, file, key);
80 snprintf(buf, sizeof(buf), "/@%p@%lx@/%s", xinf->disp, xinf->root, file);
85 snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//@%p@%lx@/%s//://%s", lo->scale_down_by, lo->dpi, lo->w, lo->h, xinf->disp, xinf->root, file, key);
87 snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//@%p@%lx@/%s", lo->scale_down_by, lo->dpi, lo->w, lo->h, xinf->disp, xinf->root, file);
89 im = __xre_image_find(buf);
95 im = calloc(1, sizeof(XR_Image));
97 im->im = evas_common_load_image_from_file(file, key, lo);
104 im->xinf->references++;
105 im->cs.space = EVAS_COLORSPACE_ARGB8888;
106 im->fkey = strdup(buf);
107 im->file = evas_stringshare_add(file);
108 if (key) im->key = evas_stringshare_add(key);
109 im->w = im->im->cache_entry.w;
110 im->h = im->im->cache_entry.h;
112 if (lo) im->load_opts = *lo;
113 if (im->im->info.comment) im->comment = evas_stringshare_add(im->im->info.comment);
114 // if (im->im->info.format == 1) im->format = evas_stringshare_add("png");
115 if (im->im->cache_entry.flags.alpha) im->alpha = 1;
116 _xr_image_hash = evas_hash_direct_add(_xr_image_hash, im->fkey, im);
121 _xre_image_new_from_data(Ximage_Info *xinf, int w, int h, void *data, int alpha, int cspace)
125 im = calloc(1, sizeof(XR_Image));
126 if (!im) return NULL;
128 im->xinf->references++;
129 im->cs.space = cspace;
133 switch (im->cs.space)
135 case EVAS_COLORSPACE_ARGB8888:
139 case EVAS_COLORSPACE_YCBCR422P601_PL:
140 case EVAS_COLORSPACE_YCBCR422P709_PL:
149 __xre_image_dirty_hash_add(im);
154 _xre_image_new_from_copied_data(Ximage_Info *xinf, int w, int h, void *data, int alpha, int cspace)
158 im = calloc(1, sizeof(XR_Image));
159 if (!im) return NULL;
160 im->cs.space = cspace;
161 switch (im->cs.space)
163 case EVAS_COLORSPACE_ARGB8888:
164 im->data = malloc(w * h * 4);
174 func = evas_common_draw_func_copy_get(w * h, 0);
175 if (func) func(data, im->data, w * h);
176 evas_common_cpu_end_opt();
181 case EVAS_COLORSPACE_YCBCR422P601_PL:
182 case EVAS_COLORSPACE_YCBCR422P709_PL:
184 im->cs.data = calloc(1, h * sizeof(unsigned char *) * 2);
185 if ((data) && (im->cs.data))
186 memcpy(im->cs.data, data, h * sizeof(unsigned char *) * 2);
196 im->xinf->references++;
198 __xre_image_dirty_hash_add(im);
203 _xre_image_new(Ximage_Info *xinf, int w, int h)
207 im = calloc(1, sizeof(XR_Image));
208 if (!im) return NULL;
209 im->data = malloc(w * h * 4);
218 im->cs.space = EVAS_COLORSPACE_ARGB8888;
220 im->xinf->references++;
224 __xre_image_dirty_hash_add(im);
229 __xre_image_real_free(XR_Image *im)
233 if (!im->cs.no_free) free(im->cs.data);
235 if (im->file) evas_stringshare_del(im->file);
236 if (im->key) evas_stringshare_del(im->key);
237 if (im->fkey) free(im->fkey);
238 if (im->im) evas_cache_image_drop(&im->im->cache_entry);
239 if ((im->data) && (im->dirty)) __xre_image_dirty_hash_del(im);
240 if ((im->free_data) && (im->data)) free(im->data);
241 if (im->surface) _xr_render_surface_free(im->surface);
242 if (im->format) evas_stringshare_del(im->format);
243 if (im->comment) evas_stringshare_del(im->comment);
244 if (im->updates) evas_common_tilebuf_free(im->updates);
245 _xr_image_info_free(im->xinf);
250 _xre_image_free(XR_Image *im)
253 if (im->references != 0) return;
257 _xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
258 _xr_image_cache = evas_list_prepend(_xr_image_cache, im);
259 _xr_image_cache_usage += (im->w * im->h * 4);
260 _xre_image_cache_set(_xr_image_cache_size);
264 __xre_image_real_free(im);
269 _xre_image_region_dirty(XR_Image *im, int x, int y, int w, int h)
273 im->updates = evas_common_tilebuf_new(im->w, im->h);
274 if (im->updates) evas_common_tilebuf_set_tile_size(im->updates, 8, 8);
277 evas_common_tilebuf_add_redraw(im->updates, x, y, w, h);
281 _xre_image_dirty(XR_Image *im)
283 if (im->dirty) return;
285 _xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
287 __xre_image_dirty_hash_add(im);
291 _xre_image_copy(XR_Image *im)
296 if (im->data) data = im->data;
297 else if (im->cs.data) data = im->cs.data;
301 im->im = evas_common_load_image_from_file(im->file, im->key, &(im->load_opts));
304 evas_cache_image_load_data(&im->im->cache_entry);
305 data = im->im->image.data;
308 if (!data) return NULL;
309 im2 = _xre_image_new_from_copied_data(im->xinf, im->w, im->h, data, im->alpha, im->cs.space);
314 _xre_image_resize(XR_Image *im, int w, int h)
316 if ((w == im->w) && (h == im->h)) return;
319 Xrender_Surface *old_surface;
320 old_surface = im->surface;
321 im->surface = _xr_render_surface_new(old_surface->xinf, w + 2, h + 2, old_surface->fmt, old_surface->alpha);
322 _xr_render_surface_free(old_surface);
324 switch (im->cs.space)
326 case EVAS_COLORSPACE_ARGB8888:
331 if (im->data) free(im->data);
332 im->data = malloc(w * h * 4);
337 evas_cache_image_drop(&im->im->cache_entry);
341 if (im->data) free(im->data);
342 im->data = malloc(w * h * 4);
347 im->data = malloc(w * h * 4);
351 case EVAS_COLORSPACE_YCBCR422P601_PL:
352 case EVAS_COLORSPACE_YCBCR422P709_PL:
357 if (im->data) free(im->data);
363 evas_cache_image_drop(&im->im->cache_entry);
368 if (im->cs.data) free(im->cs.data);
369 im->cs.data = calloc(1, h * sizeof(unsigned char *) * 2);
376 __xre_image_dirty_hash_del(im);
377 __xre_image_dirty_hash_add(im);
383 _xre_image_data_get(XR_Image *im)
387 if (im->data) data = im->data;
388 else if (im->cs.data) data = im->cs.data;
391 if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key, &(im->load_opts));
394 evas_cache_image_load_data(&im->im->cache_entry);
395 data = im->im->image.data;
402 _xre_image_data_find(void *data)
406 im = __xre_image_dirty_hash_find(data);
415 _xre_image_data_put(XR_Image *im, void *data)
418 switch (im->cs.space)
420 case EVAS_COLORSPACE_ARGB8888:
423 if (data == im->im->image.data) return;
424 evas_cache_image_drop(&im->im->cache_entry);
427 if (im->cs.data == data) return;
430 if (im->data == data) return;
431 if (im->free_data) free(im->data);
437 case EVAS_COLORSPACE_YCBCR422P601_PL:
438 case EVAS_COLORSPACE_YCBCR422P709_PL:
441 if (im->free_data) free(im->data);
445 if (data == im->cs.data) return;
448 if (im->cs.data) free(im->cs.data);
456 __xre_image_dirty_hash_del(im);
457 __xre_image_dirty_hash_add(im);
460 _xr_render_surface_free(im->surface);
466 _xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
471 evas_common_tilebuf_free(im->updates);
477 _xre_image_alpha_set(XR_Image *im, int alpha)
479 if (im->alpha == alpha) return;
480 switch (im->cs.space)
482 case EVAS_COLORSPACE_ARGB8888:
486 Xrender_Surface *old_surface;
488 old_surface = im->surface;
491 im->surface = _xr_render_surface_new(im->xinf, im->w + 2, im->h + 2, im->xinf->fmt32, 1);
494 /* FIXME: if im->depth == 16, use xinf->fmtdef */
495 if ((im->xinf->depth == 16) &&
496 (im->xinf->vis->red_mask == 0xf800) &&
497 (im->xinf->vis->green_mask == 0x07e0) &&
498 (im->xinf->vis->blue_mask == 0x001f))
499 im->surface = _xr_render_surface_new(im->xinf, im->w + 2, im->h + 2, im->xinf->fmtdef, 0);
501 im->surface = _xr_render_surface_new(im->xinf, im->w + 2, im->h + 2, im->xinf->fmt24, 0);
504 _xr_render_surface_copy(old_surface, im->surface, 0, 0, 0, 0, im->w + 2, im->h + 2);
505 _xr_render_surface_free(old_surface);
509 evas_common_tilebuf_free(im->updates);
518 _xre_image_alpha_get(XR_Image *im)
522 if (im->im->cache_entry.space != EVAS_COLORSPACE_ARGB8888) return 0;
528 _xre_image_border_set(XR_Image *im, int l, int r, int t, int b)
531 _xre_image_surface_gen(im);
539 im->surface->bordered = 1;
541 im->surface->bordered = 0;
546 _xre_image_border_get(XR_Image *im, int *l, int *r, int *t, int *b)
551 _xre_image_surface_gen(XR_Image *im)
553 void *data = NULL, *tdata = NULL;
555 if ((im->surface) && (!im->updates)) return;
556 if (im->data) data = im->data;
559 if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key, &(im->load_opts));
562 evas_cache_image_load_data(&im->im->cache_entry);
563 data = im->im->image.data;
568 switch (im->cs.space)
570 case EVAS_COLORSPACE_ARGB8888:
573 case EVAS_COLORSPACE_YCBCR422P601_PL:
574 case EVAS_COLORSPACE_YCBCR422P709_PL:
575 if ((im->cs.data) && (*((unsigned char **)im->cs.data)))
577 tdata = malloc(im->w * im->h * sizeof(DATA32));
579 evas_common_convert_yuv_420p_601_rgba(im->cs.data,
595 Tilebuf_Rect *rects, *r;
597 rects = evas_common_tilebuf_get_render_rects(im->updates);
600 for (r = rects; r; r = (Tilebuf_Rect *)((Evas_Object_List *)r)->next)
604 rx = r->x; ry = r->y; rw = r->w, rh = r->h;
605 RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, im->w, im->h);
607 _xr_render_surface_argb_pixels_fill(im->surface, im->w, im->h, data, rx, ry, rw, rh, 1, 1);
609 /* FIXME: if im->depth == 16 - convert to 16bpp then
611 _xr_render_surface_rgb_pixels_fill(im->surface, im->w, im->h, data, rx, ry, rw, rh, 1, 1);
613 evas_common_tilebuf_free_render_rects(rects);
615 evas_common_tilebuf_free(im->updates);
618 if (tdata) free(tdata);
623 im->surface = _xr_render_surface_new(im->xinf, im->w + 2, im->h + 2, im->xinf->fmt32, 1);
624 _xr_render_surface_argb_pixels_fill(im->surface, im->w, im->h, data, 0, 0, im->w, im->h, 1, 1);
628 /* FIXME: if im->xinf->depth == 16, use xinf->fmtdef */
629 if ((im->xinf->depth == 16) &&
630 (im->xinf->vis->red_mask == 0xf800) &&
631 (im->xinf->vis->green_mask == 0x07e0) &&
632 (im->xinf->vis->blue_mask == 0x001f))
633 im->surface = _xr_render_surface_new(im->xinf, im->w + 2, im->h + 2, im->xinf->fmtdef, 0);
635 im->surface = _xr_render_surface_new(im->xinf, im->w + 2, im->h + 2, im->xinf->fmt24, 0);
636 /* FIXME: if im->depth == 16 - convert to 16bpp then
638 _xr_render_surface_rgb_pixels_fill(im->surface, im->w, im->h, data, 0, 0, im->w, im->h, 1, 1);
641 _xr_render_surface_copy(im->surface, im->surface,
645 _xr_render_surface_copy(im->surface, im->surface,
649 _xr_render_surface_copy(im->surface, im->surface,
653 _xr_render_surface_copy(im->surface, im->surface,
657 if ((im->im) && (!im->dirty))
659 evas_cache_image_drop(&im->im->cache_entry);
662 if (tdata) free(tdata);
666 _xre_image_cache_set(int size)
668 _xr_image_cache_size = size;
669 while (_xr_image_cache_usage > _xr_image_cache_size)
673 l = evas_list_last(_xr_image_cache);
679 _xr_image_cache = evas_list_remove_list(_xr_image_cache, l);
680 _xr_image_cache_usage -= (im->w * im->h * 4);
681 __xre_image_real_free(im);
687 _xre_image_cache_get(void)
689 return _xr_image_cache_size;