jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=9b1ea2fc6b21be05c7959d2d14402310c9c68784

commit 9b1ea2fc6b21be05c7959d2d14402310c9c68784
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Wed Mar 15 14:49:50 2017 +0900

    evas: Pass obscuring region to the filters
    
    This will be most useful in a special case, where a filter is
    used in a window decoration, applied to a snapshot object.
    
    Another optimization that might be wanted is passing a list
    of update regions (from the proxy or snapshot).
    
    The filters don't support the obscuring region yet, only some
    of the high-level logic is implemented.
---
 src/lib/evas/canvas/efl_canvas_filter_internal.eo |  1 +
 src/lib/evas/canvas/evas_filter_mixin.c           | 86 +++++++++++++++++------
 src/lib/evas/canvas/evas_object_main.c            |  2 +-
 src/lib/evas/canvas/evas_object_textblock.c       | 34 ++++-----
 src/lib/evas/canvas/evas_render.c                 | 75 +++++++++++++++++---
 src/lib/evas/filters/evas_filter.c                | 57 +++++++++++++++
 src/lib/evas/filters/evas_filter_parser.c         | 44 +++++++-----
 src/lib/evas/filters/evas_filter_private.h        | 12 +++-
 src/lib/evas/include/evas_filter.h                | 10 ++-
 src/lib/evas/include/evas_private.h               |  2 +
 10 files changed, 253 insertions(+), 70 deletions(-)

diff --git a/src/lib/evas/canvas/efl_canvas_filter_internal.eo 
b/src/lib/evas/canvas/efl_canvas_filter_internal.eo
index 8b44d40..a60b3f1 100644
--- a/src/lib/evas/canvas/efl_canvas_filter_internal.eo
+++ b/src/lib/evas/canvas/efl_canvas_filter_internal.eo
@@ -1,4 +1,5 @@
 // import efl_gfx_types -> need to add Efl.Gfx.Color
+import eina_types;
 
 /* Everything in this file is internal to Evas. It is not meant to be used
    from outside EFL itself! */
diff --git a/src/lib/evas/canvas/evas_filter_mixin.c 
b/src/lib/evas/canvas/evas_filter_mixin.c
index b19e4e6..a0d3b3e 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -157,6 +157,24 @@ _evas_filter_state_set_internal(Evas_Filter_Program *pgm, 
Evas_Filter_Data *pd)
    return evas_filter_program_state_set(pgm, &state);
 }
 
+static inline Eina_Bool
+_evas_filter_obscured_region_changed(Evas_Filter_Data *pd)
+{
+   Eina_Rectangle inter;
+
+   inter = pd->data->prev_obscured;
+   if (eina_rectangle_is_empty(&pd->data->obscured) &&
+       eina_rectangle_is_empty(&inter))
+     return EINA_FALSE;
+   if (!eina_rectangle_intersection(&inter, &pd->data->obscured))
+     return EINA_TRUE;
+   if ((inter.w != pd->data->prev_obscured.w) ||
+       (inter.h != pd->data->prev_obscured.h))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
 Eina_Bool
 evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
                           void *output, void *context, void *surface,
@@ -166,12 +184,13 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
 
    if (!pd->data->invalid && (pd->data->chain || pd->data->code))
      {
-        int X, Y, W, H, l = 0, r = 0, t = 0, b = 0;
+        int X, Y, W, H;
         Evas_Filter_Context *filter;
         void *drawctx;
         Eina_Bool ok;
         void *previous = pd->data->output;
         Evas_Object_Filter_Data *fcow;
+        Evas_Filter_Padding pad;
 
         /* NOTE: Filter rendering is now done ENTIRELY on CPU.
          * So we rely on cache/cache2 to allocate a real image buffer,
@@ -229,17 +248,15 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
           }
         else if (previous && !pd->data->changed)
           {
-             Eina_Bool redraw;
+             Eina_Bool redraw = EINA_TRUE;
 
-             redraw = _evas_filter_state_set_internal(pd->data->chain, pd);
-             if (redraw)
+             if (_evas_filter_state_set_internal(pd->data->chain, pd))
                DBG("Filter redraw by state change!");
              else if (obj->changed)
-               {
-                  // FIXME: Check that something else than X,Y changed!
-                  redraw = EINA_TRUE;
-                  DBG("Filter redraw by object content change!");
-               }
+               DBG("Filter redraw by object content change!");
+             else if (_evas_filter_obscured_region_changed(pd))
+               DBG("Filter redraw by obscure regions change!");
+             else redraw = EINA_FALSE;
 
              // Scan proxies to find if any changed
              if (!redraw && pd->data->sources)
@@ -303,13 +320,16 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
         drawctx = ENFN->context_new(ENDT);
         ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
 
+        // Set obscured region
+        evas_filter_context_obscured_region_set(filter, pd->data->obscured);
+
         // Allocate all buffers now
         evas_filter_context_buffers_allocate_all(filter);
         evas_filter_target_set(filter, context, surface, X + x, Y + y);
 
         // Request rendering from the object itself (child class)
-        evas_filter_program_padding_get(pd->data->chain, &l, &r, &t, &b);
-        ok = evas_filter_input_render(eo_obj, filter, drawctx, NULL, l, r, t, 
b, 0, 0, do_async);
+        evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
+        ok = evas_filter_input_render(eo_obj, filter, drawctx, NULL, pad.l, 
pad.r, pad.t, pad.b, 0, 0, do_async);
         if (!ok) ERR("Filter input render failed.");
 
         ENFN->context_free(ENDT, drawctx);
@@ -321,7 +341,8 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
         fcow = FCOW_BEGIN(pd);
         fcow->changed = EINA_FALSE;
         fcow->async = do_async;
-        if (!ok) fcow->invalid = EINA_TRUE;
+        fcow->prev_obscured = fcow->obscured;
+        fcow->invalid = !ok;
         FCOW_END(fcow, pd);
 
         if (ok)
@@ -534,15 +555,15 @@ EOLIAN static void
 _efl_canvas_filter_internal_efl_gfx_filter_filter_padding_get(Eo *eo_obj 
EINA_UNUSED, Evas_Filter_Data *pd,
                                                               int *l, int *r, 
int *t, int *b)
 {
-   if (!pd->data->chain)
-     {
-        if (l) *l = 0;
-        if (r) *r = 0;
-        if (t) *t = 0;
-        if (b) *b = 0;
-        return;
-     }
-   evas_filter_program_padding_get(pd->data->chain, l, r, t, b);
+   Evas_Filter_Padding pad = { 0, 0, 0, 0 };
+
+   if (pd->data->chain)
+     evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
+
+   if (l) *l = pad.l;
+   if (r) *r = pad.r;
+   if (t) *t = pad.t;
+   if (b) *b = pad.b;
 }
 
 EOLIAN static void
@@ -697,4 +718,27 @@ _efl_canvas_filter_internal_filter_output_buffer_get(Eo 
*obj EINA_UNUSED, Evas_F
    return pd->data->output;
 }
 
+void
+_evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj,
+                                 const Eina_Rectangle rect)
+{
+   Evas_Filter_Data *pd;
+   Evas_Object_Filter_Data *fcow;
+
+   pd = efl_data_scope_get(obj->object, MY_CLASS);
+   if (!pd->data) return;
+
+   fcow = FCOW_BEGIN(pd);
+   if ((rect.w <= 0) || (rect.h <= 0))
+     memset(&fcow->obscured, 0, sizeof(fcow->obscured));
+   else
+     {
+        fcow->obscured.x = rect.x - obj->cur->geometry.x;
+        fcow->obscured.y = rect.y - obj->cur->geometry.y;
+        fcow->obscured.w = rect.w;
+        fcow->obscured.h = rect.h;
+     }
+   FCOW_END(fcow, pd);
+}
+
 #include "canvas/efl_canvas_filter_internal.eo.c"
diff --git a/src/lib/evas/canvas/evas_object_main.c 
b/src/lib/evas/canvas/evas_object_main.c
index dcfecfc..cab4bd1 100644
--- a/src/lib/evas/canvas/evas_object_main.c
+++ b/src/lib/evas/canvas/evas_object_main.c
@@ -33,7 +33,7 @@ static const Evas_Object_Protected_State default_state = {
   1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, 
EINA_FALSE
 };
 static const Evas_Object_Filter_Data default_filter = {
-  NULL, NULL, NULL, NULL, NULL, NULL, NULL, { { NULL, 0.0 }, { NULL, 0.0 }, 
0.0 }, EINA_FALSE, EINA_FALSE, EINA_TRUE
+  NULL, NULL, NULL, NULL, NULL, NULL, {}, {}, NULL, {}, EINA_FALSE, 
EINA_FALSE, EINA_TRUE
 };
 const void * const evas_object_filter_cow_default = &default_filter;
 static const Evas_Object_Mask_Data default_mask = {
diff --git a/src/lib/evas/canvas/evas_object_textblock.c 
b/src/lib/evas/canvas/evas_object_textblock.c
index 4de5938..f021649 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -478,9 +478,7 @@ struct _Efl_Canvas_Text_Filter
    Evas_Object          *eo_obj;
    Evas_Public_Data     *evas;
    void                 *dc; /* draw context - no clip, white, no colmul... */
-   struct {
-      int                l, r, t, b;
-   } pad;
+   Evas_Filter_Padding   pad;
    Eina_Bool             invalid;
    Eina_Bool             redraw;
 };
@@ -4051,15 +4049,15 @@ _text_item_update_sizes(Ctxt *c, 
Evas_Object_Textblock_Text_Item *ti)
 
    if (EINA_UNLIKELY(ti->parent.format->gfx_filter != NULL))
      {
-        int l = 0, r = 0, t = 0, b = 0;
+        Evas_Filter_Padding pad = { 0, 0, 0, 0 };
         Evas_Filter_Program *pgm;
 
         pgm = _format_filter_program_get(c->o, ti->parent.format);
         if (pgm)
           {
-             evas_filter_program_padding_get(pgm, &l, &r, &t, &b);
+             evas_filter_program_padding_get(pgm, &pad, NULL);
 
-             ti->x_adjustment = r + l;
+             ti->x_adjustment = pad.r + pad.l;
              ti->parent.w = tw + ti->x_adjustment; // FIXME: why add l+r here,
              ti->parent.h = th;                    // but not t+b here?
              ti->parent.adv = advw;
@@ -4647,21 +4645,21 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c,
      }
 
      {
-        Evas_Coord pad_l = 0, pad_r = 0, pad_t = 0, pad_b = 0;
+        Evas_Filter_Padding pad = { 0, 0, 0, 0 };
         Evas_Filter_Program *pgm = NULL;
 
         if (EINA_UNLIKELY(fmt->gfx_filter != NULL))
           pgm = _format_filter_program_get(efl_data_scope_get(obj, MY_CLASS), 
fmt);
 
         if (EINA_UNLIKELY(pgm != NULL))
-          evas_filter_program_padding_get(pgm, &pad_l, &pad_r, &pad_t, &pad_b);
+          evas_filter_program_padding_get(pgm, &pad, NULL);
         else
-          evas_text_style_pad_get(fmt->style, &pad_l, &pad_r, &pad_t, &pad_b);
+          evas_text_style_pad_get(fmt->style, &pad.l, &pad.r, &pad.t, &pad.b);
 
-        if (pad_l > *style_pad_l) *style_pad_l = pad_l;
-        if (pad_r > *style_pad_r) *style_pad_r = pad_r;
-        if (pad_t > *style_pad_t) *style_pad_t = pad_t;
-        if (pad_b > *style_pad_b) *style_pad_b = pad_b;
+        if (pad.l > *style_pad_l) *style_pad_l = pad.l;
+        if (pad.r > *style_pad_r) *style_pad_r = pad.r;
+        if (pad.t > *style_pad_t) *style_pad_t = pad.t;
+        if (pad.b > *style_pad_b) *style_pad_b = pad.b;
      }
 
    if (fmt->underline2)
@@ -13487,9 +13485,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
           }
 
         // target position
-        evas_filter_program_padding_get(pgm,
-                                        &filter->pad.l, &filter->pad.r,
-                                        &filter->pad.t, &filter->pad.b);
+        evas_filter_program_padding_get(pgm, &filter->pad, NULL);
         target = _filter_target_position_calc(obj, ti, x, y);
         ENFN->context_color_set(ENDT, context, 255, 255, 255, 255);
         ENFN->context_multiplier_set(ENDT, context,
@@ -13828,7 +13824,7 @@ 
_efl_canvas_text_efl_canvas_filter_internal_filter_state_prepare(
    Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_TEXT_CLASS);
    Evas_Object_Textblock_Text_Item *ti = data;
    Efl_Canvas_Text_Filter_Program *program;
-   int l = 0, r = 0, t = 0, b = 0;
+   Evas_Filter_Padding pad = {};
 
 #define STATE_COLOR(dst, src) dst.r = src.r; dst.g = src.g; dst.b = src.b; 
dst.a = src.a
    STATE_COLOR(state->color, ti->parent.format->color.normal);
@@ -13839,9 +13835,9 @@ 
_efl_canvas_text_efl_canvas_filter_internal_filter_state_prepare(
 #undef STATE_COLOR
 
    program = _filter_program_find(o, ti->parent.format->gfx_filter->name);
-   if (program) evas_filter_program_padding_get(program->pgm, &l, &r, &t, &b);
+   if (program) evas_filter_program_padding_get(program->pgm, &pad, NULL);
    state->w = ti->parent.w; // + l + r; (already included)
-   state->h = ti->parent.h + t + b;
+   state->h = ti->parent.h + pad.t + pad.b;
    state->scale = obj->cur->scale;
 }
 
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index a13c693..e464026 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -12,6 +12,10 @@
 
 #include "evas_render2.h"
 
+// FIXME: Ugly!
+#define EFL_CANVAS_FILTER_INTERNAL_PROTECTED
+#include "efl_canvas_filter_internal.eo.h"
+
 /* Enable this for extra verbose rendering debug logs */
 //#define REND_DBG 1
 #define STDOUT_DBG
@@ -2737,29 +2741,78 @@ _is_obj_in_rect(Evas_Object *eo_obj, 
Evas_Object_Protected_Data *obj,
 }
 #endif
 
+static inline Eina_Bool
+_rectangle_inside(Eina_Rectangle *big, Eina_Rectangle *small)
+{
+   Eina_Rectangle inter = *big;
+
+   if (!eina_rectangle_intersection(&inter, small))
+     return EINA_FALSE;
+   if ((inter.w == small->w) && (inter.h == small->h))
+     return EINA_TRUE;
+   return EINA_FALSE;
+}
+
 static Eina_Bool
-_snapshot_needs_redraw(Evas_Public_Data *evas, Evas_Object_Protected_Data 
*snap)
+_snapshot_needs_redraw(Evas_Public_Data *evas, Evas_Object_Protected_Data 
*snap,
+                       Eina_Rectangle *opaque)
 {
+   Eina_Bool above = EINA_FALSE, ret = EINA_FALSE;
    const int x = snap->cur->geometry.x;
    const int y = snap->cur->geometry.y;
    const int w = snap->cur->geometry.w;
    const int h = snap->cur->geometry.h;
    Evas_Object_Protected_Data *obj;
    Evas_Active_Entry *ent;
+   Eina_Rectangle snap_rect = { x, y, w, h };
    void *surface;
 
    surface = _evas_object_image_surface_get(snap, EINA_FALSE);
-   if (!surface) return EINA_TRUE;
+   if (!surface) ret = EINA_TRUE;
 
+   memset(opaque, 0, sizeof(*opaque));
    EINA_INARRAY_FOREACH(&evas->active_objects, ent)
      {
         obj = ent->obj;
-        if (obj == snap) break;
-        if (!obj->is_smart && obj->changed &&
-            evas_object_is_in_output_rect(obj->object, obj, x, y, w, h))
-          return EINA_TRUE;
+        if (obj == snap)
+          {
+             above = EINA_TRUE;
+             continue;
+          }
+
+        if (!above)
+          {
+             if (ret) continue;
+             if (!obj->is_smart && obj->changed &&
+                 evas_object_is_in_output_rect(obj->object, obj, x, y, w, h))
+               ret = EINA_TRUE;
+          }
+        else
+          {
+             if (!obj->is_smart && !obj->clip.clipees &&
+                 evas_object_is_opaque(obj->object, obj))
+               {
+                  Eina_Rectangle cur = {
+                     obj->cur->geometry.x, obj->cur->geometry.y,
+                     obj->cur->geometry.w, obj->cur->geometry.h
+                  };
+
+                  if (!eina_rectangles_intersect(&snap_rect, &cur))
+                    continue;
+
+                  if (!opaque->w || !opaque->h)
+                    *opaque = cur;
+                  else if (_rectangle_inside(&cur, opaque))
+                    *opaque = cur;
+                  else if (!_rectangle_inside(opaque, &cur))
+                    {
+                       *opaque = (Eina_Rectangle) { 0, 0, 0, 0 };
+                       break;
+                    }
+               }
+          }
      }
-   return EINA_FALSE;
+   return ret;
 }
 
 static Eina_Bool
@@ -3196,7 +3249,7 @@ evas_render_updates_internal(Evas *eo_e,
              eina_evlog("+render_snapshots", eo_e, 0.0, NULL);
              for (j = e->snapshot_objects.count - 1; j >= 0; j--)
                {
-                  Eina_Rectangle output, cr, ur;
+                  Eina_Rectangle output, cr, ur, opaque;
 
                   obj = eina_array_data_get(&e->snapshot_objects, j);
 
@@ -3208,7 +3261,7 @@ evas_render_updates_internal(Evas *eo_e,
                   EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh);
 
                   if (eina_rectangle_intersection(&ur, &output) &&
-                      _snapshot_needs_redraw(evas, obj))
+                      _snapshot_needs_redraw(evas, obj, &opaque))
                     {
                        void *pseudo_canvas;
                        unsigned int restore_offset = offset;
@@ -3219,6 +3272,10 @@ evas_render_updates_internal(Evas *eo_e,
 
                        pseudo_canvas = _evas_object_image_surface_get(obj, 
EINA_TRUE);
 
+                       // TODO: List of canvas regions that need redraw
+                       // Add obscure region (make it a list?)
+                       _evas_filter_obscured_region_set(obj, opaque);
+
                        RD(0, "  SNAPSHOT %s [sfc:%p ur:%d,%d %dx%d]\n", 
RDNAME(obj), pseudo_canvas, ur.x, ur.y, ur.w, ur.h);
                        ctx = ENFN->context_new(ENDT);
                        clean_them |= evas_render_updates_internal_loop(eo_e, 
e, pseudo_canvas, ctx,
diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index 5efe9e4..a37fe40 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -1281,6 +1281,12 @@ evas_filter_command_transform_add(Evas_Filter_Context 
*ctx,
    return cmd;
 }
 
+void
+evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, 
Eina_Rectangle rect)
+{
+   ctx->obscured.real = rect;
+}
+
 /* Final target */
 Eina_Bool
 evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
@@ -1601,6 +1607,55 @@ _filter_thread_run_cb(void *data)
      ctx->post_run.cb(ctx, ctx->post_run.data, success);
 }
 
+static void
+_filter_obscured_region_calc(Evas_Filter_Context *ctx)
+{
+   Eina_Rectangle rect = ctx->obscured.real;
+
+   // left
+   if (rect.x > 0)
+     {
+        rect.x += ctx->pad.calculated.l;
+        rect.w -= ctx->pad.calculated.l;
+     }
+   else
+     {
+        rect.w -= (-rect.x);
+        rect.x = 0;
+     }
+   if (rect.w < 0) rect.w = 0;
+
+   // right
+   if ((rect.x + rect.w) <= ctx->w)
+     rect.w -= ctx->pad.calculated.r;
+   else
+     rect.w = ctx->w - rect.x;
+
+   // top
+   if (rect.y > 0)
+     {
+        rect.y += ctx->pad.calculated.t;
+        rect.h -= ctx->pad.calculated.t;
+     }
+   else
+     {
+        rect.h -= (-rect.y);
+        rect.y = 0;
+     }
+   if (rect.h < 0) rect.h = 0;
+
+   // bottom
+   if ((rect.y + rect.h) <= ctx->h)
+     rect.h -= ctx->pad.calculated.b;
+   else
+     rect.h = ctx->h - rect.y;
+
+   if ((rect.w <= 0) || (rect.h <= 0))
+     memset(&rect, 0, sizeof(rect));
+
+   ctx->obscured.effective = rect;
+}
+
 Eina_Bool
 evas_filter_run(Evas_Filter_Context *ctx)
 {
@@ -1611,6 +1666,8 @@ evas_filter_run(Evas_Filter_Context *ctx)
    if (!ctx->commands)
      return EINA_TRUE;
 
+   _filter_obscured_region_calc(ctx);
+
    if (ctx->async)
      {
         evas_thread_queue_flush(_filter_thread_run_cb, ctx);
diff --git a/src/lib/evas/filters/evas_filter_parser.c 
b/src/lib/evas/filters/evas_filter_parser.c
index 9bebd19..9c14e5d 100644
--- a/src/lib/evas/filters/evas_filter_parser.c
+++ b/src/lib/evas/filters/evas_filter_parser.c
@@ -324,7 +324,7 @@ struct _Evas_Filter_Program
    Eina_Inlist /* Buffer */ *buffers;
    struct {
       // Note: padding can't be in the state as it's calculated after running 
Lua
-      int l, r, t, b;
+      Evas_Filter_Padding calculated, final;
    } pad;
    Efl_Canvas_Filter_State state;
    Eina_Inlist *data; // Evas_Filter_Data_Binding
@@ -2882,21 +2882,22 @@ _buffers_update(Evas_Filter_Context *ctx, 
Evas_Filter_Program *pgm)
 
 EAPI Eina_Bool
 evas_filter_program_padding_get(Evas_Filter_Program *pgm,
-                                int *l, int *r, int *t, int *b)
+                                Evas_Filter_Padding *out_final,
+                                Evas_Filter_Padding *out_calculated)
 {
    Evas_Filter_Instruction *instr;
    int pl = 0, pr = 0, pt = 0, pb = 0;
    int maxl = 0, maxr = 0, maxt = 0, maxb = 0;
+   int setl = 0, setr = 0, sett = 0, setb = 0;
+   Eina_Bool was_set = EINA_FALSE;
    Buffer *buf;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
 
-   if (pgm->padding_calc || pgm->padding_set)
+   if (pgm->padding_calc)
      {
-        if (l) *l = pgm->pad.l;
-        if (r) *r = pgm->pad.r;
-        if (t) *t = pgm->pad.t;
-        if (b) *b = pgm->pad.b;
+        if (out_final) *out_final = pgm->pad.final;
+        if (out_calculated) *out_calculated = pgm->pad.calculated;
         return EINA_TRUE;
      }
 
@@ -2909,8 +2910,8 @@ evas_filter_program_padding_get(Evas_Filter_Program *pgm,
      {
         if (instr->type == EVAS_FILTER_MODE_PADDING_SET)
           {
-             instr->pad.update(pgm, instr, &maxl, &maxr, &maxt, &maxb);
-             break;
+             instr->pad.update(pgm, instr, &setl, &setr, &sett, &setb);
+             was_set = EINA_TRUE;
           }
         else if (instr->pad.update)
           {
@@ -2922,16 +2923,23 @@ evas_filter_program_padding_get(Evas_Filter_Program 
*pgm,
           }
      }
 
-   pgm->pad.l = maxl;
-   pgm->pad.r = maxr;
-   pgm->pad.t = maxt;
-   pgm->pad.b = maxb;
+   pgm->pad.calculated.l = maxl;
+   pgm->pad.calculated.r = maxr;
+   pgm->pad.calculated.t = maxt;
+   pgm->pad.calculated.b = maxb;
+   if (!was_set)
+     pgm->pad.final = pgm->pad.calculated;
+   else
+     {
+        pgm->pad.final.l = setl;
+        pgm->pad.final.r = setr;
+        pgm->pad.final.t = sett;
+        pgm->pad.final.b = setb;
+     }
    pgm->padding_calc = EINA_TRUE;
 
-   if (l) *l = maxl;
-   if (r) *r = maxr;
-   if (t) *t = maxt;
-   if (b) *b = maxb;
+   if (out_final) *out_final = pgm->pad.final;
+   if (out_calculated) *out_calculated = pgm->pad.calculated;
 
    return EINA_TRUE;
 }
@@ -3503,7 +3511,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx,
    _buffers_update(ctx, pgm);
 
    // Compute and save padding info
-   evas_filter_program_padding_get(pgm, &ctx->padl, &ctx->padr, &ctx->padt, 
&ctx->padb);
+   evas_filter_program_padding_get(pgm, &ctx->pad.final, &ctx->pad.calculated);
 
    dc = ENFN->context_new(ENDT);
    ENFN->context_color_set(ENDT, dc, 255, 255, 255, 255);
diff --git a/src/lib/evas/filters/evas_filter_private.h 
b/src/lib/evas/filters/evas_filter_private.h
index afb89a3..e61b01b 100644
--- a/src/lib/evas/filters/evas_filter_private.h
+++ b/src/lib/evas/filters/evas_filter_private.h
@@ -111,6 +111,7 @@ typedef enum _Evas_Filter_Interpolation_Mode 
Evas_Filter_Interpolation_Mode;
 
 typedef Evas_Filter_Buffer * 
(*evas_filter_buffer_scaled_get_func)(Evas_Filter_Context *ctx, 
Evas_Filter_Buffer *src, unsigned w, unsigned h);
 
+
 struct _Evas_Filter_Context
 {
    Evas_Public_Data *evas;
@@ -125,7 +126,16 @@ struct _Evas_Filter_Context
 
    // Variables changing at each run
    int w, h; // Dimensions of the input/output buffers
-   int padl, padt, padr, padb; // Padding in the current input/output buffers
+
+   struct {
+      // Padding in the current input/output buffers
+      Evas_Filter_Padding calculated, final;
+   } pad;
+
+   struct {
+      // Useless region: obscured by other objects
+      Eina_Rectangle real, effective;
+   } obscured;
 
    struct
    {
diff --git a/src/lib/evas/include/evas_filter.h 
b/src/lib/evas/include/evas_filter.h
index 533bc24..34a09c4 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -36,6 +36,7 @@ typedef struct _Evas_Filter_Context Evas_Filter_Context;
 typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction;
 typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer;
 typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding;
+typedef struct _Evas_Filter_Padding Evas_Filter_Padding;
 typedef enum _Evas_Filter_Mode Evas_Filter_Mode;
 typedef enum _Evas_Filter_Blur_Type Evas_Filter_Blur_Type;
 typedef enum _Evas_Filter_Channel Evas_Filter_Channel;
@@ -124,6 +125,12 @@ enum _Evas_Filter_Transform_Flags
    EVAS_FILTER_TRANSFORM_VFLIP = 1
 };
 
+/** @internal */
+struct _Evas_Filter_Padding
+{
+   int l, r, t, b;
+};
+
 #define EFL_CANVAS_FILTER_STATE_DEFAULT { {}, { 255, 255, 255, 255 }, { 
"default", 0.0 }, {}, 0, 0, 1.0, 0.0 }
 
 /* Parser stuff (high level API) */
@@ -131,7 +138,7 @@ EAPI Evas_Filter_Program *evas_filter_program_new(const 
char *name, Eina_Bool in
 EAPI Eina_Bool           evas_filter_program_state_set(Evas_Filter_Program 
*pgm, const Efl_Canvas_Filter_State *state);
 EAPI Eina_Bool           evas_filter_program_parse(Evas_Filter_Program *pgm, 
const char *str);
 EAPI void                evas_filter_program_del(Evas_Filter_Program *pgm);
-EAPI Eina_Bool           evas_filter_program_padding_get(Evas_Filter_Program 
*pgm, int *l, int *r, int *t, int *b);
+EAPI Eina_Bool           evas_filter_program_padding_get(Evas_Filter_Program 
*pgm, Evas_Filter_Padding *final, Evas_Filter_Padding *calc);
 EAPI void                
evas_filter_program_source_set_all(Evas_Filter_Program *pgm, Eina_Hash 
*sources);
 void                     evas_filter_program_data_set_all(Evas_Filter_Program 
*pgm, Eina_Inlist *data);
 
@@ -145,6 +152,7 @@ void                     
evas_filter_context_proxy_render_all(Evas_Filter_Contex
 void                     
evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, 
Evas_Filter_Cb cb, void *data);
 #define                  evas_filter_context_autodestroy(ctx) 
evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) 
evas_filter_context_destroy), ctx)
 Eina_Bool                
evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);
+void                     
evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, 
Eina_Rectangle rect);
 
 int                      evas_filter_buffer_empty_new(Evas_Filter_Context 
*ctx, Eina_Bool alpha_only);
 void                    *evas_filter_buffer_backing_steal(Evas_Filter_Context 
*ctx, int bufid);
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 02e14f2..7034da4 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1290,6 +1290,7 @@ struct _Evas_Object_Filter_Data
    Evas_Filter_Program *chain;
    Eina_Hash           *sources; // Evas_Filter_Proxy_Binding
    Eina_Inlist         *data; // Evas_Filter_Data_Binding
+   Eina_Rectangle       prev_obscured, obscured;
    void                *output;
    struct {
       struct {
@@ -2034,6 +2035,7 @@ void *efl_input_hold_legacy_info_fill(Efl_Input_Hold 
*evt, Evas_Event_Flags **pf
 Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char 
*key EINA_UNUSED);
 
 void *_evas_object_image_surface_get(Evas_Object_Protected_Data *obj, 
Eina_Bool create);
+void _evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj, const 
Eina_Rectangle rect);
 Eina_Bool _evas_image_proxy_source_clip_get(const Eo *eo_obj);
 
 void _evas_focus_dispatch_event(Evas_Object_Protected_Data *obj,

-- 


Reply via email to