0f6a3cda347ed311d702723d47dd21b54ca14978
[ffmpeg.git] / postproc / swscale_altivec_template.c
1 /*
2   AltiVec-enhanced yuv2yuvX
3
4     Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
5     based on the equivalent C code in "postproc/swscale.c"
6
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program 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 General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22
23 static const vector unsigned int altivec_vectorShiftInt19 = {19, 19, 19, 19};
24 static inline void
25 altivec_packIntArrayToCharArray(int *val, uint8_t* dest, int dstW) {
26   register int i;
27   if ((unsigned long)dest % 16) {
28     /* badly aligned store, we force store alignement */
29     /* and will handle load misalignement on val w/ vec_perm */
30     for (i = 0 ; (i < dstW) &&
31            (((unsigned long)dest + i) % 16) ; i++) {
32       int t = val[i] >> 19;
33       dest[i] = (t < 0) ? 0 : ((t > 255) ? 255 : t);
34     }
35     vector unsigned char perm1 = vec_lvsl(i << 2, val);
36     vector signed int v1 = vec_ld(i << 2, val);
37     for ( ; i < (dstW - 15); i+=16) {
38       int offset = i << 2;
39       vector signed int v2 = vec_ld(offset + 16, val);
40       vector signed int v3 = vec_ld(offset + 32, val);
41       vector signed int v4 = vec_ld(offset + 48, val);
42       vector signed int v5 = vec_ld(offset + 64, val);
43       vector signed int v12 = vec_perm(v1,v2,perm1);
44       vector signed int v23 = vec_perm(v2,v3,perm1);
45       vector signed int v34 = vec_perm(v3,v4,perm1);
46       vector signed int v45 = vec_perm(v4,v5,perm1);
47       
48       vector signed int vA = vec_sra(v12, altivec_vectorShiftInt19);
49       vector signed int vB = vec_sra(v23, altivec_vectorShiftInt19);
50       vector signed int vC = vec_sra(v34, altivec_vectorShiftInt19);
51       vector signed int vD = vec_sra(v45, altivec_vectorShiftInt19);
52       vector unsigned short vs1 = vec_packsu(vA, vB);
53       vector unsigned short vs2 = vec_packsu(vC, vD);
54       vector unsigned char vf = vec_packsu(vs1, vs2);
55       vec_st(vf, i, dest);
56       v1 = v5;
57     }
58   } else { // dest is properly aligned, great
59     for (i = 0; i < (dstW - 15); i+=16) {
60       int offset = i << 2;
61       vector signed int v1 = vec_ld(offset, val);
62       vector signed int v2 = vec_ld(offset + 16, val);
63       vector signed int v3 = vec_ld(offset + 32, val);
64       vector signed int v4 = vec_ld(offset + 48, val);
65       vector signed int v5 = vec_sra(v1, altivec_vectorShiftInt19);
66       vector signed int v6 = vec_sra(v2, altivec_vectorShiftInt19);
67       vector signed int v7 = vec_sra(v3, altivec_vectorShiftInt19);
68       vector signed int v8 = vec_sra(v4, altivec_vectorShiftInt19);
69       vector unsigned short vs1 = vec_packsu(v5, v6);
70       vector unsigned short vs2 = vec_packsu(v7, v8);
71       vector unsigned char vf = vec_packsu(vs1, vs2);
72       vec_st(vf, i, dest);
73     }
74   }
75   for ( ; i < dstW ; i++) {
76     int t = val[i] >> 19;
77     dest[i] = (t < 0) ? 0 : ((t > 255) ? 255 : t);
78   }
79 }
80
81 static inline void
82 yuv2yuvX_altivec_real(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
83                       int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
84                       uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW)
85 {
86   const vector signed int vini = {(1 << 18), (1 << 18), (1 << 18), (1 << 18)};
87   register int i, j;
88   {
89     int __attribute__ ((aligned (16))) val[dstW];
90     
91     for (i = 0; i < (dstW -7); i+=4) {
92       vec_st(vini, i << 2, val);
93     }
94     for (; i < dstW; i++) {
95       val[i] = (1 << 18);
96     }
97     
98     for (j = 0; j < lumFilterSize; j++) {
99       vector signed short vLumFilter = vec_ld(j << 1, lumFilter);
100       vector unsigned char perm0 = vec_lvsl(j << 1, lumFilter);
101       vLumFilter = vec_perm(vLumFilter, vLumFilter, perm0);
102       vLumFilter = vec_splat(vLumFilter, 0); // lumFilter[j] is loaded 8 times in vLumFilter
103       
104       vector unsigned char perm = vec_lvsl(0, lumSrc[j]);
105       vector signed short l1 = vec_ld(0, lumSrc[j]);
106       
107       for (i = 0; i < (dstW - 7); i+=8) {
108         int offset = i << 2;
109         vector signed short l2 = vec_ld((i << 1) + 16, lumSrc[j]);
110         
111         vector signed int v1 = vec_ld(offset, val);
112         vector signed int v2 = vec_ld(offset + 16, val);
113         
114         vector signed short ls = vec_perm(l1, l2, perm); // lumSrc[j][i] ... lumSrc[j][i+7]
115         
116         vector signed int i1 = vec_mule(vLumFilter, ls);
117         vector signed int i2 = vec_mulo(vLumFilter, ls);
118         
119         vector signed int vf1 = vec_mergeh(i1, i2);
120         vector signed int vf2 = vec_mergel(i1, i2); // lumSrc[j][i] * lumFilter[j] ... lumSrc[j][i+7] * lumFilter[j]
121         
122         vector signed int vo1 = vec_add(v1, vf1);
123         vector signed int vo2 = vec_add(v2, vf2);
124         
125         vec_st(vo1, offset, val);
126         vec_st(vo2, offset + 16, val);
127         
128         l1 = l2;
129       }
130       for ( ; i < dstW; i++) {
131         val[i] += lumSrc[j][i] * lumFilter[j];
132       }
133     }
134     altivec_packIntArrayToCharArray(val,dest,dstW);
135   }
136   if (uDest != 0) {
137     int  __attribute__ ((aligned (16))) u[chrDstW];
138     int  __attribute__ ((aligned (16))) v[chrDstW];
139
140     for (i = 0; i < (chrDstW -7); i+=4) {
141       vec_st(vini, i << 2, u);
142       vec_st(vini, i << 2, v);
143     }
144     for (; i < chrDstW; i++) {
145       u[i] = (1 << 18);
146       v[i] = (1 << 18);
147     }
148     
149     for (j = 0; j < chrFilterSize; j++) {
150       vector signed short vChrFilter = vec_ld(j << 1, chrFilter);
151       vector unsigned char perm0 = vec_lvsl(j << 1, chrFilter);
152       vChrFilter = vec_perm(vChrFilter, vChrFilter, perm0);
153       vChrFilter = vec_splat(vChrFilter, 0); // chrFilter[j] is loaded 8 times in vChrFilter
154       
155       vector unsigned char perm = vec_lvsl(0, chrSrc[j]);
156       vector signed short l1 = vec_ld(0, chrSrc[j]);
157       vector signed short l1_V = vec_ld(2048 << 1, chrSrc[j]);
158       
159       for (i = 0; i < (chrDstW - 7); i+=8) {
160         int offset = i << 2;
161         vector signed short l2 = vec_ld((i << 1) + 16, chrSrc[j]);
162         vector signed short l2_V = vec_ld(((i + 2048) << 1) + 16, chrSrc[j]);
163         
164         vector signed int v1 = vec_ld(offset, u);
165         vector signed int v2 = vec_ld(offset + 16, u);
166         vector signed int v1_V = vec_ld(offset, v);
167         vector signed int v2_V = vec_ld(offset + 16, v);
168         
169         vector signed short ls = vec_perm(l1, l2, perm); // chrSrc[j][i] ... chrSrc[j][i+7]
170         vector signed short ls_V = vec_perm(l1_V, l2_V, perm); // chrSrc[j][i+2048] ... chrSrc[j][i+2055]
171         
172         vector signed int i1 = vec_mule(vChrFilter, ls);
173         vector signed int i2 = vec_mulo(vChrFilter, ls);
174         vector signed int i1_V = vec_mule(vChrFilter, ls_V);
175         vector signed int i2_V = vec_mulo(vChrFilter, ls_V);
176         
177         vector signed int vf1 = vec_mergeh(i1, i2);
178         vector signed int vf2 = vec_mergel(i1, i2); // chrSrc[j][i] * chrFilter[j] ... chrSrc[j][i+7] * chrFilter[j]
179         vector signed int vf1_V = vec_mergeh(i1_V, i2_V);
180         vector signed int vf2_V = vec_mergel(i1_V, i2_V); // chrSrc[j][i] * chrFilter[j] ... chrSrc[j][i+7] * chrFilter[j]
181         
182         vector signed int vo1 = vec_add(v1, vf1);
183         vector signed int vo2 = vec_add(v2, vf2);
184         vector signed int vo1_V = vec_add(v1_V, vf1_V);
185         vector signed int vo2_V = vec_add(v2_V, vf2_V);
186         
187         vec_st(vo1, offset, u);
188         vec_st(vo2, offset + 16, u);
189         vec_st(vo1_V, offset, v);
190         vec_st(vo2_V, offset + 16, v);
191         
192         l1 = l2;
193         l1_V = l2_V;
194       }
195       for ( ; i < chrDstW; i++) {
196         u[i] += chrSrc[j][i] * chrFilter[j];
197         v[i] += chrSrc[j][i + 2048] * chrFilter[j];
198       } 
199     }
200     altivec_packIntArrayToCharArray(u,uDest,chrDstW);
201     altivec_packIntArrayToCharArray(v,vDest,chrDstW);
202   }
203 }