evas: another improvement part of the previous lock less font rendering patch.

Now evas will in all case do the layout during the prepare stage. It will do that
once and as long as the text didn't change. This does improve by a factor of at
least 2.3 in all expedite test case except the text change that only get a 30%
increase (I expect a drop in performance on non pipe rendering for text change
expedite test only, but this case is not common in real life).

This also fix the issue that show random size glyph when using pipe rendering.


SVN revision: 71220
This commit is contained in:
Cedric BAIL 2012-05-18 02:16:54 +00:00
parent b2c9b6552a
commit b0d3526d89
18 changed files with 83 additions and 54 deletions

View File

@ -36,6 +36,15 @@ struct cinfo
} bm;
};
typedef struct _Evas_Glyph Evas_Glyph;
struct _Evas_Glyph
{
RGBA_Font_Glyph *fg;
void *data;
Eina_Rectangle coord;
FT_UInt idx;
int j;
};
EAPI void
evas_common_font_draw_init(void)
@ -54,39 +63,22 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, in
int ext_h, int im_w, int im_h __UNUSED__)
{
DATA32 *im;
RGBA_Font_Int *fi;
EVAS_FONT_WALK_TEXT_INIT();
fi = text_props->font_instance;
if (!fi) return;
evas_common_font_int_reload(fi);
if (fi->src->current_size != fi->size)
{
FTLOCK();
FT_Activate_Size(fi->ft.size);
FTUNLOCK();
fi->src->current_size = fi->size;
}
Evas_Glyph *glyphs;
unsigned int length;
unsigned int it;
im = dst->image.data;
EVAS_FONT_WALK_TEXT_START()
glyphs = (void*) eina_binbuf_string_get(text_props->bin);
length = eina_binbuf_length_get(text_props->bin) / sizeof (Evas_Glyph);
for (it = 0; it < length; ++it)
{
FT_UInt idx;
RGBA_Font_Glyph *fg;
int chr_x, chr_y;
if (!EVAS_FONT_WALK_IS_VISIBLE) continue;
idx = EVAS_FONT_WALK_INDEX;
fg = evas_common_font_int_cache_glyph_get(fi, idx);
if (!fg) continue;
if ((!fg->glyph_out) && (!evas_common_font_int_cache_glyph_render(fg)))
continue;
fg = glyphs[it].fg;
idx = glyphs[it].idx;
if (dc->font_ext.func.gl_new)
{
@ -95,19 +87,19 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, in
fg->ext_dat_free = dc->font_ext.func.gl_free;
}
chr_x = x + EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR;
chr_y = y + EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
chr_x = x + glyphs[it].coord.x/* EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR */;
chr_y = y + glyphs[it].coord.y/* EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR */;
if (chr_x < (ext_x + ext_w))
{
DATA8 *data;
int i, j, w, h;
data = fg->glyph_out->bitmap.buffer;
j = fg->glyph_out->bitmap.pitch;
w = fg->glyph_out->bitmap.width;
data = glyphs[it].data;
j = glyphs[it].j;
w = glyphs[it].coord.w;
if (j < w) j = w;
h = fg->glyph_out->bitmap.rows;
h = glyphs[it].coord.h;
/*
if ((fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays)
&& (fg->glyph_out->bitmap.num_grays == 256)
@ -260,8 +252,6 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, in
else
break;
}
EVAS_FONT_WALK_TEXT_END();
evas_common_font_int_use_trim();
}
EAPI void
@ -273,11 +263,17 @@ evas_common_font_draw_prepare(Evas_Text_Props *text_props)
fi = text_props->font_instance;
if (!fi) return;
if (!text_props->changed && text_props->generation == fi->generation && text_props->bin)
return ;
if (!text_props->bin) text_props->bin = eina_binbuf_new();
else eina_binbuf_reset(text_props->bin);
evas_common_font_int_reload(fi);
if (fi->src->current_size != fi->size)
{
evas_common_font_source_reload(fi->src);
FTLOCK();
FT_Activate_Size(fi->ft.size);
FTUNLOCK();
@ -286,8 +282,9 @@ evas_common_font_draw_prepare(Evas_Text_Props *text_props)
EVAS_FONT_WALK_TEXT_START()
{
FT_UInt idx;
Evas_Glyph glyph;
RGBA_Font_Glyph *fg;
FT_UInt idx;
if (!EVAS_FONT_WALK_IS_VISIBLE) continue;
idx = EVAS_FONT_WALK_INDEX;
@ -295,6 +292,17 @@ evas_common_font_draw_prepare(Evas_Text_Props *text_props)
fg = evas_common_font_int_cache_glyph_get(fi, idx);
if (!fg) continue;
if (!fg->glyph_out) evas_common_font_int_cache_glyph_render(fg);
glyph.fg = fg;
glyph.coord.x = EVAS_FONT_WALK_PEN_X + EVAS_FONT_WALK_X_OFF + EVAS_FONT_WALK_X_BEAR;
glyph.coord.y = EVAS_FONT_WALK_PEN_Y + EVAS_FONT_WALK_Y_OFF + EVAS_FONT_WALK_Y_BEAR;
glyph.coord.w = fg->glyph_out->bitmap.width;
glyph.coord.h = fg->glyph_out->bitmap.rows;
glyph.j = fg->glyph_out->bitmap.pitch;
glyph.idx = idx;
glyph.data = fg->glyph_out->bitmap.buffer;
eina_binbuf_append_length(text_props->bin, (void*) &glyph, sizeof (Evas_Glyph));
}
EVAS_FONT_WALK_TEXT_END();

View File

@ -3,6 +3,8 @@
#include "evas_font_private.h"
#include <assert.h>
#include FT_OUTLINE_H
FT_Library evas_ft_lib = 0;

View File

@ -350,7 +350,7 @@ evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
static void
evas_common_pipe_op_text_free(RGBA_Pipe_Op *op)
{
evas_common_text_props_content_unref(&(op->op.text.intl_props));
evas_common_text_props_content_unref(op->op.text.intl_props);
evas_common_pipe_op_free(op);
}
@ -363,17 +363,17 @@ evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa
memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
evas_common_font_draw(dst, &(context), op->op.text.x, op->op.text.y, &op->op.text.intl_props);
evas_common_font_draw(dst, &(context), op->op.text.x, op->op.text.y, op->op.text.intl_props);
}
else
{
evas_common_font_draw(dst, &(op->context), op->op.text.x, op->op.text.y, &op->op.text.intl_props);
evas_common_font_draw(dst, &(op->context), op->op.text.x, op->op.text.y, op->op.text.intl_props);
}
}
EAPI void
evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
int x, int y, const Evas_Text_Props *intl_props)
int x, int y, Evas_Text_Props *intl_props)
{
RGBA_Pipe_Op *op;
@ -381,8 +381,8 @@ evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
if (!dst->cache_entry.pipe) return;
op->op.text.x = x;
op->op.text.y = y;
evas_common_text_props_content_copy_and_ref(&(op->op.text.intl_props),
intl_props);
op->op.text.intl_props = intl_props;
evas_common_text_props_content_ref(intl_props);
op->op_func = evas_common_pipe_text_draw_do;
op->free_func = evas_common_pipe_op_text_free;
evas_common_pipe_draw_context_copy(dc, op);
@ -807,7 +807,7 @@ evas_common_pipe_text_prepare(const Evas_Text_Props *text_props)
fi = text_props->font_instance;
if (!fi) return ;
if (!text_props->changed && text_props->generation == fi->generation)
if (!text_props->changed && text_props->generation == fi->generation && text_props->bin)
return ;
fi = text_props->font_instance;

View File

@ -22,7 +22,7 @@ EAPI void evas_common_pipe_free(RGBA_Image *im);
EAPI void evas_common_pipe_rectangle_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h);
EAPI void evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x0, int y0, int x1, int y1);
EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points, int x, int y);
EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, const Evas_Text_Props *intl_props);
EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, Evas_Text_Props *intl_props);
EAPI void evas_common_pipe_text_prepare(const Evas_Text_Props *text_props);
EAPI void evas_common_pipe_image_load(RGBA_Image *im);
EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);

View File

@ -58,6 +58,12 @@ evas_common_text_props_content_unref(Evas_Text_Props *props)
if (--(props->info->refcount) == 0)
{
if (props->bin)
{
eina_binbuf_free(props->bin);
props->bin = NULL;
}
if (props->info->glyph)
free(props->info->glyph);
#ifdef OT_SUPPORT
@ -469,6 +475,7 @@ evas_common_text_props_content_create(void *_fi, const Eina_Unicode *text,
free(base_str);
# endif
#endif
text_props->text_len = len;
text_props->info->refcount = 1;
return EINA_TRUE;

View File

@ -25,6 +25,8 @@ struct _Evas_Text_Props
Evas_Text_Props_Info *info;
void *font_instance;
Eina_Binbuf *bin;
int generation;
Eina_Bool changed : 1;
};

View File

@ -741,7 +741,7 @@ struct _RGBA_Pipe_Op
} poly;
struct {
int x, y;
Evas_Text_Props intl_props;
Evas_Text_Props *intl_props;
} text;
struct {
RGBA_Image *src;

View File

@ -810,7 +810,7 @@ struct _Evas_Func
int (*font_v_advance_get) (void *data, Evas_Font_Set *font, const Evas_Text_Props *intl_props);
int (*font_char_coords_get) (void *data, Evas_Font_Set *font, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch);
int (*font_char_at_coords_get) (void *data, Evas_Font_Set *font, const Evas_Text_Props *intl_props, int x, int y, int *cx, int *cy, int *cw, int *ch);
void (*font_draw) (void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w, int h, int ow, int oh, const Evas_Text_Props *intl_props);
void (*font_draw) (void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w, int h, int ow, int oh, Evas_Text_Props *intl_props);
void (*font_cache_flush) (void *data);
void (*font_cache_set) (void *data, int bytes);

View File

@ -389,7 +389,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image)
}
static void
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w, int h, int ow, int oh, const Evas_Text_Props *intl_props)
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w, int h, int ow, int oh, Evas_Text_Props *intl_props)
{
Render_Engine *re = (Render_Engine *)data;
RGBA_Image im;
@ -403,6 +403,7 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int
evas_direct3d_font_texture_new,
evas_direct3d_font_texture_free,
evas_direct3d_font_texture_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(&im, context, x, y, intl_props);
evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL);
}

View File

@ -1037,7 +1037,7 @@ evas_engine_dfb_output_idle_flush(void *data)
* memory.
*/
static void
evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *intl_props)
{
DirectFB_Engine_Image_Entry *eim = surface;
IDirectFBSurface *screen;
@ -1049,6 +1049,7 @@ evas_engine_dfb_font_draw(void *data, void *context, void *surface, void *font,
if (!_dfb_lock_and_sync_image(screen, im, DSLF_READ | DSLF_WRITE))
return;
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(im, context, x, y, intl_props);
evas_common_cpu_end_opt();

View File

@ -1046,7 +1046,7 @@ eng_image_stride_get(void *data __UNUSED__, void *image, int *stride)
}
static void
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *intl_props)
{
Render_Engine *re;
@ -1067,6 +1067,7 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(im, context, x, y, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,

View File

@ -838,7 +838,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image)
}
static void
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *intl_props)
{
Render_Engine *re;
@ -858,6 +858,7 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(im, context, x, y, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,

View File

@ -2833,7 +2833,7 @@ eng_image_stride_get(void *data __UNUSED__, void *image, int *stride)
}
static void
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *intl_props)
{
Render_Engine *re;
@ -2854,6 +2854,7 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font __UN
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(im, context, x, y, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,

View File

@ -292,7 +292,7 @@ eng_image_cache_get(void *data __UNUSED__)
}
static void
eng_font_draw(void *data __UNUSED__, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *text_props)
eng_font_draw(void *data __UNUSED__, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *text_props)
{
static RGBA_Image *im = NULL;
Soft16_Image *dst = surface;
@ -305,6 +305,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, Evas_Font_Set
evas_common_soft16_font_glyph_new,
evas_common_soft16_font_glyph_free,
evas_common_soft16_font_glyph_draw);
evas_common_font_draw_prepare(text_props);
evas_common_font_draw(im, context, x, y, text_props);
evas_common_draw_context_font_ext_set(context,
NULL,

View File

@ -899,7 +899,7 @@ evas_engine_sdl16_image_format_get(void *data __UNUSED__, void *image __UNUSED__
}
static void
evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *intl_props)
{
static RGBA_Image *im = NULL;
SDL_Engine_Image_Entry *eim = surface;
@ -917,6 +917,7 @@ evas_engine_sdl16_font_draw(void *data __UNUSED__, void *context, void *surface,
evas_common_soft16_font_glyph_new,
evas_common_soft16_font_glyph_free,
evas_common_soft16_font_glyph_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw((RGBA_Image *) eim->cache_entry.src, context, x, y, intl_props);
evas_common_draw_context_font_ext_set(context,
NULL,

View File

@ -343,6 +343,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface,
Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__,
int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *text_props)
{
evas_common_font_draw_prepare(text_props);
evas_common_font_draw(surface, context, x, y, text_props);
evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL);
}

View File

@ -1274,7 +1274,7 @@ eng_font_run_font_end_get(void *data __UNUSED__, Evas_Font_Set *font, Evas_Font_
}
static void
eng_font_draw(void *data __UNUSED__, void *context, void *surface, Evas_Font_Set *font __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *text_props)
eng_font_draw(void *data __UNUSED__, void *context, void *surface, Evas_Font_Set *font __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *text_props)
{
#ifdef BUILD_PIPE_RENDER
if ((cpunum > 1))
@ -1282,6 +1282,7 @@ eng_font_draw(void *data __UNUSED__, void *context, void *surface, Evas_Font_Set
else
#endif
{
evas_common_font_draw_prepare(text_props);
evas_common_font_draw(surface, context, x, y, text_props);
evas_common_cpu_end_opt();
}

View File

@ -1911,7 +1911,7 @@ eng_image_stride_get(void *data __UNUSED__, void *image, int *stride)
}
static void
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props)
eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font __UNUSED__, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, Evas_Text_Props *intl_props)
{
Render_Engine *re;
@ -1932,6 +1932,7 @@ eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font __UN
evas_gl_font_texture_new,
evas_gl_font_texture_free,
evas_gl_font_texture_draw);
evas_common_font_draw_prepare(intl_props);
evas_common_font_draw(im, context, x, y, intl_props);
evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL);
}