jpeg pushed a commit to branch master.

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

commit c53f1526f11113d52aefcf7d9ac0f70846fd60fe
Author: Jean-Philippe Andre <[email protected]>
Date:   Tue Mar 28 16:09:34 2017 +0900

    evas: Make save() work on snapshots
    
    This make save() work on snapshot objects, provided the call
    is done from inside render_post.
    
    Also, this saves the filtered output of an image, rather than
    its source pixels. Any call to save() on a filtered image must
    be done from post-render as well.
    
    Fixes T2102
    
    @feature
---
 src/bin/elementary/test_evas_snapshot.c            |  48 ++++-
 src/lib/evas/canvas/efl_canvas_snapshot.c          |  12 ++
 src/lib/evas/canvas/efl_canvas_snapshot.eo         |   1 +
 src/lib/evas/canvas/evas_image_private.h           |   1 +
 src/lib/evas/canvas/evas_object_image.c            | 200 +++++++++------------
 src/lib/evas/canvas/evas_render.c                  |   5 +
 src/lib/evas/include/evas_private.h                |   1 +
 .../evas/engines/gl_common/evas_gl_common.h        |   1 +
 src/modules/evas/engines/gl_generic/evas_engine.c  |  85 ++++++---
 9 files changed, 213 insertions(+), 141 deletions(-)

diff --git a/src/bin/elementary/test_evas_snapshot.c 
b/src/bin/elementary/test_evas_snapshot.c
index 13e0458..845c95c 100644
--- a/src/bin/elementary/test_evas_snapshot.c
+++ b/src/bin/elementary/test_evas_snapshot.c
@@ -54,6 +54,35 @@ _anim_toggle(void *data, const Efl_Event *ev EINA_UNUSED)
 }
 
 static void
+_render_post(void *data, const Efl_Event *ev)
+{
+   Eo *snap = data;
+
+   efl_event_callback_del(ev->object, EFL_CANVAS_EVENT_RENDER_POST, 
_render_post, data);
+   efl_file_save(snap, eina_slstr_printf("%s/snap-efl.png", 
eina_environment_tmp_get()), NULL, NULL);
+}
+
+static void
+_save_image(void *data, const Efl_Event *ev EINA_UNUSED)
+{
+   Eo *win = data;
+   Eo *snap;
+   int w, h;
+
+   // Save is available only during render_post
+   snap = efl_key_wref_get(win, "snap");
+   efl_event_callback_add(win, EFL_CANVAS_EVENT_RENDER_POST, _render_post, 
snap);
+
+   // Force a render in order to ensure post_render is called. EO API provides
+   // no way to do manual render, so we add a damage to the snapshot object.
+   // This is a special case handled by snapshot for the purpose of taking
+   // screenshots like this. This is useful only if the button click has no
+   // animation on screen and there is no spinning wheel either.
+   efl_gfx_size_get(snap, &w, &h);
+   efl_gfx_buffer_update_add(snap, 0, 0, w, h);
+}
+
+static void
 _radius_set(void *data, const Efl_Event *ev)
 {
    char buf[128];
@@ -76,7 +105,7 @@ _close(void *data, const Efl_Event *ev EINA_UNUSED)
 void
 test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
 {
-   Eo *win, *grid, *o, *snap;
+   Eo *win, *grid, *o, *snap, *box;
    const char *path;
 
    win = efl_add(EFL_UI_WIN_STANDARD_CLASS, NULL,
@@ -141,19 +170,32 @@ test_evas_snapshot(void *data EINA_UNUSED, Evas_Object 
*obj EINA_UNUSED, void *e
            efl_event_callback_add(efl_added, ELM_SLIDER_EVENT_CHANGED, 
_radius_set, win),
            efl_gfx_visible_set(efl_added, 1));
 
+   box = efl_add(EFL_UI_BOX_CLASS, win,
+                 efl_gfx_size_hint_align_set(efl_added, -1.0, -1.0),
+                 efl_pack_grid(grid, efl_added, 0, GRID_SIZE + 1, GRID_SIZE, 
1),
+                 efl_gfx_visible_set(efl_added, 1));
+
    efl_add(ELM_BUTTON_CLASS, win,
            efl_text_set(efl_added, "Toggle animation"),
            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_grid(grid, efl_added, 0, GRID_SIZE + 1, (GRID_SIZE + 1) / 
2, 1),
+           efl_pack(box, efl_added),
            efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, 
_anim_toggle, win),
            efl_gfx_visible_set(efl_added, 1));
 
    efl_add(ELM_BUTTON_CLASS, win,
+           efl_text_set(efl_added, "Save to file"),
+           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, 
_save_image, 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),
-           efl_pack_grid(grid, efl_added, (GRID_SIZE + 1) / 2, GRID_SIZE + 1, 
(GRID_SIZE + 1) / 2, 1),
+           efl_pack(box, efl_added),
            efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _close, 
win),
            efl_gfx_visible_set(efl_added, 1));
 
diff --git a/src/lib/evas/canvas/efl_canvas_snapshot.c 
b/src/lib/evas/canvas/efl_canvas_snapshot.c
index 9f77ce6..fcb7a7a 100644
--- a/src/lib/evas/canvas/efl_canvas_snapshot.c
+++ b/src/lib/evas/canvas/efl_canvas_snapshot.c
@@ -21,4 +21,16 @@ _efl_canvas_snapshot_efl_object_constructor(Eo *eo_obj, void 
*pd EINA_UNUSED)
    return eo_obj;
 }
 
+EOLIAN static void
+_efl_canvas_snapshot_efl_gfx_buffer_buffer_update_add(Eo *eo_obj, void *_pd 
EINA_UNUSED,
+                                                      int x EINA_UNUSED, int y 
EINA_UNUSED,
+                                                      int w EINA_UNUSED, int h 
EINA_UNUSED)
+{
+   Evas_Object_Protected_Data *obj;
+
+   // FIXME: Prevent obscures in the region x,y,w,h
+   obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+   evas_object_change(eo_obj, obj);
+}
+
 #include "efl_canvas_snapshot.eo.c"
diff --git a/src/lib/evas/canvas/efl_canvas_snapshot.eo 
b/src/lib/evas/canvas/efl_canvas_snapshot.eo
index e370581..e917aeb 100644
--- a/src/lib/evas/canvas/efl_canvas_snapshot.eo
+++ b/src/lib/evas/canvas/efl_canvas_snapshot.eo
@@ -9,5 +9,6 @@ class Efl.Canvas.Snapshot (Efl.Canvas.Image.Internal)
    data: null;
    implements {
       Efl.Object.constructor;
+      Efl.Gfx.Buffer.buffer_update_add;
    }
 }
diff --git a/src/lib/evas/canvas/evas_image_private.h 
b/src/lib/evas/canvas/evas_image_private.h
index 52512d0..48e6e8b 100644
--- a/src/lib/evas/canvas/evas_image_private.h
+++ b/src/lib/evas/canvas/evas_image_private.h
@@ -148,6 +148,7 @@ struct _Evas_Image_Data
 void _evas_image_init_set(const Eina_File *f, const char *file, const char 
*key, Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Image_Data *o, 
Evas_Image_Load_Opts *lo);
 void _evas_image_done_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, 
Evas_Image_Data *o);
 void _evas_image_cleanup(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, 
Evas_Image_Data *o);
+void *_evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj, void 
*output, void *context, void *surface, int x, int y, int *imagew, int *imageh, 
int *uvw, int *uvh, Eina_Bool filtered, Eina_Bool needs_post_render);
 
 /* Efl.Gfx.Fill */
 void _evas_image_fill_set(Eo *eo_obj, Evas_Image_Data *o, int x, int y, int w, 
int h);
diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index b76f876..ae2a1c4 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -753,6 +753,8 @@ 
_efl_canvas_image_internal_efl_gfx_buffer_buffer_update_add(Eo *eo_obj, Evas_Ima
 
    RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, o->cur->image.w, o->cur->image.h);
    if ((w <= 0)  || (h <= 0)) return;
+   if (obj->cur->snapshot)
+     evas_object_change(eo_obj, obj);
    if (!o->written) return;
    evas_object_async_block(obj);
    cnt = eina_list_count(o->pixels->pixel_updates);
@@ -875,69 +877,33 @@ _efl_canvas_image_internal_efl_image_ratio_get(Eo *eo_obj 
EINA_UNUSED, Evas_Imag
 EOLIAN static Eina_Bool
 _efl_canvas_image_internal_efl_file_save(const Eo *eo_obj, Evas_Image_Data *o, 
const char *file, const char *key, const char *flags)
 {
-   DATA32 *data = NULL;
    int quality = 80, compress = 9, ok = 0;
    char *encoding = NULL;
    Image_Entry *ie;
-   Eina_Bool putback = EINA_FALSE, tofree = EINA_FALSE, tgv = EINA_FALSE;
    Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
    Evas_Colorspace want_cspace = EVAS_COLORSPACE_ARGB8888;
-   int imagew, imageh;
-   void *pixels;
-
-   Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, 
EFL_CANVAS_OBJECT_CLASS);
-   Evas_Object_Protected_Data *source = (o->cur->source ? 
efl_data_scope_get(o->cur->source, EFL_CANVAS_OBJECT_CLASS) : NULL);
+   Evas_Object_Protected_Data *obj;
+   Eina_Bool unmap_it = EINA_FALSE;
+   int imagew, imageh, uvw, uvh;
+   Eina_Rw_Slice slice = {};
+   DATA32 *data = NULL;
+   void *pixels = NULL;
 
-   // FIXME: Use _evas_image_pixels_get()
+   obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
 
+   EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
    evas_object_async_block(obj);
 
-   if (o->cur->scene)
-     {
-        _evas_image_3d_render(obj->layer->evas->evas, (Eo *) eo_obj, obj, o, 
o->cur->scene);
-        pixels = obj->data_3d->surface;
-        imagew = obj->data_3d->w;
-        imageh = obj->data_3d->h;
-     }
-   else if (!o->cur->source)
-     {
-        // pixels = evas_process_dirty_pixels(eo_obj, obj, o, output, surface, 
o->engine_data);
-        pixels = o->engine_data;
-        imagew = o->cur->image.w;
-        imageh = o->cur->image.h;
-        putback = EINA_TRUE;
-     }
-   else if (source->proxy->surface && !source->proxy->redraw)
-     {
-        pixels = source->proxy->surface;
-        imagew = source->proxy->w;
-        imageh = source->proxy->h;
-     }
-   else if (source->type == o_type &&
-            ((Evas_Image_Data *)efl_data_scope_get(o->cur->source, 
MY_CLASS))->engine_data)
-     {
-        Evas_Image_Data *oi;
-        oi = efl_data_scope_get(o->cur->source, MY_CLASS);
-        pixels = oi->engine_data;
-        imagew = oi->cur->image.w;
-        imageh = oi->cur->image.h;
-     }
-   else
-     {
-        o->proxyrendering = EINA_TRUE;
-        evas_render_proxy_subrender(obj->layer->evas->evas, o->cur->source,
-                                    (Eo *) eo_obj, obj, o->proxy_src_clip, 
EINA_FALSE);
-        pixels = source->proxy->surface;
-        imagew = source->proxy->w;
-        imageh = source->proxy->h;
-        o->proxyrendering = EINA_FALSE;
-     }
+   pixels = _evas_image_pixels_get((Eo *) eo_obj, obj, ENDT, NULL, NULL, 0, 0,
+                                   &imagew, &imageh, &uvw, &uvh, EINA_TRUE, 
EINA_TRUE);
+   if (!pixels) goto no_pixels;
 
    cspace = ENFN->image_file_colorspace_get(ENDT, pixels);
    want_cspace = cspace;
 
    if (flags)
      {
+        const char *ext;
         char *p, *pp;
         char *tflags;
 
@@ -955,69 +921,61 @@ _efl_canvas_image_internal_efl_file_save(const Eo 
*eo_obj, Evas_Image_Data *o, c
              else break;
           }
 
-        if (file)
+        if (encoding)
           {
-             const char *ext = strrchr(file, '.');
+             ext = strrchr(file, '.');
              if (ext && !strcasecmp(ext, ".tgv"))
-               tgv = EINA_TRUE;
-          }
-
-        if (encoding && tgv)
-          {
-             if (!strcmp(encoding, "auto"))
-               want_cspace = cspace;
-             else if (!strcmp(encoding, "etc1"))
-               want_cspace = EVAS_COLORSPACE_ETC1;
-             else if (!strcmp(encoding, "etc2"))
                {
-                  if (!ENFN->image_alpha_get(ENDT, pixels))
-                    want_cspace = EVAS_COLORSPACE_RGB8_ETC2;
-                  else
-                    want_cspace = EVAS_COLORSPACE_RGBA8_ETC2_EAC;
+                  if (!strcmp(encoding, "auto"))
+                    want_cspace = cspace;
+                  else if (!strcmp(encoding, "etc1"))
+                    want_cspace = EVAS_COLORSPACE_ETC1;
+                  else if (!strcmp(encoding, "etc2"))
+                    {
+                       if (!ENFN->image_alpha_get(ENDT, pixels))
+                         want_cspace = EVAS_COLORSPACE_RGB8_ETC2;
+                       else
+                         want_cspace = EVAS_COLORSPACE_RGBA8_ETC2_EAC;
+                    }
+                  else if (!strcmp(encoding, "etc1+alpha"))
+                    want_cspace = EVAS_COLORSPACE_ETC1_ALPHA;
                }
-             else if (!strcmp(encoding, "etc1+alpha"))
-               want_cspace = EVAS_COLORSPACE_ETC1_ALPHA;
-          }
-        else
-          {
-             free(encoding);
-             encoding = NULL;
           }
      }
 
    if (ENFN->image_data_direct_get && (o->cur->orient == 
EVAS_IMAGE_ORIENT_NONE))
      {
         Evas_Colorspace cs;
-        Eina_Slice slice;
+        Eina_Slice sl;
 
-        ENFN->image_colorspace_set(ENDT, pixels, want_cspace);
-        ok = ENFN->image_data_direct_get(ENDT, pixels, 0, &slice, &cs, 
EINA_TRUE);
-        if (ok && (want_cspace == cs))
-          {
-             data = (DATA32 *) slice.mem;
-             putback = EINA_FALSE;
-          }
-        else ENFN->image_colorspace_set(ENDT, pixels, cspace);
+        ok = ENFN->image_data_direct_get(ENDT, pixels, 0, &sl, &cs, EINA_TRUE);
+        if (ok && (cs == want_cspace))
+          data = (DATA32 *) sl.mem;
      }
 
-   if (!data)
+   if ((o->cur->orient == EVAS_IMAGE_ORIENT_90) ||
+       (o->cur->orient == EVAS_IMAGE_ORIENT_270) ||
+       (o->cur->orient == EVAS_IMAGE_FLIP_TRANSPOSE) ||
+       (o->cur->orient == EVAS_IMAGE_FLIP_TRANSVERSE))
      {
-        cspace = EVAS_COLORSPACE_ARGB8888;
-        ENFN->image_colorspace_set(ENDT, pixels, cspace);
-        pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, 
&tofree);
+        int tmp = imagew;
+        imagew = imageh;
+        imageh = tmp;
      }
 
-   if (EINA_UNLIKELY(cspace != o->cur->cspace))
+   if (!data)
      {
-        EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
-          state_write->cspace = cspace;
-        EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
-     }
+        int stride;
 
-   if (!pixels || !data)
-     {
-        WRN("Could not get image pixels.");
-        return EINA_FALSE;
+        cspace = EVAS_COLORSPACE_ARGB8888;
+        ok = ENFN->image_data_map(ENDT, &pixels, &slice, &stride, 0, 0, 
imagew, imageh,
+                                  cspace, EFL_GFX_BUFFER_ACCESS_MODE_READ, 0);
+        if (!ok || !slice.mem) goto no_pixels;
+        unmap_it = EINA_TRUE;
+        data = slice.mem;
+
+        if (stride != (imagew * 4))
+          WRN("Invalid stride: saved image may look wrong!");
      }
 
    ie = evas_cache_image_data(evas_common_image_cache_get(),
@@ -1031,13 +989,16 @@ _efl_canvas_image_internal_efl_file_save(const Eo 
*eo_obj, Evas_Image_Data *o, c
      }
    else ok = EINA_FALSE;
 
-   if (tofree)
-     ENFN->image_free(ENDT, pixels);
-   else if (putback)
-     o->engine_data = ENFN->image_data_put(ENDT, pixels, data);
+   if (unmap_it)
+     ENFN->image_data_unmap(ENDT, pixels, &slice);
 
    free(encoding);
+   if (!ok) ERR("Image save failed.");
    return ok;
+
+no_pixels:
+   ERR("Could not get image pixels for saving.");
+   return EINA_FALSE;
 }
 
 EOLIAN static Efl_Gfx_Colorspace
