forked from enlightenment/efl
evas filters: Fix maps with filtered snapshots
Another wonder of evas render... maps, clips, snapshots, filters... This fixes animations with windows that have a snapshot decoration.
This commit is contained in:
parent
b5a5f61cd6
commit
4cbff5f0ea
|
@ -25,6 +25,24 @@ static const char *filter =
|
|||
"print ('Evaluating filter: ' .. input.width .. 'x' .. input.height)"
|
||||
;
|
||||
|
||||
static inline void
|
||||
_efl_key_int_set(Eo *obj, const char *key, int val)
|
||||
{
|
||||
Eina_Value *v = eina_value_new(EINA_VALUE_TYPE_INT);
|
||||
eina_value_set(v, val);
|
||||
efl_key_value_set(obj, key, v);
|
||||
}
|
||||
|
||||
static inline int
|
||||
_efl_key_int_get(Eo *obj, const char *key)
|
||||
{
|
||||
Eina_Value *v = efl_key_value_get(obj, key);
|
||||
int val;
|
||||
|
||||
if (!eina_value_get(v, &val)) return 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline Eo *
|
||||
_image_create(Eo *win, const char *path)
|
||||
{
|
||||
|
@ -102,6 +120,49 @@ _close(void *data, const Efl_Event *ev EINA_UNUSED)
|
|||
efl_del(win);
|
||||
}
|
||||
|
||||
static void
|
||||
_map_do(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
Eo *snap = data;
|
||||
int x, y, w, h;
|
||||
|
||||
// Prevent recursive infinite loop :(
|
||||
static int here = 0;
|
||||
if (here) return;
|
||||
here = 1;
|
||||
|
||||
efl_gfx_map_populate(snap, 0);
|
||||
efl_gfx_geometry_get(snap, &x, &y, &w, &h);
|
||||
efl_gfx_map_zoom(snap, 0.8, 0.8, x + w/2., y + h/2.);
|
||||
efl_gfx_map_rotate(snap, 45., x + w/2., y + h/2.);
|
||||
efl_gfx_map_enable_set(snap, EINA_TRUE);
|
||||
|
||||
here = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_toggle_map(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
Eo *win = data;
|
||||
Eo *snap;
|
||||
|
||||
snap = efl_key_wref_get(win, "snap");
|
||||
if (!_efl_key_int_get(snap, "map"))
|
||||
{
|
||||
_efl_key_int_set(snap, "map", 1);
|
||||
_map_do(snap, NULL);
|
||||
efl_event_callback_add(snap, EFL_GFX_EVENT_RESIZE, _map_do, snap);
|
||||
efl_event_callback_add(snap, EFL_GFX_EVENT_MOVE, _map_do, snap);
|
||||
}
|
||||
else
|
||||
{
|
||||
_efl_key_int_set(snap, "map", 0);
|
||||
efl_event_callback_del(snap, EFL_GFX_EVENT_RESIZE, _map_do, snap);
|
||||
efl_event_callback_del(snap, EFL_GFX_EVENT_MOVE, _map_do, snap);
|
||||
efl_gfx_map_enable_set(snap, EINA_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
|
@ -191,6 +252,14 @@ test_evas_snapshot(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *e
|
|||
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, "Map"),
|
||||
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, _toggle_map, 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),
|
||||
|
|
|
@ -266,6 +266,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
Eina_Bool ok;
|
||||
void *previous = pd->data->output;
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
Eina_Bool use_map = EINA_FALSE;
|
||||
Evas_Filter_Padding pad;
|
||||
|
||||
W = obj->cur->geometry.w;
|
||||
|
@ -288,6 +289,15 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
else
|
||||
ENFN->context_multiplier_unset(output, context);
|
||||
|
||||
if (obj->map->cur.usemap && obj->map->cur.map && (obj->map->cur.map->count >= 4))
|
||||
{
|
||||
int iw, ih;
|
||||
|
||||
use_map = EINA_TRUE;
|
||||
ENFN->image_size_get(ENDT, previous, &iw, &ih);
|
||||
evas_object_map_update(eo_obj, x, y, iw, ih, iw, ih);
|
||||
}
|
||||
|
||||
if (!pd->data->chain)
|
||||
{
|
||||
Evas_Filter_Program *pgm;
|
||||
|
@ -348,12 +358,20 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
if (!redraw)
|
||||
{
|
||||
// Render this image only
|
||||
ENFN->image_draw(ENDT, context,
|
||||
surface, previous,
|
||||
0, 0, W, H, // src
|
||||
X + x, Y + y, W, H, // dst
|
||||
EINA_FALSE, // smooth
|
||||
do_async);
|
||||
if (use_map)
|
||||
{
|
||||
ENFN->image_map_draw(ENDT, context, surface, previous,
|
||||
obj->map->spans, EINA_TRUE, 0, do_async);
|
||||
}
|
||||
else
|
||||
{
|
||||
ENFN->image_draw(ENDT, context,
|
||||
surface, previous,
|
||||
0, 0, W, H, // src
|
||||
X + x, Y + y, W, H, // dst
|
||||
EINA_FALSE, // smooth
|
||||
do_async);
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +445,8 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
|
||||
// Allocate all buffers now
|
||||
evas_filter_context_buffers_allocate_all(filter);
|
||||
evas_filter_target_set(filter, context, surface, X + x, Y + y);
|
||||
evas_filter_target_set(filter, context, surface, X + x, Y + y,
|
||||
use_map ? obj->map->spans : NULL);
|
||||
|
||||
// Request rendering from the object itself (child class)
|
||||
evas_filter_program_padding_get(pd->data->chain, &pad, NULL);
|
||||
|
|
|
@ -19,7 +19,7 @@ static void evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_
|
|||
int x, int y, Eina_Bool do_async);
|
||||
static void _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
||||
void *output, void *context, void *surface,
|
||||
int x, int y, int l, int t, int r, int b, Eina_Bool do_async);
|
||||
int x, int y, int l, int t, int r, int b, Eina_Bool skip_map, Eina_Bool do_async);
|
||||
static void evas_object_image_free(Evas_Object *eo_obj,
|
||||
Evas_Object_Protected_Data *obj);
|
||||
static void evas_object_image_render_pre(Evas_Object *eo_obj,
|
||||
|
@ -1726,12 +1726,6 @@ _image_has_border(Evas_Object_Protected_Data *obj EINA_UNUSED, Evas_Image_Data *
|
|||
o->cur->border.b || (o->cur->border.fill == 0);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_image_has_map(Evas_Object_Protected_Data *obj, Evas_Image_Data *o EINA_UNUSED)
|
||||
{
|
||||
return ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && (obj->map->cur.usemap));
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_image_is_filled(Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
|
||||
{
|
||||
|
@ -1765,8 +1759,7 @@ _efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render(
|
|||
output = ENDT;
|
||||
|
||||
// FIXME: In GL we could use the image even if scaled
|
||||
if (!_image_has_border(obj, o) && !_image_has_map(obj, o) && _image_is_filled(obj, o)
|
||||
&& !_image_is_scaled(obj, o))
|
||||
if (!_image_has_border(obj, o) && _image_is_filled(obj, o) && !_image_is_scaled(obj, o))
|
||||
{
|
||||
int imagew, imageh, uvw, uvh;
|
||||
|
||||
|
@ -1802,7 +1795,7 @@ _efl_canvas_image_internal_efl_canvas_filter_internal_filter_input_render(
|
|||
_evas_image_render(eo_obj, obj, output, ctx, surface,
|
||||
x + l - obj->cur->geometry.x,
|
||||
y + t - obj->cur->geometry.y,
|
||||
l, t, r, b, do_async);
|
||||
l, t, r, b, EINA_TRUE, do_async);
|
||||
|
||||
ENFN->context_free(output, ctx);
|
||||
|
||||
|
@ -1892,7 +1885,7 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
|||
return;
|
||||
}
|
||||
|
||||
_evas_image_render(eo_obj, obj, output, context, surface, x, y, 0, 0, 0, 0, do_async);
|
||||
_evas_image_render(eo_obj, obj, output, context, surface, x, y, 0, 0, 0, 0, EINA_FALSE, do_async);
|
||||
}
|
||||
|
||||
void *
|
||||
|
@ -2008,7 +2001,7 @@ _evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
static void
|
||||
_evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
||||
void *output, void *context, void *surface, int x, int y,
|
||||
int l, int t, int r, int b, Eina_Bool do_async)
|
||||
int l, int t, int r, int b, Eina_Bool skip_map, Eina_Bool do_async)
|
||||
{
|
||||
Evas_Image_Data *o = obj->private_data;
|
||||
int imagew, imageh, uvw, uvh, cw, ch;
|
||||
|
@ -2023,7 +2016,8 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
if (ENFN->context_clip_get(ENDT, context, NULL, NULL, &cw, &ch) && (!cw || !ch))
|
||||
return;
|
||||
|
||||
if ((obj->map->cur.map) && (obj->map->cur.map->count > 3) && (obj->map->cur.usemap))
|
||||
if (!skip_map && (obj->map->cur.map) && (obj->map->cur.map->count > 3)
|
||||
&& (obj->map->cur.usemap))
|
||||
{
|
||||
evas_object_map_update(eo_obj, x, y, imagew, imageh, uvw, uvh);
|
||||
|
||||
|
|
|
@ -13493,7 +13493,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
obj->cur->cache.clip.b, obj->cur->cache.clip.a);
|
||||
evas_filter_context_proxy_render_all(ctx, eo_obj, EINA_FALSE);
|
||||
evas_filter_context_buffers_allocate_all(ctx);
|
||||
evas_filter_target_set(ctx, context, surface, target.x, target.y);
|
||||
evas_filter_target_set(ctx, context, surface, target.x, target.y, NULL);
|
||||
ti->gfx_filter->ctx = ctx;
|
||||
ti->gfx_filter->do_async = do_async;
|
||||
|
||||
|
|
|
@ -2797,7 +2797,7 @@ _snapshot_redraw_update(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap
|
|||
}
|
||||
}
|
||||
|
||||
if (snap->snapshot_no_obscure)
|
||||
if (snap->snapshot_no_obscure || _evas_render_has_map(snap))
|
||||
goto skip_obscures;
|
||||
|
||||
tiler = eina_tiler_new(w, h);
|
||||
|
@ -2881,6 +2881,8 @@ evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *evas,
|
|||
OBJ_ARRAY_PUSH(&evas->temporary_objects, obj);
|
||||
|
||||
if (above_top) continue;
|
||||
if (obj->cur->snapshot && !evas_object_is_opaque(obj->object, obj))
|
||||
continue;
|
||||
|
||||
/* reset the background of the area if needed (using cutout and engine alpha flag to help) */
|
||||
if (alpha && !skip_cutouts)
|
||||
|
@ -2985,7 +2987,11 @@ evas_render_updates_internal_loop(Evas *eo_e, Evas_Public_Data *evas,
|
|||
|
||||
obj2 = eina_array_data_get(&evas->temporary_objects, j);
|
||||
if (obj2 == top) above_top = EINA_TRUE;
|
||||
if (above_top && obj2->cur->snapshot) continue;
|
||||
if (obj2->cur->snapshot)
|
||||
{
|
||||
if (above_top) continue;
|
||||
if (!evas_object_is_opaque(obj2->object, obj2)) continue;
|
||||
}
|
||||
#if 1
|
||||
if (
|
||||
RECTS_INTERSECT
|
||||
|
|
|
@ -1489,7 +1489,7 @@ evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle
|
|||
/* Final target */
|
||||
Eina_Bool
|
||||
evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
|
||||
void *surface, int x, int y)
|
||||
void *surface, int x, int y, const RGBA_Map *map)
|
||||
{
|
||||
void *mask = NULL;
|
||||
|
||||
|
@ -1509,11 +1509,20 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
|
|||
ctx->target.color_use = EINA_FALSE;
|
||||
ctx->target.rop = ENFN->context_render_op_get(ENDT, draw_context);
|
||||
|
||||
free(ctx->target.map);
|
||||
if (!map) ctx->target.map = NULL;
|
||||
else
|
||||
{
|
||||
size_t len = sizeof(RGBA_Map) + sizeof(RGBA_Map_Point) * (map->count - 1);
|
||||
ctx->target.map = malloc(len);
|
||||
memcpy(ctx->target.map, map, len);
|
||||
}
|
||||
|
||||
ENFN->context_clip_image_get
|
||||
(ENDT, draw_context, &mask, &ctx->target.mask_x, &ctx->target.mask_y);
|
||||
if (ctx->target.mask)
|
||||
ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask);
|
||||
ctx->target.mask = mask;
|
||||
ctx->target.mask = mask; // FIXME: why no ref???
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
@ -1558,10 +1567,18 @@ _filter_target_render(Evas_Filter_Context *ctx)
|
|||
}
|
||||
|
||||
ENFN->context_render_op_set(ENDT, drawctx, ctx->target.rop);
|
||||
ENFN->image_draw(ENDT, drawctx, surface, image,
|
||||
0, 0, src->w, src->h,
|
||||
ctx->target.x, ctx->target.y, src->w, src->h,
|
||||
EINA_TRUE, EINA_FALSE);
|
||||
if (ctx->target.map)
|
||||
{
|
||||
ENFN->image_map_draw(ENDT, drawctx, surface, image,
|
||||
ctx->target.map, EINA_TRUE, 0, EINA_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ENFN->image_draw(ENDT, drawctx, surface, image,
|
||||
0, 0, src->w, src->h,
|
||||
ctx->target.x, ctx->target.y, src->w, src->h,
|
||||
EINA_TRUE, EINA_FALSE);
|
||||
}
|
||||
|
||||
ENFN->context_free(ENDT, drawctx);
|
||||
evas_ector_buffer_engine_image_release(src->buffer, image);
|
||||
|
|
|
@ -153,6 +153,7 @@ struct _Evas_Filter_Context
|
|||
void *mask; // mask
|
||||
int mask_x, mask_y; // mask offset
|
||||
Evas_Render_Op rop;
|
||||
RGBA_Map *map;
|
||||
Eina_Bool clip_use : 1;
|
||||
Eina_Bool color_use : 1;
|
||||
} target;
|
||||
|
|
|
@ -164,7 +164,7 @@ Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context
|
|||
Eina_Bool evas_filter_context_run(Evas_Filter_Context *ctx);
|
||||
|
||||
Eina_Bool evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props *text_props, Eina_Bool do_async);
|
||||
Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y);
|
||||
Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y, const RGBA_Map *map);
|
||||
|
||||
// utility function
|
||||
void _evas_filter_source_hash_free_cb(void *data);
|
||||
|
|
Loading…
Reference in New Issue