* evas: improve thread rendering by moving image loading in worker thread.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 24 Mar 2010 19:07:59 +0000 (19:07 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 24 Mar 2010 19:07:59 +0000 (19:07 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/evas@47434 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/cache/evas_cache.h
src/lib/cache/evas_cache_image.c
src/lib/engines/common/evas_pipe.c
src/lib/engines/common/evas_pipe.h
src/lib/include/evas_common.h
src/modules/engines/software_generic/evas_engine.c

index c146db3..0217de4 100644 (file)
@@ -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);
index 0821b3a..7c34c52 100644 (file)
@@ -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)
 {
index 7841951..bafb95a 100644 (file)
@@ -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
index 92e1721..77c5dd3 100644 (file)
@@ -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,
index 926c486..2605e06 100644 (file)
@@ -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
index f15dbc0..c9c5345 100644 (file)
@@ -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);