summaryrefslogtreecommitdiff
path: root/src/modules/evas/engines/software_generic/filters
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-01-17 16:13:35 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-04-14 11:26:42 +0900
commit0740010a061d15a4ecaa00dc21c10301e0af4847 (patch)
treeecd597c41438ca03a1f85cfb5a09bfbcffe6d094 /src/modules/evas/engines/software_generic/filters
parentf370ea803b977c245f173bae1b3b904e9bb68e38 (diff)
evas filters: Move blend to software_generic (1/8)
This is an attempt at refactoring the filters code so I can later implement GL support. This patch adds a few extra changes to remove avoid calling functions of libevas from the software engine: use the draw functions from static_libs/draw rather than evas_common APIs.
Diffstat (limited to 'src/modules/evas/engines/software_generic/filters')
-rw-r--r--src/modules/evas/engines/software_generic/filters/evas_filter_blend.c452
1 files changed, 452 insertions, 0 deletions
diff --git a/src/modules/evas/engines/software_generic/filters/evas_filter_blend.c b/src/modules/evas/engines/software_generic/filters/evas_filter_blend.c
new file mode 100644
index 0000000000..be43af9203
--- /dev/null
+++ b/src/modules/evas/engines/software_generic/filters/evas_filter_blend.c
@@ -0,0 +1,452 @@
1#include "../evas_engine_filter.h"
2#include "ector_buffer.h"
3#include "draw.h"
4
5// FIXME: This should all be based on ector renderer
6
7// Use a better formula than R+G+B for rgba to alpha conversion (RGB to YCbCr)
8#define RGBA2ALPHA_WEIGHTED 1
9
10typedef Eina_Bool (*draw_func) (void *data, void *context, const void *src_map, unsigned int src_stride, void *dst_map, unsigned int dst_stride, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth, Eina_Bool do_async);
11static Eina_Bool _mapped_blend(void *data, void *drawctx, const void *src_map, unsigned int src_stride, void *dst_map, unsigned int dst_stride, Evas_Filter_Fill_Mode fillmode, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, draw_func image_draw);
12
13struct Filter_Blend_Draw_Context
14{
15 Efl_Gfx_Render_Op rop;
16 uint32_t color;
17};
18
19#define LINELEN(stride, ptr) (stride / (sizeof(*ptr)))
20
21static Eina_Bool
22_image_draw_cpu_alpha_alpha(void *data EINA_UNUSED, void *context,
23 const void *src_map, unsigned int src_stride,
24 void *dst_map, unsigned int dst_stride,
25 int src_x, int src_y, int src_w, int src_h,
26 int dst_x, int dst_y, int dst_w, int dst_h,
27 int smooth EINA_UNUSED,
28 Eina_Bool do_async EINA_UNUSED)
29{
30 struct Filter_Blend_Draw_Context *dc = context;
31 const uint8_t *srcdata = src_map;
32 uint8_t *dstdata = dst_map;
33 Draw_Func_Alpha func;
34 int y, sw, dw;
35
36 EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
37
38 func = efl_draw_alpha_func_get(dc->rop, EINA_FALSE);
39 EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
40
41 sw = LINELEN(src_stride, srcdata);
42 dw = LINELEN(dst_stride, dstdata);
43
44 srcdata += src_y * sw;
45 dstdata += dst_y * dw;
46 for (y = src_h; y; y--)
47 {
48 func(dstdata + dst_x, srcdata + src_x, src_w);
49 srcdata += sw;
50 dstdata += dw;
51 }
52
53 return EINA_TRUE;
54}
55
56static Eina_Bool
57_image_draw_cpu_alpha_rgba(void *data EINA_UNUSED, void *context,
58 const void *src_map, unsigned int src_stride,
59 void *dst_map, unsigned int dst_stride,
60 int src_x, int src_y, int src_w, int src_h,
61 int dst_x, int dst_y, int dst_w, int dst_h,
62 int smooth EINA_UNUSED,
63 Eina_Bool do_async EINA_UNUSED)
64{
65 struct Filter_Blend_Draw_Context *dc = context;
66 uint8_t *srcdata = (uint8_t *) src_map;
67 uint32_t *dstdata = dst_map;
68 RGBA_Comp_Func_Mask func;
69 int y, sw, dw;
70
71 EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
72
73 func = efl_draw_func_mask_span_get(dc->rop, dc->color);
74 EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
75
76 sw = LINELEN(src_stride, srcdata);
77 dw = LINELEN(dst_stride, dstdata);
78
79 srcdata += src_y * sw;
80 dstdata += dst_y * dw;
81 for (y = src_h; y; y--)
82 {
83 func(dstdata + dst_x, srcdata + src_x, src_w, dc->color);
84 srcdata += sw;
85 dstdata += dw;
86 }
87
88 return EINA_TRUE;
89}
90
91static Eina_Bool
92_image_draw_cpu_rgba_rgba(void *data EINA_UNUSED, void *context,
93 const void *src_map, unsigned int src_stride,
94 void *dst_map, unsigned int dst_stride,
95 int src_x, int src_y, int src_w, int src_h,
96 int dst_x, int dst_y, int dst_w, int dst_h,
97 int smooth EINA_UNUSED,
98 Eina_Bool do_async EINA_UNUSED)
99{
100 struct Filter_Blend_Draw_Context *dc = context;
101 uint32_t *srcdata = (uint32_t *) src_map;
102 uint32_t *dstdata = dst_map;
103 RGBA_Comp_Func func;
104 int y, sw, dw;
105
106 EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
107
108 if (!dc->color)
109 return EINA_TRUE;
110 else
111 func = efl_draw_func_span_get(dc->rop, dc->color, EINA_TRUE);
112 EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
113
114 sw = LINELEN(src_stride, srcdata);
115 dw = LINELEN(dst_stride, dstdata);
116
117 srcdata += src_y * sw;
118 dstdata += dst_y * dw;
119 for (y = src_h; y; y--)
120 {
121 func(dstdata + dst_x, srcdata + src_x, src_w, dc->color, 255);
122 srcdata += sw;
123 dstdata += dw;
124 }
125
126 return EINA_TRUE;
127}
128
129static Eina_Bool
130_image_draw_cpu_rgba_alpha(void *data EINA_UNUSED, void *context EINA_UNUSED,
131 const void *src_map, unsigned int src_stride,
132 void *dst_map, unsigned int dst_stride,
133 int src_x, int src_y, int src_w, int src_h,
134 int dst_x, int dst_y, int dst_w, int dst_h,
135 int smooth EINA_UNUSED,
136 Eina_Bool do_async EINA_UNUSED)
137{
138 uint32_t *srcdata = (uint32_t *) src_map;
139 uint8_t *dstdata = dst_map;
140 int x, y, sw, dw;
141#if RGBA2ALPHA_WEIGHTED
142 const int WR = 299;
143 const int WG = 587;
144 const int WB = 114;
145#else
146 const int WR = 1;
147 const int WG = 1;
148 const int WB = 1;
149#endif
150 DEFINE_DIVIDER(WR + WG + WB);
151
152 EINA_SAFETY_ON_FALSE_RETURN_VAL((src_w == dst_w) && (src_h == dst_h), EINA_FALSE);
153
154 sw = LINELEN(src_stride, srcdata);
155 dw = LINELEN(dst_stride, dstdata);
156
157 /* FIXME: no draw function here? */
158
159 srcdata += src_y * sw;
160 dstdata += dst_y * dw;
161 for (y = src_h; y; y--)
162 {
163 uint32_t *s = srcdata + src_x;
164 uint8_t *d = dstdata + dst_x;
165 for (x = src_w; x; x--, d++, s++)
166 *d = DIVIDE((R_VAL(s) * WR) + (G_VAL(s) * WG) + (B_VAL(s) * WB));
167 srcdata += sw;
168 dstdata += dw;
169 }
170
171 return EINA_TRUE;
172}
173
174static Eina_Bool
175_filter_blend_cpu_generic_do(Evas_Filter_Command *cmd, draw_func image_draw)
176{
177 unsigned int src_len, src_stride, dst_len, dst_stride;
178 int sw, sh, dx, dy, dw, dh, sx, sy;
179 struct Filter_Blend_Draw_Context dc;
180 Eina_Bool ret = EINA_FALSE;
181 Evas_Filter_Buffer *src_fb;
182 void *src = NULL, *dst = NULL;
183
184 sx = 0;
185 sy = 0;
186 ector_buffer_size_get(cmd->input->buffer, &sw, &sh);
187
188 dx = cmd->draw.ox;
189 dy = cmd->draw.oy;
190 ector_buffer_size_get(cmd->output->buffer, &dw, &dh);
191
192 if ((dw <= 0) || (dh <= 0) || (sw <= 0) || (sh <= 0))
193 return EINA_TRUE;
194
195 // Stretch if necessary.
196
197 /* NOTE: As of 2014/03/11, this will happen only with RGBA buffers, since
198 * only proxy sources may be scaled. So, we don't need an alpha scaling
199 * algorithm just now.
200 */
201
202 if ((sw != dw || sh != dh) && (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_XY))
203 {
204 EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->ctx->buffer_scaled_get, EINA_FALSE);
205
206 if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
207 sw = dw;
208 if (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
209 sh = dh;
210
211 BUFFERS_LOCK();
212 src_fb = cmd->ctx->buffer_scaled_get(cmd->ctx, cmd->input, sw, sh);
213 BUFFERS_UNLOCK();
214
215 EINA_SAFETY_ON_NULL_GOTO(src_fb, end);
216 src_fb->locked = EINA_FALSE;
217 }
218 else src_fb = cmd->input;
219
220 src = _buffer_map_all(src_fb->buffer, &src_len, E_READ, src_fb->alpha_only ? E_ALPHA : E_ARGB, &src_stride);
221 dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, cmd->output->alpha_only ? E_ALPHA : E_ARGB, &dst_stride);
222 EINA_SAFETY_ON_FALSE_GOTO(src && dst, end);
223
224 dc.rop = cmd->draw.rop;
225 dc.color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
226
227 ret = _mapped_blend(cmd->ENDT, &dc, src, src_stride, dst, dst_stride, cmd->draw.fillmode,
228 sx, sy, sw, sh, dx, dy, dw, dh, image_draw);
229
230end:
231 if (src) ector_buffer_unmap(src_fb->buffer, src, src_len);
232 if (dst) ector_buffer_unmap(cmd->output->buffer, dst, dst_len);
233 return ret;
234}
235
236static Eina_Bool
237_filter_blend_cpu_alpha(Evas_Filter_Command *cmd)
238{
239 return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_alpha_alpha);
240}
241
242static Eina_Bool
243_filter_blend_cpu_alpha_rgba(Evas_Filter_Command *cmd)
244{
245 return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_alpha_rgba);
246}
247
248static Eina_Bool
249_filter_blend_cpu_rgba_alpha(Evas_Filter_Command *cmd)
250{
251 return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_rgba_alpha);
252}
253
254static Eina_Bool
255_filter_blend_cpu_rgba(Evas_Filter_Command *cmd)
256{
257 return _filter_blend_cpu_generic_do(cmd, _image_draw_cpu_rgba_rgba);
258}
259
260static Eina_Bool
261_mapped_blend(void *data, void *drawctx,
262 const void *src_map, unsigned int src_stride,
263 void *dst_map, unsigned int dst_stride,
264 Evas_Filter_Fill_Mode fillmode,
265 int sx, int sy,
266 int sw, int sh,
267 int dx, int dy,
268 int dw, int dh,
269 draw_func image_draw)
270{
271 int right = 0, bottom = 0, left = 0, top = 0;
272 int row, col, rows, cols;
273 Eina_Bool ret = EINA_TRUE;
274
275 EINA_SAFETY_ON_FALSE_RETURN_VAL((sx == 0) && (sy == 0), EINA_FALSE);
276
277 if (fillmode == EVAS_FILTER_FILL_MODE_NONE)
278 {
279 _clip_to_target(&sx, &sy, sw, sh, dx, dy, dw, dh, &dx, &dy, &rows, &cols);
280 XDBG("blend: %d,%d,%d,%d --> %d,%d,%d,%d (from %dx%d to %dx%d +%d,%d)",
281 0, 0, sw, sh, dx, dy, cols, rows, sw, sh, dw, dh, dx, dy);
282 image_draw(data, drawctx,
283 src_map, src_stride, dst_map, dst_stride,
284 sx, sy, cols, rows, // src
285 dx, dy, cols, rows, // dst
286 EINA_TRUE, // smooth
287 EINA_FALSE); // Not async
288 return EINA_TRUE;
289 }
290
291 if (fillmode & EVAS_FILTER_FILL_MODE_REPEAT_X)
292 {
293 if (dx > 0) left = dx % sw;
294 else if (dx < 0) left = sw + (dx % sw);
295 cols = (dw /*- left*/) / sw;
296 if (left > 0)
297 right = dw - (sw * (cols - 1)) - left;
298 else
299 right = dw - (sw * cols);
300 dx = 0;
301 }
302 else if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
303 {
304 cols = 0;
305 dx = 0;
306 }
307 else
308 {
309 // FIXME: Probably wrong if dx != 0
310 cols = 0;
311 dw -= dx;
312 }
313
314 if (fillmode & EVAS_FILTER_FILL_MODE_REPEAT_Y)
315 {
316 if (dy > 0) top = dy % sh;
317 else if (dy < 0) top = sh + (dy % sh);
318 rows = (dh /*- top*/) / sh;
319 if (top > 0)
320 bottom = dh - (sh * (rows - 1)) - top;
321 else
322 bottom = dh - (sh * rows);
323 dy = 0;
324 }
325 else if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
326 {
327 rows = 0;
328 dy = 0;
329 }
330 else
331 {
332 // FIXME: Probably wrong if dy != 0
333 rows = 0;
334 dh -= dy;
335 }
336
337 if (top > 0) row = -1;
338 else row = 0;
339 for (; row <= rows; row++)
340 {
341 int src_x, src_y, src_w, src_h;
342 int dst_x, dst_y, dst_w, dst_h;
343
344 if (row == -1 && top > 0)
345 {
346 // repeat only
347 src_h = top;
348 src_y = sh - top;
349 dst_y = dy;
350 dst_h = src_h;
351 }
352 else if (row == rows && bottom > 0)
353 {
354 // repeat only
355 src_h = bottom;
356 src_y = 0;
357 dst_y = top + dy + row * sh;
358 dst_h = src_h;
359 }
360 else
361 {
362 src_y = 0;
363 if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y)
364 {
365 src_h = sh;
366 dst_h = dh;
367 dst_y = 0;
368 }
369 else
370 {
371 dst_y = top + dy + row * sh;
372 src_h = MIN(dh - dst_y, sh);
373 dst_h = src_h;
374 }
375 }
376 if (src_h <= 0 || dst_h <= 0) break;
377
378 if (left > 0) col = -1;
379 else col = 0;
380 for (; col <= cols; col++)
381 {
382 if (col == -1 && left > 0)
383 {
384 // repeat only
385 src_w = left;
386 src_x = sw - left;
387 dst_x = dx;
388 dst_w = src_w;
389 }
390 else if (col == cols && right > 0)
391 {
392 // repeat only
393 src_w = right;
394 src_x = 0;
395 dst_x = left + dx + col * sw;
396 dst_w = src_w;
397 }
398 else
399 {
400 src_x = 0;
401 if (fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X)
402 {
403 src_w = sw;
404 dst_w = dw;
405 dst_x = 0;
406 }
407 else
408 {
409 dst_x = left + dx + col * sw;
410 src_w = MIN(dw - dst_x, sw);
411 dst_w = src_w;
412 }
413 }
414 if (src_w <= 0 || dst_w <= 0) break;
415
416 XDBG("blend: [%d,%d] %d,%d,%dx%d --> %d,%d,%dx%d "
417 "(src %dx%d, dst %dx%d)",
418 col, row, src_x, src_y, src_w, src_h,
419 dst_x, dst_y, dst_w, dst_h,
420 sw, sh, dw, dh);
421 image_draw(data, drawctx,
422 src_map, src_stride, dst_map, dst_stride,
423 src_x, src_y, src_w, src_h,
424 dst_x, dst_y, dst_w, dst_h,
425 EINA_TRUE, EINA_FALSE);
426 }
427 }
428 return ret;
429}
430
431Evas_Filter_Apply_Func
432eng_filter_blend_func_get(Evas_Filter_Command *cmd)
433{
434 EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
435 EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
436 EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
437
438 if (cmd->input->alpha_only)
439 {
440 if (cmd->output->alpha_only)
441 return _filter_blend_cpu_alpha;
442 else
443 return _filter_blend_cpu_alpha_rgba;
444 }
445 else
446 {
447 if (cmd->output->alpha_only)
448 return _filter_blend_cpu_rgba_alpha;
449 else
450 return _filter_blend_cpu_rgba;
451 }
452}