forked from enlightenment/efl
evas filters: Force redraw of snapshot if cutout shrank
The situation is clearly visible in the Snapshot test case: increase the radius and a red glow would appear. This is because the snapshot object was not marked as needing redraw and so had no pixels under the opaque rectangle.
This commit is contained in:
parent
a8b6c1cd7f
commit
530399acde
|
@ -27,6 +27,7 @@ struct _Evas_Object_Filter_Data
|
|||
Eina_Hash *sources; // Evas_Filter_Proxy_Binding
|
||||
Eina_Inlist *data; // Evas_Filter_Data_Binding
|
||||
Eina_Rectangle prev_obscured, obscured;
|
||||
Evas_Filter_Padding prev_padding, padding;
|
||||
void *output;
|
||||
struct {
|
||||
struct {
|
||||
|
@ -283,36 +284,31 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
if (!pd->data->chain)
|
||||
{
|
||||
Evas_Filter_Program *pgm;
|
||||
Eina_Bool invalid;
|
||||
|
||||
pgm = evas_filter_program_new(pd->data->name, alpha);
|
||||
evas_filter_program_source_set_all(pgm, pd->data->sources);
|
||||
evas_filter_program_data_set_all(pgm, pd->data->data);
|
||||
_evas_filter_state_set_internal(pgm, pd);
|
||||
if (!evas_filter_program_parse(pgm, pd->data->code))
|
||||
invalid = !evas_filter_program_parse(pgm, pd->data->code);
|
||||
if (invalid)
|
||||
{
|
||||
ERR("Filter program parsing failed");
|
||||
evas_filter_program_del(pgm);
|
||||
|
||||
if (!pd->data->invalid)
|
||||
{
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
fcow->invalid = EINA_TRUE;
|
||||
FCOW_END(fcow, pd);
|
||||
}
|
||||
|
||||
return EINA_FALSE;
|
||||
pgm = NULL;
|
||||
}
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
if (!invalid) evas_filter_program_padding_get(pgm, NULL, &fcow->padding);
|
||||
fcow->chain = pgm;
|
||||
fcow->invalid = EINA_FALSE;
|
||||
fcow->invalid = invalid;
|
||||
FCOW_END(fcow, pd);
|
||||
if (invalid) return EINA_FALSE;
|
||||
}
|
||||
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)
|
||||
DBG("Filter redraw by object content change!");
|
||||
|
@ -441,6 +437,8 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
fcow->changed = EINA_FALSE;
|
||||
fcow->async = do_async;
|
||||
fcow->prev_obscured = fcow->obscured;
|
||||
fcow->prev_padding = fcow->padding;
|
||||
fcow->padding = pad;
|
||||
fcow->invalid = EINA_FALSE;
|
||||
FCOW_END(fcow, pd);
|
||||
|
||||
|
@ -470,6 +468,7 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_F
|
|||
Evas_Object_Protected_Data *obj;
|
||||
Evas_Filter_Program *pgm = NULL;
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
Eina_Bool invalid = pd->data->invalid;
|
||||
Eina_Bool alpha;
|
||||
|
||||
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
|
@ -494,16 +493,21 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_F
|
|||
evas_filter_program_source_set_all(pgm, fcow->sources);
|
||||
evas_filter_program_data_set_all(pgm, fcow->data);
|
||||
_evas_filter_state_set_internal(pgm, pd);
|
||||
if (!evas_filter_program_parse(pgm, code))
|
||||
invalid = !evas_filter_program_parse(pgm, code);
|
||||
if (invalid)
|
||||
{
|
||||
ERR("Parsing failed!");
|
||||
evas_filter_program_del(pgm);
|
||||
pgm = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
evas_filter_program_padding_get(pgm, NULL, &fcow->padding);
|
||||
}
|
||||
}
|
||||
fcow->chain = pgm;
|
||||
fcow->changed = EINA_TRUE;
|
||||
fcow->invalid = (pgm == NULL);
|
||||
fcow->invalid = invalid;
|
||||
eina_stringshare_replace(&fcow->code, code);
|
||||
}
|
||||
FCOW_END(fcow, pd);
|
||||
|
@ -526,6 +530,7 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_source_set(Eo *eo_obj, Evas_Fi
|
|||
Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
|
||||
Evas_Object_Protected_Data *source = NULL;
|
||||
Evas_Object_Filter_Data *fcow = NULL;
|
||||
Eina_Bool invalid = pd->data->invalid;
|
||||
|
||||
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
if (eo_source)
|
||||
|
@ -589,14 +594,15 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_source_set(Eo *eo_obj, Evas_Fi
|
|||
eina_hash_add(fcow->sources, pb->name, pb);
|
||||
evas_filter_program_source_set_all(fcow->chain, fcow->sources);
|
||||
evas_filter_program_data_set_all(fcow->chain, fcow->data);
|
||||
evas_filter_program_parse(fcow->chain, fcow->code);
|
||||
invalid = !evas_filter_program_parse(fcow->chain, fcow->code);
|
||||
if (!invalid) evas_filter_program_padding_get(fcow->chain, NULL, &fcow->padding);
|
||||
|
||||
// Update object
|
||||
update:
|
||||
if (fcow)
|
||||
{
|
||||
fcow->changed = EINA_TRUE;
|
||||
fcow->invalid = EINA_FALSE;
|
||||
fcow->invalid = invalid;
|
||||
FCOW_END(fcow, pd);
|
||||
}
|
||||
|
||||
|
@ -755,6 +761,7 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_data_set(Eo *eo_obj, Evas_Filt
|
|||
{
|
||||
Evas_Filter_Data_Binding *db, *found = NULL;
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
Eina_Bool invalid = pd->data->invalid;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(pd->data);
|
||||
EINA_SAFETY_ON_NULL_RETURN(name);
|
||||
|
@ -789,12 +796,13 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_data_set(Eo *eo_obj, Evas_Filt
|
|||
db->execute = execute;
|
||||
fcow->data = eina_inlist_append(fcow->data, EINA_INLIST_GET(db));
|
||||
}
|
||||
fcow->invalid = EINA_FALSE;
|
||||
if (fcow->chain)
|
||||
{
|
||||
evas_filter_program_data_set_all(fcow->chain, fcow->data);
|
||||
evas_filter_program_parse(fcow->chain, fcow->code);
|
||||
invalid = !evas_filter_program_parse(fcow->chain, fcow->code);
|
||||
if (!invalid) evas_filter_program_padding_get(fcow->chain, NULL, &fcow->padding);
|
||||
}
|
||||
fcow->invalid = invalid;
|
||||
fcow->changed = 1;
|
||||
}
|
||||
FCOW_END(fcow, pd);
|
||||
|
@ -832,15 +840,18 @@ _efl_canvas_filter_internal_filter_output_buffer_get(Eo *obj EINA_UNUSED, Evas_F
|
|||
return pd->data->output;
|
||||
}
|
||||
|
||||
void
|
||||
Eina_Bool
|
||||
_evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj,
|
||||
const Eina_Rectangle rect)
|
||||
{
|
||||
Evas_Filter_Data *pd;
|
||||
Evas_Object_Filter_Data *fcow;
|
||||
Evas_Filter_Data *pd;
|
||||
Eina_Rectangle prev;
|
||||
|
||||
pd = efl_data_scope_get(obj->object, MY_CLASS);
|
||||
if (!pd->data) return;
|
||||
if (!pd->data) return EINA_FALSE;
|
||||
|
||||
prev = pd->data->prev_obscured;
|
||||
|
||||
fcow = FCOW_BEGIN(pd);
|
||||
if ((rect.w <= 0) || (rect.h <= 0))
|
||||
|
@ -853,6 +864,19 @@ _evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj,
|
|||
fcow->obscured.h = rect.h;
|
||||
}
|
||||
FCOW_END(fcow, pd);
|
||||
|
||||
// Snapshot objects need to be redrawn if the padding has increased
|
||||
if ((pd->data->prev_padding.l < pd->data->padding.l) ||
|
||||
(pd->data->prev_padding.r < pd->data->padding.r) ||
|
||||
(pd->data->prev_padding.t < pd->data->padding.t) ||
|
||||
(pd->data->prev_padding.b < pd->data->padding.b))
|
||||
return EINA_TRUE;
|
||||
|
||||
// Snapshot objects need to be redrawn if the obscured region has shrank
|
||||
if (!_evas_eina_rectangle_inside(&prev, &pd->data->obscured))
|
||||
return EINA_TRUE;
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -2747,18 +2747,6 @@ _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 void
|
||||
_snapshot_redraw_update(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap)
|
||||
{
|
||||
|
@ -2769,16 +2757,23 @@ _snapshot_redraw_update(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap
|
|||
const int h = snap->cur->geometry.h;
|
||||
Evas_Object_Protected_Data *obj;
|
||||
Evas_Active_Entry *ent;
|
||||
Eina_Rectangle snap_rect = { x, y, w, h };
|
||||
Eina_Rectangle snap_clip, snap_rect = { x, y, w, h };
|
||||
Eina_Rectangle opaque = {};
|
||||
void *surface;
|
||||
|
||||
// FIXME: Use evas' standard rectangle logic instead of this bad algo
|
||||
// FIXME: This walks ALL the objects in the canvas to find the opaque region
|
||||
// TODO: Improve opaque region support, maybe have more than one
|
||||
// TODO: Also list redraw regions (partial updates)
|
||||
|
||||
if (!evas_object_is_visible(snap->object, snap)) return;
|
||||
|
||||
evas_object_clip_recalc(snap);
|
||||
snap_clip.x = snap->cur->cache.clip.x;
|
||||
snap_clip.y = snap->cur->cache.clip.y;
|
||||
snap_clip.w = snap->cur->cache.clip.w;
|
||||
snap_clip.h = snap->cur->cache.clip.h;
|
||||
|
||||
surface = _evas_object_image_surface_get(snap, EINA_FALSE);
|
||||
if (!surface) need_redraw = EINA_TRUE;
|
||||
if (snap->changed) add_rect = EINA_TRUE;
|
||||
|
@ -2788,7 +2783,6 @@ _snapshot_redraw_update(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap
|
|||
obj = ent->obj;
|
||||
if (obj == snap)
|
||||
{
|
||||
if (!need_redraw) break;
|
||||
above = EINA_TRUE;
|
||||
continue;
|
||||
}
|
||||
|
@ -2811,35 +2805,28 @@ _snapshot_redraw_update(Evas_Public_Data *evas, Evas_Object_Protected_Data *snap
|
|||
};
|
||||
|
||||
if ((opaque.w * opaque.h) < (cur.w * cur.h))
|
||||
{
|
||||
opaque = cur;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!eina_rectangles_intersect(&snap_rect, &cur))
|
||||
opaque = cur;
|
||||
else if (!eina_rectangles_intersect(&snap_rect, &cur))
|
||||
continue;
|
||||
else if (!opaque.w || !opaque.h)
|
||||
opaque = cur;
|
||||
else if (_evas_eina_rectangle_inside(&cur, &opaque))
|
||||
opaque = cur;
|
||||
//else if (!_evas_eina_rectangle_inside(&opaque, &cur))
|
||||
|
||||
if (!opaque.w || !opaque.h)
|
||||
opaque = cur;
|
||||
else if (_rectangle_inside(&cur, &opaque))
|
||||
opaque = cur;
|
||||
//else if (!_rectangle_inside(&opaque, &cur))
|
||||
if (_evas_eina_rectangle_inside(&opaque, &snap_clip))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_evas_filter_obscured_region_set(snap, opaque);
|
||||
need_redraw |= _evas_filter_obscured_region_set(snap, opaque);
|
||||
snap->snapshot_needs_redraw |= need_redraw;
|
||||
|
||||
if (add_rect || need_redraw)
|
||||
{
|
||||
// FIXME: Only add necessary rects
|
||||
// Note that with filters this is extremely tricky: a simple color
|
||||
// change would mean redraw all. Also blurs, displace, etc... need
|
||||
// to expand by the cutout_margin (filter padding).
|
||||
ENFN->output_redraws_rect_add(ENDT,
|
||||
snap->cur->geometry.x, snap->cur->geometry.y,
|
||||
snap->cur->geometry.w, snap->cur->geometry.h);
|
||||
// FIXME: Only add necessary rects (if object itself hasn't changed)
|
||||
ENFN->output_redraws_rect_add(ENDT, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -327,6 +327,18 @@ evas_common_draw_context_cache_update(RGBA_Draw_Context *dc)
|
|||
}
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_evas_eina_rectangle_inside(const Eina_Rectangle *big, const 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;
|
||||
}
|
||||
|
||||
#define _EVAS_COLOR_CLAMP(x, y) do { \
|
||||
if (x > y) { x = y; bad = 1; } \
|
||||
if (x < 0) { x = 0; bad = 1; } } while (0)
|
||||
|
|
|
@ -2012,7 +2012,7 @@ Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char *ke
|
|||
|
||||
void *_evas_object_image_surface_get(Evas_Object_Protected_Data *obj, Eina_Bool create);
|
||||
void _evas_filter_radius_get(Evas_Object_Protected_Data *obj, int *l, int *r, int *t, int *b);
|
||||
void _evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj, const Eina_Rectangle rect);
|
||||
Eina_Bool _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,
|
||||
|
|
Loading…
Reference in New Issue