1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 21 нояб. 2018 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef DSP_ARCH_ARM_NEON_D32_GRAPHICS_EFFECTS_H_
23 #define DSP_ARCH_ARM_NEON_D32_GRAPHICS_EFFECTS_H_
24 
25 #ifndef DSP_ARCH_ARM_NEON_32_IMPL
26     #error "This header should not be included directly"
27 #endif /* DSP_ARCH_ARM_NEON_32_IMPL */
28 
29 namespace neon_d32
30 {
31     IF_ARCH_ARM
32     (
33         static const float EFF_HSLA_HUE_XC[] __lsp_aligned16 =
34         {
35             1.0f, 1.0f, 1.0f, 1.0f
36         };
37     )
38 
39 
40 #define X8_TRANSPOSE \
41     __ASM_EMIT("vtrn.32         q0, q1") \
42     __ASM_EMIT("vtrn.32         q2, q3") \
43     __ASM_EMIT("vtrn.32         q4, q5") \
44     __ASM_EMIT("vtrn.32         q6, q7") \
45     __ASM_EMIT("vswp            d4, d1") \
46     __ASM_EMIT("vswp            d12, d9") \
47     __ASM_EMIT("vswp            d6, d3") \
48     __ASM_EMIT("vswp            d14, d11")
49 
50 #define EFF_HSLA_HUE_CORE   \
51     /* q0   = v0        */ \
52     /* q1   = v1        */ \
53     /* q8   = h         */ \
54     /* q9   = s         */ \
55     /* q10  = l         */ \
56     /* q11  = a         */ \
57     /* q12  = T         */ \
58     /* q13  = KT        */ \
59     /* q14  = 0         */ \
60     /* q15  = 1         */ \
61     __ASM_EMIT("vmov            q4, q1")                /* q4   = v1 */ \
62     __ASM_EMIT("vsub.f32        q2, q15, q0")           /* q2   = 1 - v */ \
63     __ASM_EMIT("vsub.f32        q6, q15, q4") \
64     __ASM_EMIT("vcge.f32        q3, q14, q0")           /* q3   = 0 > v  */ \
65     __ASM_EMIT("vcge.f32        q7, q14, q4") \
66     __ASM_EMIT("vadd.f32        q0, q0, q15")           /* q0   = v + 1 */ \
67     __ASM_EMIT("vadd.f32        q4, q4, q15") \
68     __ASM_EMIT("vbif            q0, q2, q3")            /* q0   = V = (v+1)&[0>v] | (1-v)&[0<=v] */ \
69     __ASM_EMIT("vbif            q4, q6, q7") \
70     __ASM_EMIT("vsub.f32        q3, q0, q12")           /* q3   = V - T */ \
71     __ASM_EMIT("vsub.f32        q7, q4, q12") \
72     __ASM_EMIT("vcge.f32        q1, q3, q14")           /* q1   = [(V-T)>=0] */ \
73     __ASM_EMIT("vcge.f32        q5, q7, q14") \
74     __ASM_EMIT("vmul.f32        q3, q3, q13")           /* q3   = (V-T)*KT */ \
75     __ASM_EMIT("vmul.f32        q7, q7, q13") \
76     __ASM_EMIT("vbit            q0, q12, q1")           /* q0   = EH = T&[(V-T)>=0] | V&[(V-T)<0] */ \
77     __ASM_EMIT("vbit            q4, q12, q5") \
78     __ASM_EMIT("vand            q3, q3, q1")            /* q3   = A = ((V-T)*KT) & [(V-T)>=0] */ \
79     __ASM_EMIT("vand            q7, q7, q5") \
80     __ASM_EMIT("vadd.f32        q0, q0, q8")            /* q0   = H = h + T&[(V-T)>=0] | V&[(V-T)<0] */ \
81     __ASM_EMIT("vadd.f32        q4, q4, q8") \
82     __ASM_EMIT("vmov            q1, q9")                /* q1   = s */ \
83     __ASM_EMIT("vmov            q2, q10")               /* q2   = l */ \
84     __ASM_EMIT("vmov            q5, q9") \
85     __ASM_EMIT("vmov            q6, q10") \
86     /* Transpose back */ \
87     X8_TRANSPOSE
88 
89     /*
90         float t     = 1.0f - eff->thresh;
91         float kt    = 1.0f / eff->thresh;
92 
93         value   = v[i];
94         value   = (0 > value) ? 1.0f + value : 1.0f - value;
95 
96         if ((value - t) >= 0)
97         {
98             hue         = eff->h + t;
99             alpha       = ((value - t) * kt);
100         }
101         else
102         {
103             hue         = eff->h + value;
104             alpha       = 0.0f;
105         }
106 
107         dst[0]      = (hue < 1.0f) ? hue : hue - 1.0f;
108         dst[1]      = eff->s;
109         dst[2]      = eff->l;
110         dst[3]      = alpha;
111     */
112 
eff_hsla_hue(float * dst,const float * v,const dsp::hsla_hue_eff_t * eff,size_t count)113     void eff_hsla_hue(float *dst, const float *v, const dsp::hsla_hue_eff_t *eff, size_t count)
114     {
115         ARCH_ARM_ASM
116         (
117             __ASM_EMIT("vld1.32         {q8}, [%[eff]]!")           /* q8   = hsla */
118             __ASM_EMIT("vldm            %[XC], {q15}")              /* q15  = 1 */
119             __ASM_EMIT("vmov            q9, q8")                    /* q9   = hsla */
120             __ASM_EMIT("vld1.32         {d24[], d25[]}, [%[eff]]")  /* q12  = t */
121             __ASM_EMIT("vmov            q10, q8")                   /* q10  = hsla */
122             __ASM_EMIT("veor            q14, q14")                  /* q14  = 0 */
123             __ASM_EMIT("vmov            q11, q8")                   /* q11  = hsla */
124             __ASM_EMIT("vrecpe.f32      q0, q12")                   /* q0   = TD */
125             __ASM_EMIT("vtrn.32         q8, q9")
126             __ASM_EMIT("vrecps.f32      q1, q0, q12")               /* q1   = (2 - TD*T) */
127             __ASM_EMIT("vtrn.32         q10, q11")
128             __ASM_EMIT("vmul.f32        q0, q1, q0")                /* q0   = t' = TD * (2 - TD*T) */
129             __ASM_EMIT("vswp            d20, d17")
130             __ASM_EMIT("vrecps.f32      q1, q0, q12")               /* q1   = (2 - TD*t') */
131             __ASM_EMIT("vswp            d22, d19")
132             __ASM_EMIT("vsub.f32        q12, q15, q12")             /* q12  = T = 1 - t */
133             __ASM_EMIT("vmul.f32        q13, q1, q0")               /* q13  = KT = 1/t = t' * (2 - TD*t') */
134 
135             __ASM_EMIT("subs            %[count], $8")
136             __ASM_EMIT("blo             2f")
137 
138             //-----------------------------------------------------------------
139             // 8x blocks
140             __ASM_EMIT("1:")
141 
142             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")        /* q0 = v0, q1 = v1 */
143 
144             EFF_HSLA_HUE_CORE
145 
146             __ASM_EMIT("subs            %[count], $8")
147             __ASM_EMIT("vstm            %[dst]!, {q0-q7}")
148             __ASM_EMIT("bhs             1b")
149 
150             //-----------------------------------------------------------------
151             // 1x-8x block
152             __ASM_EMIT("2:")
153             __ASM_EMIT("adds            %[count], $8")
154             __ASM_EMIT("bls             14f")
155 
156             __ASM_EMIT("tst             %[count], $4")
157             __ASM_EMIT("beq             4f")
158             __ASM_EMIT("vld1.32         {q0}, [%[src]]!")
159             __ASM_EMIT("4:")
160             __ASM_EMIT("tst             %[count], $2")
161             __ASM_EMIT("beq             6f")
162             __ASM_EMIT("vld1.32         {d2}, [%[src]]!")
163             __ASM_EMIT("6:")
164             __ASM_EMIT("tst             %[count], $1")
165             __ASM_EMIT("beq             8f")
166             __ASM_EMIT("vld1.32         d3[0], [%[src]]")
167             __ASM_EMIT("8:")
168 
169             EFF_HSLA_HUE_CORE
170 
171             __ASM_EMIT("tst             %[count], $4")
172             __ASM_EMIT("beq             10f")
173             __ASM_EMIT("vstm            %[dst]!, {q0-q3}")
174             __ASM_EMIT("10:")
175             __ASM_EMIT("tst             %[count], $2")
176             __ASM_EMIT("beq             12f")
177             __ASM_EMIT("vstm            %[dst]!, {q4-q5}")
178             __ASM_EMIT("12:")
179             __ASM_EMIT("tst             %[count], $1")
180             __ASM_EMIT("beq             14f")
181             __ASM_EMIT("vstm            %[dst], {q6}")
182 
183             __ASM_EMIT("14:")
184 
185 
186             : [dst] "+r" (dst), [src] "+r" (v), [count] "+r" (count),
187               [eff] "+r" (eff)
188             : [XC] "r" (&EFF_HSLA_HUE_XC[0])
189             : "cc", "memory",
190               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
191               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
192         );
193     }
194 
195 #undef EFF_HSLA_HUE_CORE
196 
197 #define EFF_HSLA_SAT_CORE   \
198     /* q0   = v0        */ \
199     /* q1   = v1        */ \
200     /* q8   = h         */ \
201     /* q9   = s         */ \
202     /* q10  = l         */ \
203     /* q11  = a         */ \
204     /* q13  = 0         */ \
205     /* q14  = T         */ \
206     /* q15  = KT        */ \
207     __ASM_EMIT("vabs.f32        q5, q1")                /* q5   = V1 = abs(v1) */ \
208     __ASM_EMIT("vabs.f32        q1, q0")                /* q1   = V  = abs(v) */ \
209     __ASM_EMIT("vsub.f32        q3, q14, q1")           /* q3   = T - V */ \
210     __ASM_EMIT("vsub.f32        q7, q14, q5") \
211     __ASM_EMIT("vcgt.f32        q2, q3, q13")           /* q2   = [(T-V) > 0] */ \
212     __ASM_EMIT("vcgt.f32        q6, q7, q13") \
213     __ASM_EMIT("vmul.f32        q3, q3, q15")           /* q3   = (T-V)*KT */ \
214     __ASM_EMIT("vmul.f32        q7, q7, q15") \
215     __ASM_EMIT("vbit            q1, q14, q2")           /* q1   = ES = V&[(T-V) <= 0] | T&[(T-V) > 0] */ \
216     __ASM_EMIT("vbit            q5, q14, q6") \
217     __ASM_EMIT("vand            q3, q3, q2")            /* q3   = A = ((T-V)*KT) & [(T-V) > 0] */ \
218     __ASM_EMIT("vand            q7, q7, q6") \
219     __ASM_EMIT("vmul.f32        q1, q1, q9")            /* q1   = ES*s = S */ \
220     __ASM_EMIT("vmul.f32        q5, q5, q9") \
221     __ASM_EMIT("vmov            q0, q8") \
222     __ASM_EMIT("vmov            q2, q10") \
223     __ASM_EMIT("vmov            q4, q8") \
224     __ASM_EMIT("vmov            q6, q10") \
225     /* Transpose back */ \
226     X8_TRANSPOSE
227 
228     /*
229         kt      = 1.0f / eff->thresh;
230         value   = (value >= 0.0f) ? value : -value;
231 
232         if ((eff->thresh - value) <= 0)
233         {
234             dst[1]      = eff->s * value;
235             dst[3]      = 0.0f;
236         }
237         else
238         {
239             dst[1]      = eff->s * eff->thresh;
240             dst[3]      = (eff->thresh - value) * kt;
241         }
242 
243         dst[0]      = eff->h;
244         dst[2]      = eff->l;
245      */
246 
eff_hsla_sat(float * dst,const float * v,const dsp::hsla_sat_eff_t * eff,size_t count)247     void eff_hsla_sat(float *dst, const float *v, const dsp::hsla_sat_eff_t *eff, size_t count)
248     {
249         ARCH_ARM_ASM
250         (
251             __ASM_EMIT("vld1.32         {q8}, [%[eff]]!")           /* q8   = hsla */
252             __ASM_EMIT("vld1.32         {d28[], d29[]}, [%[eff]]")  /* q14  = T */
253             __ASM_EMIT("vmov            q9, q8")                    /* q9   = hsla */
254             __ASM_EMIT("vrecpe.f32      q0, q14")                   /* q0   = TD */
255             __ASM_EMIT("vtrn.32         q8, q9")
256             __ASM_EMIT("vrecps.f32      q1, q0, q14")               /* q1   = (2 - TD*T) */
257             __ASM_EMIT("vmov            q10, q8")                   /* q10  = hsla */
258             __ASM_EMIT("vmul.f32        q0, q1, q0")                /* q0   = t' = TD * (2 - TD*T) */
259             __ASM_EMIT("vmov            q11, q9")                   /* q11  = hsla */
260             __ASM_EMIT("vrecps.f32      q1, q0, q14")               /* q1   = (2 - TD*t') */
261             __ASM_EMIT("vswp            d20, d17")
262             __ASM_EMIT("vmul.f32        q15, q1, q0")               /* q15  = KT = 1/t = t' * (2 - TD*t') */
263             __ASM_EMIT("vswp            d22, d19")
264             __ASM_EMIT("veor            q13, q13")                  /* q13  = 0 */
265 
266             __ASM_EMIT("subs            %[count], $8")
267             __ASM_EMIT("blo             2f")
268 
269             //-----------------------------------------------------------------
270             // 8x blocks
271             __ASM_EMIT("1:")
272 
273             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")        /* q0 = v0, q1 = v1 */
274 
275             EFF_HSLA_SAT_CORE
276 
277             __ASM_EMIT("subs            %[count], $8")
278             __ASM_EMIT("vstm            %[dst]!, {q0-q7}")
279             __ASM_EMIT("bhs             1b")
280 
281             //-----------------------------------------------------------------
282             // 1x-8x block
283             __ASM_EMIT("2:")
284             __ASM_EMIT("adds            %[count], $8")
285             __ASM_EMIT("bls             14f")
286 
287             __ASM_EMIT("tst             %[count], $4")
288             __ASM_EMIT("beq             4f")
289             __ASM_EMIT("vld1.32         {q0}, [%[src]]!")
290             __ASM_EMIT("4:")
291             __ASM_EMIT("tst             %[count], $2")
292             __ASM_EMIT("beq             6f")
293             __ASM_EMIT("vld1.32         {d2}, [%[src]]!")
294             __ASM_EMIT("6:")
295             __ASM_EMIT("tst             %[count], $1")
296             __ASM_EMIT("beq             8f")
297             __ASM_EMIT("vld1.32         d3[0], [%[src]]")
298             __ASM_EMIT("8:")
299 
300             EFF_HSLA_SAT_CORE
301 
302             __ASM_EMIT("tst             %[count], $4")
303             __ASM_EMIT("beq             10f")
304             __ASM_EMIT("vstm            %[dst]!, {q0-q3}")
305             __ASM_EMIT("10:")
306             __ASM_EMIT("tst             %[count], $2")
307             __ASM_EMIT("beq             12f")
308             __ASM_EMIT("vstm            %[dst]!, {q4-q5}")
309             __ASM_EMIT("12:")
310             __ASM_EMIT("tst             %[count], $1")
311             __ASM_EMIT("beq             14f")
312             __ASM_EMIT("vstm            %[dst], {q6}")
313 
314             __ASM_EMIT("14:")
315 
316 
317             : [dst] "+r" (dst), [src] "+r" (v), [count] "+r" (count),
318               [eff] "+r" (eff)
319             :
320             : "cc", "memory",
321               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
322               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
323         );
324     }
325 
326 #undef EFF_HSLA_SAT_CORE
327 
328 
329 #define EFF_HSLA_LIGHT_CORE   \
330     /* q0   = v0        */ \
331     /* q1   = v1        */ \
332     /* q8   = h         */ \
333     /* q9   = s         */ \
334     /* q10  = l         */ \
335     /* q11  = a         */ \
336     /* q13  = 0         */ \
337     /* q14  = T         */ \
338     /* q15  = KT        */ \
339     __ASM_EMIT("vabs.f32        q5, q1")                /* q5   = V1 = abs(v1) */ \
340     __ASM_EMIT("vabs.f32        q1, q0")                /* q1   = V  = abs(v) */ \
341     __ASM_EMIT("vsub.f32        q3, q14, q1")           /* q3   = T - V */ \
342     __ASM_EMIT("vsub.f32        q7, q14, q5") \
343     __ASM_EMIT("vcgt.f32        q2, q3, q13")           /* q2   = [(T-V) > 0] */ \
344     __ASM_EMIT("vcgt.f32        q6, q7, q13") \
345     __ASM_EMIT("vmul.f32        q3, q3, q15")           /* q3   = (T-V)*KT */ \
346     __ASM_EMIT("vmul.f32        q7, q7, q15") \
347     __ASM_EMIT("vbit            q1, q14, q2")           /* q1   = EL = V&[(T-V) <= 0] | T&[(T-V) > 0] */ \
348     __ASM_EMIT("vbit            q5, q14, q6") \
349     __ASM_EMIT("vand            q3, q3, q2")            /* q3   = A = ((T-V)*KT) & [(T-V) > 0] */ \
350     __ASM_EMIT("vand            q7, q7, q6") \
351     __ASM_EMIT("vmul.f32        q2, q1, q10")           /* q2   = EL*l = L */ \
352     __ASM_EMIT("vmul.f32        q6, q5, q10") \
353     __ASM_EMIT("vmov            q0, q8") \
354     __ASM_EMIT("vmov            q1, q9") \
355     __ASM_EMIT("vmov            q4, q8") \
356     __ASM_EMIT("vmov            q5, q9") \
357     /* Transpose back */ \
358     X8_TRANSPOSE
359 
360     /*
361         kt      = 1.0f / eff->thresh;
362         value   = (value >= 0.0f) ? value : -value;
363 
364         if ((eff->thresh - value) <= 0)
365         {
366             dst[2]      = eff->l * value;
367             dst[3]      = 0.0f;
368         }
369         else
370         {
371             dst[2]      = eff->l * eff->thresh;
372             dst[3]      = (eff->thresh - value) * kt;
373         }
374 
375         dst[0]      = eff->h;
376         dst[1]      = eff->s;
377      */
378 
eff_hsla_light(float * dst,const float * v,const dsp::hsla_light_eff_t * eff,size_t count)379     void eff_hsla_light(float *dst, const float *v, const dsp::hsla_light_eff_t *eff, size_t count)
380     {
381         ARCH_ARM_ASM
382         (
383             __ASM_EMIT("vld1.32         {q8}, [%[eff]]!")           /* q8   = hsla */
384             __ASM_EMIT("vld1.32         {d28[], d29[]}, [%[eff]]")  /* q14  = T */
385             __ASM_EMIT("vmov            q9, q8")                    /* q9   = hsla */
386             __ASM_EMIT("vrecpe.f32      q0, q14")                   /* q0   = TD */
387             __ASM_EMIT("vtrn.32         q8, q9")
388             __ASM_EMIT("vrecps.f32      q1, q0, q14")               /* q1   = (2 - TD*T) */
389             __ASM_EMIT("vmov            q10, q8")                   /* q10  = hsla */
390             __ASM_EMIT("vmul.f32        q0, q1, q0")                /* q0   = t' = TD * (2 - TD*T) */
391             __ASM_EMIT("vmov            q11, q9")                   /* q11  = hsla */
392             __ASM_EMIT("vrecps.f32      q1, q0, q14")               /* q1   = (2 - TD*t') */
393             __ASM_EMIT("vswp            d20, d17")
394             __ASM_EMIT("vmul.f32        q15, q1, q0")               /* q15  = KT = 1/t = t' * (2 - TD*t') */
395             __ASM_EMIT("vswp            d22, d19")
396             __ASM_EMIT("veor            q13, q13")                  /* q13  = 0 */
397 
398             __ASM_EMIT("subs            %[count], $8")
399             __ASM_EMIT("blo             2f")
400 
401             //-----------------------------------------------------------------
402             // 8x blocks
403             __ASM_EMIT("1:")
404 
405             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")        /* q0 = v0, q1 = v1 */
406 
407             EFF_HSLA_LIGHT_CORE
408 
409             __ASM_EMIT("subs            %[count], $8")
410             __ASM_EMIT("vstm            %[dst]!, {q0-q7}")
411             __ASM_EMIT("bhs             1b")
412 
413             //-----------------------------------------------------------------
414             // 1x-8x block
415             __ASM_EMIT("2:")
416             __ASM_EMIT("adds            %[count], $8")
417             __ASM_EMIT("bls             14f")
418 
419             __ASM_EMIT("tst             %[count], $4")
420             __ASM_EMIT("beq             4f")
421             __ASM_EMIT("vld1.32         {q0}, [%[src]]!")
422             __ASM_EMIT("4:")
423             __ASM_EMIT("tst             %[count], $2")
424             __ASM_EMIT("beq             6f")
425             __ASM_EMIT("vld1.32         {d2}, [%[src]]!")
426             __ASM_EMIT("6:")
427             __ASM_EMIT("tst             %[count], $1")
428             __ASM_EMIT("beq             8f")
429             __ASM_EMIT("vld1.32         d3[0], [%[src]]")
430             __ASM_EMIT("8:")
431 
432             EFF_HSLA_LIGHT_CORE
433 
434             __ASM_EMIT("tst             %[count], $4")
435             __ASM_EMIT("beq             10f")
436             __ASM_EMIT("vstm            %[dst]!, {q0-q3}")
437             __ASM_EMIT("10:")
438             __ASM_EMIT("tst             %[count], $2")
439             __ASM_EMIT("beq             12f")
440             __ASM_EMIT("vstm            %[dst]!, {q4-q5}")
441             __ASM_EMIT("12:")
442             __ASM_EMIT("tst             %[count], $1")
443             __ASM_EMIT("beq             14f")
444             __ASM_EMIT("vstm            %[dst], {q6}")
445 
446             __ASM_EMIT("14:")
447 
448 
449             : [dst] "+r" (dst), [src] "+r" (v), [count] "+r" (count),
450               [eff] "+r" (eff)
451             :
452             : "cc", "memory",
453               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
454               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
455         );
456     }
457 
458 #undef EFF_HSLA_LIGHT_CORE
459 
460 IF_ARCH_ARM
461 (
462     static const float EFF_HSLA_ALPHA_XC[] __lsp_aligned16 =
463     {
464         1.0f, 1.0f, 1.0f, 1.0f
465     };
466 )
467 
468 
469 #define EFF_HSLA_ALPHA_CORE   \
470     /* q0   = v0        */ \
471     /* q1   = v1        */ \
472     /* q8   = h         */ \
473     /* q9   = s         */ \
474     /* q10  = l         */ \
475     /* q11  = a         */ \
476     /* q14  = 0         */ \
477     /* q15  = 1         */ \
478     __ASM_EMIT("vsub.f32        q2, q15, q0")           /* q2   = 1 - v */ \
479     __ASM_EMIT("vsub.f32        q6, q15, q1") \
480     __ASM_EMIT("vcgt.f32        q4, q14, q0")           /* q4   = 0 > v  */ \
481     __ASM_EMIT("vcgt.f32        q5, q14, q1") \
482     __ASM_EMIT("vadd.f32        q3, q0, q15")           /* q3   = v + 1 */ \
483     __ASM_EMIT("vadd.f32        q7, q1, q15") \
484     __ASM_EMIT("vbif            q3, q2, q4")            /* q0   = V = (v+1)&[0>v] | (1-v)&[0<=v] */ \
485     __ASM_EMIT("vbif            q7, q6, q5") \
486     __ASM_EMIT("vmov            q0, q8") \
487     __ASM_EMIT("vmov            q1, q9") \
488     __ASM_EMIT("vmov            q2, q10") \
489     __ASM_EMIT("vmov            q4, q8") \
490     __ASM_EMIT("vmov            q5, q9") \
491     __ASM_EMIT("vmov            q6, q10") \
492     /* Transpose back */ \
493     X8_TRANSPOSE
494 
495     /*
496         value   = v[i];
497         value   = (0.0f > value) ? 1.0f + value : 1.0f - value;
498 
499         dst[0]  = eff->h;
500         dst[1]  = eff->s;
501         dst[2]  = eff->l;
502         dst[3]  = value; // Fill alpha channel
503      */
504 
eff_hsla_alpha(float * dst,const float * v,const dsp::hsla_alpha_eff_t * eff,size_t count)505     void eff_hsla_alpha(float *dst, const float *v, const dsp::hsla_alpha_eff_t *eff, size_t count)
506     {
507         ARCH_ARM_ASM
508         (
509             __ASM_EMIT("vld1.32         {q8}, [%[eff]]")            /* q8   = hsla */
510             __ASM_EMIT("vldm            %[XC], {q15}")              /* q15  = 1 */
511             __ASM_EMIT("vmov            q9, q8")                    /* q9   = hsla */
512             __ASM_EMIT("veor            q14, q14")                  /* q14  = 0 */
513             __ASM_EMIT("vtrn.32         q8, q9")
514             __ASM_EMIT("vmov            q10, q8")
515             __ASM_EMIT("vmov            q11, q9")
516             __ASM_EMIT("vswp            d20, d17")
517             __ASM_EMIT("vswp            d22, d19")
518 
519             __ASM_EMIT("subs            %[count], $8")
520             __ASM_EMIT("blo             2f")
521 
522             //-----------------------------------------------------------------
523             // 8x blocks
524             __ASM_EMIT("1:")
525 
526             __ASM_EMIT("vld1.32         {q0-q1}, [%[src]]!")        /* q0 = v0, q1 = v1 */
527 
528             EFF_HSLA_ALPHA_CORE
529 
530             __ASM_EMIT("subs            %[count], $8")
531             __ASM_EMIT("vstm            %[dst]!, {q0-q7}")
532             __ASM_EMIT("bhs             1b")
533 
534             //-----------------------------------------------------------------
535             // 1x-8x block
536             __ASM_EMIT("2:")
537             __ASM_EMIT("adds            %[count], $8")
538             __ASM_EMIT("bls             14f")
539 
540             __ASM_EMIT("tst             %[count], $4")
541             __ASM_EMIT("beq             4f")
542             __ASM_EMIT("vld1.32         {q0}, [%[src]]!")
543             __ASM_EMIT("4:")
544             __ASM_EMIT("tst             %[count], $2")
545             __ASM_EMIT("beq             6f")
546             __ASM_EMIT("vld1.32         {d2}, [%[src]]!")
547             __ASM_EMIT("6:")
548             __ASM_EMIT("tst             %[count], $1")
549             __ASM_EMIT("beq             8f")
550             __ASM_EMIT("vld1.32         d3[0], [%[src]]")
551             __ASM_EMIT("8:")
552 
553             EFF_HSLA_ALPHA_CORE
554 
555             __ASM_EMIT("tst             %[count], $4")
556             __ASM_EMIT("beq             10f")
557             __ASM_EMIT("vstm            %[dst]!, {q0-q3}")
558             __ASM_EMIT("10:")
559             __ASM_EMIT("tst             %[count], $2")
560             __ASM_EMIT("beq             12f")
561             __ASM_EMIT("vstm            %[dst]!, {q4-q5}")
562             __ASM_EMIT("12:")
563             __ASM_EMIT("tst             %[count], $1")
564             __ASM_EMIT("beq             14f")
565             __ASM_EMIT("vstm            %[dst], {q6}")
566 
567             __ASM_EMIT("14:")
568 
569 
570             : [dst] "+r" (dst), [src] "+r" (v), [count] "+r" (count)
571             : [XC] "r" (&EFF_HSLA_ALPHA_XC[0]), [eff] "r" (eff)
572             : "cc", "memory",
573               "q0", "q1", "q2", "q3" , "q4", "q5", "q6", "q7",
574               "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
575         );
576     }
577 
578 #undef EFF_HSLA_ALPHA_CORE
579 
580 #undef X8_TRANSPOSE
581 
582 }
583 
584 #endif /* DSP_ARCH_ARM_NEON_D32_GRAPHICS_EFFECTS_H_ */
585