]> git.sesse.net Git - ffmpeg/blob - libavcodec/ppc/h264chroma_template.c
Merge commit 'b0e6b3f4777910d61083976aa9fc78a1e0731aae'
[ffmpeg] / libavcodec / ppc / h264chroma_template.c
1 /*
2  * Copyright (c) 2004 Romain Dolbeau <romain@dolbeau.org>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/mem.h"
22 #include "libavutil/ppc/types_altivec.h"
23 #include "libavutil/ppc/util_altivec.h"
24
25 /* this code assume that stride % 16 == 0 */
26
27 #define CHROMA_MC8_ALTIVEC_CORE(BIAS1, BIAS2) \
28         vsrc2ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc2uc);\
29         vsrc3ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc3uc);\
30 \
31         psum = vec_mladd(vA, vsrc0ssH, BIAS1);\
32         psum = vec_mladd(vB, vsrc1ssH, psum);\
33         psum = vec_mladd(vC, vsrc2ssH, psum);\
34         psum = vec_mladd(vD, vsrc3ssH, psum);\
35         psum = BIAS2(psum);\
36         psum = vec_sr(psum, v6us);\
37 \
38         vdst = vec_ld(0, dst);\
39         ppsum = (vec_u8)vec_pack(psum, psum);\
40         vfdst = vec_perm(vdst, ppsum, fperm);\
41 \
42         OP_U8_ALTIVEC(fsum, vfdst, vdst);\
43 \
44         vec_st(fsum, 0, dst);\
45 \
46         vsrc0ssH = vsrc2ssH;\
47         vsrc1ssH = vsrc3ssH;\
48 \
49         dst += stride;\
50         src += stride;
51
52 #define CHROMA_MC8_ALTIVEC_CORE_SIMPLE \
53 \
54         vsrc0ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc0uc);\
55         vsrc1ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc1uc);\
56 \
57         psum = vec_mladd(vA, vsrc0ssH, v32ss);\
58         psum = vec_mladd(vE, vsrc1ssH, psum);\
59         psum = vec_sr(psum, v6us);\
60 \
61         vdst = vec_ld(0, dst);\
62         ppsum = (vec_u8)vec_pack(psum, psum);\
63         vfdst = vec_perm(vdst, ppsum, fperm);\
64 \
65         OP_U8_ALTIVEC(fsum, vfdst, vdst);\
66 \
67         vec_st(fsum, 0, dst);\
68 \
69         dst += stride;\
70         src += stride;
71
72 #define noop(a) a
73 #define add28(a) vec_add(v28ss, a)
74
75 #if HAVE_BIGENDIAN
76 #define GET_VSRC1(vs0, off, b, perm0, s){    \
77     vec_u8 vsrcCuc, vsrcDuc;                 \
78     vsrcCuc = vec_ld(off, s);                \
79     if (loadSecond){                         \
80         vsrcDuc = vec_ld(off + b, s);        \
81     } else                                   \
82         vsrcDuc = vsrcCuc;                   \
83                                              \
84     vs0 = vec_perm(vsrcCuc, vsrcDuc, perm0); \
85 }
86 #define GET_VSRC(vs0, vs1, off, b, perm0, perm1, s){ \
87     vec_u8 vsrcCuc, vsrcDuc;                         \
88     vsrcCuc = vec_ld(off, s);                        \
89     if (loadSecond){                                 \
90         vsrcDuc = vec_ld(off + b, s);                \
91     } else                                           \
92         vsrcDuc = vsrcCuc;                           \
93                                                      \
94     vs0 = vec_perm(vsrcCuc, vsrcDuc, perm0);         \
95     if (reallyBadAlign){                             \
96         vs1 = vsrcDuc;                               \
97     } else                                           \
98         vs1 = vec_perm(vsrcCuc, vsrcDuc, perm1);     \
99  }
100
101 #else
102
103 #define GET_VSRC1(vs0, off, b, perm0, s){            \
104     vs0 = vec_vsx_ld(off, s);                        \
105  }
106 #define GET_VSRC(vs0, vs1, off, b, perm0, perm1, s){ \
107     vs0 = vec_vsx_ld(off, s);                        \
108     vs1 = vec_vsx_ld(off + 1, s);                    \
109  }
110 #endif /* HAVE_BIGENDIAN */
111
112 #ifdef PREFIX_h264_chroma_mc8_altivec
113 static void PREFIX_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src,
114                                            ptrdiff_t stride, int h,
115                                            int x, int y)
116 {
117     DECLARE_ALIGNED(16, signed int, ABCD)[4] =
118                         {((8 - x) * (8 - y)),
119                          ((    x) * (8 - y)),
120                          ((8 - x) * (    y)),
121                          ((    x) * (    y))};
122     register int i;
123     vec_u8 fperm;
124     LOAD_ZERO;
125     const vec_s32 vABCD = vec_ld(0, ABCD);
126     const vec_s16 vA = VEC_SPLAT16(vABCD, 1);
127     const vec_s16 vB = VEC_SPLAT16(vABCD, 3);
128     const vec_s16 vC = VEC_SPLAT16(vABCD, 5);
129     const vec_s16 vD = VEC_SPLAT16(vABCD, 7);
130     const vec_s16 v32ss = vec_sl(vec_splat_s16(1),vec_splat_u16(5));
131     const vec_u16 v6us = vec_splat_u16(6);
132
133     vec_u8 vsrcperm0, vsrcperm1;
134     vec_u8 vsrc0uc, vsrc1uc;
135     vec_s16 vsrc0ssH, vsrc1ssH;
136     vec_u8 vsrc2uc, vsrc3uc;
137     vec_s16 vsrc2ssH, vsrc3ssH, psum;
138     vec_u8 vdst, ppsum, vfdst, fsum;
139 #if HAVE_BIGENDIAN
140     register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
141     register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
142     vsrcperm0 = vec_lvsl(0, src);
143     vsrcperm1 = vec_lvsl(1, src);
144 #endif
145
146     if (((unsigned long)dst) % 16 == 0) {
147         fperm = (vec_u8){0x10, 0x11, 0x12, 0x13,
148                          0x14, 0x15, 0x16, 0x17,
149                          0x08, 0x09, 0x0A, 0x0B,
150                          0x0C, 0x0D, 0x0E, 0x0F};
151     } else {
152         fperm = (vec_u8){0x00, 0x01, 0x02, 0x03,
153                          0x04, 0x05, 0x06, 0x07,
154                          0x18, 0x19, 0x1A, 0x1B,
155                          0x1C, 0x1D, 0x1E, 0x1F};
156     }
157
158     GET_VSRC(vsrc0uc, vsrc1uc, 0, 16, vsrcperm0, vsrcperm1, src);
159
160     vsrc0ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc0uc);
161     vsrc1ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc1uc);
162
163     if (ABCD[3]) {
164         for (i = 0 ; i < h ; i++) {
165             GET_VSRC(vsrc2uc, vsrc3uc, stride, 16, vsrcperm0, vsrcperm1, src);
166             CHROMA_MC8_ALTIVEC_CORE(v32ss, noop);
167         }
168     } else {
169         const vec_s16 vE = vec_add(vB, vC);
170         if (ABCD[2]) { // x == 0 B == 0
171             for (i = 0 ; i < h ; i++) {
172                 GET_VSRC1(vsrc1uc, stride, 15, vsrcperm0, src);
173                 CHROMA_MC8_ALTIVEC_CORE_SIMPLE;
174                 vsrc0uc = vsrc1uc;
175             }
176         } else { // y == 0 C == 0
177             for (i = 0 ; i < h ; i++) {
178                GET_VSRC(vsrc0uc, vsrc1uc, 0, 15, vsrcperm0, vsrcperm1, src);
179                CHROMA_MC8_ALTIVEC_CORE_SIMPLE;
180             }
181         }
182     }
183 }
184 #endif
185
186 /* this code assume that stride % 16 == 0 */
187 #ifdef PREFIX_no_rnd_vc1_chroma_mc8_altivec
188 static void PREFIX_no_rnd_vc1_chroma_mc8_altivec(uint8_t *dst, uint8_t *src,
189                                                  ptrdiff_t stride, int h,
190                                                  int x, int y)
191 {
192    DECLARE_ALIGNED(16, signed int, ABCD)[4] =
193                         {((8 - x) * (8 - y)),
194                          ((    x) * (8 - y)),
195                          ((8 - x) * (    y)),
196                          ((    x) * (    y))};
197     register int i;
198     vec_u8 fperm;
199     LOAD_ZERO;
200     const vec_s32 vABCD = vec_ld(0, ABCD);
201     const vec_s16 vA = VEC_SPLAT16(vABCD, 1);
202     const vec_s16 vB = VEC_SPLAT16(vABCD, 3);
203     const vec_s16 vC = VEC_SPLAT16(vABCD, 5);
204     const vec_s16 vD = VEC_SPLAT16(vABCD, 7);
205     const vec_s16 v28ss = vec_sub(vec_sl(vec_splat_s16(1),vec_splat_u16(5)),vec_splat_s16(4));
206     const vec_u16 v6us  = vec_splat_u16(6);
207
208     vec_u8 vsrcperm0, vsrcperm1;
209     vec_u8 vsrc0uc, vsrc1uc;
210     vec_s16 vsrc0ssH, vsrc1ssH;
211     vec_u8 vsrc2uc, vsrc3uc;
212     vec_s16 vsrc2ssH, vsrc3ssH, psum;
213     vec_u8 vdst, ppsum, vfdst, fsum;
214 #if HAVE_BIGENDIAN
215     register int loadSecond     = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
216     register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
217     vsrcperm0 = vec_lvsl(0, src);
218     vsrcperm1 = vec_lvsl(1, src);
219 #endif
220
221     if (((unsigned long)dst) % 16 == 0) {
222         fperm = (vec_u8){0x10, 0x11, 0x12, 0x13,
223                          0x14, 0x15, 0x16, 0x17,
224                          0x08, 0x09, 0x0A, 0x0B,
225                          0x0C, 0x0D, 0x0E, 0x0F};
226     } else {
227         fperm = (vec_u8){0x00, 0x01, 0x02, 0x03,
228                          0x04, 0x05, 0x06, 0x07,
229                          0x18, 0x19, 0x1A, 0x1B,
230                          0x1C, 0x1D, 0x1E, 0x1F};
231     }
232
233     GET_VSRC(vsrc0uc, vsrc1uc, 0, 16, vsrcperm0, vsrcperm1, src);
234
235     vsrc0ssH = (vec_s16)VEC_MERGEH(zero_u8v, (vec_u8)vsrc0uc);
236     vsrc1ssH = (vec_s16)VEC_MERGEH(zero_u8v, (vec_u8)vsrc1uc);
237
238     for (i = 0 ; i < h ; i++) {
239         GET_VSRC(vsrc2uc, vsrc3uc, stride, 16, vsrcperm0, vsrcperm1, src);
240         CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28);
241     }
242 }
243 #endif
244
245 #undef noop
246 #undef add28
247 #undef CHROMA_MC8_ALTIVEC_CORE