forked from enlightenment/efl
evas: Fix unsafe code in previous patches (tb filters)
This also reduces the overhead required per text item when there is no filter.
This commit is contained in:
parent
13c62c10e1
commit
59bda411b9
|
@ -237,6 +237,12 @@ typedef struct _Efl_Canvas_Text_Filter_Post_Render Efl_Canvas_Text_Filter_Post_R
|
|||
* Filter name - code database
|
||||
*/
|
||||
typedef struct _Efl_Canvas_Text_Filter_Program Efl_Canvas_Text_Filter_Program;
|
||||
/**
|
||||
* @internal
|
||||
* @typedef Text_Item_Filter
|
||||
* Text item filter properties (run context, output buffer, ...)
|
||||
*/
|
||||
typedef struct _Text_Item_Filter Text_Item_Filter;
|
||||
/**
|
||||
* @internal
|
||||
* @def IS_AT_END(ti, ind)
|
||||
|
@ -437,8 +443,7 @@ struct _Evas_Object_Textblock_Text_Item
|
|||
Evas_Object_Textblock_Item parent; /**< Textblock item. */
|
||||
Evas_Text_Props text_props; /**< Props for this item. */
|
||||
Evas_Coord x_adjustment; /**< Used to indicate by how much we adjusted sizes */
|
||||
Evas_Filter_Context *gfx_filter_ctx; /* temp variable FIXME */
|
||||
void *gfx_buffer; /* FIXME */
|
||||
Text_Item_Filter *gfx_filter;
|
||||
};
|
||||
|
||||
struct _Evas_Object_Textblock_Format_Item
|
||||
|
@ -452,6 +457,15 @@ struct _Evas_Object_Textblock_Format_Item
|
|||
Eina_Bool formatme : 1; /**< EINA_TRUE if format required, else EINA_FALSE */
|
||||
};
|
||||
|
||||
struct _Text_Item_Filter
|
||||
{
|
||||
Evas_Object_Textblock_Text_Item *ti; /**< associated text item. if null, it was deleted */
|
||||
Evas_Filter_Context *ctx; /**< running context for the filter */
|
||||
Evas_Public_Data *evas; /**< evas instance */
|
||||
void *output; /**< output rgba buffer for this text item (engine image) */
|
||||
Eina_Bool do_async; /**< do_async flag when running the filter */
|
||||
};
|
||||
|
||||
struct _Efl_Canvas_Text_Filter
|
||||
{
|
||||
Eina_Stringshare *name;
|
||||
|
@ -948,31 +962,14 @@ _format_unref_free(const Evas_Object *eo_obj, Evas_Object_Textblock_Format *fmt)
|
|||
free(fmt);
|
||||
}
|
||||
|
||||
typedef struct _Post_Render_Image_Unref_Job
|
||||
{
|
||||
Evas_Public_Data *evas;
|
||||
void *image;
|
||||
} Post_Render_Image_Unref_Job;
|
||||
|
||||
static void
|
||||
_image_post_render_unref_cb(void *data)
|
||||
{
|
||||
Post_Render_Image_Unref_Job *job = data;
|
||||
|
||||
job->evas->engine.func->image_free(job->evas->engine.data.output, job->image);
|
||||
free(job);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_image_safe_unref(Evas_Public_Data *e, void *image)
|
||||
_image_safe_unref(Evas_Public_Data *e, void *image, Eina_Bool async)
|
||||
{
|
||||
Post_Render_Image_Unref_Job *job;
|
||||
|
||||
if (!image) return;
|
||||
job = calloc(1, sizeof(*job));
|
||||
job->evas = e;
|
||||
job->image = image;
|
||||
evas_post_render_job_add(e, _image_post_render_unref_cb, job);
|
||||
if (async)
|
||||
evas_unref_queue_image_put(e, image);
|
||||
else
|
||||
e->engine.func->image_free(e->engine.data.output, image);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -990,15 +987,21 @@ _item_free(const Evas_Object *eo_obj, Evas_Object_Textblock_Line *ln, Evas_Objec
|
|||
Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
|
||||
|
||||
evas_common_text_props_content_unref(&ti->text_props);
|
||||
if (ti->gfx_filter_ctx)
|
||||
if (EINA_UNLIKELY(ti->gfx_filter != NULL))
|
||||
{
|
||||
WRN("filter context still alive? (ignored)");
|
||||
}
|
||||
if (ti->gfx_buffer)
|
||||
{
|
||||
Evas_Public_Data *e = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS);
|
||||
_image_safe_unref(e, ti->gfx_buffer);
|
||||
ti->gfx_buffer = NULL;
|
||||
if (ti->gfx_filter->output)
|
||||
{
|
||||
Evas *eo_evas = evas_object_evas_get(eo_obj);
|
||||
Evas_Public_Data *evas = efl_data_scope_get(eo_evas, EVAS_CANVAS_CLASS);
|
||||
Eina_Bool async = ti->gfx_filter->do_async;
|
||||
|
||||
_image_safe_unref(evas, ti->gfx_filter->output, async);
|
||||
ti->gfx_filter->output = NULL;
|
||||
}
|
||||
if (!ti->gfx_filter->ctx)
|
||||
free(ti->gfx_filter);
|
||||
else
|
||||
ti->gfx_filter->ti = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -12943,42 +12946,46 @@ evas_object_textblock_free(Evas_Object *eo_obj)
|
|||
free(o->utf8);
|
||||
}
|
||||
|
||||
static Evas_Filter_Context *
|
||||
static inline Evas_Filter_Context *
|
||||
_filter_context_get(Evas_Object_Textblock_Text_Item *ti)
|
||||
{
|
||||
// FIXME: optimize this (memory usage)
|
||||
if (!ti) return NULL;
|
||||
return ti->gfx_filter_ctx;
|
||||
if (!ti || !ti->gfx_filter) return NULL;
|
||||
return ti->gfx_filter->ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
_filter_context_set(Evas_Object_Textblock_Text_Item *ti, Evas_Filter_Context *ctx)
|
||||
static inline void *
|
||||
_filter_output_get(Evas_Object_Textblock_Text_Item *ti)
|
||||
{
|
||||
if (!ti) return;
|
||||
ti->gfx_filter_ctx = ctx;
|
||||
if (!ti || !ti->gfx_filter) return NULL;
|
||||
return ti->gfx_filter->output;
|
||||
}
|
||||
|
||||
static void
|
||||
_filter_sync_end(Evas_Filter_Context *ctx, Eina_Bool success)
|
||||
{
|
||||
Evas_Object_Textblock_Text_Item *ti;
|
||||
Efl_Canvas_Text_Filter *filter;
|
||||
void *buffer;
|
||||
Text_Item_Filter *filter;
|
||||
Eina_Bool async;
|
||||
|
||||
ti = evas_filter_context_data_get(ctx);
|
||||
filter = ti->parent.format->gfx_filter;
|
||||
filter = evas_filter_context_data_get(ctx);
|
||||
EINA_SAFETY_ON_NULL_RETURN(filter);
|
||||
|
||||
buffer = evas_filter_buffer_backing_steal(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
||||
if (buffer)
|
||||
async = evas_filter_context_async_get(ctx);
|
||||
_image_safe_unref(filter->evas, filter->output, async);
|
||||
|
||||
if (filter->ti)
|
||||
{
|
||||
if (ti->gfx_buffer)
|
||||
_image_safe_unref(filter->evas, ti->gfx_buffer);
|
||||
ti->gfx_buffer = buffer;
|
||||
filter->output = evas_filter_buffer_backing_steal(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
||||
if (filter->ti->parent.format->gfx_filter)
|
||||
filter->ti->parent.format->gfx_filter->invalid = !success;
|
||||
// else just avoid sigsegv
|
||||
filter->ti = NULL;
|
||||
filter->ctx = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(filter);
|
||||
}
|
||||
|
||||
evas_filter_context_destroy(ctx);
|
||||
_filter_context_set(ti, NULL);
|
||||
filter->invalid = !success;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -12994,7 +13001,7 @@ static void
|
|||
_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
||||
{
|
||||
Efl_Canvas_Text_Filter_Post_Render *post_data;
|
||||
Efl_Canvas_Text_Filter *filter = data;
|
||||
Evas_Public_Data *evas = data;
|
||||
|
||||
if (!evas_filter_context_async_get(ctx))
|
||||
{
|
||||
|
@ -13005,7 +13012,7 @@ _filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
|||
post_data = calloc(1, sizeof(*post_data));
|
||||
post_data->success = success;
|
||||
post_data->ctx = ctx;
|
||||
evas_post_render_job_add(filter->evas, _filter_post_render_cb, post_data);
|
||||
evas_post_render_job_add(evas, _filter_post_render_cb, post_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -13169,9 +13176,9 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
#define DRAW_TEXT(ox, oy) do { \
|
||||
if (ti->parent.format->font.font) \
|
||||
{ \
|
||||
if (EINA_LIKELY(!ti->gfx_filter_ctx)) \
|
||||
if (EINA_LIKELY(!_filter_context_get(ti))) \
|
||||
DRAW_TEXT_NOFILTER(ox, oy); \
|
||||
else if (!ti->gfx_buffer) \
|
||||
else if (!_filter_output_get(ti)) \
|
||||
DRAW_TEXT_FILTER(ti->parent.format->gfx_filter, ox, oy); \
|
||||
} } while(0)
|
||||
|
||||
|
@ -13314,6 +13321,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
Efl_Canvas_Text_Filter *filter;
|
||||
Evas_Filter_Program *pgm;
|
||||
Evas_Filter_Context *ctx;
|
||||
void *previous_output;
|
||||
Eina_Bool ok;
|
||||
int X, Y;
|
||||
|
||||
|
@ -13327,16 +13335,23 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
}
|
||||
|
||||
// previous run
|
||||
if (ti->gfx_buffer)
|
||||
previous_output = _filter_output_get(ti);
|
||||
if (previous_output)
|
||||
{
|
||||
if (!filter->redraw) continue;
|
||||
|
||||
_image_safe_unref(obj->layer->evas, ti->gfx_buffer);
|
||||
ti->gfx_buffer = NULL;
|
||||
_image_safe_unref(obj->layer->evas, previous_output, do_async);
|
||||
previous_output = NULL;
|
||||
}
|
||||
|
||||
// prepare filter context
|
||||
ctx = evas_filter_context_new(obj->layer->evas, do_async, ti);
|
||||
if (!ti->gfx_filter)
|
||||
{
|
||||
ti->gfx_filter = calloc(1, sizeof(*ti->gfx_filter));
|
||||
ti->gfx_filter->evas = obj->layer->evas;
|
||||
ti->gfx_filter->ti = ti;
|
||||
}
|
||||
ctx = evas_filter_context_new(obj->layer->evas, do_async, ti->gfx_filter);
|
||||
evas_filter_state_prepare(eo_obj, &state, ti);
|
||||
evas_filter_program_state_set(pgm, &state);
|
||||
ok = evas_filter_context_program_use(ctx, pgm);
|
||||
|
@ -13361,7 +13376,8 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
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, X, Y);
|
||||
_filter_context_set(ti, ctx);
|
||||
ti->gfx_filter->ctx = ctx;
|
||||
ti->gfx_filter->do_async = do_async;
|
||||
|
||||
// common data for all items (FIXME: should be common to object)
|
||||
if (!filter->dc)
|
||||
|
@ -13388,7 +13404,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
yoff = itr->yoff;
|
||||
ln = itr->ln;
|
||||
|
||||
if (EINA_UNLIKELY(ti->gfx_filter_ctx != NULL))
|
||||
if (EINA_UNLIKELY(_filter_context_get(ti) != NULL))
|
||||
context = ti->parent.format->gfx_filter->dc;
|
||||
|
||||
shad_dst = shad_sz = dx = dy = haveshad = 0;
|
||||
|
@ -13503,7 +13519,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
yoff = itr->yoff;
|
||||
ln = itr->ln;
|
||||
|
||||
if (EINA_UNLIKELY(ti->gfx_filter_ctx != NULL))
|
||||
if (EINA_UNLIKELY(_filter_context_get(ti) != NULL))
|
||||
context = ti->parent.format->gfx_filter->dc;
|
||||
|
||||
if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_GLOW)
|
||||
|
@ -13541,7 +13557,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
yoff = itr->yoff;
|
||||
ln = itr->ln;
|
||||
|
||||
if (EINA_UNLIKELY(ti->gfx_filter_ctx != NULL))
|
||||
if (EINA_UNLIKELY(_filter_context_get(ti) != NULL))
|
||||
context = ti->parent.format->gfx_filter->dc;
|
||||
|
||||
if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) ||
|
||||
|
@ -13626,7 +13642,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
{
|
||||
void *fi = _ITEM_TEXT(itr)->text_props.font_instance;
|
||||
|
||||
if (EINA_UNLIKELY(ti->gfx_filter_ctx != NULL))
|
||||
if (EINA_UNLIKELY(_filter_context_get(ti) != NULL))
|
||||
context = ti->parent.format->gfx_filter->dc;
|
||||
|
||||
COLOR_SET(normal);
|
||||
|
@ -13640,7 +13656,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
{
|
||||
Evas_Filter_Context *ctx = _filter_context_get(ti);
|
||||
Efl_Canvas_Text_Filter *filter = ti->parent.format->gfx_filter;
|
||||
void *buffer = ti->gfx_buffer;
|
||||
void *buffer = _filter_output_get(ti);
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
|
@ -13657,7 +13673,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
|||
}
|
||||
else if (ctx)
|
||||
{
|
||||
evas_filter_context_post_run_callback_set(ctx, _filter_cb, filter);
|
||||
evas_filter_context_post_run_callback_set(ctx, _filter_cb, obj->layer->evas);
|
||||
evas_filter_run(ctx);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue