1 #ifndef _Painter_AlphaBlend_h_
2 #define _Painter_AlphaBlend_h_
3
4 namespace Upp {
5
6 void AlphaBlend(RGBA *t, const RGBA& c, int alpha);
7 void AlphaBlend(RGBA *t, const RGBA *s, int alpha, int len);
8 void AlphaBlend(RGBA *t, const RGBA& c, int alpha, int len);
9
10 #ifdef CPU_SIMD
11
12 force_inline
BroadcastAlpha(i16x8 x)13 i16x8 BroadcastAlpha(i16x8 x)
14 {
15 #ifdef PLATFORM_MACOS
16 return BroadcastLH0(x);
17 #else
18 return BroadcastLH3(x);
19 #endif
20 }
21
22 force_inline
Mul8(i16x8 x,int alpha)23 i16x8 Mul8(i16x8 x, int alpha)
24 {
25 return i16all(alpha) * x >> 8;
26 }
27
28 force_inline
MakeAlpha(i16x8 x)29 i16x8 MakeAlpha(i16x8 x)
30 {
31 x = BroadcastAlpha(x);
32 #ifdef PLATFORM_MACOS
33 x = i16x8(129, 129, 129, 128, 129, 129, 129, 128) * x >> 7;
34 #else
35 x = i16x8(128, 129, 129, 129, 128, 129, 129, 129) * x >> 7; // a for alpha, 256*a/255 for color
36 #endif
37 return i16all(256) - x; // 256 - a for alpha, 256 - 256*a/255 for color;
38 }
39
40 force_inline
AlphaBlendSIMD(i16x8 t,i16x8 s,i16x8 alpha)41 i16x8 AlphaBlendSIMD(i16x8 t, i16x8 s, i16x8 alpha)
42 {
43 return s + (t * alpha >> 8);
44 }
45
46 force_inline
AlphaBlend1(RGBA * t,i16x8 s,i16x8 alpha)47 void AlphaBlend1(RGBA *t, i16x8 s, i16x8 alpha)
48 {
49 StoreRGBA(t, AlphaBlendSIMD(LoadRGBA(t), s, alpha));
50 }
51
52 force_inline
AlphaBlend2(RGBA * t,i16x8 s,i16x8 alpha)53 void AlphaBlend2(RGBA *t, i16x8 s, i16x8 alpha)
54 {
55 StoreRGBA2(t, AlphaBlendSIMD(LoadRGBA2(t), s, alpha));
56 }
57
58 force_inline
AlphaBlend4(RGBA * t,i16x8 sl,i16x8 al,i16x8 sh,i16x8 ah)59 void AlphaBlend4(RGBA *t, i16x8 sl, i16x8 al, i16x8 sh, i16x8 ah)
60 {
61 i16x8 t4(t);
62 PackRGBA(
63 AlphaBlendSIMD(LoadRGBAL(t4), sl, al),
64 AlphaBlendSIMD(LoadRGBAH(t4), sh, ah)
65 ).Store(t);
66 }
67
68 force_inline
AlphaBlend(RGBA * t,const RGBA & c)69 void AlphaBlend(RGBA *t, const RGBA& c)
70 {
71 i16x8 s = LoadRGBA(&c);
72 StoreRGBA(t, AlphaBlendSIMD(LoadRGBA(t), s, MakeAlpha(s)));
73 }
74
75 force_inline
AlphaBlend(RGBA * t,const RGBA & c,int alpha)76 void AlphaBlend(RGBA *t, const RGBA& c, int alpha)
77 {
78 i16x8 s = Mul8(LoadRGBA(&c), alpha);
79 StoreRGBA(t, AlphaBlendSIMD(LoadRGBA(t), s, MakeAlpha(s)));
80 }
81
82 force_inline
AlphaBlend(RGBA * t,const RGBA & c,int alpha,int len)83 void AlphaBlend(RGBA *t, const RGBA& c, int alpha, int len)
84 {
85 i16x8 s = Mul8(LoadRGBA2(c), alpha);
86 i16x8 a = MakeAlpha(s);
87 while(len >= 4) {
88 AlphaBlend4(t, s, a, s, a);
89 t += 4;
90 len -= 4;
91 }
92 if(len & 2) {
93 AlphaBlend2(t, s, a);
94 t += 2;
95 }
96 if(len & 1)
97 AlphaBlend1(t, s, a);
98 }
99
100 force_inline
AlphaBlend(RGBA * t,const RGBA * s,int alpha,int len)101 void AlphaBlend(RGBA *t, const RGBA *s, int alpha, int len)
102 {
103 if(alpha == 256) {
104 while(len >= 4) {
105 i16x8 m(s);
106 i16x8 s0 = LoadRGBAL(m);
107 i16x8 s1 = LoadRGBAH(m);
108 AlphaBlend4(t, s0, MakeAlpha(s0), s1, MakeAlpha(s1));
109 t += 4;
110 s += 4;
111 len -= 4;
112 }
113 if(len & 2) {
114 i16x8 s0 = LoadRGBA2(s);
115 AlphaBlend2(t, s0, MakeAlpha(s0));
116 t += 2;
117 s += 2;
118 }
119 if(len & 1) {
120 i16x8 s0 = LoadRGBA(s);
121 AlphaBlend1(t, s0, MakeAlpha(s0));
122 }
123 }
124 else {
125 while(len >= 4) {
126 i16x8 m(s);
127 i16x8 s0 = Mul8(LoadRGBAL(m), alpha);
128 i16x8 s1 = Mul8(LoadRGBAH(m), alpha);
129 AlphaBlend4(t, s0, MakeAlpha(s0), s1, MakeAlpha(s1));
130 t += 4;
131 s += 4;
132 len -= 4;
133 }
134 if(len & 2) {
135 i16x8 s0 = Mul8(LoadRGBA2(s), alpha);
136 AlphaBlend2(t, s0, MakeAlpha(s0));
137 t += 2;
138 s += 2;
139 }
140 if(len & 1) {
141 i16x8 s0 = Mul8(LoadRGBA(s), alpha);
142 AlphaBlend1(t, s0, MakeAlpha(s0));
143 }
144 }
145 }
146
147 #else
148
149 force_inline
AlphaBlend__(RGBA & t,const RGBA & c)150 void AlphaBlend__(RGBA& t, const RGBA& c)
151 {
152 int alpha = 256 - (c.a + (c.a >> 7));
153 t.r = c.r + (alpha * t.r >> 8);
154 t.g = c.g + (alpha * t.g >> 8);
155 t.b = c.b + (alpha * t.b >> 8);
156 t.a = c.a + ((256 - c.a) * t.a >> 8);
157 }
158
159 force_inline
AlphaBlend__(RGBA & t,const RGBA & c,int cover)160 void AlphaBlend__(RGBA& t, const RGBA& c, int cover)
161 {
162 int a = c.a * cover >> 8;
163 int alpha = 256 - a - (a >> 7);
164 t.r = (c.r * cover >> 8) + (alpha * t.r >> 8);
165 t.g = (c.g * cover >> 8) + (alpha * t.g >> 8);
166 t.b = (c.b * cover >> 8) + (alpha * t.b >> 8);
167 t.a = a + (alpha * t.a >> 8);
168 }
169
170 force_inline
AlphaBlend(RGBA * t,const RGBA & c)171 void AlphaBlend(RGBA *t, const RGBA& c)
172 {
173 AlphaBlend__(*t, c);
174 }
175
176 force_inline
AlphaBlend(RGBA * t,const RGBA & c,int alpha)177 void AlphaBlend(RGBA *t, const RGBA& c, int alpha)
178 {
179 AlphaBlend__(*t, c, alpha);
180 }
181
182 force_inline
AlphaBlend(RGBA * t,const RGBA & c,int alpha,int len)183 void AlphaBlend(RGBA *t, const RGBA& c, int alpha, int len)
184 {
185 RGBA c1;
186 if(alpha != 256)
187 c1 = Mul8(c, alpha);
188 else
189 c1 = c;
190 RGBA *e = t + len;
191 while(t < e)
192 AlphaBlend__(*t++, c1);
193 }
194
195 force_inline
AlphaBlend(RGBA * t,const RGBA * s,int alpha,int len)196 void AlphaBlend(RGBA *t, const RGBA *s, int alpha, int len)
197 {
198 if(alpha == 256) {
199 for(int i = 0; i < len; i++) {
200 if(s[i].a == 255)
201 t[i] = s[i];
202 else
203 AlphaBlend__(t[i], s[i]);
204 }
205 }
206 else {
207 const RGBA *e = t + len;
208 while(t < e)
209 AlphaBlend__(*t++, *s++, alpha);
210 }
211 }
212
213 #endif
214
215 };
216
217 #endif
218