jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=4cbff5f0ea011e93a7b2ea6db202dbd8ddf700c8

commit 4cbff5f0ea011e93a7b2ea6db202dbd8ddf700c8
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Tue Apr 4 14:28:29 2017 +0900

    evas filters: Fix maps with filtered snapshots
    
    Another wonder of evas render... maps, clips, snapshots, filters...
    This fixes animations with windows that have a snapshot decoration.
---
 src/bin/elementary/test_evas_snapshot.c     | 69 +++++++++++++++++++++++++++++
 src/lib/evas/canvas/evas_filter_mixin.c     | 33 +++++++++++---
 src/lib/evas/canvas/evas_object_image.c     | 20 +++------
 src/lib/evas/canvas/evas_object_textblock.c |  2 +-
 src/lib/evas/canvas/evas_render.c           | 10 ++++-
 src/lib/evas/filters/evas_filter.c          | 29 +++++++++---
 src/lib/evas/filters/evas_filter_private.h  |  1 +
 src/lib/evas/include/evas_filter.h          |  2 +-
 8 files changed, 136 insertions(+), 30 deletions(-)

diff --git a/src/bin/elementary/test_evas_snapshot.c 
b/src/bin/elementary/test_evas_snapshot.c
index 845c95c..75ca1ce 100644
--- a/src/bin/elementary/test_evas_snapshot.c
+++ b/src/bin/elementary/test_evas_snapshot.c
@@ -25,6 +25,24 @@ static const char *filter =
       "print ('Evaluating filter: ' .. input.width .. 'x' .. input.height)"
       ;
 
+static inline void
+_efl_key_int_set(Eo *obj, const char *key, int val)
+{
+   Eina_Value *v = eina_value_new(EINA_VALUE_TYPE_INT);
+   eina_value_set(v, val);
+   efl_key_value_set(obj, key, v);
+}
+
+static inline int
+_efl_key_int_get(Eo *obj, const char *key)
+{
+   Eina_Value *v = efl_key_value_get(obj, key);
+   int val;
+
+   if (!eina_value_get(v, &val)) return 0;
+   return val;
+}
+
 static inline Eo *
 _image_create(Eo *win, const char *path)
 {
@@ -102,6 +120,49 @@ _close(void *data, const Efl_Event *ev EINA_UNUSED)
    efl_del(win);
 }
 
+static void
+_map_do(void *data, const Efl_Event *ev EINA_UNUSED)
+{
+   Eo *snap = data;
+   int x, y, w, h;
+
+   // Prevent recursive infinite loop :(
+   static int here = 0;
+   if (here) return;
+   here = 1;
+
+   efl_gfx_map_populate(snap, 0);
+   efl_gfx_geometry_get(snap, &x, &y, &w, &h);
+   efl_gfx_map_zoom(snap, 0.8, 0.8, x + w/2., y + h/2.);
+   efl_gfx_map_rotate(snap, 45., x + w/2., y + h/2.);
+   efl_gfx_map_enable_set(snap, EINA_TRUE);
+
+   here = 0;
+}
+
+static void
+_toggle_map(void *data, const Efl_Event *ev EINA_UNUSED)
+{
+   Eo *win = data;
+   Eo *snap;
+
+   snap = efl_key_wref_get(win, "snap");
+   if (!_efl_key_int_get(snap, "map"))
+     {
+        _efl_key_int_set(snap, "map", 1);
+        _map_do(snap, NULL);
+        efl_event_callback_add(snap, EFL_GFX_EVENT_RESIZE, _map_do, snap);
+        efl_event_callback_add(snap, EFL_GFX_EVENT_MOVE, _map_do, snap);
+     }
+   else
+     {
+        _efl_key_int_set(snap, "map", 0);
+        efl_event_callback_del(snap, EFL_GFX_EVENT_RESIZE, _map_do, snap);
+        efl_event_callback_del(snap, EFL_GFX_EVENT_MOVE, _map_do, snap);
+        efl_gfx_map_enable_set(snap, EINA_FALSE);
+     }
+}
+
 void
 test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
 {
@@ -192,6 +253,14 @@ test_evas_snapshot(void *data EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED, void *e
            efl_gfx_visible_set(efl_added, 1));
 
    efl_add(ELM_BUTTON_CLASS, win,
+           efl_text_set(efl_added, "Map"),
+           efl_gfx_size_hint_align_set(efl_added, -1.0, -1.0),
+           efl_gfx_size_hint_weight_set(efl_added, 1.0, 0.0),
+           efl_pack(box, efl_added),
+           efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, 
_toggle_map, win),
+           efl_gfx_visible_set(efl_added, 1));
+
+   efl_add(ELM_BUTTON_CLASS, win,
            efl_text_set(efl_added, "Close"),
            efl_gfx_size_hint_align_set(efl_added, -1.0, -1.0),
            efl_gfx_size_hint_weight_set(efl_added, 1.0, 0.0),
diff --git a/src/lib/evas/canvas/evas_filter_mixin.c 
b/src/lib/evas/canvas/evas_filter_mixin.c
index 1ac5e1c..d9ada4f 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -266,6 +266,7 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
         Eina_Bool ok;
         void *previous = pd->data->output;
         Evas_Object_Filter_Data *fcow;
+        Eina_Bool use_map = EINA_FALSE;
         Evas_Filter_Padding pad;
 
         W = obj->cur->geometry.w;
@@ -288,6 +289,15 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
         else
           ENFN->context_multiplier_unset(output, context);
 
+        if (obj->map->cur.usemap && obj->map->cur.map && 
(obj->map->cur.map->count >= 4))
+          {
+             int iw, ih;
+
+             use_map = EINA_TRUE;
+             ENFN->image_size_get(ENDT, previous, &iw, &ih);
+             evas_object_map_update(eo_obj, x, y, iw, ih, iw, ih);
+          }
+
         if (!pd->data->chain)
           {
              Evas_Filter_Program *pgm;
@@ -348,12 +358,20 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
              if (!redraw)
                {
                   // Render this image only
-                  ENFN->image_draw(ENDT, context,
-                                   surface, previous,
-                                   0, 0, W, H,         // src
-                                   X + x, Y + y, W, H, // dst
-                                   EINA_FALSE,         // smooth
-                                   do_async);
+                  if (use_map)
+                    {
+                       ENFN->image_map_draw(ENDT, context, surface, previous,
+                                            obj->map->spans, EINA_TRUE, 0, 
do_async);
+                    }
+                  else
+                    {
+                       ENFN->image_draw(ENDT, context,
+                                        surface, previous,
+                                        0, 0, W, H,         // src
+                                        X + x, Y + y, W, H, // dst
+                                        EINA_FALSE,         // smooth
+                                        do_async);
+                    }
                   return EINA_TRUE;
                }
           }
@@ -427,7 +445,8 @@ evas_filter_object_render(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
 
         // Allocate all buffers now
         evas_filter_context_buffers_allocate_all(filter);
-        evas_filter_target_set(filter, context, surface, X + x, Y + y);
+        evas_filter_target_set(filter, context, surface, X + x, Y + y,
+                               use_map ? obj->map->spans : NULL);
 
         // Request rendering from the object itself (child class)
         evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index 0205ed6..41ed31d 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -19,7 +19,7 @@ static void evas_object_image_render(Evas_Object *eo_obj, 
Evas_Object_Protected_
                                     int x, int y, Eina_Bool do_async);
 static void _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
                                void *output, void *context, void *surface,
-                               int x, int y, int l, int t, int r, int b, 
Eina_Bool do_async);
+                               int x, int y, int l, int t, int r, int b, 
Eina_Bool skip_map, Eina_Bool do_async);
 static void evas_object_image_free(Evas_Object *eo_obj,
                                   Evas_Object_Protected_Data *obj);
 static void evas_object_image_render_pre(Evas_Object *eo_obj,
@@ -1727,12 +1727,6 @@ _image_has_border(Evas_Object_Protected_Data *obj 
EINA_UNUSED, Evas_Image_Data *
 }
 
 static inline Eina_Bool
-_image_has_map(Evas_Object_Protected_Data *obj, Evas_Image_Data *o EINA_UNUSED)
-{
-   return ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && 
(obj->map->cur.usemap));
-}
-
-static inline Eina_Bool
 _image_is_filled(Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
 {
    if (o->filled) return EINA_TRUE;
@@ -1765,8 +1759,7 @@ 
_efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render(
    output = ENDT;
 
    // FIXME: In GL we could use the image even if scaled
-   if (!_image_has_border(obj, o) && !_image_has_map(obj, o) && 
_image_is_filled(obj, o)
-       && !_image_is_scaled(obj, o))
+   if (!_image_has_border(obj, o) && _image_is_filled(obj, o) && 
!_image_is_scaled(obj, o))
      {
         int imagew, imageh, uvw, uvh;
 
@@ -1802,7 +1795,7 @@ 
_efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render(
    _evas_image_render(eo_obj, obj, output, ctx, surface,
                       x + l - obj->cur->geometry.x,
                       y + t - obj->cur->geometry.y,
-                      l, t, r, b, do_async);
+                      l, t, r, b, EINA_TRUE, do_async);
 
    ENFN->context_free(output, ctx);
 
@@ -1892,7 +1885,7 @@ evas_object_image_render(Evas_Object *eo_obj, 
Evas_Object_Protected_Data *obj, v
           return;
      }
 
-   _evas_image_render(eo_obj, obj, output, context, surface, x, y, 0, 0, 0, 0, 
do_async);
+   _evas_image_render(eo_obj, obj, output, context, surface, x, y, 0, 0, 0, 0, 
EINA_FALSE, do_async);
 }
 
 void *
@@ -2008,7 +2001,7 @@ _evas_image_pixels_get(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
 static void
 _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
                    void *output, void *context, void *surface, int x, int y,
-                   int l, int t, int r, int b, Eina_Bool do_async)
+                   int l, int t, int r, int b, Eina_Bool skip_map, Eina_Bool 
do_async)
 {
    Evas_Image_Data *o = obj->private_data;
    int imagew, imageh, uvw, uvh, cw, ch;
@@ -2023,7 +2016,8 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data 
*obj,
    if (ENFN->context_clip_get(ENDT, context, NULL, NULL, &cw, &ch) && (!cw || 
!ch))
      return;
 
-   if ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && 
(obj->map->cur.usemap))
+   if (!skip_map && (obj->map->cur.map) && (obj->map->cur.map->count > 3)
+       && (obj->map->cur.usemap))
      {
         evas_object_map_update(eo_obj, x, y, imagew, imageh, uvw, uvh);
 
diff --git a/src/lib/evas/canvas/evas_object_textblock.c 
b/src/lib/evas/canvas/evas_object_textblock.c
index 8032abf..f65624f 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -13493,7 +13493,7 @@ evas_object_textblock_render(Evas_Object *eo_obj 
EINA_UNUSED,
                                      obj->cur->cache.clip.b, 
obj->cur->cache.clip.a);
         evas_filter_context_proxy_render_all(ctx, eo_obj, EINA_FALSE);
         evas_filter_context_buffers_allocate_all(ctx);
-        evas_filter_target_set(ctx, context, surface, target.x, target.y);
+        evas_filter_target_set(ctx, context, surface, target.x, target.y, 
NULL);
         ti->gfx_filter->ctx = ctx;
         ti->gfx_filter->do_async = do_async;
 
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index 02209f4..5f82dd5 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -2797,7 +2797,7 @@ _snapshot_redraw_update(Evas_Public_Data *evas, 
Evas_Object_Protected_Data *snap
           }
      }
 
-   if (snap->snapshot_no_obscure)
+   if (snap->snapshot_no_obscure || _evas_render_has_map(snap))
      goto skip_obscures;
 
    tiler = eina_tiler_new(w, h);
@@ -2881,6 +2881,8 @@ evas_render_updates_internal_loop(Evas *eo_e, 
Evas_Public_Data *evas,
              OBJ_ARRAY_PUSH(&evas->temporary_objects, obj);
 
              if (above_top) continue;
+             if (obj->cur->snapshot && !evas_object_is_opaque(obj->object, 
obj))
+               continue;
 
              /* reset the background of the area if needed (using cutout and 
engine alpha flag to help) */
              if (alpha && !skip_cutouts)
@@ -2985,7 +2987,11 @@ evas_render_updates_internal_loop(Evas *eo_e, 
Evas_Public_Data *evas,
 
                             obj2 = 
eina_array_data_get(&evas->temporary_objects, j);
                             if (obj2 == top) above_top = EINA_TRUE;
-                            if (above_top && obj2->cur->snapshot) continue;
+                            if (obj2->cur->snapshot)
+                              {
+                                 if (above_top) continue;
+                                 if (!evas_object_is_opaque(obj2->object, 
obj2)) continue;
+                              }
 #if 1
                             if (
                                 RECTS_INTERSECT
diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index e5391f2..c9ce182 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -1489,7 +1489,7 @@ 
evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle
 /* Final target */
 Eina_Bool
 evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
-                       void *surface, int x, int y)
+                       void *surface, int x, int y, const RGBA_Map *map)
 {
    void *mask = NULL;
 
@@ -1509,11 +1509,20 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void 
*draw_context,
      ctx->target.color_use = EINA_FALSE;
    ctx->target.rop = ENFN->context_render_op_get(ENDT, draw_context);
 
+   free(ctx->target.map);
+   if (!map) ctx->target.map = NULL;
+   else
+     {
+        size_t len = sizeof(RGBA_Map) + sizeof(RGBA_Map_Point) * (map->count - 
1);
+        ctx->target.map = malloc(len);
+        memcpy(ctx->target.map, map, len);
+     }
+
    ENFN->context_clip_image_get
       (ENDT, draw_context, &mask, &ctx->target.mask_x, &ctx->target.mask_y);
    if (ctx->target.mask)
      ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, 
ctx->target.mask);
-   ctx->target.mask = mask;
+   ctx->target.mask = mask; // FIXME: why no ref???
 
    return EINA_TRUE;
 }
@@ -1558,10 +1567,18 @@ _filter_target_render(Evas_Filter_Context *ctx)
      }
 
    ENFN->context_render_op_set(ENDT, drawctx, ctx->target.rop);
-   ENFN->image_draw(ENDT, drawctx, surface, image,
-                    0, 0, src->w, src->h,
-                    ctx->target.x, ctx->target.y, src->w, src->h,
-                    EINA_TRUE, EINA_FALSE);
+   if (ctx->target.map)
+     {
+        ENFN->image_map_draw(ENDT, drawctx, surface, image,
+                             ctx->target.map, EINA_TRUE, 0, EINA_FALSE);
+     }
+   else
+     {
+        ENFN->image_draw(ENDT, drawctx, surface, image,
+                         0, 0, src->w, src->h,
+                         ctx->target.x, ctx->target.y, src->w, src->h,
+                         EINA_TRUE, EINA_FALSE);
+     }
 
    ENFN->context_free(ENDT, drawctx);
    evas_ector_buffer_engine_image_release(src->buffer, image);
diff --git a/src/lib/evas/filters/evas_filter_private.h 
b/src/lib/evas/filters/evas_filter_private.h
index 6896ff8..01cda48 100644
--- a/src/lib/evas/filters/evas_filter_private.h
+++ b/src/lib/evas/filters/evas_filter_private.h
@@ -153,6 +153,7 @@ struct _Evas_Filter_Context
       void *mask; // mask
       int mask_x, mask_y; // mask offset
       Evas_Render_Op rop;
+      RGBA_Map *map;
       Eina_Bool clip_use : 1;
       Eina_Bool color_use : 1;
    } target;
diff --git a/src/lib/evas/include/evas_filter.h 
b/src/lib/evas/include/evas_filter.h
index 3c20aa0..6972159 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -164,7 +164,7 @@ Eina_Bool                
evas_filter_buffer_backing_release(Evas_Filter_Context
 Eina_Bool                evas_filter_context_run(Evas_Filter_Context *ctx);
 
 Eina_Bool                evas_filter_font_draw(Evas_Filter_Context *ctx, void 
*draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props 
*text_props, Eina_Bool do_async);
-Eina_Bool                evas_filter_target_set(Evas_Filter_Context *ctx, void 
*draw_context, void *surface, int x, int y);
+Eina_Bool                evas_filter_target_set(Evas_Filter_Context *ctx, void 
*draw_context, void *surface, int x, int y, const RGBA_Map *map);
 
 // utility function
 void                     _evas_filter_source_hash_free_cb(void *data);

-- 


Reply via email to