evas: clean up GL images for emojis when GL context is free'd
authorYoungbok Shin <youngb.shin@samsung.com>
Wed, 8 Mar 2017 10:33:15 +0000 (19:33 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 8 Mar 2017 10:35:03 +0000 (19:35 +0900)
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>
src/lib/evas/common/evas_draw.h
src/lib/evas/common/evas_draw_main.c
src/lib/evas/common/evas_font_draw.c
src/lib/evas/include/evas_common_private.h
src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_context.c
src/modules/evas/engines/gl_common/evas_gl_font.c
src/modules/evas/engines/gl_common/evas_gl_image.c
src/modules/evas/engines/gl_generic/evas_engine.c

index 6323e8d..28b7c94 100644 (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);
index d7c26c7..d6b0a89 100644 (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;
 }
index b4b0a99..f7fcb13 100644 (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
index f576fc3..0da1e32 100644 (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;
index d78c21a..ef91f7b 100644 (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);
index 45ea677..cc70c2b 100644 (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;
index 968168d..5a5fdeb 100644 (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);
+}
index bfbef7b..3b02db1 100644 (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);
-}
index 4fdcced..5f97c36 100644 (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,