Evas masking: Fix major memory leak
authorJean-Philippe Andre <jp.andre@samsung.com>
Wed, 21 Jan 2015 08:30:18 +0000 (17:30 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 21 Jan 2015 08:51:15 +0000 (17:51 +0900)
The memory usage graph was going up and to the right!
I was told this is always a good thing!

... maybe not this time :)

Hopefully I didn't forget a case. An intense session of
genlist scrolling with masks all over the place and masks
of masks didn't show any glitch, crash or memory leak.

src/lib/evas/canvas/evas_object_main.c
src/lib/evas/canvas/evas_render.c
src/lib/evas/filters/evas_filter.c
src/modules/evas/engines/gl_generic/evas_engine.c
src/modules/evas/engines/software_generic/evas_engine.c

index 65ed189..bf8aac2 100644 (file)
@@ -179,6 +179,21 @@ evas_object_free(Evas_Object *eo_obj, int clean_layer)
           map_write->surface = NULL;
         EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
      }
+   if (obj->mask->is_mask)
+     {
+        EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, Evas_Object_Mask_Data, mask)
+          mask->is_mask = EINA_FALSE;
+          mask->redraw = EINA_FALSE;
+          mask->is_alpha = EINA_FALSE;
+          mask->x = mask->y = mask->w = mask->h = 0;
+          if (mask->surface)
+            {
+               obj->layer->evas->engine.func->image_map_surface_free
+                     (obj->layer->evas->engine.data.output, mask->surface);
+               mask->surface = NULL;
+            }
+        EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mask);
+     }
    evas_object_grabs_cleanup(eo_obj, obj);
    evas_object_intercept_cleanup(eo_obj);
    if (obj->smart.parent) was_smart_child = 1;
index 18560bf..d67a4e5 100644 (file)
@@ -1519,6 +1519,7 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj,
                }
              else
                {
+                  Eina_Bool unset_image_clip = EINA_FALSE;
                   RDI(level);
 
                   if (obj->cur->clipper)
@@ -1540,6 +1541,7 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj,
 
                             if (mask->mask->surface)
                               {
+                                 unset_image_clip = EINA_TRUE;
                                  e->engine.func->context_clip_image_set
                                        (e->engine.data.output, ctx,
                                         mask->mask->surface,
@@ -1551,6 +1553,11 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj,
                   obj->func->render(eo_obj, obj, obj->private_data,
                                    e->engine.data.output, ctx,
                                     surface, off_x, off_y, EINA_FALSE);
+                  if (unset_image_clip)
+                    {
+                       e->engine.func->context_clip_image_unset
+                             (e->engine.data.output, ctx);
+                    }
                }
              if (!use_mapped_ctx)
                e->engine.func->context_free(e->engine.data.output, ctx);
@@ -1808,6 +1815,8 @@ evas_render_mask_subrender(Evas_Public_Data *evas,
           mdata->is_alpha = EINA_TRUE;
        }
 
+     mdata->surface = ENFN->image_dirty_region(ENDT, mdata->surface, 0, 0, w, h);
+
      /* END OF HACK */
 
 end:
index f7eba26..894f0fd 100644 (file)
@@ -1635,6 +1635,9 @@ _filter_target_render(Evas_Filter_Context *ctx)
                     ctx->target.x, ctx->target.y, src->w, src->h,
                     EINA_TRUE, EINA_FALSE);
 
+   if (ctx->target.mask)
+     ENFN->context_clip_image_unset(ENDT, drawctx);
+
    if (!ctx->gl_engine)
      ENFN->context_free(ENDT, drawctx);
    else if (use_clip)
index ed628e4..fe8125a 100644 (file)
@@ -1750,6 +1750,17 @@ eng_context_clip_image_get(void *data EINA_UNUSED, void *context, void **ie, int
 }
 
 static void
+eng_context_free(void *data, void *context)
+{
+   RGBA_Draw_Context *ctx = context;
+
+   if (!ctx) return;
+   if (ctx->clip.mask)
+     eng_context_clip_image_unset(data, context);
+   evas_common_draw_context_free(context);
+}
+
+static void
 eng_context_3d_use(void *data)
 {
    Render_Engine_GL_Generic *re = data;
@@ -1942,6 +1953,7 @@ module_open(Evas_Module *em)
    ORD(context_clip_image_set);
    ORD(context_clip_image_unset);
    ORD(context_clip_image_get);
+   ORD(context_free);
 
    ORD(rectangle_draw);
    ORD(line_draw);
index 17ed7f3..95032e2 100644 (file)
@@ -411,12 +411,6 @@ eng_context_new(void *data EINA_UNUSED)
 }
 
 static void
-eng_context_free(void *data EINA_UNUSED, void *context)
-{
-   evas_common_draw_context_free(context);
-}
-
-static void
 eng_context_clip_set(void *data EINA_UNUSED, void *context, int x, int y, int w, int h)
 {
    evas_common_draw_context_set_clip(context, x, y, w, h);
@@ -477,6 +471,17 @@ eng_context_clip_image_get(void *data EINA_UNUSED, void *context, void **ie, int
 }
 
 static void
+eng_context_free(void *data, void *context)
+{
+   RGBA_Draw_Context *ctx = context;
+
+   if (!ctx) return;
+   if (ctx->clip.mask)
+     eng_context_clip_image_unset(data, context);
+   evas_common_draw_context_free(context);
+}
+
+static void
 eng_context_clip_clip(void *data EINA_UNUSED, void *context, int x, int y, int w, int h)
 {
    evas_common_draw_context_clip_clip(context, x, y, w, h);