and add in the 8bpp gray stuff
[framework/uifw/evas.git] / src / lib / engines / common_8 / evas_soft8_scanline_blend.c
1 /** NOTE: This file is meant to be included by users **/
2
3 /** NOTE2: r, g, b parameters are 16bits, so you can pass 0 to 256 inclusive.
4  **        this is due our division by 256 when multiplying the color.
5  **/
6
7 /*****************************************************************************
8  * Scanline processing
9  *
10  *    _soft8_scanline_<description>_<src>_<dst>[_<modifier>]()
11  *
12  ****************************************************************************/
13
14 static always_inline void
15 _soft8_pt_blend_transp_solid(DATA8 * p_dst, DATA8 src, DATA8 alpha)
16 {
17    if (alpha == 0xff)
18       *p_dst = src;
19    else if (alpha != 0)
20      {
21         *p_dst = GRY_8_BLEND(src, *p_dst, alpha);
22      }
23 }
24
25 /***********************************************************************
26  * Regular blend operations
27  */
28 static void
29 _soft8_scanline_blend_transp_solid(DATA8 * src, DATA8 * alpha, DATA8 * dst,
30                                    int size)
31 {
32    DATA8 *start, *end;
33
34    start = dst;
35    end = start + (size & ~7);
36
37    pld(alpha, 0);
38    pld(src, 0);
39
40    /* work on 8 pixels per time, do data preload */
41    while (start < end)
42      {
43         DATA8 alpha1, alpha2;
44
45         alpha1 = alpha[0];
46         alpha += 8;
47
48         /* empirical tests show these give the best performance */
49         pld(alpha, 8);
50         pld(src, 32);
51
52         src += 8;
53         start += 8;
54
55         alpha2 = alpha[-7];
56         _soft8_pt_blend_transp_solid(start - 8, src[-8], alpha1);
57
58         alpha1 = alpha[-6];
59         _soft8_pt_blend_transp_solid(start - 7, src[-7], alpha2);
60
61         alpha2 = alpha[-5];
62         _soft8_pt_blend_transp_solid(start - 6, src[-6], alpha1);
63
64         alpha1 = alpha[-4];
65         _soft8_pt_blend_transp_solid(start - 5, src[-5], alpha2);
66
67         alpha2 = alpha[-3];
68         _soft8_pt_blend_transp_solid(start - 4, src[-4], alpha1);
69
70         alpha1 = alpha[-2];
71         _soft8_pt_blend_transp_solid(start - 3, src[-3], alpha2);
72
73         alpha2 = alpha[-1];
74         _soft8_pt_blend_transp_solid(start - 2, src[-2], alpha1);
75
76         _soft8_pt_blend_transp_solid(start - 1, src[-1], alpha2);
77      }
78
79    /* remaining pixels (up to 7) */
80    end = start + (size & 7);
81    for (; start < end; start++, src++, alpha++)
82       _soft8_pt_blend_transp_solid(start, *src, *alpha);
83 }
84
85 static always_inline void
86 _soft8_pt_blend_solid_solid(DATA8 * p_dst, DATA8 src)
87 {
88    *p_dst = src;
89 }
90
91 static inline void
92 _soft8_scanline_blend_solid_solid(DATA8 * src, DATA8 * dst, int size)
93 {
94    memcpy(dst, src, size * sizeof(DATA8));
95 }
96
97 /***********************************************************************
98  * Blend operations taking an extra alpha (fade in, out)
99  */
100
101 static inline void
102 _soft8_pt_blend_transp_solid_mul_alpha(DATA8 * p_dst, DATA8 src, DATA8 alpha,
103                                        DATA8 rel_alpha)
104 {
105    alpha = alpha * rel_alpha;
106    if (alpha == 0)
107       return;
108
109    alpha++;
110    *p_dst = GRY_8_BLEND((src * rel_alpha) & 0xff, *p_dst, alpha);
111 }
112
113 static void
114 _soft8_scanline_blend_transp_solid_mul_alpha(DATA8 * src, DATA8 * alpha,
115                                              DATA8 * dst, int size,
116                                              const DATA8 rel_alpha)
117 {
118    DATA8 *start, *end;
119
120    start = dst;
121    end = start + (size & ~7);
122
123    pld(alpha, 0);
124    pld(src, 0);
125
126    while (start < end)
127      {
128         DATA8 alpha1, alpha2;
129
130         alpha1 = alpha[0];
131         alpha += 8;
132
133         pld(alpha, 8);
134         pld(src, 32);
135
136         src += 8;
137         start += 8;
138
139         alpha2 = alpha[-7];
140         _soft8_pt_blend_transp_solid_mul_alpha
141             (start - 8, src[-8], alpha1, rel_alpha);
142
143         alpha1 = alpha[-6];
144         _soft8_pt_blend_transp_solid_mul_alpha
145             (start - 7, src[-7], alpha2, rel_alpha);
146
147         alpha2 = alpha[-5];
148         _soft8_pt_blend_transp_solid_mul_alpha
149             (start - 6, src[-6], alpha1, rel_alpha);
150
151         alpha1 = alpha[-4];
152         _soft8_pt_blend_transp_solid_mul_alpha
153             (start - 5, src[-5], alpha2, rel_alpha);
154
155         alpha2 = alpha[-3];
156         _soft8_pt_blend_transp_solid_mul_alpha
157             (start - 4, src[-4], alpha1, rel_alpha);
158
159         alpha1 = alpha[-2];
160         _soft8_pt_blend_transp_solid_mul_alpha
161             (start - 3, src[-3], alpha2, rel_alpha);
162
163         alpha2 = alpha[-1];
164         _soft8_pt_blend_transp_solid_mul_alpha
165             (start - 2, src[-2], alpha1, rel_alpha);
166
167         _soft8_pt_blend_transp_solid_mul_alpha
168             (start - 1, src[-1], alpha2, rel_alpha);
169      }
170
171    end = start + (size & 7);
172    for (; start < end; start++, src++, alpha++)
173       _soft8_pt_blend_transp_solid_mul_alpha(start, *src, *alpha, rel_alpha);
174 }
175
176 static always_inline void
177 _soft8_pt_blend_solid_solid_mul_alpha(DATA8 * p_dst, DATA8 src, DATA8 rel_alpha)
178 {
179    *p_dst = GRY_8_BLEND_UNMUL(src, *p_dst, rel_alpha);
180 }
181
182 static void
183 _soft8_scanline_blend_solid_solid_mul_alpha(DATA8 * src, DATA8 * dst, int size,
184                                             DATA8 rel_alpha)
185 {
186    DATA8 *start, *end;
187
188    start = dst;
189    end = start + (size & ~7);
190
191    pld(src, 0);
192
193    while (start < end)
194      {
195         pld(src, 32);
196         UNROLL8(
197                   {
198                   _soft8_pt_blend_solid_solid_mul_alpha(start, *src, rel_alpha);
199                   start++; src++;}
200         );
201      }
202
203    end = start + (size & 7);
204    for (; start < end; start++, src++)
205       _soft8_pt_blend_solid_solid_mul_alpha(start, *src, rel_alpha);
206 }
207
208 /***********************************************************************
209  * Blend operations with extra alpha and multiply color
210  */
211
212 static always_inline void
213 _soft8_pt_blend_transp_solid_mul_color_transp(DATA8 * p_dst, DATA8 src,
214                                               DATA8 alpha, DATA8 rel_alpha,
215                                               DATA8 r, DATA8 g, DATA8 b)
216 {
217    alpha = alpha * rel_alpha;
218    if (alpha == 0)
219       return;
220
221    alpha++;
222
223    DATA8 gry8 = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
224    *p_dst = GRY_8_BLEND(gry8, *p_dst, alpha);
225 }
226
227 static void
228 _soft8_scanline_blend_transp_solid_mul_color_transp(DATA8 * src, DATA8 * alpha,
229                                                     DATA8 * dst, int size,
230                                                     DATA8 rel_alpha, DATA8 r,
231                                                     DATA8 g, DATA8 b)
232 {
233    DATA8 *start, *end;
234
235    start = dst;
236    end = start + (size & ~7);
237
238    pld(alpha, 0);
239    pld(src, 0);
240
241    while (start < end)
242      {
243         DATA8 alpha1, alpha2;
244
245         alpha1 = alpha[0];
246         alpha += 8;
247
248         pld(src, 32);
249         pld(start, 32);
250
251         src += 8;
252         start += 8;
253
254         alpha2 = alpha[-7];
255         _soft8_pt_blend_transp_solid_mul_color_transp
256             (start - 8, src[-8], alpha1, rel_alpha, r, g, b);
257
258         alpha1 = alpha[-6];
259         _soft8_pt_blend_transp_solid_mul_color_transp
260             (start - 7, src[-7], alpha2, rel_alpha, r, g, b);
261
262         alpha2 = alpha[-5];
263         _soft8_pt_blend_transp_solid_mul_color_transp
264             (start - 6, src[-6], alpha1, rel_alpha, r, g, b);
265
266         alpha1 = alpha[-4];
267         _soft8_pt_blend_transp_solid_mul_color_transp
268             (start - 5, src[-5], alpha2, rel_alpha, r, g, b);
269
270         alpha2 = alpha[-3];
271         _soft8_pt_blend_transp_solid_mul_color_transp
272             (start - 4, src[-4], alpha1, rel_alpha, r, g, b);
273
274         alpha1 = alpha[-2];
275         _soft8_pt_blend_transp_solid_mul_color_transp
276             (start - 3, src[-3], alpha2, rel_alpha, r, g, b);
277
278         alpha2 = alpha[-1];
279         _soft8_pt_blend_transp_solid_mul_color_transp
280             (start - 2, src[-2], alpha1, rel_alpha, r, g, b);
281
282         _soft8_pt_blend_transp_solid_mul_color_transp
283             (start - 1, src[-1], alpha2, rel_alpha, r, g, b);
284      }
285
286    end = start + (size & 7);
287    for (; start < end; start++, src++, alpha++)
288       _soft8_pt_blend_transp_solid_mul_color_transp
289           (start, *src, *alpha, rel_alpha, r, g, b);
290 }
291
292 static always_inline void
293 _soft8_pt_blend_solid_solid_mul_color_transp(DATA8 * p_dst, DATA8 src,
294                                              DATA8 rel_alpha, DATA8 r, DATA8 g,
295                                              DATA8 b)
296 {
297    DATA8 gry8 = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
298    *p_dst = GRY_8_BLEND(gry8, *p_dst, rel_alpha);
299 }
300
301 static void
302 _soft8_scanline_blend_solid_solid_mul_color_transp(DATA8 * src, DATA8 * dst,
303                                                    int size, DATA8 rel_alpha,
304                                                    DATA8 r, DATA8 g, DATA8 b)
305 {
306    DATA8 *start, *end;
307
308    start = dst;
309    end = start + (size & ~7);
310
311    pld(src, 0);
312
313    while (start < end)
314      {
315         pld(src, 32);
316         UNROLL8(
317                   {
318                   _soft8_pt_blend_solid_solid_mul_color_transp
319                   (start, *src, rel_alpha, r, g, b); start++; src++;}
320         );
321      }
322
323    end = start + (size & 7);
324    for (; start < end; start++, src++)
325       _soft8_pt_blend_solid_solid_mul_color_transp
326           (start, *src, rel_alpha, r, g, b);
327 }
328
329 /***********************************************************************
330  * Blend operations with extra multiply color
331  */
332 static always_inline void
333 _soft8_pt_blend_transp_solid_mul_color_solid(DATA8 * p_dst, DATA8 src,
334                                              DATA8 alpha, DATA8 r, DATA8 g,
335                                              DATA8 b)
336 {
337    if (alpha == 0)
338       return;
339
340    DATA8 gry8 = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
341
342    if (alpha == 0xff)
343       *p_dst = gry8;
344    else
345      {
346         *p_dst = GRY_8_BLEND(gry8, *p_dst, alpha);
347      }
348 }
349
350 static void
351 _soft8_scanline_blend_transp_solid_mul_color_solid(DATA8 * src, DATA8 * alpha,
352                                                    DATA8 * dst, int size,
353                                                    DATA8 r, DATA8 g, DATA8 b)
354 {
355    DATA8 *start, *end;
356
357    start = dst;
358    end = start + (size & ~7);
359
360    pld(alpha, 0);
361    pld(src, 0);
362
363    while (start < end)
364      {
365         DATA8 alpha1, alpha2;
366
367         alpha1 = alpha[0];
368         alpha += 8;
369
370         pld(alpha, 8);
371         pld(src, 32);
372
373         src += 8;
374         start += 8;
375
376         alpha2 = alpha[-7];
377         _soft8_pt_blend_transp_solid_mul_color_solid
378             (start - 8, src[-8], alpha1, r, g, b);
379
380         alpha1 = alpha[-6];
381         _soft8_pt_blend_transp_solid_mul_color_solid
382             (start - 7, src[-7], alpha2, r, g, b);
383
384         alpha2 = alpha[-5];
385         _soft8_pt_blend_transp_solid_mul_color_solid
386             (start - 6, src[-6], alpha1, r, g, b);
387
388         alpha1 = alpha[-4];
389         _soft8_pt_blend_transp_solid_mul_color_solid
390             (start - 5, src[-5], alpha2, r, g, b);
391
392         alpha2 = alpha[-3];
393         _soft8_pt_blend_transp_solid_mul_color_solid
394             (start - 4, src[-4], alpha1, r, g, b);
395
396         alpha1 = alpha[-2];
397         _soft8_pt_blend_transp_solid_mul_color_solid
398             (start - 3, src[-3], alpha2, r, g, b);
399
400         alpha2 = alpha[-1];
401         _soft8_pt_blend_transp_solid_mul_color_solid
402             (start - 2, src[-2], alpha1, r, g, b);
403
404         _soft8_pt_blend_transp_solid_mul_color_solid
405             (start - 1, src[-1], alpha2, r, g, b);
406      }
407
408    end = start + (size & 7);
409    for (; start < end; start++, src++, alpha++)
410       _soft8_pt_blend_transp_solid_mul_color_solid
411           (start, *src, *alpha, r, g, b);
412 }
413
414 static always_inline void
415 _soft8_pt_blend_solid_solid_mul_color_solid(DATA8 * p_dst, DATA8 src, DATA8 r,
416                                             DATA8 g, DATA8 b)
417 {
418    *p_dst = (src * GRY_8_FROM_COMPONENTS(r, g, b)) >> 8;
419 }
420
421 static void
422 _soft8_scanline_blend_solid_solid_mul_color_solid(DATA8 * src, DATA8 * dst,
423                                                   int size, DATA8 r, DATA8 g,
424                                                   DATA8 b)
425 {
426    DATA8 *start, *end;
427
428    start = dst;
429    end = start + (size & ~7);
430
431    pld(src, 0);
432
433    while (start < end)
434      {
435         pld(src, 32);
436         UNROLL8(
437                   {
438                   _soft8_pt_blend_solid_solid_mul_color_solid(start, *src, r, g,
439                                                               b); start++;
440                   src++;}
441         );
442      }
443
444    end = start + (size & 7);
445    for (; start < end; start++, src++)
446       _soft8_pt_blend_solid_solid_mul_color_solid(start, *src, r, g, b);
447 }