evas: clean up GL images for emojis when GL context is free'd

If GL context is free'd before processing font shutdown,
textures for emoji glyph's GL images will be free'd without clean
up its GL images. It causes eina mempool infinite loop issue when
emoji's GL images are free'd in shutdown process.

So, the patch will make a list for emoji's GL images in context and
clean up them when the context is free'd. Just like font textures in
context.

@fix

Differential Revision: https://phab.enlightenment.org/D4695

Signed-off-by: Jean-Philippe Andre <jp.andre@samsung.com>
This commit is contained in:
Youngbok Shin 2017-03-08 19:33:15 +09:00 committed by Jean-Philippe Andre
parent 437ae4a3d3
commit f83ce20e1c
9 changed files with 71 additions and 45 deletions

View File

@ -12,9 +12,9 @@ EAPI void evas_common_draw_context_font_ext_set (RGBA_D
void *(*gl_new) (void *data, RGBA_Font_Glyph *fg),
void (*gl_free) (void *ext_dat),
void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y),
void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace),
void *(*gl_image_new) (void *gc, RGBA_Font_Glyph *fg, int alpha, Evas_Colorspace cspace),
void (*gl_image_free) (void *image),
void (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth));
void (*gl_image_draw) (void *gc, void *im, int dx, int dy, int dw, int dh, int smooth));
EAPI void evas_common_draw_context_clip_clip (RGBA_Draw_Context *dc, int x, int y, int w, int h);
EAPI void evas_common_draw_context_set_clip (RGBA_Draw_Context *dc, int x, int y, int w, int h);
EAPI void evas_common_draw_context_unset_clip (RGBA_Draw_Context *dc);

View File

@ -216,15 +216,15 @@ evas_common_draw_context_font_ext_set(RGBA_Draw_Context *dc,
void *(*gl_new) (void *data, RGBA_Font_Glyph *fg),
void (*gl_free) (void *ext_dat),
void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y),
void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace),
void *(*gl_image_new) (void *gc, RGBA_Font_Glyph *fg, int alpha, Evas_Colorspace cspace),
void (*gl_image_free) (void *image),
void (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth))
void (*gl_image_draw) (void *gc, void *im, int dx, int dy, int dw, int dh, int smooth))
{
dc->font_ext.data = data;
dc->font_ext.func.gl_new = gl_new;
dc->font_ext.func.gl_free = gl_free;
dc->font_ext.func.gl_draw = gl_draw;
dc->font_ext.func.gl_image_new_from_data = gl_image_new_from_data;
dc->font_ext.func.gl_image_new = gl_image_new;
dc->font_ext.func.gl_image_free = gl_image_free;
dc->font_ext.func.gl_image_draw = gl_image_draw;
}

View File

@ -123,13 +123,11 @@ evas_common_font_rgba_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y,
if ((!fg->ext_dat) && FT_HAS_COLOR(fg->fi->src->ft.face))
{
if (dc->font_ext.func.gl_image_new_from_data)
if (dc->font_ext.func.gl_image_new)
{
/* extension calls */
fg->ext_dat = dc->font_ext.func.gl_image_new_from_data
(dc->font_ext.data, (unsigned int)w, (unsigned int)h,
(DATA32 *)fg->glyph_out->bitmap.buffer, EINA_TRUE,
EVAS_COLORSPACE_ARGB8888);
fg->ext_dat = dc->font_ext.func.gl_image_new
(dc->font_ext.data, fg, EINA_TRUE, EVAS_COLORSPACE_ARGB8888);
fg->ext_dat_free = dc->font_ext.func.gl_image_free;
}
else
@ -163,7 +161,7 @@ evas_common_font_rgba_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y,
{
if (dc->font_ext.func.gl_image_draw)
dc->font_ext.func.gl_image_draw
(dc->font_ext.data, fg->ext_dat, 0, 0, w, h,
(dc->font_ext.data, fg->ext_dat,
chr_x, y - (chr_y - y), w, h, EINA_TRUE);
else
_evas_font_image_draw

View File

@ -748,9 +748,9 @@ struct _RGBA_Draw_Context
void *(*gl_new) (void *data, RGBA_Font_Glyph *fg);
void (*gl_free) (void *ext_dat);
void (*gl_draw) (void *data, void *dest, void *context, RGBA_Font_Glyph *fg, int x, int y);
void *(*gl_image_new_from_data) (void *gc, unsigned int w, unsigned int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace);
void *(*gl_image_new) (void *gc, RGBA_Font_Glyph *fg, int alpha, Evas_Colorspace cspace);
void (*gl_image_free) (void *image);
void (*gl_image_draw) (void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth);
void (*gl_image_draw) (void *gc, void *im, int dx, int dy, int dw, int dh, int smooth);
} func;
void *data;
} font_ext;

View File

@ -331,6 +331,7 @@ struct _Evas_Engine_GL_Context
} pipe[MAX_PIPES];
Eina_List *font_glyph_textures;
Eina_List *font_glyph_images;
Evas_GL_Image *def_surface;
RGBA_Image *font_surface;
@ -414,6 +415,7 @@ struct _Evas_GL_Image
RGBA_Image *im;
Evas_GL_Texture *tex;
Evas_Image_Load_Opts load_opts;
RGBA_Font_Glyph *fglyph;
int references;
// if im->im == NULL, it's a render-surface so these here are used
int w, h;
@ -690,9 +692,9 @@ void evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_
void *evas_gl_font_texture_new(void *gc, RGBA_Font_Glyph *fg);
void evas_gl_font_texture_free(void *);
void evas_gl_font_texture_draw(void *gc, void *surface, void *dc, RGBA_Font_Glyph *fg, int x, int y);
void *evas_gl_image_new_from_data(void *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace);
void evas_gl_image_free(void *im);
void evas_gl_image_draw(void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth);
void *evas_gl_font_image_new(void *gc, RGBA_Font_Glyph *fg, int alpha, Evas_Colorspace cspace);
void evas_gl_font_image_free(void *im);
void evas_gl_font_image_draw(void *gc, void *im, int dx, int dy, int dw, int dh, int smooth);
Evas_GL_Polygon *evas_gl_common_poly_point_add(Evas_GL_Polygon *poly, int x, int y);
Evas_GL_Polygon *evas_gl_common_poly_points_clear(Evas_GL_Polygon *poly);

View File

@ -1386,6 +1386,9 @@ evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
while (gc->font_glyph_textures)
evas_gl_common_texture_free(gc->font_glyph_textures->data, EINA_TRUE);
while (gc->font_glyph_images)
evas_gl_common_image_free(gc->font_glyph_images->data);
if ((gc->shared) && (gc->shared->references == 0))
{
Evas_GL_Texture_Pool *pt;

View File

@ -185,3 +185,44 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c
/* restore clip info */
gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch;
}
void *
evas_gl_font_image_new(void *gc, RGBA_Font_Glyph *fg, int alpha, Evas_Colorspace cspace)
{
Evas_Engine_GL_Context *context = (Evas_Engine_GL_Context *)gc;
Evas_GL_Image *im = evas_gl_common_image_new_from_data(context,
(unsigned int)fg->glyph_out->bitmap.width,
(unsigned int)fg->glyph_out->bitmap.rows,
(DATA32 *)fg->glyph_out->bitmap.buffer,
alpha,
cspace);
if (im)
{
im->fglyph = fg;
context->font_glyph_images = eina_list_append(context->font_glyph_images, im);
}
return (void *)im;
}
void
evas_gl_font_image_free(void *im)
{
evas_gl_common_image_free((Evas_GL_Image *)im);
}
void
evas_gl_font_image_draw(void *gc, void *gl_image, int dx, int dy, int dw, int dh, int smooth)
{
Evas_GL_Image *im = (Evas_GL_Image *)gl_image;
if (!im || !im->fglyph) return;
evas_gl_common_image_draw((Evas_Engine_GL_Context *)gc,
im, 0, 0,
(unsigned int)im->fglyph->glyph_out->bitmap.width,
(unsigned int)im->fglyph->glyph_out->bitmap.rows,
dx, dy, dw, dh,
smooth);
}

View File

@ -766,6 +766,14 @@ evas_gl_common_image_free(Evas_GL_Image *im)
{
im->references--;
if (im->references > 0) return;
if (im->fglyph)
{
im->gc->font_glyph_images = eina_list_remove(im->gc->font_glyph_images, im);
im->fglyph->ext_dat = NULL;
im->fglyph->ext_dat_free = NULL;
}
evas_gl_common_context_flush(im->gc);
evas_gl_common_image_preload_unwatch(im);
@ -1355,29 +1363,3 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
/* restore clip info */
gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch;
}
void *
evas_gl_image_new_from_data(void *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace)
{
return (void *)evas_gl_common_image_new_from_data((Evas_Engine_GL_Context *)gc,
w, h,
data,
alpha,
cspace);
}
void
evas_gl_image_free(void *im)
{
evas_gl_common_image_free((Evas_GL_Image *)im);
}
void
evas_gl_image_draw(void *gc, void *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth)
{
evas_gl_common_image_draw((Evas_Engine_GL_Context *)gc,
(Evas_GL_Image *)im,
sx, sy, sw, sh,
dx, dy, dw, dh,
smooth);
}

View File

@ -1532,9 +1532,9 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font EINA
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw,
evas_gl_image_new_from_data,
evas_gl_image_free,
evas_gl_image_draw);
evas_gl_font_image_new,
evas_gl_font_image_free,
evas_gl_font_image_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(gl_context->font_surface, context, x, y, intl_props->glyphs);
evas_common_draw_context_font_ext_set(context,