zmike pushed a commit to branch efl-1.22.

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

commit 957d0574e45e6386e8e164ae2958395d6b4794c9
Author: Shinwoo Kim <[email protected]>
Date:   Thu May 2 20:50:24 2019 +0900

    evas_object_image: save EVAS_IMAGE_CONTENT_HINT_DYNAMIC image
    
    Summary:
    evas_gl_common_image_content_hint_set makes RGBA_Image NULL if content hint
    is EVAS_IMAGE_CONTENT_HINT_DYNAMIC with 'sec_tbm_surface' and 'egl_tbm_ext'.
    
    efl_file_save(_efl_canvas_image_internal_efl_file_save_save) does not work
    in this case because ENFN->image_data_direct_get returns FALSE.
    
    This patch makes ENFN->image_data_direct_get work but you need to free its
    returned data after using it.
    
    Reviewers: Hermet, jsuya
    
    Reviewed By: Hermet
    
    Subscribers: cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D8516
---
 src/lib/evas/canvas/efl_canvas_image.c             |  3 +-
 src/lib/evas/canvas/evas_object_image.c            |  5 +-
 src/lib/evas/include/evas_private.h                |  2 +-
 src/modules/evas/engines/gl_generic/evas_engine.c  | 76 ++++++++++++++++++++--
 .../evas/engines/software_generic/evas_engine.c    |  3 +-
 5 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/src/lib/evas/canvas/efl_canvas_image.c 
b/src/lib/evas/canvas/efl_canvas_image.c
index 9d4c6c4594..9b19be0775 100644
--- a/src/lib/evas/canvas/efl_canvas_image.c
+++ b/src/lib/evas/canvas/efl_canvas_image.c
@@ -722,7 +722,8 @@ _efl_canvas_image_efl_gfx_buffer_buffer_managed_get(Eo 
*eo_obj, void *_pd EINA_U
    if (!o->buffer_data_set || !o->engine_data || !ENFN->image_data_direct_get)
      return slice;
 
-   ENFN->image_data_direct_get(ENC, o->engine_data, plane, &slice, &cspace, 
EINA_FALSE);
+   ENFN->image_data_direct_get(ENC, o->engine_data, plane, &slice, &cspace, 
EINA_FALSE, NULL);
+
    return slice;
 }
 
diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index 1d9ede0de7..289ffaaa3d 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -880,6 +880,7 @@ _efl_canvas_image_internal_efl_file_save_save(const Eo 
*eo_obj, Evas_Image_Data
    Evas_Colorspace want_cspace = EVAS_COLORSPACE_ARGB8888;
    Evas_Object_Protected_Data *obj;
    Eina_Bool unmap_it = EINA_FALSE;
+   Eina_Bool tofree = EINA_FALSE;
    int imagew, imageh, uvw, uvh;
    Eina_Rw_Slice slice = {};
    DATA32 *data = NULL;
@@ -932,7 +933,7 @@ _efl_canvas_image_internal_efl_file_save_save(const Eo 
*eo_obj, Evas_Image_Data
         Evas_Colorspace cs;
         Eina_Slice sl;
 
-        ok = ENFN->image_data_direct_get(ENC, pixels, 0, &sl, &cs, EINA_TRUE);
+        ok = ENFN->image_data_direct_get(ENC, pixels, 0, &sl, &cs, EINA_TRUE, 
&tofree);
         if (ok && (cs == want_cspace))
           data = (DATA32 *)sl.mem;
      }
@@ -966,6 +967,8 @@ _efl_canvas_image_internal_efl_file_save_save(const Eo 
*eo_obj, Evas_Image_Data
    if (unmap_it)
      ENFN->image_data_unmap(ENC, pixels, &slice);
 
+   if (tofree) free(data);
+
    if (!ok) ERR("Image save failed.");
    return ok;
 
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 5a4bd9cc5e..7d6d1c452f 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1336,7 +1336,7 @@ struct _Evas_Func
    void *(*image_dirty_region)             (void *engine, void *image, int x, 
int y, int w, int h);
    void *(*image_data_get)                 (void *engine, void *image, int 
to_write, DATA32 **image_data, int *err, Eina_Bool *tofree);
    void *(*image_data_put)                 (void *engine, void *image, DATA32 
*image_data);
-   Eina_Bool (*image_data_direct_get)      (void *engine, void *image, int 
plane, Eina_Slice *slice, Evas_Colorspace *cspace, Eina_Bool load);
+   Eina_Bool (*image_data_direct_get)      (void *engine, void *image, int 
plane, Eina_Slice *slice, Evas_Colorspace *cspace, Eina_Bool load, Eina_Bool 
*tofree);
    void  (*image_data_preload_request)     (void *engine, void *image, const 
Eo *target);
    void  (*image_data_preload_cancel)      (void *engine, void *image, const 
Eo *target, Eina_Bool force);
    void *(*image_alpha_set)                (void *engine, void *image, int 
has_alpha);
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index 2659498611..90fb3fc80b 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -301,20 +301,86 @@ eng_image_file_colorspace_get(void *engine EINA_UNUSED, 
void *image)
 static Eina_Bool
 eng_image_data_direct_get(void *engine EINA_UNUSED, void *image, int plane,
                           Eina_Slice *slice, Evas_Colorspace *cspace,
-                          Eina_Bool load)
+                          Eina_Bool load, Eina_Bool *tofree)
 {
+   Eina_Bool ret = EINA_FALSE;
    Evas_GL_Image *im = image;
+   int bpp = 0;
 
-   if (!slice || !im || !im->im)
-     return EINA_FALSE;
+   if (!slice || !im) return ret;
+
+   /* If content hint is DYNAMIC, the im->im could be NULL. If the im->im does 
+      not exist, eng_image_data_direct_get needs to return copied dyn.data to
+      make functions including efl_file_save work. */
+   if ((im->content_hint == EVAS_IMAGE_CONTENT_HINT_DYNAMIC) &&
+       tofree &&
+       (im->tex_only) && (!im->im) &&
+       (im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data))
+     {
+        *tofree = EINA_FALSE;
+        switch ( im->cs.space)
+          {
+           case EFL_GFX_COLORSPACE_ARGB8888:
+             bpp = 4;
+             EINA_FALLTHROUGH;
+             // falltrhough is intended
+           case EFL_GFX_COLORSPACE_AGRY88:
+             if (!bpp) bpp = 2;
+             EINA_FALLTHROUGH;
+             // falltrhough is intended
+           case EFL_GFX_COLORSPACE_GRY8:
+             if (!bpp) bpp = 1;
+             *tofree = EINA_TRUE;
+             im->im = (RGBA_Image 
*)evas_cache_image_empty(evas_common_image_cache_get());
+             im->im->cache_entry.flags.alpha = im->alpha;
+             im->im->cache_entry.space = im->cs.space;
+             evas_cache_image_colorspace(&im->im->cache_entry, im->cs.space);
+             im->im = (RGBA_Image 
*)evas_cache_image_size_set(&im->im->cache_entry, im->w, im->h);
+
+             DATA8 *pixels = (DATA8 *)im->tex->pt->dyn.data;
+             for (int i = 0; i < im->tex->pt->dyn.h; i++)
+               {
+                  memcpy(im->im->image.data + (im->w * i),
+                         pixels + (im->tex->pt->dyn.stride * i),
+                         im->w * bpp);
+               }
+             break;
+           default: break;
+          }
+     }
+
+   if (!im->im) return ret;
 
    if (cspace) *cspace = im->im->cache_entry.space;
    if (load)
      {
         if (evas_cache_image_load_data(&im->im->cache_entry) != 0)
-          return EINA_FALSE;
+          {
+             /* Only valid when content hint is DYNAMIC */
+             if (tofree && *tofree)
+               {
+                  evas_cache_image_drop(&im->im->cache_entry);
+                  im->im = NULL;
+               }
+
+             return ret;
+          }
      }
-   return _evas_common_rgba_image_plane_get(im->im, plane, slice);
+
+   ret = _evas_common_rgba_image_plane_get(im->im, plane, slice);
+
+   /* The im->im is not necessary, because it is created temporal purpose to
+      get the slice used by out side of this function. */
+   if (tofree && *tofree)
+     {
+        if (ret)
+          *slice = eina_rw_slice_slice_get(eina_slice_dup(*slice));
+
+        evas_cache_image_drop(&im->im->cache_entry);
+        im->im = NULL;
+     }
+
+   return ret;
 }
 
 static void
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index 7007f3a2fd..0504980f86 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1049,9 +1049,10 @@ eng_image_file_colorspace_get(void *data EINA_UNUSED, 
void *image)
 static Eina_Bool
 eng_image_data_direct_get(void *data EINA_UNUSED, void *image, int plane,
                           Eina_Slice *slice, Evas_Colorspace *cspace,
-                          Eina_Bool load)
+                          Eina_Bool load, Eina_Bool *tofree)
 {
    RGBA_Image *im = image;
+   if (tofree) *tofree = EINA_FALSE;
 
    if (!slice || !im)
      return EINA_FALSE;

-- 


Reply via email to