forked from enlightenment/efl
filters: Safety++
This is an attempt at fixing crashes in empc. Test scenario: ELM_ACCEL="" elementary_test -to "Gfx Filters" And mouse scroll like crazy in the spinner. @fix
This commit is contained in:
parent
743c80ad8b
commit
c0514d948a
|
@ -120,13 +120,13 @@ _filter_end_sync(Evas_Filter_Context *ctx, Evas_Object_Protected_Data *obj,
|
||||||
if (previous)
|
if (previous)
|
||||||
ENFN->image_free(ENC, previous);
|
ENFN->image_free(ENC, previous);
|
||||||
|
|
||||||
if (destroy)
|
if (destroy && (ctx == pd->data->context))
|
||||||
{
|
{
|
||||||
evas_filter_context_destroy(ctx);
|
evas_filter_context_unref(ctx); // local ref
|
||||||
ctx = NULL;
|
FCOW_WRITE(pd, context, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
FCOW_WRITE(pd, context, ctx);
|
evas_filter_context_unref(ctx); // run ref
|
||||||
efl_unref(eo_obj);
|
efl_unref(eo_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
||||||
if ((!pd->data->reuse) || (was_async != do_async) ||
|
if ((!pd->data->reuse) || (was_async != do_async) ||
|
||||||
(prev_w != W) || (prev_h != H))
|
(prev_w != W) || (prev_h != H))
|
||||||
{
|
{
|
||||||
evas_filter_context_destroy(filter);
|
evas_filter_context_unref(filter);
|
||||||
FCOW_WRITE(pd, context, NULL);
|
FCOW_WRITE(pd, context, NULL);
|
||||||
filter = NULL;
|
filter = NULL;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +390,7 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
||||||
ok = evas_filter_context_program_use(engine, output, filter, pd->data->chain, EINA_TRUE, X, Y);
|
ok = evas_filter_context_program_use(engine, output, filter, pd->data->chain, EINA_TRUE, X, Y);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
evas_filter_context_destroy(filter);
|
evas_filter_context_unref(filter);
|
||||||
FCOW_WRITE(pd, context, NULL);
|
FCOW_WRITE(pd, context, NULL);
|
||||||
filter = NULL;
|
filter = NULL;
|
||||||
}
|
}
|
||||||
|
@ -405,8 +405,9 @@ evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
||||||
if (!filter || !ok)
|
if (!filter || !ok)
|
||||||
{
|
{
|
||||||
ERR("Parsing failed?");
|
ERR("Parsing failed?");
|
||||||
evas_filter_context_destroy(filter);
|
evas_filter_context_unref(filter);
|
||||||
FCOW_WRITE(pd, invalid, EINA_TRUE);
|
FCOW_WRITE(pd, invalid, EINA_TRUE);
|
||||||
|
FCOW_WRITE(pd, context, NULL);
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,8 +475,8 @@ _efl_canvas_filter_internal_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_F
|
||||||
{
|
{
|
||||||
fcow->obj = obj;
|
fcow->obj = obj;
|
||||||
|
|
||||||
if (fcow->context)
|
evas_filter_context_unref(fcow->context);
|
||||||
evas_filter_context_destroy(fcow->context);
|
fcow->context = NULL;
|
||||||
|
|
||||||
// Parse filter program
|
// Parse filter program
|
||||||
evas_filter_program_del(fcow->chain);
|
evas_filter_program_del(fcow->chain);
|
||||||
|
@ -710,6 +711,7 @@ EOLIAN static void
|
||||||
_efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *pd)
|
_efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *pd)
|
||||||
{
|
{
|
||||||
Evas_Object_Protected_Data *obj;
|
Evas_Object_Protected_Data *obj;
|
||||||
|
Evas_Object_Filter_Data *fcow;
|
||||||
Evas_Filter_Data_Binding *db;
|
Evas_Filter_Data_Binding *db;
|
||||||
Evas_Public_Data *e;
|
Evas_Public_Data *e;
|
||||||
Eina_Inlist *il;
|
Eina_Inlist *il;
|
||||||
|
@ -721,7 +723,10 @@ _efl_canvas_filter_internal_efl_object_destructor(Eo *eo_obj, Evas_Filter_Data *
|
||||||
e = obj->layer->evas;
|
e = obj->layer->evas;
|
||||||
|
|
||||||
if (pd->data->context)
|
if (pd->data->context)
|
||||||
evas_filter_context_destroy(pd->data->context);
|
{
|
||||||
|
evas_filter_context_unref(pd->data->context);
|
||||||
|
FCOW_WRITE(pd, context, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (pd->data->output)
|
if (pd->data->output)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1043,7 +1043,11 @@ _item_free(Evas_Public_Data *evas,
|
||||||
ti->gfx_filter = NULL;
|
ti->gfx_filter = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ti->gfx_filter->ti = NULL;
|
{
|
||||||
|
evas_filter_context_unref(ti->gfx_filter->ctx);
|
||||||
|
ti->gfx_filter->ctx = NULL;
|
||||||
|
ti->gfx_filter->ti = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -12958,6 +12962,7 @@ evas_object_textblock_free(Evas_Object *eo_obj)
|
||||||
EINA_INLIST_FREE(o->gfx_filter.programs, prg)
|
EINA_INLIST_FREE(o->gfx_filter.programs, prg)
|
||||||
{
|
{
|
||||||
EINA_INLIST_REMOVE(o->gfx_filter.programs, prg);
|
EINA_INLIST_REMOVE(o->gfx_filter.programs, prg);
|
||||||
|
evas_filter_program_del(prg->pgm);
|
||||||
eina_stringshare_del(prg->name);
|
eina_stringshare_del(prg->name);
|
||||||
eina_stringshare_del(prg->code);
|
eina_stringshare_del(prg->code);
|
||||||
free(prg);
|
free(prg);
|
||||||
|
@ -13035,13 +13040,20 @@ _filter_sync_end(Evas_Filter_Context *ctx, Eina_Bool success)
|
||||||
if (filter->ti->parent.format->gfx_filter)
|
if (filter->ti->parent.format->gfx_filter)
|
||||||
filter->ti->parent.format->gfx_filter->invalid = !success;
|
filter->ti->parent.format->gfx_filter->invalid = !success;
|
||||||
// else just avoid sigsegv
|
// else just avoid sigsegv
|
||||||
filter->ctx = NULL;
|
if (filter->ctx == ctx)
|
||||||
|
{
|
||||||
|
// release local ref
|
||||||
|
evas_filter_context_unref(ctx);
|
||||||
|
filter->ctx = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free(filter);
|
free(filter);
|
||||||
}
|
}
|
||||||
evas_filter_context_destroy(ctx);
|
|
||||||
|
// release run ref
|
||||||
|
evas_filter_context_unref(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -13158,7 +13170,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
Eina_List *shadows = NULL;
|
Eina_List *shadows = NULL;
|
||||||
Eina_List *glows = NULL;
|
Eina_List *glows = NULL;
|
||||||
Eina_List *outlines = NULL;
|
Eina_List *outlines = NULL;
|
||||||
Eina_List *gfx_filters = NULL, *li;
|
Eina_List *gfx_filters = NULL;
|
||||||
void *context_save = context;
|
void *context_save = context;
|
||||||
int strikethrough_thickness, underline_thickness, underline_position;
|
int strikethrough_thickness, underline_thickness, underline_position;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -13448,7 +13460,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
* in "_text_item_update_sizes" should not modify one without the other. */
|
* in "_text_item_update_sizes" should not modify one without the other. */
|
||||||
|
|
||||||
/* gfx filters preparation */
|
/* gfx filters preparation */
|
||||||
EINA_LIST_FOREACH(gfx_filters, li, itr)
|
EINA_LIST_FREE(gfx_filters, itr)
|
||||||
{
|
{
|
||||||
Efl_Canvas_Filter_State state = EFL_CANVAS_FILTER_STATE_DEFAULT;
|
Efl_Canvas_Filter_State state = EFL_CANVAS_FILTER_STATE_DEFAULT;
|
||||||
Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(itr);
|
Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(itr);
|
||||||
|
@ -13509,7 +13521,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
ok = evas_filter_context_program_use(engine, output, ctx, pgm, EINA_FALSE, 0, 0);
|
ok = evas_filter_context_program_use(engine, output, ctx, pgm, EINA_FALSE, 0, 0);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
evas_filter_context_destroy(ctx);
|
evas_filter_context_unref(ctx);
|
||||||
filter->invalid = EINA_TRUE;
|
filter->invalid = EINA_TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -13524,6 +13536,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
evas_filter_context_proxy_render_all(ctx, eo_obj, output, EINA_FALSE);
|
evas_filter_context_proxy_render_all(ctx, eo_obj, output, EINA_FALSE);
|
||||||
evas_filter_context_buffers_allocate_all(ctx);
|
evas_filter_context_buffers_allocate_all(ctx);
|
||||||
evas_filter_target_set(ctx, context, surface, target.x, target.y, NULL);
|
evas_filter_target_set(ctx, context, surface, target.x, target.y, NULL);
|
||||||
|
if (ti->gfx_filter->ctx)
|
||||||
|
evas_filter_context_unref(ti->gfx_filter->ctx);
|
||||||
ti->gfx_filter->ctx = ctx;
|
ti->gfx_filter->ctx = ctx;
|
||||||
ti->gfx_filter->do_async = do_async;
|
ti->gfx_filter->do_async = do_async;
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,9 @@ static void _filter_buffer_unlock_all(Evas_Filter_Context *ctx);
|
||||||
|
|
||||||
/* Main functions */
|
/* Main functions */
|
||||||
|
|
||||||
|
#define _free(ptr) free(ptr)
|
||||||
|
//eina_freeq_ptr_main_add(ptr, NULL, sizeof(*ptr))
|
||||||
|
|
||||||
Evas_Filter_Context *
|
Evas_Filter_Context *
|
||||||
evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data)
|
evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data)
|
||||||
{
|
{
|
||||||
|
@ -55,6 +58,7 @@ evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data
|
||||||
ctx->user_data = user_data;
|
ctx->user_data = user_data;
|
||||||
ctx->buffer_scaled_get = &evas_filter_buffer_scaled_get;
|
ctx->buffer_scaled_get = &evas_filter_buffer_scaled_get;
|
||||||
ctx->gl = (ENFN->gl_surface_read_pixels != NULL);
|
ctx->gl = (ENFN->gl_surface_read_pixels != NULL);
|
||||||
|
ctx->refcount = 1;
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
@ -205,26 +209,39 @@ _context_destroy(void *data)
|
||||||
{
|
{
|
||||||
Evas_Filter_Context *ctx = data;
|
Evas_Filter_Context *ctx = data;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN(ctx->refcount == 0);
|
||||||
evas_filter_context_clear(ctx, EINA_FALSE);
|
evas_filter_context_clear(ctx, EINA_FALSE);
|
||||||
free(ctx);
|
_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evas_filter_context_ref(Evas_Filter_Context *ctx)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
|
||||||
|
|
||||||
|
#ifdef FILTERS_DEBUG
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_main_loop_is(), -1);
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(ctx->refcount > 0, -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (++ctx->refcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
evas_filter_context_destroy(Evas_Filter_Context *ctx)
|
evas_filter_context_unref(Evas_Filter_Context *ctx)
|
||||||
{
|
{
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
|
|
||||||
#ifdef FILTERS_DEBUG
|
#ifdef FILTERS_DEBUG
|
||||||
EINA_SAFETY_ON_FALSE_RETURN(eina_main_loop_is());
|
EINA_SAFETY_ON_FALSE_RETURN(eina_main_loop_is());
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN(ctx->refcount > 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ctx->delete_me) return;
|
if ((--ctx->refcount) != 0) return;
|
||||||
ctx->delete_me = EINA_TRUE;
|
|
||||||
|
|
||||||
if (ctx->running)
|
if (!ctx->running)
|
||||||
evas_post_render_job_add(ctx->evas, _context_destroy, ctx);
|
|
||||||
else
|
|
||||||
_context_destroy(ctx);
|
_context_destroy(ctx);
|
||||||
|
// else: post_run_cb will be called
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -509,7 +526,7 @@ _buffer_alloc_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only,
|
||||||
if (!fb->buffer)
|
if (!fb->buffer)
|
||||||
{
|
{
|
||||||
ERR("Failed to create ector buffer!");
|
ERR("Failed to create ector buffer!");
|
||||||
free(fb);
|
_free(fb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +540,7 @@ _buffer_free(Evas_Filter_Buffer *fb)
|
||||||
_filter_buffer_backing_free(fb);
|
_filter_buffer_backing_free(fb);
|
||||||
eina_stringshare_del(fb->source_name);
|
eina_stringshare_del(fb->source_name);
|
||||||
efl_unref(fb->source);
|
efl_unref(fb->source);
|
||||||
free(fb);
|
_free(fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
Evas_Filter_Buffer *
|
Evas_Filter_Buffer *
|
||||||
|
@ -627,10 +644,10 @@ _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd)
|
||||||
ctx->commands = eina_inlist_remove(ctx->commands, EINA_INLIST_GET(cmd));
|
ctx->commands = eina_inlist_remove(ctx->commands, EINA_INLIST_GET(cmd));
|
||||||
switch (cmd->mode)
|
switch (cmd->mode)
|
||||||
{
|
{
|
||||||
case EVAS_FILTER_MODE_CURVE: free(cmd->curve.data); break;
|
case EVAS_FILTER_MODE_CURVE: _free(cmd->curve.data); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
free(cmd);
|
_free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Evas_Filter_Buffer *
|
Evas_Filter_Buffer *
|
||||||
|
@ -1334,7 +1351,7 @@ evas_filter_command_curve_add(Evas_Filter_Context *ctx,
|
||||||
cmd = _command_new(ctx, EVAS_FILTER_MODE_CURVE, in, NULL, out);
|
cmd = _command_new(ctx, EVAS_FILTER_MODE_CURVE, in, NULL, out);
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
{
|
{
|
||||||
free(copy);
|
_free(copy);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1559,7 +1576,7 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
|
||||||
ctx->target.color_use = EINA_FALSE;
|
ctx->target.color_use = EINA_FALSE;
|
||||||
ctx->target.rop = ENFN->context_render_op_get(ENC, draw_context);
|
ctx->target.rop = ENFN->context_render_op_get(ENC, draw_context);
|
||||||
|
|
||||||
free(ctx->target.map);
|
_free(ctx->target.map);
|
||||||
if (!map) ctx->target.map = NULL;
|
if (!map) ctx->target.map = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1820,9 +1837,7 @@ end:
|
||||||
ctx->running = EINA_FALSE;
|
ctx->running = EINA_FALSE;
|
||||||
DEBUG_TIME_END();
|
DEBUG_TIME_END();
|
||||||
|
|
||||||
if (ctx->post_run.cb)
|
ctx->post_run.cb(ctx, ctx->post_run.data, ok);
|
||||||
ctx->post_run.cb(ctx, ctx->post_run.data, ok);
|
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1840,7 +1855,7 @@ _filter_thread_run_cb(void *data)
|
||||||
Filter_Thread_Data *ftd = data;
|
Filter_Thread_Data *ftd = data;
|
||||||
|
|
||||||
_filter_chain_run(ftd->engine, ftd->output, ftd->ctx);
|
_filter_chain_run(ftd->engine, ftd->output, ftd->ctx);
|
||||||
free(ftd);
|
_free(ftd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1895,6 +1910,7 @@ _filter_obscured_region_calc(Evas_Filter_Context *ctx)
|
||||||
Eina_Bool
|
Eina_Bool
|
||||||
evas_filter_context_run(void *engine, void *output, Evas_Filter_Context *ctx)
|
evas_filter_context_run(void *engine, void *output, Evas_Filter_Context *ctx)
|
||||||
{
|
{
|
||||||
|
evas_filter_context_ref(ctx);
|
||||||
_filter_obscured_region_calc(ctx);
|
_filter_obscured_region_calc(ctx);
|
||||||
|
|
||||||
ctx->run_count++;
|
ctx->run_count++;
|
||||||
|
@ -1903,9 +1919,7 @@ evas_filter_context_run(void *engine, void *output, Evas_Filter_Context *ctx)
|
||||||
{
|
{
|
||||||
Filter_Thread_Data *ftd;
|
Filter_Thread_Data *ftd;
|
||||||
|
|
||||||
ftd = calloc(1, sizeof (Filter_Thread_Data));
|
ftd = calloc(1, sizeof(*ftd));
|
||||||
if (!ftd) return EINA_FALSE;
|
|
||||||
|
|
||||||
ftd->engine = engine;
|
ftd->engine = engine;
|
||||||
ftd->output = output;
|
ftd->output = output;
|
||||||
ftd->ctx = ctx;
|
ftd->ctx = ctx;
|
||||||
|
|
|
@ -160,10 +160,10 @@ struct _Evas_Filter_Context
|
||||||
Eina_Bool color_use : 1;
|
Eina_Bool color_use : 1;
|
||||||
} target;
|
} target;
|
||||||
|
|
||||||
int run_count;
|
short run_count;
|
||||||
|
short refcount;
|
||||||
|
|
||||||
Eina_Bool running : 1;
|
Eina_Bool running : 1;
|
||||||
Eina_Bool delete_me : 1;
|
|
||||||
Eina_Bool async : 1;
|
Eina_Bool async : 1;
|
||||||
Eina_Bool has_proxies : 1;
|
Eina_Bool has_proxies : 1;
|
||||||
Eina_Bool gl : 1;
|
Eina_Bool gl : 1;
|
||||||
|
|
|
@ -150,11 +150,11 @@ Evas_Filter_Context *evas_filter_context_new(Evas_Public_Data *evas, Eina_Bo
|
||||||
void *evas_filter_context_data_get(Evas_Filter_Context *ctx);
|
void *evas_filter_context_data_get(Evas_Filter_Context *ctx);
|
||||||
Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx);
|
Eina_Bool evas_filter_context_async_get(Evas_Filter_Context *ctx);
|
||||||
void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H);
|
void evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H);
|
||||||
void evas_filter_context_destroy(Evas_Filter_Context *ctx);
|
int evas_filter_context_ref(Evas_Filter_Context *ctx);
|
||||||
|
void evas_filter_context_unref(Evas_Filter_Context *ctx);
|
||||||
Eina_Bool evas_filter_context_program_use(void *engine, void *output, Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse, int object_x, int object_y);
|
Eina_Bool evas_filter_context_program_use(void *engine, void *output, Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse, int object_x, int object_y);
|
||||||
void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, void *output, Eina_Bool do_async);
|
void evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, void *output, Eina_Bool do_async);
|
||||||
void evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
|
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);
|
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);
|
void evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue