improvement to gl engine wrt. caching.
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 8 Feb 2011 11:41:38 +0000 (11:41 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 8 Feb 2011 11:41:38 +0000 (11:41 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@56801 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/modules/engines/gl_common/evas_gl_common.h
src/modules/engines/gl_common/evas_gl_image.c
src/modules/engines/gl_common/evas_gl_texture.c
src/modules/engines/gl_x11/evas_engine.c

index 10b6520..79ada45 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
         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.
index 864c33b..c8917f1 100644 (file)
@@ -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);
index fd24f5d..175c37b 100644 (file)
@@ -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);
index e03b2d9..0810472 100644 (file)
@@ -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);
    //  +-+
    //  +-+
    // 
index 851cfc7..8434daf 100644 (file)
@@ -1815,6 +1815,42 @@ eng_image_content_hint_get(void *data __UNUSED__, void *image)
 }
 
 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)
 {
    Evas_GL_Image *im = image;
@@ -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);