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
This commit is contained in:
Jean-Philippe Andre 2017-03-28 16:09:34 +09:00
parent e7eb97f3b0
commit c53f1526f1
9 changed files with 216 additions and 144 deletions

View File

@ -53,6 +53,35 @@ _anim_toggle(void *data, const Efl_Event *ev EINA_UNUSED)
eina_iterator_free(it); 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 static void
_radius_set(void *data, const Efl_Event *ev) _radius_set(void *data, const Efl_Event *ev)
{ {
@ -76,7 +105,7 @@ _close(void *data, const Efl_Event *ev EINA_UNUSED)
void void
test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) 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; const char *path;
win = efl_add(EFL_UI_WIN_STANDARD_CLASS, NULL, 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_event_callback_add(efl_added, ELM_SLIDER_EVENT_CHANGED, _radius_set, win),
efl_gfx_visible_set(efl_added, 1)); 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_add(ELM_BUTTON_CLASS, win,
efl_text_set(efl_added, "Toggle animation"), efl_text_set(efl_added, "Toggle animation"),
efl_gfx_size_hint_align_set(efl_added, -1.0, -1.0), 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_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_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _anim_toggle, win),
efl_gfx_visible_set(efl_added, 1)); 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_add(ELM_BUTTON_CLASS, win,
efl_text_set(efl_added, "Close"), efl_text_set(efl_added, "Close"),
efl_gfx_size_hint_align_set(efl_added, -1.0, -1.0), 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_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_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _close, win),
efl_gfx_visible_set(efl_added, 1)); efl_gfx_visible_set(efl_added, 1));

View File

@ -21,4 +21,16 @@ _efl_canvas_snapshot_efl_object_constructor(Eo *eo_obj, void *pd EINA_UNUSED)
return eo_obj; 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" #include "efl_canvas_snapshot.eo.c"

View File

@ -9,5 +9,6 @@ class Efl.Canvas.Snapshot (Efl.Canvas.Image.Internal)
data: null; data: null;
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Gfx.Buffer.buffer_update_add;
} }
} }

View File

@ -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_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_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_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 */ /* Efl.Gfx.Fill */
void _evas_image_fill_set(Eo *eo_obj, Evas_Image_Data *o, int x, int y, int w, int h); void _evas_image_fill_set(Eo *eo_obj, Evas_Image_Data *o, int x, int y, int w, int h);

View File

@ -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); 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 ((w <= 0) || (h <= 0)) return;
if (obj->cur->snapshot)
evas_object_change(eo_obj, obj);
if (!o->written) return; if (!o->written) return;
evas_object_async_block(obj); evas_object_async_block(obj);
cnt = eina_list_count(o->pixels->pixel_updates); 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 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) _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; int quality = 80, compress = 9, ok = 0;
char *encoding = NULL; char *encoding = NULL;
Image_Entry *ie; Image_Entry *ie;
Eina_Bool putback = EINA_FALSE, tofree = EINA_FALSE, tgv = EINA_FALSE;
Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888; Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
Evas_Colorspace want_cspace = EVAS_COLORSPACE_ARGB8888; Evas_Colorspace want_cspace = EVAS_COLORSPACE_ARGB8888;
int imagew, imageh; Evas_Object_Protected_Data *obj;
void *pixels; 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); 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()
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
evas_object_async_block(obj); evas_object_async_block(obj);
if (o->cur->scene) pixels = _evas_image_pixels_get((Eo *) eo_obj, obj, ENDT, NULL, NULL, 0, 0,
{ &imagew, &imageh, &uvw, &uvh, EINA_TRUE, EINA_TRUE);
_evas_image_3d_render(obj->layer->evas->evas, (Eo *) eo_obj, obj, o, o->cur->scene); if (!pixels) goto no_pixels;
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;
}
cspace = ENFN->image_file_colorspace_get(ENDT, pixels); cspace = ENFN->image_file_colorspace_get(ENDT, pixels);
want_cspace = cspace; want_cspace = cspace;
if (flags) if (flags)
{ {
const char *ext;
char *p, *pp; char *p, *pp;
char *tflags; char *tflags;
@ -955,14 +921,10 @@ _efl_canvas_image_internal_efl_file_save(const Eo *eo_obj, Evas_Image_Data *o, c
else break; else break;
} }
if (file) if (encoding)
{ {
const char *ext = strrchr(file, '.'); ext = strrchr(file, '.');
if (ext && !strcasecmp(ext, ".tgv")) if (ext && !strcasecmp(ext, ".tgv"))
tgv = EINA_TRUE;
}
if (encoding && tgv)
{ {
if (!strcmp(encoding, "auto")) if (!strcmp(encoding, "auto"))
want_cspace = cspace; want_cspace = cspace;
@ -978,46 +940,42 @@ _efl_canvas_image_internal_efl_file_save(const Eo *eo_obj, Evas_Image_Data *o, c
else if (!strcmp(encoding, "etc1+alpha")) else if (!strcmp(encoding, "etc1+alpha"))
want_cspace = EVAS_COLORSPACE_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)) if (ENFN->image_data_direct_get && (o->cur->orient == EVAS_IMAGE_ORIENT_NONE))
{ {
Evas_Colorspace cs; 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, &sl, &cs, EINA_TRUE);
ok = ENFN->image_data_direct_get(ENDT, pixels, 0, &slice, &cs, EINA_TRUE); if (ok && (cs == want_cspace))
if (ok && (want_cspace == cs)) data = (DATA32 *) sl.mem;
{
data = (DATA32 *) slice.mem;
putback = EINA_FALSE;
} }
else ENFN->image_colorspace_set(ENDT, pixels, cspace);
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) if (!data)
{ {
int stride;
cspace = EVAS_COLORSPACE_ARGB8888; cspace = EVAS_COLORSPACE_ARGB8888;
ENFN->image_colorspace_set(ENDT, pixels, cspace); ok = ENFN->image_data_map(ENDT, &pixels, &slice, &stride, 0, 0, imagew, imageh,
pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, &tofree); 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)) if (stride != (imagew * 4))
{ WRN("Invalid stride: saved image may look wrong!");
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;
} }
ie = evas_cache_image_data(evas_common_image_cache_get(), 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; else ok = EINA_FALSE;
if (tofree) if (unmap_it)
ENFN->image_free(ENDT, pixels); ENFN->image_data_unmap(ENDT, pixels, &slice);
else if (putback)
o->engine_data = ENFN->image_data_put(ENDT, pixels, data);
free(encoding); free(encoding);
if (!ok) ERR("Image save failed.");
return ok; return ok;
no_pixels:
ERR("Could not get image pixels for saving.");
return EINA_FALSE;
} }
EOLIAN static Efl_Gfx_Colorspace EOLIAN static Efl_Gfx_Colorspace
@ -1890,20 +1851,32 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
void * void *
_evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj, _evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj,
void *output, void *context, void *surface, int x, int y, 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_Image_Data *o = obj->private_data, *oi = NULL;
Evas_Object_Protected_Data *source = 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); source = efl_data_scope_get(o->cur->source, EFL_CANVAS_OBJECT_CLASS);
if (source && (source->type == o_type)) if (source && (source->type == o_type))
oi = efl_data_scope_get(o->cur->source, MY_CLASS); 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); _evas_image_3d_render(obj->layer->evas->evas, eo_obj, obj, o, o->cur->scene);
pixels = obj->data_3d->surface; 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) else if (!o->cur->source || !source)
{ {
// normal image (from file or user pixel set)
needs_post_render = EINA_FALSE;
if (output && surface) if (output && surface)
pixels = evas_process_dirty_pixels(eo_obj, obj, o, output, surface, o->engine_data); pixels = evas_process_dirty_pixels(eo_obj, obj, o, output, surface, o->engine_data);
else else
@ -1941,14 +1916,10 @@ _evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj,
} }
else if (oi && oi->engine_data) else if (oi && oi->engine_data)
{ {
pixels = oi->engine_data;
if (oi->has_filter) if (oi->has_filter)
{ pixels = evas_filter_output_buffer_get(source->object);
void *output_buffer = NULL; if (!pixels)
output_buffer = evas_filter_output_buffer_get(source->object); pixels = oi->engine_data;
if (output_buffer)
pixels = output_buffer;
}
*imagew = oi->cur->image.w; *imagew = oi->cur->image.w;
*imageh = oi->cur->image.h; *imageh = oi->cur->image.h;
*uvw = source->cur->geometry.w; *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; 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; return pixels;
} }
@ -1991,7 +1970,7 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
void *pixels; void *pixels;
pixels = _evas_image_pixels_get(eo_obj, obj, output, context, surface, x, y, 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 (!pixels) return;
if (ENFN->context_clip_get(ENDT, context, NULL, NULL, &cw, &ch) && (!cw || !ch)) 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. * draw, just get the pixels so we can check the transparency.
*/ */
pixels = _evas_image_pixels_get(eo_obj, obj, ENDT, NULL, NULL, 0, 0, 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; if (!pixels) return is_inside;
/* TODO: not handling o->dirty_pixels && o->pixels->func.get_pixels, /* TODO: not handling o->dirty_pixels && o->pixels->func.get_pixels,

View File

@ -3513,7 +3513,9 @@ evas_render_updates_internal(Evas *eo_e,
ru->surface = NULL; ru->surface = NULL;
} }
eina_spinlock_take(&(e->render.lock)); eina_spinlock_take(&(e->render.lock));
e->inside_post_render = EINA_TRUE;
_cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post); _cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
e->inside_post_render = EINA_FALSE;
eina_spinlock_release(&(e->render.lock)); eina_spinlock_release(&(e->render.lock));
if (post.updated_area) eina_list_free(post.updated_area); 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); jobs_il = EINA_INLIST_GET(evas->post_render.jobs);
evas->post_render.jobs = NULL; evas->post_render.jobs = NULL;
SLKU(evas->post_render.lock); SLKU(evas->post_render.lock);
evas->inside_post_render = EINA_TRUE;
EINA_INLIST_FREE(jobs_il, job) EINA_INLIST_FREE(jobs_il, job)
{ {
jobs_il = eina_inlist_remove(jobs_il, EINA_INLIST_GET(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; post.updated_area = ret_updates;
_cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post); _cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
evas->inside_post_render = EINA_FALSE;
evas_render_updates_free(ret_updates); evas_render_updates_free(ret_updates);

View File

@ -956,6 +956,7 @@ struct _Evas_Public_Data
Eina_Bool rendering : 1; Eina_Bool rendering : 1;
Eina_Bool render2 : 1; Eina_Bool render2 : 1;
Eina_Bool common_init : 1; Eina_Bool common_init : 1;
Eina_Bool inside_post_render : 1;
}; };
struct _Evas_Layer struct _Evas_Layer

View File

@ -527,6 +527,7 @@ struct _Evas_GL_Image_Data_Map
EINA_INLIST; EINA_INLIST;
Evas_GL_Texture *tex; // one or the other Evas_GL_Texture *tex; // one or the other
RGBA_Image *im; // one or the other RGBA_Image *im; // one or the other
Evas_GL_Image *glim;
Eina_Rw_Slice slice; Eina_Rw_Slice slice;
int stride; // in bytes int stride; // in bytes
int rx, ry, rw, rh; // actual map region int rx, ry, rw, rh; // actual map region

View File

@ -2688,27 +2688,51 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
} }
static Eina_Bool 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, int *stride, int x, int y, int w, int h,
Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode, Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode,
int plane) int plane)
{ {
Render_Engine_GL_Generic *re = engdata;
Evas_GL_Image_Data_Map *map = NULL; Evas_GL_Image_Data_Map *map = NULL;
Evas_GL_Image *im; Evas_GL_Image *glim, *glim2 = NULL;
Eina_Bool ok; Eina_Bool ok = EINA_FALSE;
RGBA_Image *im = NULL;
int strid;
EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image && slice, EINA_FALSE); 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; evas_gl_common_image_ref(glim);
glim2 = glim;
}
else
{
glim2 = _rotate_image_data(re, glim);
}
// Call sw generic implementation. Should work for simple cases. if (!glim2) return EINA_FALSE;
ok = pfunc.image_data_map(NULL, (void **) &im->im, slice, &strid, 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); x, y, w, h, cspace, mode, plane);
if (ok) }
if (!ok)
{ {
eng_image_free(re, glim2);
return EINA_FALSE;
}
evas_cache_image_ref(&im->cache_entry);
map = calloc(1, sizeof(*map)); map = calloc(1, sizeof(*map));
map->cspace = cspace; map->cspace = cspace;
map->rx = x; map->rx = x;
@ -2718,16 +2742,19 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image, Eina_Rw_Slice *slice
map->mode = mode; map->mode = mode;
map->slice = *slice; map->slice = *slice;
map->stride = strid; map->stride = strid;
map->im = im->im; // ref? map->im = im;
im->maps = eina_inlist_prepend(im->maps, EINA_INLIST_GET(map)); map->glim = glim2;
} glim->maps = eina_inlist_prepend(glim->maps, EINA_INLIST_GET(map));
if (stride) *stride = strid; if (stride) *stride = strid;
return ok;
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
{
evas_gl_common_image_ref(glim2);
evas_gl_common_image_free(glim);
*image = glim2;
} }
// TODO: glReadPixels from FBO if possible return EINA_TRUE;
return EINA_FALSE;
} }
static Eina_Bool static Eina_Bool
@ -2746,13 +2773,17 @@ eng_image_data_unmap(void *engdata EINA_UNUSED, void *image, const Eina_Rw_Slice
{ {
found = EINA_TRUE; found = EINA_TRUE;
if (map->im) 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 (found)
{ {
if (im->im && im->tex && if (im->im && im->tex &&
(map->mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)) (map->mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE))
evas_gl_common_texture_update(im->tex, im->im); evas_gl_common_texture_update(im->tex, im->im);
im->maps = eina_inlist_remove(im->maps, EINA_INLIST_GET(map)); im->maps = eina_inlist_remove(im->maps, EINA_INLIST_GET(map));
if (map->glim) evas_gl_common_image_free(map->glim);
free(map); free(map);
} }
return found; return found;