From 7881c0b849011b05a0e754914cb186c54f4e9143 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Tue, 8 Feb 2011 11:41:38 +0000 Subject: [PATCH] improvement to gl engine wrt. caching. SVN revision: 56801 --- legacy/evas/ChangeLog | 7 ++ .../engines/gl_common/evas_gl_common.h | 3 + .../modules/engines/gl_common/evas_gl_image.c | 67 ++++++++++++++++++- .../engines/gl_common/evas_gl_texture.c | 1 + .../src/modules/engines/gl_x11/evas_engine.c | 40 +++++++++++ 5 files changed, 116 insertions(+), 2 deletions(-) diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index 10b6520231..79ada457bd 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -57,3 +57,10 @@ clip on the object. This is still buggy. * Software support for arbitrary maps. So you can use any size map (not just 4 points) for maps. Once again this is a little buggy. + +2011-02-02 Carsten Haitzler (The Rasterman) + + * GL engine gets a speculative texture cache to shadow the + normal image cache to avoid excess texture uploads when + cycling images often. Should improve performance in some + cases. diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h index 864c33b56a..c8917f181e 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h @@ -125,6 +125,8 @@ struct _Evas_GL_Shared { Eina_List *images; + int images_size; + struct { GLint max_texture_units; GLint max_texture_size; @@ -471,6 +473,7 @@ void evas_gl_common_image_native_enable(Evas_GL_Image *im); void evas_gl_common_image_native_disable(Evas_GL_Image *im); void evas_gl_common_image_scale_hint_set(Evas_GL_Image *im, int hint); void evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint); +void evas_gl_common_image_cache_flush(Evas_GL_Context *gc); void evas_gl_common_image_free(Evas_GL_Image *im); Evas_GL_Image *evas_gl_common_image_surface_new(Evas_GL_Context *gc, unsigned int w, unsigned int h, int alpha); void evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h); diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c index fd24f5dac3..175c37b29e 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_image.c @@ -30,11 +30,14 @@ evas_gl_common_image_load(Evas_GL_Context *gc, const char *file, const char *key im_im = evas_common_load_image_from_file(file, key, lo, error); if (!im_im) return NULL; + // FIXME: keep unreffed shared images around EINA_LIST_FOREACH(gc->shared->images, l, im) { if (im->im == im_im) { - evas_cache_image_drop(&im_im->cache_entry); +// why did i put this here? i think to free the rgba pixel data once a texture +// exists. +// evas_cache_image_drop(&im_im->cache_entry); gc->shared->images = eina_list_remove_list(gc->shared->images, l); gc->shared->images = eina_list_prepend(gc->shared->images, im); im->references++; @@ -230,6 +233,8 @@ evas_gl_common_image_native_enable(Evas_GL_Image *im) im->cs.no_free = 0; if (im->cached) { + if (im->references == 0) + im->gc->shared->images_size -= (im->w * im->h); im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); im->cached = 0; } @@ -302,6 +307,8 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint) im->cs.no_free = 0; if (im->cached) { + if (im->references == 0) + im->gc->shared->images_size -= (im->w * im->h); im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); im->cached = 0; } @@ -342,6 +349,59 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint) } } +static void +_evas_gl_image_cache_trim(Evas_GL_Context *gc) +{ + int size = evas_common_image_get_cache(); + + while (gc->shared->images_size > size) + { + Evas_GL_Image *im2; + Eina_List *l; + + EINA_LIST_REVERSE_FOREACH(gc->shared->images, l, im2) + { + if (im2->references == 0) + { + im2->cached = 0; + im2->gc->shared->images = + eina_list_remove_list(im2->gc->shared->images, l); + im2->gc->shared->images_size -= (im2->w * im2->h); + evas_gl_common_image_free(im2); + break; + } + } + if (!l) + { + printf("EEEK images_size > 0 but no 0 ref images in cache\n"); + break; // something went wrong + } + } +} + +static Eina_Bool +_evas_gl_image_cache_add(Evas_GL_Image *im) +{ + if (im->references == 0) + { + im->gc->shared->images_size += (im->w * im->h); + _evas_gl_image_cache_trim(im->gc); + return EINA_TRUE; + } + else + { + im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); + im->cached = 0; + } + return EINA_FALSE; +} + +void +evas_gl_common_image_cache_flush(Evas_GL_Context *gc) +{ + _evas_gl_image_cache_trim(gc); +} + void evas_gl_common_image_free(Evas_GL_Image *im) { @@ -355,7 +415,10 @@ evas_gl_common_image_free(Evas_GL_Image *im) { if (!im->cs.no_free) free(im->cs.data); } - if (im->cached) im->gc->shared->images = eina_list_remove(im->gc->shared->images, im); + if (im->cached) + { + if (_evas_gl_image_cache_add(im)) return; + } if (im->im) evas_cache_image_drop(&im->im->cache_entry); if (im->tex) evas_gl_common_texture_free(im->tex); free(im); diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c index e03b2d9bad..0810472736 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_texture.c @@ -847,6 +847,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im) glPixelStorei(GL_UNPACK_ALIGNMENT, 4); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); +// printf("tex upload %ix%i\n", im->cache_entry.w, im->cache_entry.h); // +-+ // +-+ // diff --git a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c index 851cfc71ff..8434dafce9 100644 --- a/legacy/evas/src/modules/engines/gl_x11/evas_engine.c +++ b/legacy/evas/src/modules/engines/gl_x11/evas_engine.c @@ -1814,6 +1814,42 @@ eng_image_content_hint_get(void *data __UNUSED__, void *image) return gim->content_hint; } +static void +eng_image_cache_flush(void *data __UNUSED__) +{ + Render_Engine *re; + int tmp_size; + + re = (Render_Engine *)data; + + tmp_size = evas_common_image_get_cache(); + evas_common_image_set_cache(0); + evas_common_rgba_image_scalecache_flush(); + evas_gl_common_image_cache_flush(re->win->gl_context); + evas_common_image_set_cache(tmp_size); +} + +static void +eng_image_cache_set(void *data __UNUSED__, int bytes) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_common_image_set_cache(bytes); + evas_common_rgba_image_scalecache_size_set(bytes); + evas_gl_common_image_cache_flush(re->win->gl_context); +} + +static int +eng_image_cache_get(void *data __UNUSED__) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + return evas_common_image_get_cache(); +} + + static void eng_image_stride_get(void *data __UNUSED__, void *image, int *stride) { @@ -1948,6 +1984,10 @@ module_open(Evas_Module *em) ORD(image_content_hint_set); ORD(image_content_hint_get); + + ORD(image_cache_flush); + ORD(image_cache_set); + ORD(image_cache_get); /* now advertise out own api */ em->functions = (void *)(&func);