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
|
* Filter name - code database
|
||||||
*/
|
*/
|
||||||
typedef struct _Efl_Canvas_Text_Filter_Program Efl_Canvas_Text_Filter_Program;
|
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
|
* @internal
|
||||||
* @def IS_AT_END(ti, ind)
|
* @def IS_AT_END(ti, ind)
|
||||||
|
@ -437,8 +443,7 @@ struct _Evas_Object_Textblock_Text_Item
|
||||||
Evas_Object_Textblock_Item parent; /**< Textblock item. */
|
Evas_Object_Textblock_Item parent; /**< Textblock item. */
|
||||||
Evas_Text_Props text_props; /**< Props for this item. */
|
Evas_Text_Props text_props; /**< Props for this item. */
|
||||||
Evas_Coord x_adjustment; /**< Used to indicate by how much we adjusted sizes */
|
Evas_Coord x_adjustment; /**< Used to indicate by how much we adjusted sizes */
|
||||||
Evas_Filter_Context *gfx_filter_ctx; /* temp variable FIXME */
|
Text_Item_Filter *gfx_filter;
|
||||||
void *gfx_buffer; /* FIXME */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Evas_Object_Textblock_Format_Item
|
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 */
|
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
|
struct _Efl_Canvas_Text_Filter
|
||||||
{
|
{
|
||||||
Eina_Stringshare *name;
|
Eina_Stringshare *name;
|
||||||
|
@ -948,31 +962,14 @@ _format_unref_free(const Evas_Object *eo_obj, Evas_Object_Textblock_Format *fmt)
|
||||||
free(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
|
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;
|
if (!image) return;
|
||||||
job = calloc(1, sizeof(*job));
|
if (async)
|
||||||
job->evas = e;
|
evas_unref_queue_image_put(e, image);
|
||||||
job->image = image;
|
else
|
||||||
evas_post_render_job_add(e, _image_post_render_unref_cb, job);
|
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_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
|
||||||
|
|
||||||
evas_common_text_props_content_unref(&ti->text_props);
|
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_filter->output)
|
||||||
}
|
{
|
||||||
if (ti->gfx_buffer)
|
Evas *eo_evas = evas_object_evas_get(eo_obj);
|
||||||
{
|
Evas_Public_Data *evas = efl_data_scope_get(eo_evas, EVAS_CANVAS_CLASS);
|
||||||
Evas_Public_Data *e = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS);
|
Eina_Bool async = ti->gfx_filter->do_async;
|
||||||
_image_safe_unref(e, ti->gfx_buffer);
|
|
||||||
ti->gfx_buffer = NULL;
|
_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
|
else
|
||||||
|
@ -12943,42 +12946,46 @@ evas_object_textblock_free(Evas_Object *eo_obj)
|
||||||
free(o->utf8);
|
free(o->utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Evas_Filter_Context *
|
static inline Evas_Filter_Context *
|
||||||
_filter_context_get(Evas_Object_Textblock_Text_Item *ti)
|
_filter_context_get(Evas_Object_Textblock_Text_Item *ti)
|
||||||
{
|
{
|
||||||
// FIXME: optimize this (memory usage)
|
if (!ti || !ti->gfx_filter) return NULL;
|
||||||
if (!ti) return NULL;
|
return ti->gfx_filter->ctx;
|
||||||
return ti->gfx_filter_ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline void *
|
||||||
_filter_context_set(Evas_Object_Textblock_Text_Item *ti, Evas_Filter_Context *ctx)
|
_filter_output_get(Evas_Object_Textblock_Text_Item *ti)
|
||||||
{
|
{
|
||||||
if (!ti) return;
|
if (!ti || !ti->gfx_filter) return NULL;
|
||||||
ti->gfx_filter_ctx = ctx;
|
return ti->gfx_filter->output;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_filter_sync_end(Evas_Filter_Context *ctx, Eina_Bool success)
|
_filter_sync_end(Evas_Filter_Context *ctx, Eina_Bool success)
|
||||||
{
|
{
|
||||||
Evas_Object_Textblock_Text_Item *ti;
|
Text_Item_Filter *filter;
|
||||||
Efl_Canvas_Text_Filter *filter;
|
Eina_Bool async;
|
||||||
void *buffer;
|
|
||||||
|
|
||||||
ti = evas_filter_context_data_get(ctx);
|
filter = evas_filter_context_data_get(ctx);
|
||||||
filter = ti->parent.format->gfx_filter;
|
EINA_SAFETY_ON_NULL_RETURN(filter);
|
||||||
|
|
||||||
buffer = evas_filter_buffer_backing_steal(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
async = evas_filter_context_async_get(ctx);
|
||||||
if (buffer)
|
_image_safe_unref(filter->evas, filter->output, async);
|
||||||
|
|
||||||
|
if (filter->ti)
|
||||||
{
|
{
|
||||||
if (ti->gfx_buffer)
|
filter->output = evas_filter_buffer_backing_steal(ctx, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
||||||
_image_safe_unref(filter->evas, ti->gfx_buffer);
|
if (filter->ti->parent.format->gfx_filter)
|
||||||
ti->gfx_buffer = buffer;
|
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);
|
evas_filter_context_destroy(ctx);
|
||||||
_filter_context_set(ti, NULL);
|
|
||||||
filter->invalid = !success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -12994,7 +13001,7 @@ static void
|
||||||
_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
|
||||||
{
|
{
|
||||||
Efl_Canvas_Text_Filter_Post_Render *post_data;
|
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))
|
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 = calloc(1, sizeof(*post_data));
|
||||||
post_data->success = success;
|
post_data->success = success;
|
||||||
post_data->ctx = ctx;
|
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
|
static void
|
||||||
|
@ -13169,9 +13176,9 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
#define DRAW_TEXT(ox, oy) do { \
|
#define DRAW_TEXT(ox, oy) do { \
|
||||||
if (ti->parent.format->font.font) \
|
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); \
|
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); \
|
DRAW_TEXT_FILTER(ti->parent.format->gfx_filter, ox, oy); \
|
||||||
} } while(0)
|
} } while(0)
|
||||||
|
|
||||||
|
@ -13314,6 +13321,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
Efl_Canvas_Text_Filter *filter;
|
Efl_Canvas_Text_Filter *filter;
|
||||||
Evas_Filter_Program *pgm;
|
Evas_Filter_Program *pgm;
|
||||||
Evas_Filter_Context *ctx;
|
Evas_Filter_Context *ctx;
|
||||||
|
void *previous_output;
|
||||||
Eina_Bool ok;
|
Eina_Bool ok;
|
||||||
int X, Y;
|
int X, Y;
|
||||||
|
|
||||||
|
@ -13327,16 +13335,23 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
}
|
}
|
||||||
|
|
||||||
// previous run
|
// previous run
|
||||||
if (ti->gfx_buffer)
|
previous_output = _filter_output_get(ti);
|
||||||
|
if (previous_output)
|
||||||
{
|
{
|
||||||
if (!filter->redraw) continue;
|
if (!filter->redraw) continue;
|
||||||
|
|
||||||
_image_safe_unref(obj->layer->evas, ti->gfx_buffer);
|
_image_safe_unref(obj->layer->evas, previous_output, do_async);
|
||||||
ti->gfx_buffer = NULL;
|
previous_output = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare filter context
|
// 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_state_prepare(eo_obj, &state, ti);
|
||||||
evas_filter_program_state_set(pgm, &state);
|
evas_filter_program_state_set(pgm, &state);
|
||||||
ok = evas_filter_context_program_use(ctx, pgm);
|
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_proxy_render_all(ctx, eo_obj, EINA_FALSE);
|
||||||
evas_filter_context_buffers_allocate_all(ctx);
|
evas_filter_context_buffers_allocate_all(ctx);
|
||||||
evas_filter_target_set(ctx, context, surface, X, Y);
|
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)
|
// common data for all items (FIXME: should be common to object)
|
||||||
if (!filter->dc)
|
if (!filter->dc)
|
||||||
|
@ -13388,7 +13404,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
yoff = itr->yoff;
|
yoff = itr->yoff;
|
||||||
ln = itr->ln;
|
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;
|
context = ti->parent.format->gfx_filter->dc;
|
||||||
|
|
||||||
shad_dst = shad_sz = dx = dy = haveshad = 0;
|
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;
|
yoff = itr->yoff;
|
||||||
ln = itr->ln;
|
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;
|
context = ti->parent.format->gfx_filter->dc;
|
||||||
|
|
||||||
if ((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_GLOW)
|
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;
|
yoff = itr->yoff;
|
||||||
ln = itr->ln;
|
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;
|
context = ti->parent.format->gfx_filter->dc;
|
||||||
|
|
||||||
if (((ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC) == EVAS_TEXT_STYLE_OUTLINE) ||
|
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;
|
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;
|
context = ti->parent.format->gfx_filter->dc;
|
||||||
|
|
||||||
COLOR_SET(normal);
|
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);
|
Evas_Filter_Context *ctx = _filter_context_get(ti);
|
||||||
Efl_Canvas_Text_Filter *filter = ti->parent.format->gfx_filter;
|
Efl_Canvas_Text_Filter *filter = ti->parent.format->gfx_filter;
|
||||||
void *buffer = ti->gfx_buffer;
|
void *buffer = _filter_output_get(ti);
|
||||||
|
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
|
@ -13657,7 +13673,7 @@ evas_object_textblock_render(Evas_Object *eo_obj EINA_UNUSED,
|
||||||
}
|
}
|
||||||
else if (ctx)
|
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);
|
evas_filter_run(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue