jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=9b1ea2fc6b21be05c7959d2d14402310c9c68784
commit 9b1ea2fc6b21be05c7959d2d14402310c9c68784 Author: Jean-Philippe Andre <jp.an...@samsung.com> Date: Wed Mar 15 14:49:50 2017 +0900 evas: Pass obscuring region to the filters This will be most useful in a special case, where a filter is used in a window decoration, applied to a snapshot object. Another optimization that might be wanted is passing a list of update regions (from the proxy or snapshot). The filters don't support the obscuring region yet, only some of the high-level logic is implemented. --- src/lib/evas/canvas/efl_canvas_filter_internal.eo | 1 + src/lib/evas/canvas/evas_filter_mixin.c | 86 +++++++++++++++++------ src/lib/evas/canvas/evas_object_main.c | 2 +- src/lib/evas/canvas/evas_object_textblock.c | 34 ++++----- src/lib/evas/canvas/evas_render.c | 75 +++++++++++++++++--- src/lib/evas/filters/evas_filter.c | 57 +++++++++++++++ src/lib/evas/filters/evas_filter_parser.c | 44 +++++++----- src/lib/evas/filters/evas_filter_private.h | 12 +++- src/lib/evas/include/evas_filter.h | 10 ++- src/lib/evas/include/evas_private.h | 2 + 10 files changed, 253 insertions(+), 70 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_filter_internal.eo b/src/lib/evas/canvas/efl_canvas_filter_internal.eo index 8b44d40..a60b3f1 100644 --- a/src/lib/evas/canvas/efl_canvas_filter_internal.eo +++ b/src/lib/evas/canvas/efl_canvas_filter_internal.eo @@ -1,4 +1,5 @@ // import efl_gfx_types -> need to add Efl.Gfx.Color +import eina_types; /* Everything in this file is internal to Evas. It is not meant to be used from outside EFL itself! */ diff --git a/src/lib/evas/canvas/evas_filter_mixin.c b/src/lib/evas/canvas/evas_filter_mixin.c index b19e4e6..a0d3b3e 100644 --- a/src/lib/evas/canvas/evas_filter_mixin.c +++ b/src/lib/evas/canvas/evas_filter_mixin.c @@ -157,6 +157,24 @@ _evas_filter_state_set_internal(Evas_Filter_Program *pgm, Evas_Filter_Data *pd) return evas_filter_program_state_set(pgm, &state); } +static inline Eina_Bool +_evas_filter_obscured_region_changed(Evas_Filter_Data *pd) +{ + Eina_Rectangle inter; + + inter = pd->data->prev_obscured; + if (eina_rectangle_is_empty(&pd->data->obscured) && + eina_rectangle_is_empty(&inter)) + return EINA_FALSE; + if (!eina_rectangle_intersection(&inter, &pd->data->obscured)) + return EINA_TRUE; + if ((inter.w != pd->data->prev_obscured.w) || + (inter.h != pd->data->prev_obscured.h)) + return EINA_TRUE; + + return EINA_FALSE; +} + Eina_Bool evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, void *output, void *context, void *surface, @@ -166,12 +184,13 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, if (!pd->data->invalid && (pd->data->chain || pd->data->code)) { - int X, Y, W, H, l = 0, r = 0, t = 0, b = 0; + int X, Y, W, H; Evas_Filter_Context *filter; void *drawctx; Eina_Bool ok; void *previous = pd->data->output; Evas_Object_Filter_Data *fcow; + Evas_Filter_Padding pad; /* NOTE: Filter rendering is now done ENTIRELY on CPU. * So we rely on cache/cache2 to allocate a real image buffer, @@ -229,17 +248,15 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, } else if (previous && !pd->data->changed) { - Eina_Bool redraw; + Eina_Bool redraw = EINA_TRUE; - redraw = _evas_filter_state_set_internal(pd->data->chain, pd); - if (redraw) + if (_evas_filter_state_set_internal(pd->data->chain, pd)) DBG("Filter redraw by state change!"); else if (obj->changed) - { - // FIXME: Check that something else than X,Y changed! - redraw = EINA_TRUE; - DBG("Filter redraw by object content change!"); - } + DBG("Filter redraw by object content change!"); + else if (_evas_filter_obscured_region_changed(pd)) + DBG("Filter redraw by obscure regions change!"); + else redraw = EINA_FALSE; // Scan proxies to find if any changed if (!redraw && pd->data->sources) @@ -303,13 +320,16 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, drawctx = ENFN->context_new(ENDT); ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255); + // Set obscured region + evas_filter_context_obscured_region_set(filter, pd->data->obscured); + // Allocate all buffers now evas_filter_context_buffers_allocate_all(filter); evas_filter_target_set(filter, context, surface, X + x, Y + y); // Request rendering from the object itself (child class) - evas_filter_program_padding_get(pd->data->chain, &l, &r, &t, &b); - ok = evas_filter_input_render(eo_obj, filter, drawctx, NULL, l, r, t, b, 0, 0, do_async); + evas_filter_program_padding_get(pd->data->chain, &pad, NULL); + ok = evas_filter_input_render(eo_obj, filter, drawctx, NULL, pad.l, pad.r, pad.t, pad.b, 0, 0, do_async); if (!ok) ERR("Filter input render failed."); ENFN->context_free(ENDT, drawctx); @@ -321,7 +341,8 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, fcow = FCOW_BEGIN(pd); fcow->changed = EINA_FALSE; fcow->async = do_async; - if (!ok) fcow->invalid = EINA_TRUE; + fcow->prev_obscured = fcow->obscured; + fcow->invalid = !ok; FCOW_END(fcow, pd); if (ok) @@ -534,15 +555,15 @@ EOLIAN static void _efl_canvas_filter_internal_efl_gfx_filter_filter_padding_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, int *l, int *r, int *t, int *b) { - if (!pd->data->chain) - { - if (l) *l = 0; - if (r) *r = 0; - if (t) *t = 0; - if (b) *b = 0; - return; - } - evas_filter_program_padding_get(pd->data->chain, l, r, t, b); + Evas_Filter_Padding pad = { 0, 0, 0, 0 }; + + if (pd->data->chain) + evas_filter_program_padding_get(pd->data->chain, &pad, NULL); + + if (l) *l = pad.l; + if (r) *r = pad.r; + if (t) *t = pad.t; + if (b) *b = pad.b; } EOLIAN static void @@ -697,4 +718,27 @@ _efl_canvas_filter_internal_filter_output_buffer_get(Eo *obj EINA_UNUSED, Evas_F return pd->data->output; } +void +_evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj, + const Eina_Rectangle rect) +{ + Evas_Filter_Data *pd; + Evas_Object_Filter_Data *fcow; + + pd = efl_data_scope_get(obj->object, MY_CLASS); + if (!pd->data) return; + + fcow = FCOW_BEGIN(pd); + if ((rect.w <= 0) || (rect.h <= 0)) + memset(&fcow->obscured, 0, sizeof(fcow->obscured)); + else + { + fcow->obscured.x = rect.x - obj->cur->geometry.x; + fcow->obscured.y = rect.y - obj->cur->geometry.y; + fcow->obscured.w = rect.w; + fcow->obscured.h = rect.h; + } + FCOW_END(fcow, pd); +} + #include "canvas/efl_canvas_filter_internal.eo.c" diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c index dcfecfc..cab4bd1 100644 --- a/src/lib/evas/canvas/evas_object_main.c +++ b/src/lib/evas/canvas/evas_object_main.c @@ -33,7 +33,7 @@ static const Evas_Object_Protected_State default_state = { 1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE }; static const Evas_Object_Filter_Data default_filter = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, { { NULL, 0.0 }, { NULL, 0.0 }, 0.0 }, EINA_FALSE, EINA_FALSE, EINA_TRUE + NULL, NULL, NULL, NULL, NULL, NULL, {}, {}, NULL, {}, EINA_FALSE, EINA_FALSE, EINA_TRUE }; const void * const evas_object_filter_cow_default = &default_filter; static const Evas_Object_Mask_Data default_mask = { diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 4de5938..f021649 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -478,9 +478,7 @@ struct _Efl_Canvas_Text_Filter Evas_Object *eo_obj; Evas_Public_Data *evas; void *dc; /* draw context - no clip, white, no colmul... */ - struct { - int l, r, t, b; - } pad; + Evas_Filter_Padding pad; Eina_Bool invalid; Eina_Bool redraw; }; @@ -4051,15 +4049,15 @@ _text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti) if (EINA_UNLIKELY(ti->parent.format->gfx_filter != NULL)) { - int l = 0, r = 0, t = 0, b = 0; + Evas_Filter_Padding pad = { 0, 0, 0, 0 }; Evas_Filter_Program *pgm; pgm = _format_filter_program_get(c->o, ti->parent.format); if (pgm) { - evas_filter_program_padding_get(pgm, &l, &r, &t, &b); + evas_filter_program_padding_get(pgm, &pad, NULL); - ti->x_adjustment = r + l; + ti->x_adjustment = pad.r + pad.l; ti->parent.w = tw + ti->x_adjustment; // FIXME: why add l+r here, ti->parent.h = th; // but not t+b here? ti->parent.adv = advw; @@ -4647,21 +4645,21 @@ _layout_do_format(const Evas_Object *obj, Ctxt *c, } { - Evas_Coord pad_l = 0, pad_r = 0, pad_t = 0, pad_b = 0; + Evas_Filter_Padding pad = { 0, 0, 0, 0 }; Evas_Filter_Program *pgm = NULL; if (EINA_UNLIKELY(fmt->gfx_filter != NULL)) pgm = _format_filter_program_get(efl_data_scope_get(obj, MY_CLASS), fmt); if (EINA_UNLIKELY(pgm != NULL)) - evas_filter_program_padding_get(pgm, &pad_l, &pad_r, &pad_t, &pad_b); + evas_filter_program_padding_get(pgm, &pad, NULL); else - evas_text_style_pad_get(fmt->style, &pad_l, &pad_r, &pad_t, &pad_b); + evas_text_style_pad_get(fmt->style, &pad.l, &pad.r, &pad.t, &pad.b); - if (pad_l > *style_pad_l) *style_pad_l = pad_l; - if (pad_r > *style_pad_r) *style_pad_r = pad_r; - if (pad_t > *style_pad_t) *style_pad_t = pad_t; - if (pad_b > *style_pad_b) *style_pad_b = pad_b; + if (pad.l > *style_pad_l) *style_pad_l = pad.l; + if (pad.r > *style_pad_r) *style_pad_r = pad.r; + if (pad.t > *style_pad_t) *style_pad_t = pad.t; + if (pad.b > *style_pad_b) *style_pad_b = pad.b; } if (fmt->underline2) @@ -13487,9 +13485,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED, } // target position - evas_filter_program_padding_get(pgm, - &filter->pad.l, &filter->pad.r, - &filter->pad.t, &filter->pad.b); + evas_filter_program_padding_get(pgm, &filter->pad, NULL); target = _filter_target_position_calc(obj, ti, x, y); ENFN->context_color_set(ENDT, context, 255, 255, 255, 255); ENFN->context_multiplier_set(ENDT, context, @@ -13828,7 +13824,7 @@ _efl_canvas_text_efl_canvas_filter_internal_filter_state_prepare( Efl_Canvas_Text_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_TEXT_CLASS); Evas_Object_Textblock_Text_Item *ti = data; Efl_Canvas_Text_Filter_Program *program; - int l = 0, r = 0, t = 0, b = 0; + Evas_Filter_Padding pad = {}; #define STATE_COLOR(dst, src) dst.r = src.r; dst.g = src.g; dst.b = src.b; dst.a = src.a STATE_COLOR(state->color, ti->parent.format->color.normal); @@ -13839,9 +13835,9 @@ _efl_canvas_text_efl_canvas_filter_internal_filter_state_prepare( #undef STATE_COLOR program = _filter_program_find(o, ti->parent.format->gfx_filter->name); - if (program) evas_filter_program_padding_get(program->pgm, &l, &r, &t, &b); + if (program) evas_filter_program_padding_get(program->pgm, &pad, NULL); state->w = ti->parent.w; // + l + r; (already included) - state->h = ti->parent.h + t + b; + state->h = ti->parent.h + pad.t + pad.b; state->scale = obj->cur->scale; } diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index a13c693..e464026 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -12,6 +12,10 @@ #include "evas_render2.h" +// FIXME: Ugly! +#define EFL_CANVAS_FILTER_INTERNAL_PROTECTED +#include "efl_canvas_filter_internal.eo.h" + /* Enable this for extra verbose rendering debug logs */ //#define REND_DBG 1 #define STDOUT_DBG @@ -2737,29 +2741,78 @@ _is_obj_in_rect(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, } #endif +static inline Eina_Bool +_rectangle_inside(Eina_Rectangle *big, Eina_Rectangle *small) +{ + Eina_Rectangle inter = *big; + + if (!eina_rectangle_intersection(&inter, small)) + return EINA_FALSE; + if ((inter.w == small->w) && (inter.h == small->h)) + return EINA_TRUE; + return EINA_FALSE; +} + static Eina_Bool -_snapshot_needs_redraw(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap) +_snapshot_needs_redraw(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap, + Eina_Rectangle *opaque) { + Eina_Bool above = EINA_FALSE, ret = EINA_FALSE; const int x = snap->cur->geometry.x; const int y = snap->cur->geometry.y; const int w = snap->cur->geometry.w; const int h = snap->cur->geometry.h; Evas_Object_Protected_Data *obj; Evas_Active_Entry *ent; + Eina_Rectangle snap_rect = { x, y, w, h }; void *surface; surface = _evas_object_image_surface_get(snap, EINA_FALSE); - if (!surface) return EINA_TRUE; + if (!surface) ret = EINA_TRUE; + memset(opaque, 0, sizeof(*opaque)); EINA_INARRAY_FOREACH(&evas->active_objects, ent) { obj = ent->obj; - if (obj == snap) break; - if (!obj->is_smart && obj->changed && - evas_object_is_in_output_rect(obj->object, obj, x, y, w, h)) - return EINA_TRUE; + if (obj == snap) + { + above = EINA_TRUE; + continue; + } + + if (!above) + { + if (ret) continue; + if (!obj->is_smart && obj->changed && + evas_object_is_in_output_rect(obj->object, obj, x, y, w, h)) + ret = EINA_TRUE; + } + else + { + if (!obj->is_smart && !obj->clip.clipees && + evas_object_is_opaque(obj->object, obj)) + { + Eina_Rectangle cur = { + obj->cur->geometry.x, obj->cur->geometry.y, + obj->cur->geometry.w, obj->cur->geometry.h + }; + + if (!eina_rectangles_intersect(&snap_rect, &cur)) + continue; + + if (!opaque->w || !opaque->h) + *opaque = cur; + else if (_rectangle_inside(&cur, opaque)) + *opaque = cur; + else if (!_rectangle_inside(opaque, &cur)) + { + *opaque = (Eina_Rectangle) { 0, 0, 0, 0 }; + break; + } + } + } } - return EINA_FALSE; + return ret; } static Eina_Bool @@ -3196,7 +3249,7 @@ evas_render_updates_internal(Evas *eo_e, eina_evlog("+render_snapshots", eo_e, 0.0, NULL); for (j = e->snapshot_objects.count - 1; j >= 0; j--) { - Eina_Rectangle output, cr, ur; + Eina_Rectangle output, cr, ur, opaque; obj = eina_array_data_get(&e->snapshot_objects, j); @@ -3208,7 +3261,7 @@ evas_render_updates_internal(Evas *eo_e, EINA_RECTANGLE_SET(&ur, ux, uy, uw, uh); if (eina_rectangle_intersection(&ur, &output) && - _snapshot_needs_redraw(evas, obj)) + _snapshot_needs_redraw(evas, obj, &opaque)) { void *pseudo_canvas; unsigned int restore_offset = offset; @@ -3219,6 +3272,10 @@ evas_render_updates_internal(Evas *eo_e, pseudo_canvas = _evas_object_image_surface_get(obj, EINA_TRUE); + // TODO: List of canvas regions that need redraw + // Add obscure region (make it a list?) + _evas_filter_obscured_region_set(obj, opaque); + RD(0, " SNAPSHOT %s [sfc:%p ur:%d,%d %dx%d]\n", RDNAME(obj), pseudo_canvas, ur.x, ur.y, ur.w, ur.h); ctx = ENFN->context_new(ENDT); clean_them |= evas_render_updates_internal_loop(eo_e, e, pseudo_canvas, ctx, diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index 5efe9e4..a37fe40 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -1281,6 +1281,12 @@ evas_filter_command_transform_add(Evas_Filter_Context *ctx, return cmd; } +void +evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect) +{ + ctx->obscured.real = rect; +} + /* Final target */ Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, @@ -1601,6 +1607,55 @@ _filter_thread_run_cb(void *data) ctx->post_run.cb(ctx, ctx->post_run.data, success); } +static void +_filter_obscured_region_calc(Evas_Filter_Context *ctx) +{ + Eina_Rectangle rect = ctx->obscured.real; + + // left + if (rect.x > 0) + { + rect.x += ctx->pad.calculated.l; + rect.w -= ctx->pad.calculated.l; + } + else + { + rect.w -= (-rect.x); + rect.x = 0; + } + if (rect.w < 0) rect.w = 0; + + // right + if ((rect.x + rect.w) <= ctx->w) + rect.w -= ctx->pad.calculated.r; + else + rect.w = ctx->w - rect.x; + + // top + if (rect.y > 0) + { + rect.y += ctx->pad.calculated.t; + rect.h -= ctx->pad.calculated.t; + } + else + { + rect.h -= (-rect.y); + rect.y = 0; + } + if (rect.h < 0) rect.h = 0; + + // bottom + if ((rect.y + rect.h) <= ctx->h) + rect.h -= ctx->pad.calculated.b; + else + rect.h = ctx->h - rect.y; + + if ((rect.w <= 0) || (rect.h <= 0)) + memset(&rect, 0, sizeof(rect)); + + ctx->obscured.effective = rect; +} + Eina_Bool evas_filter_run(Evas_Filter_Context *ctx) { @@ -1611,6 +1666,8 @@ evas_filter_run(Evas_Filter_Context *ctx) if (!ctx->commands) return EINA_TRUE; + _filter_obscured_region_calc(ctx); + if (ctx->async) { evas_thread_queue_flush(_filter_thread_run_cb, ctx); diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c index 9bebd19..9c14e5d 100644 --- a/src/lib/evas/filters/evas_filter_parser.c +++ b/src/lib/evas/filters/evas_filter_parser.c @@ -324,7 +324,7 @@ struct _Evas_Filter_Program Eina_Inlist /* Buffer */ *buffers; struct { // Note: padding can't be in the state as it's calculated after running Lua - int l, r, t, b; + Evas_Filter_Padding calculated, final; } pad; Efl_Canvas_Filter_State state; Eina_Inlist *data; // Evas_Filter_Data_Binding @@ -2882,21 +2882,22 @@ _buffers_update(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm) EAPI Eina_Bool evas_filter_program_padding_get(Evas_Filter_Program *pgm, - int *l, int *r, int *t, int *b) + Evas_Filter_Padding *out_final, + Evas_Filter_Padding *out_calculated) { Evas_Filter_Instruction *instr; int pl = 0, pr = 0, pt = 0, pb = 0; int maxl = 0, maxr = 0, maxt = 0, maxb = 0; + int setl = 0, setr = 0, sett = 0, setb = 0; + Eina_Bool was_set = EINA_FALSE; Buffer *buf; EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE); - if (pgm->padding_calc || pgm->padding_set) + if (pgm->padding_calc) { - if (l) *l = pgm->pad.l; - if (r) *r = pgm->pad.r; - if (t) *t = pgm->pad.t; - if (b) *b = pgm->pad.b; + if (out_final) *out_final = pgm->pad.final; + if (out_calculated) *out_calculated = pgm->pad.calculated; return EINA_TRUE; } @@ -2909,8 +2910,8 @@ evas_filter_program_padding_get(Evas_Filter_Program *pgm, { if (instr->type == EVAS_FILTER_MODE_PADDING_SET) { - instr->pad.update(pgm, instr, &maxl, &maxr, &maxt, &maxb); - break; + instr->pad.update(pgm, instr, &setl, &setr, &sett, &setb); + was_set = EINA_TRUE; } else if (instr->pad.update) { @@ -2922,16 +2923,23 @@ evas_filter_program_padding_get(Evas_Filter_Program *pgm, } } - pgm->pad.l = maxl; - pgm->pad.r = maxr; - pgm->pad.t = maxt; - pgm->pad.b = maxb; + pgm->pad.calculated.l = maxl; + pgm->pad.calculated.r = maxr; + pgm->pad.calculated.t = maxt; + pgm->pad.calculated.b = maxb; + if (!was_set) + pgm->pad.final = pgm->pad.calculated; + else + { + pgm->pad.final.l = setl; + pgm->pad.final.r = setr; + pgm->pad.final.t = sett; + pgm->pad.final.b = setb; + } pgm->padding_calc = EINA_TRUE; - if (l) *l = maxl; - if (r) *r = maxr; - if (t) *t = maxt; - if (b) *b = maxb; + if (out_final) *out_final = pgm->pad.final; + if (out_calculated) *out_calculated = pgm->pad.calculated; return EINA_TRUE; } @@ -3503,7 +3511,7 @@ evas_filter_context_program_use(Evas_Filter_Context *ctx, _buffers_update(ctx, pgm); // Compute and save padding info - evas_filter_program_padding_get(pgm, &ctx->padl, &ctx->padr, &ctx->padt, &ctx->padb); + evas_filter_program_padding_get(pgm, &ctx->pad.final, &ctx->pad.calculated); dc = ENFN->context_new(ENDT); ENFN->context_color_set(ENDT, dc, 255, 255, 255, 255); diff --git a/src/lib/evas/filters/evas_filter_private.h b/src/lib/evas/filters/evas_filter_private.h index afb89a3..e61b01b 100644 --- a/src/lib/evas/filters/evas_filter_private.h +++ b/src/lib/evas/filters/evas_filter_private.h @@ -111,6 +111,7 @@ typedef enum _Evas_Filter_Interpolation_Mode Evas_Filter_Interpolation_Mode; typedef Evas_Filter_Buffer * (*evas_filter_buffer_scaled_get_func)(Evas_Filter_Context *ctx, Evas_Filter_Buffer *src, unsigned w, unsigned h); + struct _Evas_Filter_Context { Evas_Public_Data *evas; @@ -125,7 +126,16 @@ struct _Evas_Filter_Context // Variables changing at each run int w, h; // Dimensions of the input/output buffers - int padl, padt, padr, padb; // Padding in the current input/output buffers + + struct { + // Padding in the current input/output buffers + Evas_Filter_Padding calculated, final; + } pad; + + struct { + // Useless region: obscured by other objects + Eina_Rectangle real, effective; + } obscured; struct { diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h index 533bc24..34a09c4 100644 --- a/src/lib/evas/include/evas_filter.h +++ b/src/lib/evas/include/evas_filter.h @@ -36,6 +36,7 @@ typedef struct _Evas_Filter_Context Evas_Filter_Context; typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction; typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer; typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding; +typedef struct _Evas_Filter_Padding Evas_Filter_Padding; typedef enum _Evas_Filter_Mode Evas_Filter_Mode; typedef enum _Evas_Filter_Blur_Type Evas_Filter_Blur_Type; typedef enum _Evas_Filter_Channel Evas_Filter_Channel; @@ -124,6 +125,12 @@ enum _Evas_Filter_Transform_Flags EVAS_FILTER_TRANSFORM_VFLIP = 1 }; +/** @internal */ +struct _Evas_Filter_Padding +{ + int l, r, t, b; +}; + #define EFL_CANVAS_FILTER_STATE_DEFAULT { {}, { 255, 255, 255, 255 }, { "default", 0.0 }, {}, 0, 0, 1.0, 0.0 } /* Parser stuff (high level API) */ @@ -131,7 +138,7 @@ EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool in EAPI Eina_Bool evas_filter_program_state_set(Evas_Filter_Program *pgm, const Efl_Canvas_Filter_State *state); EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str); EAPI void evas_filter_program_del(Evas_Filter_Program *pgm); -EAPI Eina_Bool evas_filter_program_padding_get(Evas_Filter_Program *pgm, int *l, int *r, int *t, int *b); +EAPI Eina_Bool evas_filter_program_padding_get(Evas_Filter_Program *pgm, Evas_Filter_Padding *final, Evas_Filter_Padding *calc); EAPI void evas_filter_program_source_set_all(Evas_Filter_Program *pgm, Eina_Hash *sources); void evas_filter_program_data_set_all(Evas_Filter_Program *pgm, Eina_Inlist *data); @@ -145,6 +152,7 @@ void evas_filter_context_proxy_render_all(Evas_Filter_Contex void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data); #define evas_filter_context_autodestroy(ctx) evas_filter_context_post_run_callback_set(ctx, ((Evas_Filter_Cb) evas_filter_context_destroy), ctx) Eina_Bool evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx); +void evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect); int evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, Eina_Bool alpha_only); void *evas_filter_buffer_backing_steal(Evas_Filter_Context *ctx, int bufid); diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 02e14f2..7034da4 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1290,6 +1290,7 @@ struct _Evas_Object_Filter_Data Evas_Filter_Program *chain; Eina_Hash *sources; // Evas_Filter_Proxy_Binding Eina_Inlist *data; // Evas_Filter_Data_Binding + Eina_Rectangle prev_obscured, obscured; void *output; struct { struct { @@ -2034,6 +2035,7 @@ void *efl_input_hold_legacy_info_fill(Efl_Input_Hold *evt, Evas_Event_Flags **pf Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char *key EINA_UNUSED); void *_evas_object_image_surface_get(Evas_Object_Protected_Data *obj, Eina_Bool create); +void _evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj, const Eina_Rectangle rect); Eina_Bool _evas_image_proxy_source_clip_get(const Eo *eo_obj); void _evas_focus_dispatch_event(Evas_Object_Protected_Data *obj, --