quick - evas scalecache put this in svn do i dont lose my patch. i'll revert
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 2 Dec 2008 02:32:22 +0000 (02:32 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 2 Dec 2008 02:32:22 +0000 (02:32 +0000)
and work on gettign the leak fixed.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@37898 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/lib/cache/evas_cache.h
src/lib/cache/evas_cache_engine_image.c
src/lib/cache/evas_cache_image.c
src/lib/engines/common/evas_image_load.c
src/lib/engines/common/evas_image_main.c
src/lib/engines/common/evas_scale_sample.c
src/lib/include/evas_common.h
src/modules/engines/software_generic/evas_engine.c

index 29b2ac0..b3a1093 100644 (file)
@@ -386,7 +386,9 @@ AC_CHECK_HEADERS(pthread.h sched.h,
 )
 ### disable pthreads by default for now - some wierd deadlock issue with
 # barriers (makes no sense)
-#build_pthreads="no"
+# disable pthread code - messes with scalecache (whihc really is a much
+# bigger general speedup
+build_pthreads="no"
 AC_MSG_CHECKING(whether to build pthread code)
 AC_ARG_ENABLE(pthreads,
   AC_HELP_STRING([--enable-pthreads], [enable threaded rendering]),
index f3cee96..142f3c6 100644 (file)
@@ -57,6 +57,9 @@ struct _Evas_Cache_Image
    int                           usage;
    int                           limit;
    int                           references;
+   
+   Eina_List                    *scaled;
+   int                           scaledmem;
 };
 
 struct _Evas_Cache_Engine_Image_Func
@@ -126,6 +129,7 @@ EAPI Image_Entry*             evas_cache_image_alone(Image_Entry *im);
 EAPI Image_Entry*             evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h);
 EAPI void                     evas_cache_image_load_data(Image_Entry *im);
 EAPI void                     evas_cache_image_surface_alloc(Image_Entry *im, int w, int h);
+EAPI void                     evas_cache_image_surface_dealloc(Image_Entry *im);
 EAPI DATA32*                  evas_cache_image_pixels(Image_Entry *im);
 EAPI Image_Entry*             evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace);
 EAPI Image_Entry*             evas_cache_image_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace);
index d048dc4..76b4121 100644 (file)
@@ -192,7 +192,7 @@ evas_cache_engine_image_init(const Evas_Cache_Engine_Image_Func *cb, Evas_Cache_
    parent->references++;
 
    new->brother = NULL;
-
+   
    return new;
 }
 
@@ -260,6 +260,7 @@ evas_cache_engine_image_flush(Evas_Cache_Engine_Image *cache)
         eim = (Engine_Image_Entry *) cache->lru->last;
         _evas_cache_engine_image_dealloc(cache, eim);
      }
+   evas_common_image_set_cache(evas_common_image_get_cache());
 }
 
 EAPI void
index bc9c328..73477d7 100644 (file)
@@ -45,19 +45,38 @@ static void _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry
 
 static void
 _evas_cache_image_make_dirty(Evas_Cache_Image *cache,
-                             Image_Entry *im)
+                             Image_Entry *ie)
 {
-   im->flags.cached = 1;
-   im->flags.dirty = 1;
-   im->flags.activ = 0;
-   im->flags.lru_nodata = 0;
-   cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(im));
+   ie->flags.cached = 1;
+   ie->flags.dirty = 1;
+   ie->flags.activ = 0;
+   ie->flags.lru_nodata = 0;
+   cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(ie));
 
-   if (im->cache_key)
+   if (ie->cache_key)
      {
-        eina_stringshare_del(im->cache_key);
-        im->cache_key = NULL;
+        eina_stringshare_del(ie->cache_key);
+        ie->cache_key = NULL;
      }
+
+   while (ie->scalecache.others)
+     {
+        Image_Entry *ie2;
+        
+        ie2 = ie->scalecache.others->data;
+        cache->usage -= cache->func.mem_size_get(ie2);
+        if (ie2->scalecache.usage >= 6)
+          {
+             ie->scalecache.mem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+             ie->cache->scaledmem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+             ie->cache->scaled =
+               eina_list_remove(ie->cache->scaled, ie2);
+          }
+        ie->scalecache.others = eina_list_remove_list(ie->scalecache.others, ie->scalecache.others);
+        ie2->scalecache.parent = NULL;
+        evas_cache_image_drop(ie2);
+     }
+   
 }
 
 static void
@@ -92,7 +111,6 @@ _evas_cache_image_make_inactiv(Evas_Cache_Image *cache,
        im->flags.cached = 1;
        cache->inactiv = evas_hash_direct_add(cache->inactiv, key, im);
        cache->lru = eina_inlist_prepend(cache->lru, EINA_INLIST_GET(im));
-       cache->usage += cache->func.mem_size_get(im);
      }
    else
      {
@@ -108,7 +126,6 @@ _evas_cache_image_remove_lru_nodata(Evas_Cache_Image *cache,
      {
         im->flags.lru_nodata = 0;
         cache->lru_nodata = eina_inlist_remove(cache->lru_nodata, EINA_INLIST_GET(im));
-        cache->usage -= cache->func.mem_size_get(im);
      }
 }
 
@@ -160,6 +177,24 @@ _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
    if (cache->func.debug)
      cache->func.debug("deleting", ie);
 
+   while (ie->scalecache.others)
+     {
+        Image_Entry *ie2;
+        
+        ie2 = ie->scalecache.others->data;
+        cache->usage -= cache->func.mem_size_get(ie2);
+        if (ie2->scalecache.usage >= 6)
+          {
+             ie->scalecache.mem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+             ie->cache->scaledmem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+             ie->cache->scaled =
+               eina_list_remove(ie->cache->scaled, ie2);
+          }
+        ie->scalecache.others = eina_list_remove_list(ie->scalecache.others, ie->scalecache.others);
+        ie2->scalecache.parent = NULL;
+        evas_cache_image_drop(ie2);
+     }
+   
    cache->func.destructor(ie);
 
    _evas_cache_image_remove_activ(cache, ie);
@@ -251,7 +286,7 @@ _evas_cache_image_entry_surface_alloc(Evas_Cache_Image *cache,
    wmin = w > 0 ? w : 1;
    hmin = h > 0 ? h : 1;
    if (ie->allocated.w == wmin && ie->allocated.h == hmin)
-     return ;
+     return;
 
 #ifdef BUILD_ASYNC_PRELOAD
    pthread_mutex_lock(&mutex_surface_alloc);
@@ -382,6 +417,9 @@ evas_cache_image_init(const Evas_Cache_Image_Func *cb)
 
    new->references = 1;
 
+   new->scaled = NULL;
+   new->scaledmem = 0;
+   
    return new;
 }
 
@@ -603,6 +641,20 @@ evas_cache_image_drop(Image_Entry *im)
    assert(im);
    assert(im->cache);
 
+   if (im->scalecache.parent)
+     {
+        im->scalecache.parent->cache->usage -= im->scalecache.parent->cache->func.mem_size_get(im);
+        if (im->scalecache.usage >= 6)
+          {
+             im->scalecache.parent->scalecache.mem -= im->scalecache.dst_w * im->scalecache.dst_h;
+             im->scalecache.parent->cache->scaledmem -= im->scalecache.dst_w * im->scalecache.dst_h;
+             im->scalecache.parent->cache->scaled =
+               eina_list_remove(im->scalecache.parent->cache->scaled, im);
+          }
+        im->scalecache.parent->scalecache.others = 
+          eina_list_remove(im->scalecache.parent->scalecache.others, im);
+     }
+   
    im->references--;
    cache = im->cache;
 
@@ -643,13 +695,31 @@ evas_cache_image_data_not_needed(Image_Entry *im)
 EAPI Image_Entry *
 evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
 {
-   Image_Entry          *im_dirty = im;
+   Image_Entry          *im_dirty = im, *ie = im;
    Evas_Cache_Image     *cache;
 
    assert(im);
    assert(im->cache);
 
    cache = im->cache;
+   while (ie->scalecache.others)
+     {
+        Image_Entry *ie2;
+        
+        ie2 = ie->scalecache.others->data;
+        cache->usage -= cache->func.mem_size_get(ie2);
+        if (ie2->scalecache.usage >= 6)
+          {
+             ie->scalecache.mem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+             ie->cache->scaledmem -= ie2->scalecache.dst_w * ie2->scalecache.dst_h;
+             ie->cache->scaled =
+               eina_list_remove(ie->cache->scaled, ie2);
+          }
+        ie->scalecache.others = eina_list_remove_list(ie->scalecache.others, ie->scalecache.others);
+        ie2->scalecache.parent = NULL;
+        evas_cache_image_drop(ie2);
+     }
+   
    if (!(im->flags.dirty))
      {
         if (im->references == 1) im_dirty = im;
@@ -815,6 +885,41 @@ evas_cache_image_surface_alloc(Image_Entry *im, int w, int h)
      cache->func.debug("surface-alloc", im);
 }
 
+EAPI void
+evas_cache_image_surface_dealloc(Image_Entry *im)
+{
+   Evas_Cache_Image     *cache;
+
+   assert(im);
+   assert(im->cache);
+
+   cache = im->cache;
+
+   if (!((RGBA_Image *)im)->image.data) return;
+   if (!im->info.loader) return;
+   if (!im->info.module) return;
+   if (!im->flags.loaded) return;
+   
+   im->flags.loaded = 0;
+   
+#ifdef BUILD_ASYNC_PRELOAD
+   pthread_mutex_lock(&mutex_surface_alloc);
+#endif
+
+   printf("-------- actual dealloc %p\n", im);
+   _evas_cache_image_remove_lru_nodata(cache, im);
+   cache->func.surface_delete(im);
+   im->allocated.w = 0;
+   im->allocated.h = 0;
+
+#ifdef BUILD_ASYNC_PRELOAD
+   pthread_mutex_unlock(&mutex_surface_alloc);
+#endif
+
+   if (cache->func.debug)
+     cache->func.debug("surface-dealloc", im);
+}
+
 EAPI Image_Entry *
 evas_cache_image_size_set(Image_Entry *im, int w, int h)
 {
@@ -890,7 +995,6 @@ evas_cache_image_load_data(Image_Entry *im)
      {
         _evas_cache_image_entry_surface_alloc(cache, im, im->w, im->h);
         im->flags.loaded = 0;
-
         return ;
      }
 
index 27b2eef..8d0a94c 100644 (file)
@@ -43,6 +43,10 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
    char                 *dot;
    int                   i;
 
+   if (ie->info.loader)
+     {
+        if (!evas_common_load_rgba_image_data_from_file(ie)) return 0;
+     }
    dot = strrchr (ie->file, '.');
    if (dot)
      {
index 438cfc6..623aaa0 100644 (file)
@@ -405,7 +405,36 @@ EAPI void
 evas_common_image_set_cache(int size)
 {
    if (eci != NULL)
-     evas_cache_image_set(eci, size);
+     {
+        Evas_Cache_Image *cache = eci;
+        
+        evas_cache_image_set(eci, size);
+        while (cache->scaledmem > (cache->limit >> 2))
+          {
+             Eina_List *l;
+             Image_Entry *ie;
+             
+             l = eina_list_last(cache->scaled);
+             while (l)
+               {
+                  ie = l->data;
+                  if (ie->scalecache.parent) break;
+                  l = l->prev;
+               }
+             if (!l)
+               {
+                  break;
+               }
+             ie->scalecache.parent->scalecache.mem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+             cache->scaledmem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+             cache->scaled =
+               eina_list_remove_list(cache->scaled, l);
+             ie->scalecache.parent->scalecache.others =
+               eina_list_remove(ie->scalecache.parent->scalecache.others, ie);
+             ie->scalecache.parent = NULL;
+             evas_cache_image_drop(ie);
+          }
+     }
 }
 
 EAPI int
index 0d57717..a1c3d6b 100644 (file)
@@ -271,9 +271,10 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
        /* scale to dst */
        dptr = dst_ptr;
 #ifdef DIRECT_SCALE
-       if ((!src->cache_entry.flags.alpha) &&
+       if ((dc->render_op == _EVAS_RENDER_COPY) ||
+            ((!src->cache_entry.flags.alpha) &&
             (!dst->cache_entry.flags.alpha) &&
-            (!dc->mul.use))
+            (!dc->mul.use)))
          {
             for (y = 0; y < dst_clip_h; y++)
               {
index 59f3834..30ed5f1 100644 (file)
@@ -270,64 +270,70 @@ struct _Image_Entry_Flags
 
 struct _Image_Entry
 {
-  EINA_INLIST;
-
-  Evas_Cache_Image      *cache;
-
-  const char            *cache_key;
-
-  const char            *file;
-  const char            *key;
-
-  const void            *target;
-
-  time_t                 timestamp;
-  time_t                 laststat;
-
-  int                    references;
-
-  unsigned char          scale;
-
-  RGBA_Image_Loadopts    load_opts;
-  int                    space;
-  int                    w;
-  int                    h;
-
-  struct
-  {
-     int                w;
-     int                h;
-  } allocated;
-
-  struct
-  {
-     void              *module;
-     void              *loader;
-  } info;
-
-  Image_Entry_Flags      flags;
+   EINA_INLIST;
+   
+   Evas_Cache_Image      *cache;
+   
+   const char            *cache_key;
+   
+   const char            *file;
+   const char            *key;
+   
+   const void            *target;
+   
+   time_t                 timestamp;
+   time_t                 laststat;
+   
+   int                    references;
+   
+   unsigned char          scale;
+   
+   RGBA_Image_Loadopts    load_opts;
+   int                    space;
+   int                    w;
+   int                    h;
+   
+   struct {
+      int                w;
+      int                h;
+   } allocated;
+   
+   struct {
+      void              *module;
+      void              *loader;
+   } info;
+   
+   Image_Entry_Flags      flags;
+   struct {
+      int                 usage;
+      int                 mem;
+      int                 src_x, src_y, src_w, src_h;
+      int                 dst_w, dst_h;
+      int                 smooth;
+      Image_Entry        *parent;
+      Eina_List          *others;
+   } scalecache;
 };
 
 struct _Engine_Image_Entry
 {
    EINA_INLIST;
-
+   
    /* Upper Engine data. */
    Image_Entry                  *src;
-
+   
    /* Cache stuff. */
    Evas_Cache_Engine_Image      *cache;
    const char                   *cache_key;
-
-   struct
-   {
-     Evas_Bool                   cached : 1;
-     Evas_Bool                   activ : 1;
-     Evas_Bool                   dirty : 1;
-     Evas_Bool                   loaded : 1;
-     Evas_Bool                   need_parent : 1;
+   
+   struct {
+      Evas_Bool                   cached : 1;
+      Evas_Bool                   activ : 1;
+      Evas_Bool                   dirty : 1;
+      Evas_Bool                   loaded : 1;
+      Evas_Bool                   need_parent : 1;
    } flags;
-
+   
    int                           references;
    int                           w;
    int                           h;
index 1435b31..ddd277d 100644 (file)
@@ -731,6 +731,175 @@ eng_image_data_preload_cancel(void *data, void *image)
    evas_cache_image_preload_cancel(&im->cache_entry);
 }
 
+#define SCALECACHE 1
+
+#ifdef SCALECACHE
+static Image_Entry *
+_sc_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth)
+{
+   Eina_List *l;
+   Image_Entry *ie = NULL;
+   
+   for (l = im->scalecache.others; l; l = l->next)
+     {
+        ie = l->data;
+        if ((ie->scalecache.dst_w == dst_w) &&
+            (ie->scalecache.dst_h == dst_h) &&
+            (ie->scalecache.src_w == src_w) &&
+            (ie->scalecache.src_h == src_h) &&
+            (ie->scalecache.src_x == src_x) &&
+            (ie->scalecache.src_y == src_y) &&
+            (ie->scalecache.smooth == smooth))
+          {
+             if (l != ie->scalecache.others)
+               {
+                  im->scalecache.others = eina_list_remove_list(im->scalecache.others, l);
+                  im->scalecache.others = eina_list_prepend(im->scalecache.others, ie);
+               }
+             ie->scalecache.usage++;
+             return ie;
+          }
+     }
+   return NULL;
+}
+
+static void
+_sc_clean(Image_Entry *im)
+{
+   while ((im->scalecache.mem > (im->cache->limit >> 2)) ||
+          (eina_list_count(im->scalecache.others) > 40))
+     {
+        Eina_List *l;
+        Image_Entry *ie;
+        
+        printf("clean %i > %i\n", im->cache->scaledmem, im->cache->limit >> 2);
+        l = eina_list_last(im->scalecache.others);
+        ie = l->data;
+        if (ie->scalecache.usage >= 6)
+          {
+             im->scalecache.mem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+             im->cache->scaledmem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+             im->cache->scaled =
+               eina_list_remove(im->cache->scaled, ie);
+          }
+        im->scalecache.others = eina_list_remove_list(im->scalecache.others, l);
+        ie->scalecache.parent = NULL;
+        evas_cache_image_drop(ie);
+     }
+}
+
+static Image_Entry *
+_sc_new(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth)
+{
+   Image_Entry *ie;
+
+   ie = evas_cache_image_empty(im->cache);
+   evas_cache_image_colorspace(ie, EVAS_COLORSPACE_ARGB8888);
+   im->scalecache.usage++;
+   im->scalecache.others = eina_list_prepend(im->scalecache.others, ie);
+   ie->scalecache.src_x = src_x;
+   ie->scalecache.src_y = src_y;
+   ie->scalecache.src_w = src_w;
+   ie->scalecache.src_h = src_h;
+   ie->scalecache.dst_w = dst_w;
+   ie->scalecache.dst_h = dst_h;
+   ie->scalecache.smooth = smooth;
+   ie->scalecache.parent = im;
+   return ie;
+}
+
+static int
+_sc_fill(Image_Entry *im, Image_Entry *ie)
+{
+   RGBA_Draw_Context *tctx;
+   
+   ie->scalecache.usage++;
+   if (ie->scalecache.usage < 5) return 0;
+   if (ie->scalecache.usage >= 6)
+     {
+        ie->scalecache.parent->scalecache.usage--;
+        if (ie->scalecache.parent->scalecache.usage <= 0)
+          {
+             ie->scalecache.parent->scalecache.usage = 0;
+             if ((im->info.loader) && 
+                 (im->flags.loaded) && 
+                 (im->info.module) &&
+                 (im->file) && 
+                 (((RGBA_Image*)im)->image.data));
+               {
+                  evas_cache_image_surface_dealloc(im);
+               }
+          }
+        im->cache->scaled =
+          eina_list_remove(im->cache->scaled, ie);
+        im->cache->scaled =
+          eina_list_prepend(im->cache->scaled, ie);
+        return 1;
+     }
+   im->scalecache.usage += 10;
+   im->cache->func.load(im);
+   ie->scalecache.usage = 6;
+   im->scalecache.mem += ie->scalecache.dst_w * ie->scalecache.dst_h;
+   im->cache->scaledmem += ie->scalecache.dst_w * ie->scalecache.dst_h;
+   im->cache->scaled =
+     eina_list_prepend(im->cache->scaled, ie);
+   ie->flags.alpha = im->flags.alpha;
+   ie->w = ie->scalecache.dst_w;
+   ie->h = ie->scalecache.dst_h;
+   evas_cache_image_surface_alloc(ie, ie->w, ie->h);
+   tctx = evas_common_draw_context_new();
+   evas_common_draw_context_set_render_op(tctx, _EVAS_RENDER_COPY);
+   if (ie->scalecache.smooth)
+     evas_common_scale_rgba_in_to_out_clip_smooth
+     ((RGBA_Image *)im, (RGBA_Image *)ie, tctx,
+      ie->scalecache.src_x, ie->scalecache.src_y,
+      ie->scalecache.src_w, ie->scalecache.src_h,
+      0, 0,
+      ie->scalecache.dst_w, ie->scalecache.dst_h);
+   else
+     evas_common_scale_rgba_in_to_out_clip_sample
+     ((RGBA_Image *)im, (RGBA_Image *)ie, tctx,
+      ie->scalecache.src_x, ie->scalecache.src_y,
+      ie->scalecache.src_w, ie->scalecache.src_h,
+      0, 0,
+      ie->scalecache.dst_w, ie->scalecache.dst_h);
+   evas_common_draw_context_free(tctx);
+   return 1;
+}
+
+static void
+_sc_flush(Evas_Cache_Image *cache)
+{
+   while (cache->scaledmem > (cache->limit >> 2))
+     {
+        Eina_List *l;
+        Image_Entry *ie;
+
+        printf("flush %i > %i\n", cache->scaledmem, cache->limit >> 2);
+        l = eina_list_last(cache->scaled);
+        while (l)
+          {
+             ie = l->data;
+             if (ie->scalecache.parent) break;
+             l = l->prev;
+          }
+        if (!l)
+          {
+             break;
+          }
+        ie->scalecache.parent->scalecache.mem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+        cache->scaledmem -= ie->scalecache.dst_w * ie->scalecache.dst_h;
+        cache->scaled =
+          eina_list_remove_list(cache->scaled, l);
+        ie->scalecache.parent->scalecache.others =
+          eina_list_remove(ie->scalecache.parent->scalecache.others, ie);
+        ie->scalecache.parent = NULL;
+        evas_cache_image_drop(ie);
+     }
+}
+
+#endif
+
 static void
 eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
 {
@@ -743,20 +912,72 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
    evas_common_image_colorspace_normalize(im);
 #ifdef BUILD_PTHREAD
    if (cpunum > 1)
-     evas_common_pipe_image_draw(im, surface, context, smooth,
-                                src_x, src_y, src_w, src_h,
-                                dst_x, dst_y, dst_w, dst_h);
+     {
+        if (im->image.data)
+          {
+             evas_common_pipe_image_draw(im, surface, 
+                                         context, smooth,
+                                         src_x, src_y, src_w, src_h,
+                                         dst_x, dst_y, dst_w, dst_h);
+          }
+     }
    else
 #endif
      {
-       if (smooth)
-         evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context,
-                                                      src_x, src_y, src_w, src_h,
-                                                      dst_x, dst_y, dst_w, dst_h);
-       else
-         evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context,
-                                                      src_x, src_y, src_w, src_h,
-                                                      dst_x, dst_y, dst_w, dst_h);
+#ifdef SCALECACHE        
+        Image_Entry *ie, *ie2;
+        int ok;
+        
+        ie = (Image_Entry *)im;
+        if ((src_w == dst_w) && (src_h == dst_h))
+          {
+             ie->scalecache.usage++;
+             if (smooth)
+               evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context,
+                                                            src_x, src_y, src_w, src_h,
+                                                            dst_x, dst_y, dst_w, dst_h);
+             else
+               evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context,
+                                                            src_x, src_y, src_w, src_h,
+                                                            dst_x, dst_y, dst_w, dst_h);
+          }
+        else
+          {
+             ok = 0;
+             _sc_clean(ie);
+             ie2 = _sc_find(ie, src_x, src_y, src_w, src_h, dst_w, dst_h, smooth);
+             if (ie2) ok = _sc_fill(ie, ie2);
+             else
+               {
+                  ie2 = _sc_new(ie, src_x, src_y, src_w, src_h, dst_w, dst_h, smooth);
+                  if (ie2) ok = _sc_fill(ie, ie2);
+               }
+             if ((ie2) && (ok))
+               evas_common_scale_rgba_in_to_out_clip_sample((RGBA_Image *)ie2,
+                                                            surface, context,
+                                                            0, 0, dst_w, dst_h,
+                                                            dst_x, dst_y, dst_w, dst_h);
+             else
+               {
+                  ie->scalecache.usage++;
+                  evas_cache_image_load_data(ie);
+#endif
+                  if (im->image.data)
+                    {
+                       if (smooth)
+                         evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context,
+                                                                      src_x, src_y, src_w, src_h,
+                                                                      dst_x, dst_y, dst_w, dst_h);
+                       else
+                         evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context,
+                                                                      src_x, src_y, src_w, src_h,
+                                                                      dst_x, dst_y, dst_w, dst_h);
+                    }
+#ifdef SCALECACHE        
+               }
+          }
+        _sc_flush(ie->cache);
+#endif
        evas_common_cpu_end_opt();
      }
 }