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