evas draw context - reduce size and allocations and frees

so a little perf fun shows malloc/free/realloc/etc. are, combined a
reasonable overhead. this reduced malloc overhead for draw contexts so
whne we duplicate them or create new ones, we re-use a small cache of
8 of them to avoid re-allocation. just take the first one from the
list as it really is that simple. mempool would not have helped more
here and cost more overhead.

@optimize
This commit is contained in:
Carsten Haitzler 2017-01-31 14:50:52 +09:00
parent b38c610c7e
commit a909ca1f68
5 changed files with 110 additions and 71 deletions

View File

@ -47,7 +47,6 @@ cserve2_rgba_image_scale_do(void *src_data, int src_full_w, int src_full_h,
dst.flags = RGBA_IMAGE_NOTHING; dst.flags = RGBA_IMAGE_NOTHING;
memset(&ct, 0, sizeof(ct)); memset(&ct, 0, sizeof(ct));
ct.sli.h = 1;
ct.render_op = _EVAS_RENDER_COPY; ct.render_op = _EVAS_RENDER_COPY;
if (smooth) if (smooth)

View File

@ -33,7 +33,6 @@ EAPI void evas_common_draw_context_apply_clean_cutouts (Cutout
EAPI void evas_common_draw_context_set_anti_alias (RGBA_Draw_Context *dc, unsigned char aa); EAPI void evas_common_draw_context_set_anti_alias (RGBA_Draw_Context *dc, unsigned char aa);
EAPI void evas_common_draw_context_set_color_interpolation (RGBA_Draw_Context *dc, int color_space); EAPI void evas_common_draw_context_set_color_interpolation (RGBA_Draw_Context *dc, int color_space);
EAPI void evas_common_draw_context_set_render_op (RGBA_Draw_Context *dc, int op); EAPI void evas_common_draw_context_set_render_op (RGBA_Draw_Context *dc, int op);
EAPI void evas_common_draw_context_set_sli (RGBA_Draw_Context *dc, int y, int h);
EAPI void evas_common_draw_context_target_set (RGBA_Draw_Context *dc, int x, int y, int w, int h); EAPI void evas_common_draw_context_target_set (RGBA_Draw_Context *dc, int x, int y, int w, int h);
#endif /* _EVAS_DRAW_H */ #endif /* _EVAS_DRAW_H */

View File

@ -18,13 +18,14 @@ evas_common_draw_context_cutouts_dup(Cutout_Rects *rects2, const Cutout_Rects *r
rects2->active = rects->active; rects2->active = rects->active;
rects2->max = rects->active; rects2->max = rects->active;
rects2->last_add = rects->last_add; rects2->last_add = rects->last_add;
rects2->rects = NULL;
if (rects2->max > 0) if (rects2->max > 0)
{ {
const size_t sz = sizeof(Cutout_Rect) * rects2->max; const size_t sz = sizeof(Cutout_Rect) * rects2->max;
rects2->rects = malloc(sz); rects2->rects = malloc(sz);
memcpy(rects2->rects, rects->rects, sz); memcpy(rects2->rects, rects->rects, sz);
return;
} }
else rects2->rects = NULL;
} }
EAPI void EAPI void
@ -59,12 +60,73 @@ evas_common_draw_context_cutouts_del(Cutout_Rects* rects, int idx)
} }
static int _init_count = 0; static int _init_count = 0;
static int _ctxt_spares_count = 0;
static Eina_List *_ctxt_spares = NULL;
static SLK(_ctx_spares_lock);
static void
_evas_common_draw_context_real_free(RGBA_Draw_Context *dc)
{
#ifdef HAVE_PIXMAN
# if defined(PIXMAN_FONT) || defined(PIXMAN_RECT) || defined(PIXMAN_LINE) || defined(PIXMAN_POLY)
if (dc->col.pixman_color_image)
pixman_image_unref(dc->col.pixman_color_image);
# endif
#endif
evas_common_draw_context_apply_clean_cutouts(&dc->cutout);
evas_common_draw_context_cutouts_real_free(dc->cache.rects);
free(dc);
}
static void
_evas_common_draw_context_stash(RGBA_Draw_Context *dc)
{
if (_ctxt_spares_count < 8)
{
#ifdef HAVE_PIXMAN
# if defined(PIXMAN_FONT) || defined(PIXMAN_RECT) || defined(PIXMAN_LINE) || defined(PIXMAN_POLY)
if (dc->col.pixman_color_image)
{
pixman_image_unref(dc->col.pixman_color_image);
dc->col.pixman_color_image = NULL;
}
# endif
#endif
evas_common_draw_context_apply_clean_cutouts(&dc->cutout);
evas_common_draw_context_cutouts_real_free(dc->cache.rects);
SLKL(_ctx_spares_lock);
_ctxt_spares = eina_list_prepend(_ctxt_spares, dc);
_ctxt_spares_count++;
SLKU(_ctx_spares_lock);
return;
}
_evas_common_draw_context_real_free(dc);
}
static RGBA_Draw_Context *
_evas_common_draw_context_find(void)
{
RGBA_Draw_Context *dc;
if (_ctxt_spares)
{
SLKL(_ctx_spares_lock);
dc = _ctxt_spares->data;
_ctxt_spares = eina_list_remove_list(_ctxt_spares, _ctxt_spares);
_ctxt_spares_count--;
SLKU(_ctx_spares_lock);
return dc;
}
dc = malloc(sizeof(RGBA_Draw_Context));
return dc;
}
EAPI void EAPI void
evas_common_init(void) evas_common_init(void)
{ {
if (_init_count++) return ; if (_init_count++) return;
SLKI(_ctx_spares_lock);
evas_common_cpu_init(); evas_common_cpu_init();
evas_common_blend_init(); evas_common_blend_init();
@ -83,13 +145,20 @@ evas_common_init(void)
EAPI void EAPI void
evas_common_shutdown(void) evas_common_shutdown(void)
{ {
if (--_init_count) return ; if (--_init_count) return;
evas_font_dir_cache_free(); evas_font_dir_cache_free();
evas_common_font_shutdown(); evas_common_font_shutdown();
evas_common_image_shutdown(); evas_common_image_shutdown();
evas_common_image_cache_free(); evas_common_image_cache_free();
evas_common_scale_sample_shutdown(); evas_common_scale_sample_shutdown();
// just in case any thread is still doing things... don't del this here
// RGBA_Draw_Context *dc;
// SLKL(_ctx_spares_lock);
// EINA_LIST_FREE(_ctxt_spares, dc) _evas_common_draw_context_real_free(dc);
// _ctxt_spares_count = 0;
// SLKU(_ctx_spares_lock);
// SLKD(_ctx_spares_lock);
} }
EAPI void EAPI void
@ -101,31 +170,27 @@ EAPI RGBA_Draw_Context *
evas_common_draw_context_new(void) evas_common_draw_context_new(void)
{ {
RGBA_Draw_Context *dc; RGBA_Draw_Context *dc;
dc = _evas_common_draw_context_find();
dc = calloc(1, sizeof(RGBA_Draw_Context)); if (!dc) return NULL;
dc->sli.h = 1; memset(dc, 0, sizeof(RGBA_Draw_Context));
return dc; return dc;
} }
EAPI RGBA_Draw_Context * EAPI RGBA_Draw_Context *
evas_common_draw_context_dup(RGBA_Draw_Context *dc) evas_common_draw_context_dup(RGBA_Draw_Context *dc)
{ {
RGBA_Draw_Context *dc2; RGBA_Draw_Context *dc2 = _evas_common_draw_context_find();
if (!dc) return evas_common_draw_context_new(); if (!dc) return dc2;
dc2 = malloc(sizeof(RGBA_Draw_Context));
memcpy(dc2, dc, sizeof(RGBA_Draw_Context)); memcpy(dc2, dc, sizeof(RGBA_Draw_Context));
evas_common_draw_context_cutouts_dup(&dc2->cutout, &dc->cutout); evas_common_draw_context_cutouts_dup(&dc2->cutout, &dc->cutout);
#ifdef HAVE_PIXMAN #ifdef HAVE_PIXMAN
#if defined(PIXMAN_FONT) || defined(PIXMAN_RECT) || defined(PIXMAN_LINE) || defined(PIXMAN_POLY) # if defined(PIXMAN_FONT) || defined(PIXMAN_RECT) || defined(PIXMAN_LINE) || defined(PIXMAN_POLY)
if (dc2->col.pixman_color_image) dc2->col.pixman_color_image = NULL;
pixman_image_ref(dc2->col.pixman_color_image); # endif
#endif #endif
#endif
dc2->cache.rects = NULL; dc2->cache.rects = NULL;
dc2->cache.used = 0; dc2->cache.used = 0;
return dc2; return dc2;
} }
@ -133,20 +198,7 @@ EAPI void
evas_common_draw_context_free(RGBA_Draw_Context *dc) evas_common_draw_context_free(RGBA_Draw_Context *dc)
{ {
if (!dc) return; if (!dc) return;
_evas_common_draw_context_stash(dc);
#ifdef HAVE_PIXMAN
#if defined(PIXMAN_FONT) || defined(PIXMAN_RECT) || defined(PIXMAN_LINE) || defined(PIXMAN_POLY)
if (dc->col.pixman_color_image)
{
pixman_image_unref(dc->col.pixman_color_image);
dc->col.pixman_color_image = NULL;
}
#endif
#endif
evas_common_draw_context_apply_clean_cutouts(&dc->cutout);
evas_common_draw_context_cutouts_real_free(dc->cache.rects);
free(dc);
} }
EAPI void EAPI void
@ -814,10 +866,3 @@ evas_common_draw_context_set_render_op(RGBA_Draw_Context *dc , int op)
{ {
dc->render_op = op; dc->render_op = op;
} }
EAPI void
evas_common_draw_context_set_sli(RGBA_Draw_Context *dc, int y, int h)
{
dc->sli.y = y;
dc->sli.h = h;
}

View File

@ -48,7 +48,6 @@ evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
// Basic draw context // Basic draw context
memset(&dc, 0, sizeof(dc)); memset(&dc, 0, sizeof(dc));
dc.sli.h = 1;
dc.render_op = EVAS_RENDER_COPY; dc.render_op = EVAS_RENDER_COPY;
// Do the scale // Do the scale

View File

@ -743,32 +743,6 @@ struct _Evas_Common_Transform
struct _RGBA_Draw_Context struct _RGBA_Draw_Context
{ {
struct {
Eina_Bool use : 1;
DATA32 col;
} mul;
struct {
#ifdef HAVE_PIXMAN
pixman_image_t *pixman_color_image;
#endif
DATA32 col;
} col;
struct RGBA_Draw_Context_clip {
int x, y, w, h;
Evas_Public_Data *evas; // for async unref
void *mask; // RGBA_Image (SW) or Evas_GL_Image (GL)
int mask_x, mask_y;
Eina_Bool use : 1;
Eina_Bool async : 1;
} clip;
Cutout_Rects cutout;
struct {
int x, y, w, h;
} cutout_target;
struct {
Cutout_Rects *rects;
int used;
} cache;
struct { struct {
struct { struct {
void *(*gl_new) (void *data, RGBA_Font_Glyph *fg); void *(*gl_new) (void *data, RGBA_Font_Glyph *fg);
@ -781,13 +755,36 @@ struct _RGBA_Draw_Context
void *data; void *data;
} font_ext; } font_ext;
struct { struct {
int color_space; int x, y, w, h;
} interpolation; } cutout_target;
struct RGBA_Draw_Context_clip {
Evas_Public_Data *evas; // for async unref
void *mask; // RGBA_Image (SW) or Evas_GL_Image (GL)
int x, y, w, h;
int mask_x, mask_y;
Eina_Bool use : 1;
Eina_Bool async : 1;
} clip;
struct { struct {
int y, h; #ifdef HAVE_PIXMAN
} sli; pixman_image_t *pixman_color_image;
int render_op; #endif
Eina_Bool anti_alias : 1; DATA32 col;
} col;
Cutout_Rects cutout;
struct {
DATA32 col;
Eina_Bool use : 1;
} mul;
struct {
Cutout_Rects *rects;
unsigned int used;
} cache;
struct {
unsigned char color_space;
} interpolation;
unsigned char render_op;
unsigned char anti_alias : 1;
}; };
#ifdef BUILD_PIPE_RENDER #ifdef BUILD_PIPE_RENDER