forked from enlightenment/efl
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:
parent
e7eb97f3b0
commit
c53f1526f1
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue