jpeg pushed a commit to branch master.

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

commit 2e89702d576f604332197332097591667b8fbe0f
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Tue Dec 20 17:56:09 2016 +0900

    evas: Fix image save with GL engine and orientation
    
    This fixes evas_object_image_save after changing the orientation
    of an image in the GL engine. In SW engine the pixel data is rotated
    in memory, so things worked fine from the beginning. In GL we may
    have to go through loops and hoops in order to rotate and fetch the
    data from the GL texture.
    
    This should fix ce45d44.
---
 src/lib/evas/canvas/efl_canvas_image.c             |  2 +-
 src/lib/evas/canvas/evas_object_image.c            | 97 +++++++++-------------
 src/lib/evas/include/evas_private.h                |  2 +-
 src/modules/evas/engines/gl_generic/evas_engine.c  | 63 +++++++++-----
 .../evas/engines/software_generic/evas_engine.c    |  9 +-
 5 files changed, 93 insertions(+), 80 deletions(-)

diff --git a/src/lib/evas/canvas/efl_canvas_image.c 
b/src/lib/evas/canvas/efl_canvas_image.c
index 1c97173..bfa0ca3 100644
--- a/src/lib/evas/canvas/efl_canvas_image.c
+++ b/src/lib/evas/canvas/efl_canvas_image.c
@@ -739,7 +739,7 @@ _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 EINA_FALSE;
 
-   return ENFN->image_data_direct_get(ENDT, o->engine_data, plane, slice, 
&cspace);
+   return ENFN->image_data_direct_get(ENDT, o->engine_data, plane, slice, 
&cspace, EINA_FALSE);
 }
 
 EOLIAN static Eina_Bool
diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index c4b7668..d81277f 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -874,9 +874,9 @@ _efl_canvas_image_internal_efl_file_save(const Eo *eo_obj, 
Evas_Image_Data *o, c
    int quality = 80, compress = 9, ok = 0;
    char *encoding = NULL;
    Image_Entry *ie;
-   Eina_Bool putback = EINA_FALSE, tofree = EINA_FALSE, no_convert = 
EINA_FALSE;
+   Eina_Bool putback = EINA_FALSE, tofree = EINA_FALSE, tgv = EINA_FALSE, 
free_data = EINA_FALSE;
    Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
-   int want_cspace = EVAS_COLORSPACE_ARGB8888;
+   Evas_Colorspace want_cspace = EVAS_COLORSPACE_ARGB8888;
    int imagew, imageh;
    void *pixels;
 
@@ -926,9 +926,11 @@ _efl_canvas_image_internal_efl_file_save(const Eo *eo_obj, 
Evas_Image_Data *o, c
         o->proxyrendering = EINA_FALSE;
      }
 
+   cspace = ENFN->image_file_colorspace_get(ENDT, pixels);
+   want_cspace = cspace;
+
    if (flags)
      {
-        const char *ext = NULL;
         char *p, *pp;
         char *tflags;
 
@@ -946,11 +948,17 @@ _efl_canvas_image_internal_efl_file_save(const Eo 
*eo_obj, Evas_Image_Data *o, c
              else break;
           }
 
-        if (file) ext = strrchr(file, '.');
-        if (encoding && ext && !strcasecmp(ext, ".tgv"))
+        if (file)
+          {
+             const char *ext = strrchr(file, '.');
+             if (ext && !strcasecmp(ext, ".tgv"))
+               tgv = EINA_TRUE;
+          }
+
+        if (encoding && tgv)
           {
              if (!strcmp(encoding, "auto"))
-               want_cspace = -1;
+               want_cspace = cspace;
              else if (!strcmp(encoding, "etc1"))
                want_cspace = EVAS_COLORSPACE_ETC1;
              else if (!strcmp(encoding, "etc2"))
@@ -970,49 +978,39 @@ _efl_canvas_image_internal_efl_file_save(const Eo 
*eo_obj, Evas_Image_Data *o, c
           }
      }
 
-   if (!ENFN->image_data_direct_get)
-     pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, 
&tofree);
-   else
+   if (ENFN->image_data_direct_get && (o->cur->orient == 
EVAS_IMAGE_ORIENT_NONE))
      {
+        Evas_Colorspace cs;
         Eina_Slice slice;
-        if (ENFN->image_data_direct_get(ENDT, pixels, 0, &slice, &cspace))
-          {
-             if ((want_cspace != (int) cspace) && (want_cspace != -1))
-               cspace = EVAS_COLORSPACE_ARGB8888;
-          }
-        else
+
+        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))
           {
-             cspace = ENFN->image_file_colorspace_get(ENDT, pixels);
-             if ((want_cspace != (int) cspace) && (want_cspace != -1))
-               cspace = EVAS_COLORSPACE_ARGB8888;
-             else
-               {
-                  ENFN->image_colorspace_set(ENDT, pixels, cspace);
-                  no_convert = EINA_TRUE;
-               }
+             data = (DATA32 *) slice.mem;
+             putback = EINA_FALSE;
           }
