diff --git a/src/bin/elementary/test_evas_snapshot.c b/src/bin/elementary/test_evas_snapshot.c index 13e045804c..845c95c62d 100644 --- a/src/bin/elementary/test_evas_snapshot.c +++ b/src/bin/elementary/test_evas_snapshot.c @@ -53,6 +53,35 @@ _anim_toggle(void *data, const Efl_Event *ev EINA_UNUSED) eina_iterator_free(it); } +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) { @@ -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 9f77ce6c92..fcb7a7a67d 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 e370581685..e917aeb3e9 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 52512d0d26..48e6e8b4c4 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 b76f876188..ae2a1c4959 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; + Eina_Bool unmap_it = EINA_FALSE; + int imagew, imageh, uvw, uvh; + Eina_Rw_Slice slice = {}; + DATA32 *data = NULL; + void *pixels = NULL; - 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); - - // 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 ((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)) + { + int tmp = imagew; + imagew = imageh; + imageh = tmp; } if (!data) { + int stride; + cspace = EVAS_COLORSPACE_ARGB8888; - ENFN->image_colorspace_set(ENDT, pixels, cspace); - pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, &tofree); - } + 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 (EINA_UNLIKELY(cspace != o->cur->cspace)) - { - EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) - state_write->cspace = cspace; - EINA_COW_IMAGE_STATE_WRITE_END(o, state_write) - } - - if (!pixels || !data) - { - WRN("Could not get image pixels."); - return EINA_FALSE; + 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 5c7720c113..374d893065 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 33e5a45bff..38ae7956fd 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 81cede7e37..ad5835d1ba 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 bb26c2fcb3..c8bfb80690 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)) { - int strid = 0; - - // Call sw generic implementation. Should work for simple cases. - ok = pfunc.image_data_map(NULL, (void **) &im->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; + evas_gl_common_image_ref(glim); + glim2 = glim; + } + else + { + glim2 = _rotate_image_data(re, glim); } - // TODO: glReadPixels from FBO if possible + 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); + } - return EINA_FALSE; + if (!ok) + { + eng_image_free(re, glim2); + 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;