Evas_cache: fix preload bug
authorJiyoun Park <jy0703.park@samsung.com>
Wed, 4 May 2011 02:36:03 +0000 (11:36 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Wed, 4 May 2011 04:17:04 +0000 (13:17 +0900)
if app or widget call preload more than twice to same object,
evas add two target for one object
when object free before preload done, it make crash because object is already free ,
but second target reference object is still remain.

Change-Id: I05bdca2b61b0989094091504722b838138b505fe

src/lib/cache/evas_cache_image.c
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_object_inform.c
src/lib/include/evas_private.h

index 629f583..07a474a 100755 (executable)
@@ -448,6 +448,8 @@ _evas_cache_image_async_cancel(void *data)
    if (cache) evas_cache_image_flush(cache);
 }
 
+// note - preload_add assumes a target is ONLY added ONCE to the image
+// entry. make sure you only add once, or remove first, then add
 static int
 _evas_cache_image_entry_preload_add(Image_Entry *ie, const void *target)
 {
index 2940f9d..f3c1dc5 100644 (file)
@@ -75,6 +75,7 @@ struct _Evas_Object_Image
    unsigned char     dirty_pixels : 1;
    unsigned char     filled : 1;
    unsigned char     proxyrendering : 1;
+   unsigned char     preloading : 1;
 };
 
 /* private methods for image objects */
@@ -351,9 +352,13 @@ evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
    o->prev.key = NULL;
    if (o->engine_data)
      {
-        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
-                                                                 o->engine_data,
-                                                                 obj);
+        if (o->preloading)
+          {
+             o->preloading = 0;
+             obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                      o->engine_data,
+                                                                      obj);
+          }
         obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
                                                   o->engine_data);
      }
@@ -929,6 +934,13 @@ evas_object_image_size_set(Evas_Object *obj, int w, int h)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if (w < 1) w = 1;
    if (h < 1) h = 1;
    if (w > 32768) return;
@@ -1084,6 +1096,13 @@ evas_object_image_data_convert(Evas_Object *obj, Evas_Colorspace to_cspace)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return NULL;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if (!o->engine_data) return NULL;
    if (!o->cur.cspace == to_cspace) return NULL;
    data = NULL;
@@ -1116,6 +1135,13 @@ evas_object_image_data_set(Evas_Object *obj, void *data)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
 #ifdef EVAS_FRAME_QUEUING
    if (o->engine_data)
      evas_common_pipe_op_image_flush(o->engine_data);
@@ -1277,17 +1303,32 @@ evas_object_image_preload(Evas_Object *obj, Eina_Bool cancel)
    MAGIC_CHECK_END();
    if (!o->engine_data)
      {
+        o->preloading = 1;
        evas_object_inform_call_image_preloaded(obj);
        return;
      }
+   // FIXME: if already busy preloading, then dont request again until
+   // preload done
    if (cancel)
-     obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
-                                                             o->engine_data,
-                                                             obj);
+     {
+        if (o->preloading)
+          {
+             o->preloading = 0;
+             obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                      o->engine_data,
+                                                                      obj);
+          }
+     }
    else
-     obj->layer->evas->engine.func->image_data_preload_request(obj->layer->evas->engine.data.output,
-                                                              o->engine_data,
-                                                              obj);
+     {
+        if (!o->preloading)
+          {
+             o->preloading = 1;
+             obj->layer->evas->engine.func->image_data_preload_request(obj->layer->evas->engine.data.output,
+                                                                       o->engine_data,
+                                                                       obj);
+          }
+     }
 }
 
 /**
@@ -1325,6 +1366,13 @@ evas_object_image_data_copy_set(Evas_Object *obj, void *data)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if ((o->cur.image.w <= 0) ||
        (o->cur.image.h <= 0)) return;
    if (o->engine_data)
@@ -1420,6 +1468,13 @@ evas_object_image_alpha_set(Evas_Object *obj, Eina_Bool has_alpha)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if (((has_alpha) && (o->cur.has_alpha)) ||
        ((!has_alpha) && (!o->cur.has_alpha)))
      return;
@@ -1556,6 +1611,13 @@ evas_object_image_reload(Evas_Object *obj)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if ((!o->cur.file) ||
        (o->pixels_checked_out > 0)) return;
    if (o->engine_data)
@@ -1673,6 +1735,13 @@ evas_object_image_pixels_import(Evas_Object *obj, Evas_Pixel_Import_Source *pixe
    return 0;
    MAGIC_CHECK_END();
 
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if ((pixels->w != o->cur.image.w) || (pixels->h != o->cur.image.h)) return 0;
    switch (pixels->format)
      {
@@ -2061,6 +2130,13 @@ evas_object_image_colorspace_set(Evas_Object *obj, Evas_Colorspace cspace)
    return;
    MAGIC_CHECK_END();
 
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
 #ifdef EVAS_FRAME_QUEUING
    if ((Evas_Colorspace)o->cur.cspace != cspace)
      {
@@ -2121,6 +2197,13 @@ evas_object_image_native_surface_set(Evas_Object *obj, Evas_Native_Surface *surf
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+   if ((o->preloading) && (o->engine_data))
+     {
+        o->preloading = 0;
+        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                 o->engine_data,
+                                                                 obj);
+     }
    if (o->cur.source) _proxy_unset(obj);
    if (!obj->layer->evas->engine.func->image_native_set) return;
    if ((surf) &&
@@ -2640,9 +2723,13 @@ evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty)
      }
    if (o->engine_data)
      {
-        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
-                                                                 o->engine_data,
-                                                                 obj);
+        if (o->preloading)
+          {
+             o->preloading = 0;
+             obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                      o->engine_data,
+                                                                      obj);
+          }
         obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
                                                   o->engine_data);
      }
@@ -2819,9 +2906,13 @@ evas_object_image_free(Evas_Object *obj)
    if (o->cur.source) _proxy_unset(obj);
    if (o->engine_data)
      {
-        obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
-                                                                 o->engine_data,
-                                                                 obj);
+        if (o->preloading)
+          {
+             o->preloading = 0;
+             obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
+                                                                      o->engine_data,
+                                                                      obj);
+          }
         obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
                                                   o->engine_data);
      }
@@ -2876,12 +2967,6 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
    obj->layer->evas->engine.func->context_render_op_set(output, context,
                                                        obj->cur.render_op);
 
-   if (0)
-        printf("Proxy: %p Source: %p Surface %p Redraw %s Type %s/%s %p %d %d\n",
-               obj, o->cur.source,o->cur.source->proxy.surface,
-               o->cur.source->proxy.redraw?"yep ":"nope",o->cur.source->type,
-               o_type,obj->cur.map,obj->cur.map->count, obj->cur.usemap);
-
    if (!o->cur.source)
      {
         pixels = o->engine_data;
@@ -3756,4 +3841,23 @@ evas_object_image_filled_resize_listener(void *data __UNUSED__, Evas *e __UNUSED
    evas_object_image_fill_set(obj, 0, 0, w, h);
 }
 
+
+Eina_Bool
+_evas_object_image_preloading_get(const Evas_Object *obj)
+{
+   Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
+   if (!o) return EINA_FALSE;
+   MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
+   return EINA_FALSE;
+   MAGIC_CHECK_END();
+   return o->preloading;
+}
+
+void
+_evas_object_image_preloading_set(Evas_Object *obj, Eina_Bool preloading)
+{
+   Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
+   o->preloading = preloading;
+}
+
 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
index d1dd645..f22b6f0 100644 (file)
@@ -60,6 +60,8 @@ evas_object_inform_call_changed_size_hints(Evas_Object *obj)
 void
 evas_object_inform_call_image_preloaded(Evas_Object *obj)
 {
+   if (!_evas_object_image_preloading_get(obj)) return;
+   _evas_object_image_preloading_set(obj, 0);
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
index e5b9eb4..fb9bb53 100644 (file)
@@ -754,6 +754,8 @@ void evas_smart_cb_descriptions_fix(Evas_Smart_Cb_Description_Array *a) EINA_ARG
 Eina_Bool evas_smart_cb_descriptions_resize(Evas_Smart_Cb_Description_Array *a, unsigned int size) EINA_ARG_NONNULL(1);
 const Evas_Smart_Cb_Description *evas_smart_cb_description_find(const Evas_Smart_Cb_Description_Array *a, const char *name) EINA_ARG_NONNULL(1, 2) EINA_PURE;
 
+Eina_Bool _evas_object_image_preloading_get(const Evas_Object *obj);
+void _evas_object_image_preloading_set(Evas_Object *obj, Eina_Bool preloading);
 void evas_object_smart_del(Evas_Object *obj);
 void evas_object_smart_cleanup(Evas_Object *obj);
 void evas_object_smart_member_raise(Evas_Object *member);