1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include "evas_engine.h"
4 #include "Evas_Engine_XRender_Xcb.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(Xcb_Image_Info *xcbinf, const char *file, const char *key, Evas_Image_Load_Opts *lo)
74 if (!file) return NULL;
78 snprintf(buf, sizeof(buf), "/@%p@%x@/%s//://%s", xcbinf->conn, xcbinf->root, file, key);
80 snprintf(buf, sizeof(buf), "/@%p@%x@/%s", xcbinf->conn, xcbinf->root, file);
85 snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//@%p@%x@/%s//://%s", lo->scale_down_by, lo->dpi, lo->w, lo->h, xcbinf->conn, xcbinf->root, file, key);
87 snprintf(buf, sizeof(buf), "//@/%i/%1.5f/%ix%i//@%p@%x@/%s", lo->scale_down_by, lo->dpi, lo->w, lo->h, xcbinf->conn, xcbinf->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->xcbinf->references++;
105 im->fkey = strdup(buf);
106 im->file = (char *)evas_stringshare_add(file);
107 if (key) im->key = (char *)evas_stringshare_add(key);
108 im->w = im->im->cache_entry.w;
109 im->h = im->im->cache_entry.h;
111 if (lo) im->load_opts = *lo;
112 if (im->im->info.comment) im->comment = (char *)evas_stringshare_add(im->im->info.comment);
113 /* if (im->im->info.format == 1) im->format = evas_stringshare_add("png"); */
114 if (im->im->cache_entry.flags.alpha) im->alpha = 1;
115 _xr_image_hash = evas_hash_direct_add(_xr_image_hash, im->fkey, im);
120 _xre_image_new_from_data(Xcb_Image_Info *xcbinf, int w, int h, void *data)
124 im = calloc(1, sizeof(XR_Image));
125 if (!im) return NULL;
127 im->xcbinf->references++;
134 __xre_image_dirty_hash_add(im);
139 _xre_image_new_from_copied_data(Xcb_Image_Info *xcbinf, int w, int h, void *data)
143 im = calloc(1, sizeof(XR_Image));
144 if (!im) return NULL;
145 im->data = malloc(w * h * 4);
155 func = evas_common_draw_func_copy_get(w * h, 0);
156 if (func) func(data, im->data, w * h);
157 evas_common_cpu_end_opt();
163 im->xcbinf->references++;
167 __xre_image_dirty_hash_add(im);
172 _xre_image_new(Xcb_Image_Info *xcbinf, int w, int h)
176 im = calloc(1, sizeof(XR_Image));
177 if (!im) return NULL;
178 im->data = malloc(w * h * 4);
188 im->xcbinf->references++;
192 __xre_image_dirty_hash_add(im);
197 __xre_image_real_free(XR_Image *im)
199 if (im->file) evas_stringshare_del(im->file);
200 if (im->key) evas_stringshare_del(im->key);
201 if (im->fkey) free(im->fkey);
202 if (im->im) evas_cache_image_drop(&im->im->cache_entry);
203 if ((im->data) && (im->dirty)) __xre_image_dirty_hash_del(im);
204 if ((im->free_data) && (im->data)) free(im->data);
205 if (im->surface) _xr_render_surface_free(im->surface);
206 if (im->format) evas_stringshare_del(im->format);
207 if (im->comment) evas_stringshare_del(im->comment);
208 if (im->updates) evas_common_tilebuf_free(im->updates);
209 _xr_image_info_free(im->xcbinf);
214 _xre_image_free(XR_Image *im)
217 if (im->references != 0) return;
221 _xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
222 _xr_image_cache = evas_list_prepend(_xr_image_cache, im);
223 _xr_image_cache_usage += (im->w * im->h * 4);
224 _xre_image_cache_set(_xr_image_cache_size);
228 __xre_image_real_free(im);
233 _xre_image_region_dirty(XR_Image *im, int x, int y, int w, int h)
237 im->updates = evas_common_tilebuf_new(im->w, im->h);
238 if (im->updates) evas_common_tilebuf_set_tile_size(im->updates, 8, 8);
241 evas_common_tilebuf_add_redraw(im->updates, x, y, w, h);
245 _xre_image_dirty(XR_Image *im)
247 if (im->dirty) return;
249 _xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
251 __xre_image_dirty_hash_add(im);
255 _xre_image_copy(XR_Image *im)
260 if (im->data) data = im->data;
263 if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key, &(im->load_opts));
266 evas_cache_image_load_data(&im->im->cache_entry);
267 data = im->im->image.data;
270 if (!data) return NULL;
271 im2 = _xre_image_new_from_copied_data(im->xcbinf, im->w, im->h, data);
272 if (im2) im2->alpha = im->alpha;
273 if ((im->im) && (!im->dirty))
275 evas_cache_image_drop(&im->im->cache_entry);
282 _xre_image_resize(XR_Image *im, int w, int h)
284 if ((w == im->w) && (h == im->h)) return;
287 Xcb_Render_Surface *old_surface;
288 int x = 0, y = 0, ww, hh;
291 RECTS_CLIP_TO_RECT(x, y, ww, hh, 0, 0, im->w, im->h);
292 old_surface = im->surface;
293 im->surface = _xr_render_surface_new(old_surface->xcbinf,
294 w + 1, h + 1, old_surface->fmt, old_surface->alpha);
296 _xr_render_surface_copy(old_surface, im->surface, 0, 0, 0, 0, ww, hh);
297 _xr_render_surface_free(old_surface);
302 int x = 0, y = 0, ww, hh;
303 unsigned int *sp, *dp;
306 data = malloc(w * h * 4);
311 _xr_render_surface_free(im->surface);
318 RECTS_CLIP_TO_RECT(x, y, ww, hh, 0, 0, im->w, im->h);
319 func = evas_common_draw_func_copy_get(w * h, 0);
322 for (y = 0; y < hh; y++)
324 sp = ((unsigned int *)im->data) + (y * im->w);
325 dp = ((unsigned int *)data) + (y * w);
328 evas_common_cpu_end_opt();
330 __xre_image_dirty_hash_del(im);
333 __xre_image_dirty_hash_add(im);
340 im->im = (RGBA_Image*) evas_cache_image_empty(evas_common_image_cache_get());
346 _xr_render_surface_free(im->surface);
351 evas_cache_image_load_data(&im->im->cache_entry);
352 if (im_old->image.data)
354 int x = 0, y = 0, ww, hh;
357 RECTS_CLIP_TO_RECT(x, y, ww, hh, 0, 0, im->w, im->h);
358 evas_common_blit_rectangle(im_old, im->im, 0, 0, ww, hh, 0, 0);
359 evas_common_cpu_end_opt();
363 im->data = im->im->image.data;
364 im->im->image.data = NULL;
365 evas_cache_image_drop(&im->im->cache_entry);
367 evas_cache_image_drop(&im_old->cache_entry);
368 __xre_image_dirty_hash_add(im);
372 im->data = malloc(w * h * 4);
374 __xre_image_dirty_hash_add(im);
381 _xre_image_data_get(XR_Image *im)
385 if (im->data) data = im->data;
388 if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key, &(im->load_opts));
391 evas_cache_image_load_data(&im->im->cache_entry);
392 data = im->im->image.data;
399 _xre_image_data_find(void *data)
403 im = __xre_image_dirty_hash_find(data);
412 _xre_image_data_put(XR_Image *im, void *data)
420 if (data == imdata) return;
421 __xre_image_dirty_hash_del(im);
422 if (im->free_data) free(im->data);
426 if (im->im) imdata = im->im->image.data;
427 if (data == imdata) return;
430 evas_cache_image_drop(&im->im->cache_entry);
435 __xre_image_dirty_hash_add(im);
439 _xr_render_surface_free(im->surface);
445 _xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
450 evas_common_tilebuf_free(im->updates);
456 _xre_image_alpha_set(XR_Image *im, int alpha)
458 if (im->alpha == alpha) return;
462 Xcb_Render_Surface *old_surface;
464 old_surface = im->surface;
467 im->surface = _xr_render_surface_new(im->xcbinf,
468 im->w + 1, im->h + 1, im->xcbinf->fmt32, 1);
470 im->surface = _xr_render_surface_new(im->xcbinf,
471 im->w + 1, im->h + 1, im->xcbinf->fmt24, 0);
473 _xr_render_surface_copy(old_surface,
474 im->surface, 0, 0, 0, 0, im->w + 1, im->h + 1);
475 _xr_render_surface_free(old_surface);
479 evas_common_tilebuf_free(im->updates);
485 _xre_image_alpha_get(XR_Image *im)
491 _xre_image_border_set(XR_Image *im, int l, int r, int t, int b)
494 _xre_image_surface_gen(im);
502 im->surface->bordered = 1;
504 im->surface->bordered = 0;
509 _xre_image_border_get(XR_Image *im, int *l, int *r, int *t, int *b)
514 _xre_image_surface_gen(XR_Image *im)
518 if ((im->surface) && (!im->updates)) return;
519 if (im->data) data = im->data;
522 if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key, &(im->load_opts));
525 evas_cache_image_load_data(&im->im->cache_entry);
526 data = im->im->image.data;
534 Tilebuf_Rect *rects, *r;
536 rects = evas_common_tilebuf_get_render_rects(im->updates);
539 for (r = rects; r; r = (Tilebuf_Rect *)((Evas_Object_List *)r)->next)
543 rx = r->x; ry = r->y; rw = r->w, rh = r->h;
544 RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, im->w, im->h);
546 _xr_render_surface_argb_pixels_fill(im->surface, im->w, im->h, data, rx, ry, rw, rh);
548 _xr_render_surface_rgb_pixels_fill(im->surface, im->w, im->h, data, rx, ry, rw, rh);
550 evas_common_tilebuf_free_render_rects(rects);
552 evas_common_tilebuf_free(im->updates);
559 im->surface = _xr_render_surface_new(im->xcbinf,
560 im->w + 1, im->h + 1, im->xcbinf->fmt32, 1);
561 _xr_render_surface_argb_pixels_fill(im->surface, im->w, im->h, data, 0, 0, im->w, im->h);
565 im->surface = _xr_render_surface_new(im->xcbinf,
566 im->w + 1, im->h + 1, im->xcbinf->fmt24, 0);
567 _xr_render_surface_rgb_pixels_fill(im->surface, im->w, im->h, data, 0, 0, im->w, im->h);
569 /* fill right and bottom pixel so interpolation works right */
570 _xr_render_surface_copy(im->surface, im->surface,
574 _xr_render_surface_copy(im->surface, im->surface,
578 _xr_render_surface_copy(im->surface, im->surface,
579 im->w - 1, im->h - 1,
582 if ((im->im) && (!im->dirty))
584 evas_cache_image_drop(&im->im->cache_entry);
590 _xre_image_cache_set(int size)
592 _xr_image_cache_size = size;
593 while (_xr_image_cache_usage > _xr_image_cache_size)
597 l = evas_list_last(_xr_image_cache);
603 _xr_image_cache = evas_list_remove_list(_xr_image_cache, l);
604 _xr_image_cache_usage -= (im->w * im->h * 4);
605 __xre_image_real_free(im);
611 _xre_image_cache_get(void)
613 return _xr_image_cache_size;