jpeg pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=f83ce20e1c72c3a645553feeea640e0c4b69e6c1
commit f83ce20e1c72c3a645553feeea640e0c4b69e6c1 Author: Youngbok Shin <[email protected]> Date: Wed Mar 8 19:33:15 2017 +0900 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 <[email protected]> --- src/lib/evas/common/evas_draw.h | 4 +-- src/lib/evas/common/evas_draw_main.c | 6 ++-- src/lib/evas/common/evas_font_draw.c | 10 +++--- src/lib/evas/include/evas_common_private.h | 4 +-- .../evas/engines/gl_common/evas_gl_common.h | 8 +++-- .../evas/engines/gl_common/evas_gl_context.c | 3 ++ src/modules/evas/engines/gl_common/evas_gl_font.c | 41 ++++++++++++++++++++++ src/modules/evas/engines/gl_common/evas_gl_image.c | 34 +++++------------- src/modules/evas/engines/gl_generic/evas_engine.c | 6 ++-- 9 files changed, 71 insertions(+), 45 deletions(-) diff --git a/src/lib/evas/common/evas_draw.h b/src/lib/evas/common/evas_draw.h index 6323e8d..28b7c94 100644 --- a/src/lib/evas/common/evas_draw.h +++ b/src/lib/evas/common/evas_draw.h @@ -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); diff --git a/src/lib/evas/common/evas_draw_main.c b/src/lib/evas/common/evas_draw_main.c index d7c26c7..d6b0a89 100644 --- a/src/lib/evas/common/evas_draw_main.c +++ b/src/lib/evas/common/evas_draw_main.c @@ -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; } diff --git a/src/lib/evas/common/evas_font_draw.c b/src/lib/evas/common/evas_font_draw.c index b4b0a99..f7fcb13 100644 --- a/src/lib/evas/common/evas_font_draw.c +++ b/src/lib/evas/common/evas_font_draw.c @@ -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 diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index f576fc3..0da1e32 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -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; diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index d78c21a..ef91f7b 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -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); diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 45ea677..cc70c2b 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -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; diff --git a/src/modules/evas/engines/gl_common/evas_gl_font.c b/src/modules/evas/engines/gl_common/evas_gl_font.c index 968168d..5a5fdeb 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_font.c +++ b/src/modules/evas/engines/gl_common/evas_gl_font.c @@ -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); +} diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c index bfbef7b..3b02db1 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -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); -} diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 4fdcced..5f97c36 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -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, --
