From 32f4a230e35f27005e60419ef4bbb18ce612eea5 Mon Sep 17 00:00:00 2001 From: cedric Date: Wed, 24 Mar 2010 19:07:59 +0000 Subject: [PATCH] * evas: improve thread rendering by moving image loading in worker thread. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@47434 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/cache/evas_cache.h | 1 + src/lib/cache/evas_cache_image.c | 10 + src/lib/engines/common/evas_pipe.c | 202 +++++++++++++++++---- src/lib/engines/common/evas_pipe.h | 3 +- src/lib/include/evas_common.h | 1 + src/modules/engines/software_generic/evas_engine.c | 10 +- 6 files changed, 183 insertions(+), 44 deletions(-) diff --git a/src/lib/cache/evas_cache.h b/src/lib/cache/evas_cache.h index c146db3..0217de4 100644 --- a/src/lib/cache/evas_cache.h +++ b/src/lib/cache/evas_cache.h @@ -128,6 +128,7 @@ EAPI void evas_cache_image_set(Evas_Cache_Image *cache, int EAPI Image_Entry* evas_cache_image_alone(Image_Entry *im); EAPI Image_Entry* evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h); EAPI void evas_cache_image_load_data(Image_Entry *im); +EAPI Eina_Bool evas_cache_image_is_loaded(Image_Entry *im); EAPI void evas_cache_image_surface_alloc(Image_Entry *im, int w, int h); EAPI DATA32* evas_cache_image_pixels(Image_Entry *im); EAPI Image_Entry* evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace); diff --git a/src/lib/cache/evas_cache_image.c b/src/lib/cache/evas_cache_image.c index 0821b3a..7c34c52 100644 --- a/src/lib/cache/evas_cache_image.c +++ b/src/lib/cache/evas_cache_image.c @@ -1179,6 +1179,16 @@ evas_cache_image_load_data(Image_Entry *im) #endif } +EAPI Eina_Bool +evas_cache_image_is_loaded(Image_Entry *im) +{ + assert(im); + + if (im->flags.loaded) + return EINA_TRUE; + return EINA_FALSE; +} + EAPI void evas_cache_image_preload_data(Image_Entry *im, const void *target) { diff --git a/src/lib/engines/common/evas_pipe.c b/src/lib/engines/common/evas_pipe.c index 7841951..bafb95a 100644 --- a/src/lib/engines/common/evas_pipe.c +++ b/src/lib/engines/common/evas_pipe.c @@ -116,7 +116,7 @@ static Thinfo thinfo[TH_MAX]; static pthread_barrier_t thbarrier[2]; #endif -EAPI void +static void evas_common_pipe_begin(RGBA_Image *im) { #ifdef BUILD_PTHREAD @@ -124,33 +124,6 @@ evas_common_pipe_begin(RGBA_Image *im) if (!im->pipe) return; if (thread_num == 1) return; - if (thread_num == 0) - { - int cpunum; - - cpunum = eina_cpu_count(); - thread_num = cpunum; - if (thread_num == 1) return; - pthread_barrier_init(&(thbarrier[0]), NULL, thread_num + 1); - pthread_barrier_init(&(thbarrier[1]), NULL, thread_num + 1); - for (i = 0; i < thread_num; i++) - { - pthread_attr_t attr; - cpu_set_t cpu; - - pthread_attr_init(&attr); - CPU_ZERO(&cpu); - CPU_SET(i % cpunum, &cpu); - pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu); - thinfo[i].thread_num = i; - thinfo[i].info = NULL; - thinfo[i].barrier = thbarrier; - /* setup initial locks */ - pthread_create(&(thinfo[i].thread_id), &attr, - evas_common_pipe_thread, &(thinfo[i])); - pthread_attr_destroy(&attr); - } - } y = 0; h = im->cache_entry.h / thread_num; if (h < 1) h = 1; @@ -183,7 +156,7 @@ evas_common_pipe_begin(RGBA_Image *im) #endif } -EAPI void +static void evas_common_pipe_flush(RGBA_Image *im) { @@ -675,6 +648,8 @@ evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, op->op_func = evas_common_pipe_image_draw_do; op->free_func = evas_common_pipe_op_image_free; evas_common_pipe_draw_context_copy(dc, op); + + evas_common_pipe_image_load(src); } static void @@ -743,10 +718,12 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, op->op_func = evas_common_pipe_map4_draw_do; op->free_func = evas_common_pipe_op_map4_free; evas_common_pipe_draw_context_copy(dc, op); + + evas_common_pipe_image_load(src); } -EAPI void -evas_common_pipe_map4_begin(RGBA_Image *root) +static void +evas_common_pipe_map4_render(RGBA_Image *root) { RGBA_Pipe *p; int i; @@ -759,12 +736,12 @@ evas_common_pipe_map4_begin(RGBA_Image *root) if (p->op[i].op_func == evas_common_pipe_map4_draw_do) { if (p->op[i].op.map4.src->pipe) - evas_common_pipe_map4_begin(p->op[i].op.map4.src); + evas_common_pipe_map4_render(p->op[i].op.map4.src); } else if (p->op[i].op_func == evas_common_pipe_image_draw_do) { if (p->op[i].op.image.src->pipe) - evas_common_pipe_map4_begin(p->op[i].op.image.src); + evas_common_pipe_map4_render(p->op[i].op.image.src); } } } @@ -772,4 +749,163 @@ evas_common_pipe_map4_begin(RGBA_Image *root) evas_common_pipe_begin(root); evas_common_pipe_flush(root); } + +#ifdef BUILD_PTHREAD +static Eina_List *task = NULL; +static Thinfo task_thinfo[TH_MAX]; +static pthread_barrier_t task_thbarrier[2]; +static LK(task_mutext) = PTHREAD_MUTEX_INITIALIZER; +#endif + +#ifdef BUILD_PTHREAD +static void* +evas_common_pipe_load(void *data) +{ + Thinfo *thinfo; + + thinfo = data; + for (;;) + { + /* wait for start signal */ + pthread_barrier_wait(&(thinfo->barrier[0])); + + while (task) + { + RGBA_Image *im = NULL; + + LKL(task_mutext); + im = eina_list_data_get(task); + task = eina_list_remove_list(task, task); + LKU(task_mutext); + + if (im) + { + if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888) + evas_cache_image_load_data(&im->cache_entry); + evas_common_image_colorspace_normalize(im); + + im->flags &= ~RGBA_IMAGE_TODO_LOAD; + } + } + + /* send finished signal */ + pthread_barrier_wait(&(thinfo->barrier[1])); + } + + return NULL; +} +#endif + +static void +evas_common_pipe_image_load_do(void) +{ +#ifdef BUILD_PTHREAD + /* Notify worker thread. */ + pthread_barrier_wait(&(task_thbarrier[0])); + + /* sync worker threads */ + pthread_barrier_wait(&(task_thbarrier[1])); +#endif +} + +static Eina_Bool +evas_common_pipe_init(void) +{ +#ifdef BUILD_PTHREAD + if (thread_num == 0) + { + int cpunum; + int i; + + cpunum = eina_cpu_count(); + thread_num = cpunum; + if (thread_num == 1) return EINA_FALSE; + + pthread_barrier_init(&(thbarrier[0]), NULL, thread_num + 1); + pthread_barrier_init(&(thbarrier[1]), NULL, thread_num + 1); + for (i = 0; i < thread_num; i++) + { + pthread_attr_t attr; + cpu_set_t cpu; + + pthread_attr_init(&attr); + CPU_ZERO(&cpu); + CPU_SET(i % cpunum, &cpu); + pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu); + thinfo[i].thread_num = i; + thinfo[i].info = NULL; + thinfo[i].barrier = thbarrier; + /* setup initial locks */ + pthread_create(&(thinfo[i].thread_id), &attr, + evas_common_pipe_thread, &(thinfo[i])); + pthread_attr_destroy(&attr); + } + + pthread_barrier_init(&(task_thbarrier[0]), NULL, thread_num + 1); + pthread_barrier_init(&(task_thbarrier[1]), NULL, thread_num + 1); + for (i = 0; i < thread_num; i++) + { + pthread_attr_t attr; + cpu_set_t cpu; + + pthread_attr_init(&attr); + CPU_ZERO(&cpu); + CPU_SET(i % cpunum, &cpu); + pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu); + task_thinfo[i].thread_num = i; + task_thinfo[i].info = NULL; + task_thinfo[i].barrier = task_thbarrier; + /* setup initial locks */ + pthread_create(&(task_thinfo[i].thread_id), &attr, + evas_common_pipe_load, &(task_thinfo[i])); + pthread_attr_destroy(&attr); + } + } + if (thread_num == 1) return EINA_FALSE; + return EINA_TRUE; +#endif + return EINA_FALSE; +} + +EAPI void +evas_common_pipe_image_load(RGBA_Image *im) +{ + if (im->flags & RGBA_IMAGE_TODO_LOAD) + return ; + + if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888 + && !evas_cache_image_is_loaded(&(im->cache_entry))) + goto add_task; + + if ((!im->cs.data) || ((!im->cs.dirty) && (!(im->flags & RGBA_IMAGE_IS_DIRTY)))) + goto add_task; + + return ; + + add_task: + task = eina_list_append(task, im); + im->flags |= RGBA_IMAGE_TODO_LOAD; +} + +EAPI void +evas_common_pipe_map4_begin(RGBA_Image *root) +{ + if (!evas_common_pipe_init()) + { + RGBA_Image *im; + + EINA_LIST_FREE(task, im) + { + if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888) + evas_cache_image_load_data(&im->cache_entry); + evas_common_image_colorspace_normalize(im); + + im->flags &= ~RGBA_IMAGE_TODO_LOAD; + } + } + + evas_common_pipe_image_load_do(); + + evas_common_pipe_map4_render(root); +} #endif diff --git a/src/lib/engines/common/evas_pipe.h b/src/lib/engines/common/evas_pipe.h index 92e1721..77c5dd3 100644 --- a/src/lib/engines/common/evas_pipe.h +++ b/src/lib/engines/common/evas_pipe.h @@ -6,8 +6,6 @@ * threadable */ -EAPI void evas_common_pipe_begin(RGBA_Image *im); -EAPI void evas_common_pipe_flush(RGBA_Image *im); 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); @@ -15,6 +13,7 @@ EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGB EAPI void evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient *gr); EAPI void evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, int w, int h, RGBA_Gradient2 *gr); EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const char *text); +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); EAPI void evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Map_Point *p, diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index 926c486..2605e06 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -427,6 +427,7 @@ typedef enum _RGBA_Image_Flags /* RGBA_IMAGE_ALPHA_SPARSE = (1 << 5), */ /* RGBA_IMAGE_LOADED = (1 << 6), */ /* RGBA_IMAGE_NEED_DATA = (1 << 7) */ + RGBA_IMAGE_TODO_LOAD = (1 << 8), } RGBA_Image_Flags; typedef enum _Convert_Pal_Mode diff --git a/src/modules/engines/software_generic/evas_engine.c b/src/modules/engines/software_generic/evas_engine.c index f15dbc0..c9c5345 100644 --- a/src/modules/engines/software_generic/evas_engine.c +++ b/src/modules/engines/software_generic/evas_engine.c @@ -739,9 +739,6 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image, #ifdef BUILD_PIPE_RENDER if (cpunum > 1) { - if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888) - evas_cache_image_load_data(&im->cache_entry); - evas_common_image_colorspace_normalize(im); evas_common_rgba_image_scalecache_prepare(im, surface, context, smooth, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); @@ -816,12 +813,7 @@ eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *i else #ifdef BUILD_PIPE_RENDER if (cpunum > 1) - { - if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888) - evas_cache_image_load_data(&im->cache_entry); - evas_common_image_colorspace_normalize(im); - evas_common_pipe_map4_draw(im, surface, context, p, smooth, level); - } + evas_common_pipe_map4_draw(im, surface, context, p, smooth, level); else #endif evas_common_map4_rgba(im, surface, context, p, smooth, level); -- 2.7.4