@@ -1890,20 +1851,32 @@ evas_object_image_render(Evas_Object *eo_obj, 
Evas_Object_Protected_Data *obj, v
 void *
 _evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj,
                        void *output, void *context, void *surface, int x, int 
y,
-                       int *imagew, int *imageh, int *uvw, int *uvh)
+                       int *imagew, int *imageh, int *uvw, int *uvh,
+                       Eina_Bool filtered, Eina_Bool needs_post_render)
 {
    Evas_Image_Data *o = obj->private_data, *oi = NULL;
    Evas_Object_Protected_Data *source = NULL;
-   void *pixels;
+   void *pixels = NULL;
 
-   if (o->cur->source)
+   EVAS_OBJECT_DATA_ALIVE_CHECK(obj, NULL);
+
+   if (filtered && o->has_filter)
+     pixels = evas_filter_output_buffer_get(eo_obj);
+
+   if (!pixels && o->cur->source)
      {
         source = efl_data_scope_get(o->cur->source, EFL_CANVAS_OBJECT_CLASS);
         if (source && (source->type == o_type))
           oi = efl_data_scope_get(o->cur->source, MY_CLASS);
      }
 
-   if (o->cur->scene)
+   if (pixels)
+     {
+        ENFN->image_size_get(ENDT, pixels, imagew, imageh);
+        *uvw = *imagew;
+        *uvh = *imageh;
+     }
+   else if (o->cur->scene)
      {
         _evas_image_3d_render(obj->layer->evas->evas, eo_obj, obj, o, 
o->cur->scene);
         pixels = obj->data_3d->surface;
@@ -1922,6 +1895,8 @@ _evas_image_pixels_get(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
      }
    else if (!o->cur->source || !source)
      {
+        // normal image (from file or user pixel set)
+        needs_post_render = EINA_FALSE;
         if (output && surface)
           pixels = evas_process_dirty_pixels(eo_obj, obj, o, output, surface, 
o->engine_data);
         else
@@ -1941,14 +1916,10 @@ _evas_image_pixels_get(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
      }
    else if (oi && oi->engine_data)
      {
-        pixels = oi->engine_data;
         if (oi->has_filter)
-          {
-             void *output_buffer = NULL;
-             output_buffer = evas_filter_output_buffer_get(source->object);
-             if (output_buffer)
-               pixels = output_buffer;
-          }
+          pixels = evas_filter_output_buffer_get(source->object);
+        if (!pixels)
+          pixels = oi->engine_data;
         *imagew = oi->cur->image.w;
         *imageh = oi->cur->image.h;
         *uvw = source->cur->geometry.w;
@@ -1976,6 +1947,14 @@ _evas_image_pixels_get(Eo *eo_obj, 
Evas_Object_Protected_Data *obj,
         o->proxyrendering = EINA_FALSE;
      }
 
+   if (needs_post_render && !obj->layer->evas->inside_post_render)
+     {
+        ERR("Can not save or map this image now! Proxies, snapshots and "
+            "filtered images support those operations only from inside a "
+            "post-render event.");
+        return NULL;
+     }
+
    return pixels;
 }
 
@@ -1991,7 +1970,7 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data 
*obj,
    void *pixels;
 
    pixels = _evas_image_pixels_get(eo_obj, obj, output, context, surface, x, y,
-                                   &imagew, &imageh, &uvw, &uvh);
+                                   &imagew, &imageh, &uvw, &uvh, EINA_FALSE, 
EINA_FALSE);
 
    if (!pixels) return;
    if (ENFN->context_clip_get(ENDT, context, NULL, NULL, &cw, &ch) && (!cw || 
!ch))
@@ -2965,8 +2944,7 @@ evas_object_image_is_inside(Evas_Object *eo_obj,
     * draw, just get the pixels so we can check the transparency.
     */
    pixels = _evas_image_pixels_get(eo_obj, obj, ENDT, NULL, NULL, 0, 0,
-                                   &imagew, &imageh, &uvw, &uvh);
-
+                                   &imagew, &imageh, &uvw, &uvh, EINA_TRUE, 
EINA_FALSE);
    if (!pixels) return is_inside;
 
    /* TODO: not handling o->dirty_pixels && o->pixels->func.get_pixels,
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index 5c7720c..374d893 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -3513,7 +3513,9 @@ evas_render_updates_internal(Evas *eo_e,
              ru->surface = NULL;
           }
         eina_spinlock_take(&(e->render.lock));
+        e->inside_post_render = EINA_TRUE;
         _cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
+        e->inside_post_render = EINA_FALSE;
         eina_spinlock_release(&(e->render.lock));
         if (post.updated_area) eina_list_free(post.updated_area);
      }
@@ -3600,6 +3602,8 @@ evas_render_wakeup(Evas *eo_e)
    jobs_il = EINA_INLIST_GET(evas->post_render.jobs);
    evas->post_render.jobs = NULL;
    SLKU(evas->post_render.lock);
+
+   evas->inside_post_render = EINA_TRUE;
    EINA_INLIST_FREE(jobs_il, job)
      {
         jobs_il = eina_inlist_remove(jobs_il, EINA_INLIST_GET(job));
@@ -3614,6 +3618,7 @@ evas_render_wakeup(Evas *eo_e)
 
    post.updated_area = ret_updates;
    _cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
+   evas->inside_post_render = EINA_FALSE;
 
    evas_render_updates_free(ret_updates);
 
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 33e5a45..38ae795 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -956,6 +956,7 @@ struct _Evas_Public_Data
    Eina_Bool      rendering : 1;
    Eina_Bool      render2 : 1;
    Eina_Bool      common_init : 1;
+   Eina_Bool      inside_post_render : 1;
 };
 
 struct _Evas_Layer
diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h 
b/src/modules/evas/engines/gl_common/evas_gl_common.h
index 81cede7..ad5835d 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -527,6 +527,7 @@ struct _Evas_GL_Image_Data_Map
    EINA_INLIST;
    Evas_GL_Texture *tex; // one or the other
    RGBA_Image      *im; // one or the other
+   Evas_GL_Image   *glim;
    Eina_Rw_Slice    slice;
    int              stride; // in bytes
    int              rx, ry, rw, rh; // actual map region
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index bb26c2f..c8bfb80 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -2688,46 +2688,73 @@ eng_ector_end(void *data, void *context EINA_UNUSED, 
Ector_Surface *ector,
 }
 
 static Eina_Bool
-eng_image_data_map(void *engdata EINA_UNUSED, void **image, Eina_Rw_Slice 
*slice,
+eng_image_data_map(void *engdata, void **image, Eina_Rw_Slice *slice,
                    int *stride, int x, int y, int w, int h,
                    Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode,
                    int plane)
 {
+   Render_Engine_GL_Generic *re = engdata;
    Evas_GL_Image_Data_Map *map = NULL;
-   Evas_GL_Image *im;
-   Eina_Bool ok;
+   Evas_GL_Image *glim, *glim2 = NULL;
+   Eina_Bool ok = EINA_FALSE;
+   RGBA_Image *im = NULL;
+   int strid;
 
    EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image && slice, EINA_FALSE);
-   im = *image;
 
-   if (im->im)
+   glim = *image;
+   slice->mem = NULL;
+   slice->len = 0;
+
+   if (glim->im && (glim->orient == EVAS_IMAGE_ORIENT_NONE))
+     {
+        evas_gl_common_image_ref(glim);
+        glim2 = glim;
+     }
+   else
      {
-        int strid = 0;
+        glim2 = _rotate_image_data(re, glim);
+     }
 
-        // Call sw generic implementation. Should work for simple cases.
-        ok = pfunc.image_data_map(NULL, (void **) &im->im, slice, &strid,
+   if (!glim2) return EINA_FALSE;
+   im = glim2->im;
+   if (im)
+     {
+        // Call sw generic implementation.
+        ok = pfunc.image_data_map(NULL, (void **) &im, slice, &strid,
                                   x, y, w, h, cspace, mode, plane);
-        if (ok)
-          {
-             map = calloc(1, sizeof(*map));
-             map->cspace = cspace;
-             map->rx = x;
-             map->ry = y;
-             map->rw = w;
-             map->rh = h;
-             map->mode = mode;
-             map->slice = *slice;
-             map->stride = strid;
-             map->im = im->im; // ref?
-             im->maps = eina_inlist_prepend(im->maps, EINA_INLIST_GET(map));
-          }
-        if (stride) *stride = strid;
-        return ok;
      }
 
-   // TODO: glReadPixels from FBO if possible
+   if (!ok)
+     {
+        eng_image_free(re, glim2);
+        return EINA_FALSE;
+     }
 
-   return EINA_FALSE;
+   evas_cache_image_ref(&im->cache_entry);
+
+   map = calloc(1, sizeof(*map));
+   map->cspace = cspace;
+   map->rx = x;
+   map->ry = y;
+   map->rw = w;
+   map->rh = h;
+   map->mode = mode;
+   map->slice = *slice;
+   map->stride = strid;
+   map->im = im;
+   map->glim = glim2;
+   glim->maps = eina_inlist_prepend(glim->maps, EINA_INLIST_GET(map));
+   if (stride) *stride = strid;
+
+   if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
+     {
+        evas_gl_common_image_ref(glim2);
+        evas_gl_common_image_free(glim);
+        *image = glim2;
+     }
+
+   return EINA_TRUE;
 }
 
 static Eina_Bool
@@ -2746,13 +2773,17 @@ eng_image_data_unmap(void *engdata EINA_UNUSED, void 
*image, const Eina_Rw_Slice
           {
              found = EINA_TRUE;
              if (map->im)
-               found = pfunc.image_data_unmap(NULL, map->im, slice);
+               {
+                  found = pfunc.image_data_unmap(NULL, map->im, slice);
+                  evas_cache_image_drop(&map->im->cache_entry);
+               }
              if (found)
                {
                   if (im->im && im->tex &&
                       (map->mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE))
                     evas_gl_common_texture_update(im->tex, im->im);
                   im->maps = eina_inlist_remove(im->maps, 
EINA_INLIST_GET(map));
+                  if (map->glim) evas_gl_common_image_free(map->glim);
                   free(map);
                }
              return found;

-- 


Reply via email to