+        else ENFN->image_colorspace_set(ENDT, pixels, cspace);
+     }
+
+   if (!data)
+     {
+        cspace = EVAS_COLORSPACE_ARGB8888;
+        ENFN->image_colorspace_set(ENDT, pixels, cspace);
         pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, 
&tofree);
      }
 
-   if (!pixels)
+   if (EINA_UNLIKELY(cspace != o->cur->cspace))
      {
-        WRN("Could not get image pixels.");
-        return EINA_FALSE;
+        EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
+          state_write->cspace = cspace;
+        EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
      }
 
-   switch (cspace)
+   if (!pixels || !data)
      {
-      case EVAS_COLORSPACE_ARGB8888:
-        break;
-      case EVAS_COLORSPACE_ETC1:
-      case EVAS_COLORSPACE_ETC1_ALPHA:
-      case EVAS_COLORSPACE_RGB8_ETC2:
-      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
-        break;
-      default:
-        DBG("Need to convert colorspace before saving");
-        cspace = EVAS_COLORSPACE_ARGB8888;
-        break;
+        WRN("Could not get image pixels.");
+        return EINA_FALSE;
      }
 
    ie = evas_cache_image_data(evas_common_image_cache_get(),
@@ -1020,34 +1018,19 @@ _efl_canvas_image_internal_efl_file_save(const Eo 
*eo_obj, Evas_Image_Data *o, c
    if (ie)
      {
         RGBA_Image *im = (RGBA_Image *) ie;
-        DATA32 *old_data = NULL;
 
-        // FIXME: Something is fishy here... what about the previous pointer?
-        if ((o->cur->cspace == cspace) || no_convert)
-          im->image.data = data;
-        else
-          {
-             old_data = im->image.data;
-             im->image.data = _evas_image_data_convert_internal(o, data, 
EVAS_COLORSPACE_ARGB8888);
-          }
-        if (im->image.data)
-          {
-             ok = evas_common_save_image_to_file(im, file, key, quality, 
compress, encoding);
-
-             if (old_data)
-               {
-                  free(im->image.data);
-                  im->image.data = old_data;
-               }
-          }
+        ok = evas_common_save_image_to_file(im, file, key, quality, compress, 
encoding);
         evas_cache_image_drop(ie);
      }
+   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 (free_data) free(data);
+
    free(encoding);
    return ok;
 }
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 9e0561c..7221306 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1402,7 +1402,7 @@ struct _Evas_Func
    void *(*image_dirty_region)             (void *data, void *image, int x, 
int y, int w, int h);
    void *(*image_data_get)                 (void *data, void *image, int 
to_write, DATA32 **image_data, int *err, Eina_Bool *tofree);
    void *(*image_data_put)                 (void *data, void *image, DATA32 
*image_data);
-   Eina_Bool (*image_data_direct_get)      (void *data, void *image, int 
plane, Eina_Slice *slice, Evas_Colorspace *cspace);
+   Eina_Bool (*image_data_direct_get)      (void *data, void *image, int 
plane, Eina_Slice *slice, Evas_Colorspace *cspace, Eina_Bool load);
    void  (*image_data_preload_request)     (void *data, void *image, const Eo 
*target);
    void  (*image_data_preload_cancel)      (void *data, void *image, const Eo 
*target);
    void *(*image_alpha_set)                (void *data, 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 edf6e19..bc95546 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -246,7 +246,8 @@ 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_Slice *slice, Evas_Colorspace *cspace,
+                          Eina_Bool load)
 {
    Evas_GL_Image *im = image;
 
@@ -254,6 +255,11 @@ eng_image_data_direct_get(void *data EINA_UNUSED, void 
*image, int plane,
      return EINA_FALSE;
 
    if (cspace) *cspace = im->im->cache_entry.space;
+   if (load)
+     {
+        if (evas_cache_image_load_data(&im->im->cache_entry) != 0)
+          return EINA_FALSE;
+     }
    return _evas_common_rgba_image_plane_get(im->im, plane, slice);
 }
 
@@ -733,21 +739,8 @@ eng_image_data_get(void *data, void *image, int to_write, 
DATA32 **image_data, i
    if (im->native.data)
      return im;
 
-   if (im->im &&
-       im->orient != EVAS_IMAGE_ORIENT_NONE)
-     {
-        im_new = _rotate_image_data(data, image);
-        if (!im_new)
-          {
-             if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
-             ERR("Rotation failed.");
-             return im;
-          }
-        evas_gl_common_image_free(im);
-
-        *image_data = im_new->im->image.data;
-        return im_new;
-     }
+   if ((tofree != NULL) && im->im && (im->orient != EVAS_IMAGE_ORIENT_NONE))
+     goto rotate_image;
 
 #ifdef GL_GLES
    re->window_use(re->software.ob);
@@ -863,10 +856,14 @@ eng_image_data_get(void *data, void *image, int to_write, 
DATA32 **image_data, i
 
    if (!im->im)
      {
-        // FIXME: Should we create an FBO and draw the texture there, to then 
read it back?
-        ERR("GL image has no source data, failed to get pixel data");
-        if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
-        return NULL;
+        if (tofree)
+          goto rotate_image;
+        else
+          {
+             ERR("GL image has no source data, failed to get pixel data");
+             if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+             return NULL;
+          }
      }
 
 #ifdef EVAS_CSERVE2
@@ -875,6 +872,19 @@ eng_image_data_get(void *data, void *image, int to_write, 
DATA32 **image_data, i
    else
 #endif
      error = evas_cache_image_load_data(&im->im->cache_entry);
+
+   if (error != EVAS_LOAD_ERROR_NONE)
+     {
+        if (tofree)
+          goto rotate_image;
+        else
+          {
+             ERR("Failed to reload pixels of this GL image.");
+             if (err) *err = error;
+             return NULL;
+          }
+     }
+
    evas_gl_common_image_alloc_ensure(im);
    switch (im->cs.space)
      {
@@ -924,6 +934,19 @@ eng_image_data_get(void *data, void *image, int to_write, 
DATA32 **image_data, i
      }
    if (err) *err = error;
    return im;
+
+rotate_image:
+   // rotate data for image save
+   im_new = _rotate_image_data(data, image);
+   if (!im_new)
+     {
+        if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        ERR("Image rotation failed.");
+        return im;
+     }
+   *tofree = EINA_TRUE;
+   *image_data = im_new->im->image.data;
+   return im_new;
 }
 
 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 fad9dec..20d1569 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1071,7 +1071,9 @@ 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)
+eng_image_data_direct_get(void *data EINA_UNUSED, void *image, int plane,
+                          Eina_Slice *slice, Evas_Colorspace *cspace,
+                          Eina_Bool load)
 {
    RGBA_Image *im = image;
 
@@ -1079,6 +1081,11 @@ eng_image_data_direct_get(void *data EINA_UNUSED, void 
*image, int plane, Eina_S
      return EINA_FALSE;
 
    if (cspace) *cspace = im->cache_entry.space;
+   if (load)
+     {
+        if (evas_cache_image_load_data(&im->cache_entry) != 0)
+          return EINA_FALSE;
+     }
    return _evas_common_rgba_image_plane_get(im, plane, slice);
 }
 

-- 


Reply via email to