summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCedric Bail <cedric@osg.samsung.com>2017-09-16 17:43:18 -0700
committerCedric Bail <cedric@osg.samsung.com>2017-09-17 11:49:48 -0700
commitdd297854d13832b275f9d709cdbf0b2ff359e0a8 (patch)
tree716f436fbf54620a874694356dfeb3f2f64fe183 /src/lib
parentaec79f9d0d94d2f4717d61dc8aec7f6da3a80606 (diff)
ector: add ability to run task in another thread during preparation stage.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ector/software/ector_software_private.h23
-rw-r--r--src/lib/ector/software/ector_software_surface.c183
2 files changed, 203 insertions, 3 deletions
diff --git a/src/lib/ector/software/ector_software_private.h b/src/lib/ector/software/ector_software_private.h
index 459de01..a255fd3 100644
--- a/src/lib/ector/software/ector_software_private.h
+++ b/src/lib/ector/software/ector_software_private.h
@@ -7,6 +7,16 @@
7#include "../ector_private.h" 7#include "../ector_private.h"
8 8
9typedef struct _Ector_Software_Surface_Data Ector_Software_Surface_Data; 9typedef struct _Ector_Software_Surface_Data Ector_Software_Surface_Data;
10typedef struct _Ector_Software_Thread Ector_Software_Thread;
11
12struct _Ector_Software_Thread
13{
14 Eina_Thread_Queue *queue;
15 Eina_Thread thread;
16
17 SW_FT_Raster raster;
18 SW_FT_Stroker stroker;
19};
10 20
11// Gradient related structure 21// Gradient related structure
12typedef struct _Software_Gradient_Linear_Data 22typedef struct _Software_Gradient_Linear_Data
@@ -118,19 +128,26 @@ void ector_software_rasterizer_clip_shape_set(Software_Rasterizer *rasterizer, S
118 128
119 129
120 130
121Shape_Rle_Data * ector_software_rasterizer_generate_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline); 131Shape_Rle_Data * ector_software_rasterizer_generate_rle_data(Ector_Software_Thread *thread, Software_Rasterizer *rasterizer, SW_FT_Outline *outline);
122Shape_Rle_Data * ector_software_rasterizer_generate_stroke_rle_data(Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath); 132Shape_Rle_Data * ector_software_rasterizer_generate_stroke_rle_data(Ector_Software_Thread *thread, Software_Rasterizer *rasterizer, SW_FT_Outline *outline, Eina_Bool closePath);
123 133
124void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, int x, int y, uint32_t mul_col, Efl_Gfx_Render_Op op, Shape_Rle_Data* rle); 134void ector_software_rasterizer_draw_rle_data(Software_Rasterizer *rasterizer, int x, int y, uint32_t mul_col, Efl_Gfx_Render_Op op, Shape_Rle_Data* rle);
125 135
126void ector_software_rasterizer_destroy_rle_data(Shape_Rle_Data *rle); 136void ector_software_rasterizer_destroy_rle_data(Shape_Rle_Data *rle);
127 137
128 138
129
130// Gradient Api 139// Gradient Api
131void update_color_table(Ector_Renderer_Software_Gradient_Data *gdata); 140void update_color_table(Ector_Renderer_Software_Gradient_Data *gdata);
132void destroy_color_table(Ector_Renderer_Software_Gradient_Data *gdata); 141void destroy_color_table(Ector_Renderer_Software_Gradient_Data *gdata);
133void fetch_linear_gradient(uint32_t *buffer, Span_Data *data, int y, int x, int length); 142void fetch_linear_gradient(uint32_t *buffer, Span_Data *data, int y, int x, int length);
134void fetch_radial_gradient(uint32_t *buffer, Span_Data *data, int y, int x, int length); 143void fetch_radial_gradient(uint32_t *buffer, Span_Data *data, int y, int x, int length);
135 144
145void ector_software_thread_init(Ector_Software_Thread *thread);
146void ector_software_thread_shutdown(Ector_Software_Thread *thread);
147
148typedef void (*Ector_Thread_Worker_Cb)(void *data, Ector_Software_Thread *thread);
149
150void ector_software_wait(Ector_Thread_Worker_Cb cb, Eina_Free_Cb done, void *data);
151void ector_software_schedule(Ector_Thread_Worker_Cb cb, Eina_Free_Cb done, void *data);
152
136#endif 153#endif
diff --git a/src/lib/ector/software/ector_software_surface.c b/src/lib/ector/software/ector_software_surface.c
index 1631449..016b267 100644
--- a/src/lib/ector/software/ector_software_surface.c
+++ b/src/lib/ector/software/ector_software_surface.c
@@ -10,6 +10,185 @@
10 10
11#define MY_CLASS ECTOR_SOFTWARE_SURFACE_CLASS 11#define MY_CLASS ECTOR_SOFTWARE_SURFACE_CLASS
12 12
13typedef struct _Ector_Software_Task Ector_Software_Task;
14
15struct _Ector_Software_Task
16{
17 Eina_Thread_Queue_Msg member;
18
19 Ector_Thread_Worker_Cb cb;
20 Eina_Free_Cb done;
21 void *data;
22};
23
24static int count_init = 0;
25static unsigned int current = 0;
26static unsigned int cpu_core = 0;
27static Ector_Software_Thread *ths = NULL;
28static Eina_Thread_Queue *render_queue = NULL;
29static Ector_Software_Thread render_thread;
30
31static void *
32_prepare_process(void *data, Eina_Thread t)
33{
34 Ector_Software_Thread *th = data;
35
36 eina_thread_name_set(t, "Ector Preparing Thread");
37 do
38 {
39 Ector_Software_Task *task, todo;
40 void *ref;
41
42 task = eina_thread_queue_wait(th->queue, &ref);
43
44 if (!task) break ;
45 todo.cb = task->cb;
46 todo.data = task->data;
47 todo.done = task->done;
48
49 eina_thread_queue_wait_done(th->queue, ref);
50
51 if (!todo.cb) break ;
52
53 todo.cb(todo.data, th);
54
55 task = eina_thread_queue_send(render_queue, sizeof (Ector_Software_Task), &ref);
56 task->cb = todo.cb;
57 task->data = todo.data;
58 task->done = todo.done;
59 eina_thread_queue_send_done(render_queue, ref);
60 }
61 while (1);
62
63 return th;
64}
65
66
67static void
68_ector_software_init(void)
69{
70 int cpu, i;
71
72 if (count_init++) return ;
73
74 cpu = eina_cpu_count() - 1;
75 if (cpu < 1)
76 {
77 render_thread.queue = NULL;
78 ector_software_thread_init(&render_thread);
79 return ;
80 }
81 cpu = cpu > 8 ? 8 : cpu;
82 cpu_core = cpu;
83
84 render_queue = eina_thread_queue_new();
85
86 ths = malloc(sizeof(Ector_Software_Thread) * cpu);
87 for (i = 0; i < cpu; i++)
88 {
89 Ector_Software_Thread *t;
90
91 t = &ths[i];
92 t->queue = eina_thread_queue_new();
93 if (!eina_thread_create(&t->thread, EINA_THREAD_NORMAL, -1,
94 _prepare_process, t))
95 {
96 eina_thread_queue_free(t->queue);
97 t->queue = NULL;
98 }
99 }
100}
101
102static void
103_ector_software_shutdown(void)
104{
105 Ector_Software_Thread *t;
106 unsigned int i;
107
108 if (!--count_init) return ;
109
110 if (!ths) return ;
111
112 for (i = 0; i < cpu_core; i++)
113 {
114 Ector_Software_Task *task;
115 void *ref;
116
117 t = &ths[i];
118
119 task = eina_thread_queue_send(t->queue, sizeof (Ector_Software_Task), &ref);
120 task->cb = NULL;
121 task->data = NULL;
122 eina_thread_queue_send_done(t->queue, ref);
123
124 eina_thread_join(t->thread);
125 eina_thread_queue_free(t->queue);
126 }
127
128 eina_thread_queue_free(render_queue);
129 render_queue = NULL;
130
131 free(ths);
132 ths = NULL;
133}
134
135void
136ector_software_schedule(Ector_Thread_Worker_Cb cb, Eina_Free_Cb done, void *data)
137{
138 Ector_Software_Thread *t;
139 Ector_Software_Task *task;
140 void *ref;
141
142 // Not enough CPU, doing it inline in the rendering thread
143 if (!ths) return ;
144
145 t = &ths[current];
146 current = (current + 1) % cpu_core;
147
148 task = eina_thread_queue_send(t->queue, sizeof (Ector_Software_Task), &ref);
149 task->cb = cb;
150 task->done = done;
151 task->data = data;
152 eina_thread_queue_send_done(t->queue, ref);
153}
154
155// Do not call this function if the done function has already called
156void
157ector_software_wait(Ector_Thread_Worker_Cb cb, Eina_Free_Cb done, void *data)
158{
159 Ector_Software_Task *task, covering;
160
161 // First handle case with just inlined prepare code call inside the rendering thread
162 if (!ths)
163 {
164 render_thread.thread = eina_thread_self();
165 cb(data, &render_thread);
166 done(data);
167
168 return ;
169 }
170
171 // We don't know which task is going to be done first, so
172 // we iterate until we find ourself back and trigger all
173 // the done call along the way.
174 do
175 {
176 void *ref;
177
178 task = eina_thread_queue_wait(render_queue, &ref);
179 if (!task) break;
180 covering.cb = task->cb;
181 covering.done = task->done;
182 covering.data = task->data;
183 eina_thread_queue_wait_done(render_queue, ref);
184
185 covering.done(covering.data);
186 }
187 while (covering.cb != cb ||
188 covering.done != done ||
189 covering.data != data);
190}
191
13static Ector_Renderer * 192static Ector_Renderer *
14_ector_software_surface_ector_surface_renderer_factory_new(Eo *obj, 193_ector_software_surface_ector_surface_renderer_factory_new(Eo *obj,
15 Ector_Software_Surface_Data *pd EINA_UNUSED, 194 Ector_Software_Surface_Data *pd EINA_UNUSED,
@@ -29,6 +208,8 @@ _ector_software_surface_ector_surface_renderer_factory_new(Eo *obj,
29static Eo * 208static Eo *
30_ector_software_surface_efl_object_constructor(Eo *obj, Ector_Software_Surface_Data *pd) 209_ector_software_surface_efl_object_constructor(Eo *obj, Ector_Software_Surface_Data *pd)
31{ 210{
211 _ector_software_init();
212
32 obj = efl_constructor(efl_super(obj, MY_CLASS)); 213 obj = efl_constructor(efl_super(obj, MY_CLASS));
33 pd->rasterizer = (Software_Rasterizer *) calloc(1, sizeof(Software_Rasterizer)); 214 pd->rasterizer = (Software_Rasterizer *) calloc(1, sizeof(Software_Rasterizer));
34 ector_software_rasterizer_init(pd->rasterizer); 215 ector_software_rasterizer_init(pd->rasterizer);
@@ -44,6 +225,8 @@ _ector_software_surface_efl_object_destructor(Eo *obj, Ector_Software_Surface_Da
44 free(pd->rasterizer); 225 free(pd->rasterizer);
45 pd->rasterizer = NULL; 226 pd->rasterizer = NULL;
46 efl_destructor(efl_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS)); 227 efl_destructor(efl_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS));
228
229 _ector_software_shutdown();
47} 230}
48 231
49static void 232static void