1*c0909341SAndroid Build Coastguard Worker /*
2*c0909341SAndroid Build Coastguard Worker * Copyright © 2019, VideoLAN and dav1d authors
3*c0909341SAndroid Build Coastguard Worker * Copyright © 2019, Michail Alvanos
4*c0909341SAndroid Build Coastguard Worker * All rights reserved.
5*c0909341SAndroid Build Coastguard Worker *
6*c0909341SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
7*c0909341SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
8*c0909341SAndroid Build Coastguard Worker *
9*c0909341SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright notice, this
10*c0909341SAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
11*c0909341SAndroid Build Coastguard Worker *
12*c0909341SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright notice,
13*c0909341SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
14*c0909341SAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
15*c0909341SAndroid Build Coastguard Worker *
16*c0909341SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*c0909341SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*c0909341SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*c0909341SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20*c0909341SAndroid Build Coastguard Worker * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*c0909341SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*c0909341SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*c0909341SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c0909341SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*c0909341SAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c0909341SAndroid Build Coastguard Worker */
27*c0909341SAndroid Build Coastguard Worker
28*c0909341SAndroid Build Coastguard Worker #include "src/ppc/dav1d_types.h"
29*c0909341SAndroid Build Coastguard Worker #include "src/ppc/looprestoration.h"
30*c0909341SAndroid Build Coastguard Worker
31*c0909341SAndroid Build Coastguard Worker #if BITDEPTH == 8
32*c0909341SAndroid Build Coastguard Worker
33*c0909341SAndroid Build Coastguard Worker #define REST_UNIT_STRIDE (400)
34*c0909341SAndroid Build Coastguard Worker
iclip_vec(i32x4 v,const i32x4 minv,const i32x4 maxv)35*c0909341SAndroid Build Coastguard Worker static inline i32x4 iclip_vec(i32x4 v, const i32x4 minv, const i32x4 maxv) {
36*c0909341SAndroid Build Coastguard Worker v = vec_max(minv, v);
37*c0909341SAndroid Build Coastguard Worker v = vec_min(maxv, v);
38*c0909341SAndroid Build Coastguard Worker return v;
39*c0909341SAndroid Build Coastguard Worker }
40*c0909341SAndroid Build Coastguard Worker
41*c0909341SAndroid Build Coastguard Worker #define APPLY_FILTER_H(v, f, ssum1, ssum2) do { \
42*c0909341SAndroid Build Coastguard Worker i16x8 ktmp_u16_high = (i16x8) u8h_to_u16(v); \
43*c0909341SAndroid Build Coastguard Worker i16x8 ktmp_u16_low = (i16x8) u8l_to_u16(v); \
44*c0909341SAndroid Build Coastguard Worker ssum1 = vec_madd(ktmp_u16_high, f, ssum1); \
45*c0909341SAndroid Build Coastguard Worker ssum2 = vec_madd(ktmp_u16_low, f, ssum2); \
46*c0909341SAndroid Build Coastguard Worker } while (0)
47*c0909341SAndroid Build Coastguard Worker
wiener_filter_h_vsx(int32_t * hor_ptr,uint8_t * tmp_ptr,const int16_t filterh[8],const int w,const int h)48*c0909341SAndroid Build Coastguard Worker static void wiener_filter_h_vsx(int32_t *hor_ptr,
49*c0909341SAndroid Build Coastguard Worker uint8_t *tmp_ptr,
50*c0909341SAndroid Build Coastguard Worker const int16_t filterh[8],
51*c0909341SAndroid Build Coastguard Worker const int w, const int h)
52*c0909341SAndroid Build Coastguard Worker {
53*c0909341SAndroid Build Coastguard Worker const i32x4 zerov = vec_splats(0);
54*c0909341SAndroid Build Coastguard Worker const i32x4 seven_vec = vec_splats(7);
55*c0909341SAndroid Build Coastguard Worker const i32x4 bitdepth_added_vec = vec_splats(1 << 14);
56*c0909341SAndroid Build Coastguard Worker const i32x4 round_bits_vec = vec_splats(3);
57*c0909341SAndroid Build Coastguard Worker const i32x4 rounding_off_vec = vec_splats(1<<2);
58*c0909341SAndroid Build Coastguard Worker const i32x4 clip_limit_v = vec_splats((1 << 13) - 1);
59*c0909341SAndroid Build Coastguard Worker
60*c0909341SAndroid Build Coastguard Worker i16x8 filterhvall = vec_vsx_ld(0, filterh);
61*c0909341SAndroid Build Coastguard Worker i16x8 filterhv0 = vec_splat( filterhvall, 0);
62*c0909341SAndroid Build Coastguard Worker i16x8 filterhv1 = vec_splat( filterhvall, 1);
63*c0909341SAndroid Build Coastguard Worker i16x8 filterhv2 = vec_splat( filterhvall, 2);
64*c0909341SAndroid Build Coastguard Worker i16x8 filterhv3 = vec_splat( filterhvall, 3);
65*c0909341SAndroid Build Coastguard Worker i16x8 filterhv4 = vec_splat( filterhvall, 4);
66*c0909341SAndroid Build Coastguard Worker i16x8 filterhv5 = vec_splat( filterhvall, 5);
67*c0909341SAndroid Build Coastguard Worker i16x8 filterhv6 = vec_splat( filterhvall, 6);
68*c0909341SAndroid Build Coastguard Worker
69*c0909341SAndroid Build Coastguard Worker for (int j = 0; j < h + 6; j++) {
70*c0909341SAndroid Build Coastguard Worker for (int i = 0; i < w; i+=16) {
71*c0909341SAndroid Build Coastguard Worker i32x4 sum1 = bitdepth_added_vec;
72*c0909341SAndroid Build Coastguard Worker i32x4 sum2 = bitdepth_added_vec;
73*c0909341SAndroid Build Coastguard Worker i32x4 sum3 = bitdepth_added_vec;
74*c0909341SAndroid Build Coastguard Worker i32x4 sum4 = bitdepth_added_vec;
75*c0909341SAndroid Build Coastguard Worker
76*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v0 = vec_ld(0, &tmp_ptr[i]);
77*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v7 = vec_ld(0, &tmp_ptr[i+16]);
78*c0909341SAndroid Build Coastguard Worker
79*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v1 = vec_sld( tmp_v7, tmp_v0, 15);
80*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v2 = vec_sld( tmp_v7, tmp_v0, 14);
81*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v3 = vec_sld( tmp_v7, tmp_v0, 13);
82*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v4 = vec_sld( tmp_v7, tmp_v0, 12);
83*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v5 = vec_sld( tmp_v7, tmp_v0, 11);
84*c0909341SAndroid Build Coastguard Worker u8x16 tmp_v6 = vec_sld( tmp_v7, tmp_v0, 10);
85*c0909341SAndroid Build Coastguard Worker
86*c0909341SAndroid Build Coastguard Worker u16x8 tmp_u16_high = u8h_to_u16(tmp_v3);
87*c0909341SAndroid Build Coastguard Worker u16x8 tmp_u16_low = u8l_to_u16(tmp_v3);
88*c0909341SAndroid Build Coastguard Worker
89*c0909341SAndroid Build Coastguard Worker i32x4 tmp_expanded1 = i16h_to_i32(tmp_u16_high);
90*c0909341SAndroid Build Coastguard Worker i32x4 tmp_expanded2 = i16l_to_i32(tmp_u16_high);
91*c0909341SAndroid Build Coastguard Worker i32x4 tmp_expanded3 = i16h_to_i32(tmp_u16_low);
92*c0909341SAndroid Build Coastguard Worker i32x4 tmp_expanded4 = i16l_to_i32(tmp_u16_low);
93*c0909341SAndroid Build Coastguard Worker
94*c0909341SAndroid Build Coastguard Worker i16x8 ssum1 = (i16x8) zerov;
95*c0909341SAndroid Build Coastguard Worker i16x8 ssum2 = (i16x8) zerov;
96*c0909341SAndroid Build Coastguard Worker
97*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v0, filterhv0, ssum1, ssum2);
98*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v1, filterhv1, ssum1, ssum2);
99*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v2, filterhv2, ssum1, ssum2);
100*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v3, filterhv3, ssum1, ssum2);
101*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v4, filterhv4, ssum1, ssum2);
102*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v5, filterhv5, ssum1, ssum2);
103*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_H(tmp_v6, filterhv6, ssum1, ssum2);
104*c0909341SAndroid Build Coastguard Worker
105*c0909341SAndroid Build Coastguard Worker sum1 += i16h_to_i32(ssum1) + (tmp_expanded1 << seven_vec);
106*c0909341SAndroid Build Coastguard Worker sum2 += i16l_to_i32(ssum1) + (tmp_expanded2 << seven_vec);
107*c0909341SAndroid Build Coastguard Worker sum3 += i16h_to_i32(ssum2) + (tmp_expanded3 << seven_vec);
108*c0909341SAndroid Build Coastguard Worker sum4 += i16l_to_i32(ssum2) + (tmp_expanded4 << seven_vec);
109*c0909341SAndroid Build Coastguard Worker
110*c0909341SAndroid Build Coastguard Worker sum1 = (sum1 + rounding_off_vec) >> round_bits_vec;
111*c0909341SAndroid Build Coastguard Worker sum2 = (sum2 + rounding_off_vec) >> round_bits_vec;
112*c0909341SAndroid Build Coastguard Worker sum3 = (sum3 + rounding_off_vec) >> round_bits_vec;
113*c0909341SAndroid Build Coastguard Worker sum4 = (sum4 + rounding_off_vec) >> round_bits_vec;
114*c0909341SAndroid Build Coastguard Worker
115*c0909341SAndroid Build Coastguard Worker sum1 = iclip_vec(sum1, zerov, clip_limit_v);
116*c0909341SAndroid Build Coastguard Worker sum2 = iclip_vec(sum2, zerov, clip_limit_v);
117*c0909341SAndroid Build Coastguard Worker sum3 = iclip_vec(sum3, zerov, clip_limit_v);
118*c0909341SAndroid Build Coastguard Worker sum4 = iclip_vec(sum4, zerov, clip_limit_v);
119*c0909341SAndroid Build Coastguard Worker
120*c0909341SAndroid Build Coastguard Worker vec_st(sum1, 0, &hor_ptr[i]);
121*c0909341SAndroid Build Coastguard Worker vec_st(sum2, 16, &hor_ptr[i]);
122*c0909341SAndroid Build Coastguard Worker vec_st(sum3, 32, &hor_ptr[i]);
123*c0909341SAndroid Build Coastguard Worker vec_st(sum4, 48, &hor_ptr[i]);
124*c0909341SAndroid Build Coastguard Worker }
125*c0909341SAndroid Build Coastguard Worker tmp_ptr += REST_UNIT_STRIDE;
126*c0909341SAndroid Build Coastguard Worker hor_ptr += REST_UNIT_STRIDE;
127*c0909341SAndroid Build Coastguard Worker }
128*c0909341SAndroid Build Coastguard Worker }
129*c0909341SAndroid Build Coastguard Worker
iclip_u8_vec(i16x8 v)130*c0909341SAndroid Build Coastguard Worker static inline i16x8 iclip_u8_vec(i16x8 v) {
131*c0909341SAndroid Build Coastguard Worker const i16x8 zerov = vec_splats((int16_t)0);
132*c0909341SAndroid Build Coastguard Worker const i16x8 maxv = vec_splats((int16_t)255);
133*c0909341SAndroid Build Coastguard Worker v = vec_max(zerov, v);
134*c0909341SAndroid Build Coastguard Worker v = vec_min(maxv, v);
135*c0909341SAndroid Build Coastguard Worker return v;
136*c0909341SAndroid Build Coastguard Worker }
137*c0909341SAndroid Build Coastguard Worker
138*c0909341SAndroid Build Coastguard Worker #define APPLY_FILTER_V(index, f) do { \
139*c0909341SAndroid Build Coastguard Worker i32x4 v1 = vec_ld( 0, &hor[(j + index) * REST_UNIT_STRIDE + i]); \
140*c0909341SAndroid Build Coastguard Worker i32x4 v2 = vec_ld(16, &hor[(j + index) * REST_UNIT_STRIDE + i]); \
141*c0909341SAndroid Build Coastguard Worker i32x4 v3 = vec_ld(32, &hor[(j + index) * REST_UNIT_STRIDE + i]); \
142*c0909341SAndroid Build Coastguard Worker i32x4 v4 = vec_ld(48, &hor[(j + index) * REST_UNIT_STRIDE + i]); \
143*c0909341SAndroid Build Coastguard Worker sum1 = sum1 + v1 * f; \
144*c0909341SAndroid Build Coastguard Worker sum2 = sum2 + v2 * f; \
145*c0909341SAndroid Build Coastguard Worker sum3 = sum3 + v3 * f; \
146*c0909341SAndroid Build Coastguard Worker sum4 = sum4 + v4 * f; \
147*c0909341SAndroid Build Coastguard Worker } while (0)
148*c0909341SAndroid Build Coastguard Worker
149*c0909341SAndroid Build Coastguard Worker #define LOAD_AND_APPLY_FILTER_V(sumpixelv, hor) do { \
150*c0909341SAndroid Build Coastguard Worker i32x4 sum1 = round_vec; \
151*c0909341SAndroid Build Coastguard Worker i32x4 sum2 = round_vec; \
152*c0909341SAndroid Build Coastguard Worker i32x4 sum3 = round_vec; \
153*c0909341SAndroid Build Coastguard Worker i32x4 sum4 = round_vec; \
154*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(0, filterv0); \
155*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(1, filterv1); \
156*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(2, filterv2); \
157*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(3, filterv3); \
158*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(4, filterv4); \
159*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(5, filterv5); \
160*c0909341SAndroid Build Coastguard Worker APPLY_FILTER_V(6, filterv6); \
161*c0909341SAndroid Build Coastguard Worker sum1 = sum1 >> round_bits_vec; \
162*c0909341SAndroid Build Coastguard Worker sum2 = sum2 >> round_bits_vec; \
163*c0909341SAndroid Build Coastguard Worker sum3 = sum3 >> round_bits_vec; \
164*c0909341SAndroid Build Coastguard Worker sum4 = sum4 >> round_bits_vec; \
165*c0909341SAndroid Build Coastguard Worker i16x8 sum_short_packed_1 = (i16x8) vec_pack(sum1, sum2); \
166*c0909341SAndroid Build Coastguard Worker i16x8 sum_short_packed_2 = (i16x8) vec_pack(sum3, sum4); \
167*c0909341SAndroid Build Coastguard Worker sum_short_packed_1 = iclip_u8_vec(sum_short_packed_1); \
168*c0909341SAndroid Build Coastguard Worker sum_short_packed_2 = iclip_u8_vec(sum_short_packed_2); \
169*c0909341SAndroid Build Coastguard Worker sum_pixel = (u8x16) vec_pack(sum_short_packed_1, sum_short_packed_2); \
170*c0909341SAndroid Build Coastguard Worker } while (0)
171*c0909341SAndroid Build Coastguard Worker
wiener_filter_v_vsx(uint8_t * p,const ptrdiff_t stride,const int32_t * hor,const int16_t filterv[8],const int w,const int h)172*c0909341SAndroid Build Coastguard Worker static inline void wiener_filter_v_vsx(uint8_t *p,
173*c0909341SAndroid Build Coastguard Worker const ptrdiff_t stride,
174*c0909341SAndroid Build Coastguard Worker const int32_t *hor,
175*c0909341SAndroid Build Coastguard Worker const int16_t filterv[8],
176*c0909341SAndroid Build Coastguard Worker const int w, const int h)
177*c0909341SAndroid Build Coastguard Worker {
178*c0909341SAndroid Build Coastguard Worker const i32x4 round_bits_vec = vec_splats(11);
179*c0909341SAndroid Build Coastguard Worker const i32x4 round_vec = vec_splats((1 << 10) - (1 << 18));
180*c0909341SAndroid Build Coastguard Worker
181*c0909341SAndroid Build Coastguard Worker i32x4 filterv0 = vec_splats((int32_t) filterv[0]);
182*c0909341SAndroid Build Coastguard Worker i32x4 filterv1 = vec_splats((int32_t) filterv[1]);
183*c0909341SAndroid Build Coastguard Worker i32x4 filterv2 = vec_splats((int32_t) filterv[2]);
184*c0909341SAndroid Build Coastguard Worker i32x4 filterv3 = vec_splats((int32_t) filterv[3]);
185*c0909341SAndroid Build Coastguard Worker i32x4 filterv4 = vec_splats((int32_t) filterv[4]);
186*c0909341SAndroid Build Coastguard Worker i32x4 filterv5 = vec_splats((int32_t) filterv[5]);
187*c0909341SAndroid Build Coastguard Worker i32x4 filterv6 = vec_splats((int32_t) filterv[6]);
188*c0909341SAndroid Build Coastguard Worker
189*c0909341SAndroid Build Coastguard Worker for (int j = 0; j < h; j++) {
190*c0909341SAndroid Build Coastguard Worker for (int i = 0; i <(w-w%16); i += 16) {
191*c0909341SAndroid Build Coastguard Worker u8x16 sum_pixel;
192*c0909341SAndroid Build Coastguard Worker LOAD_AND_APPLY_FILTER_V(sum_pixel, hor);
193*c0909341SAndroid Build Coastguard Worker vec_vsx_st(sum_pixel, 0, &p[j * PXSTRIDE(stride) + i]);
194*c0909341SAndroid Build Coastguard Worker }
195*c0909341SAndroid Build Coastguard Worker // remaining loop
196*c0909341SAndroid Build Coastguard Worker if (w & 0xf){
197*c0909341SAndroid Build Coastguard Worker int i=w-w%16;
198*c0909341SAndroid Build Coastguard Worker ALIGN_STK_16(uint8_t, tmp_out, 16,);
199*c0909341SAndroid Build Coastguard Worker u8x16 sum_pixel;
200*c0909341SAndroid Build Coastguard Worker
201*c0909341SAndroid Build Coastguard Worker LOAD_AND_APPLY_FILTER_V(sum_pixel, hor);
202*c0909341SAndroid Build Coastguard Worker vec_vsx_st(sum_pixel, 0, tmp_out);
203*c0909341SAndroid Build Coastguard Worker
204*c0909341SAndroid Build Coastguard Worker for (int k=0; i<w; i++, k++) {
205*c0909341SAndroid Build Coastguard Worker p[j * PXSTRIDE(stride) + i] = tmp_out[k];
206*c0909341SAndroid Build Coastguard Worker }
207*c0909341SAndroid Build Coastguard Worker }
208*c0909341SAndroid Build Coastguard Worker }
209*c0909341SAndroid Build Coastguard Worker }
210*c0909341SAndroid Build Coastguard Worker
padding(uint8_t * dst,const uint8_t * p,const ptrdiff_t stride,const uint8_t (* left)[4],const uint8_t * lpf,int unit_w,const int stripe_h,const enum LrEdgeFlags edges)211*c0909341SAndroid Build Coastguard Worker static inline void padding(uint8_t *dst, const uint8_t *p,
212*c0909341SAndroid Build Coastguard Worker const ptrdiff_t stride, const uint8_t (*left)[4],
213*c0909341SAndroid Build Coastguard Worker const uint8_t *lpf, int unit_w, const int stripe_h,
214*c0909341SAndroid Build Coastguard Worker const enum LrEdgeFlags edges)
215*c0909341SAndroid Build Coastguard Worker {
216*c0909341SAndroid Build Coastguard Worker const int have_left = !!(edges & LR_HAVE_LEFT);
217*c0909341SAndroid Build Coastguard Worker const int have_right = !!(edges & LR_HAVE_RIGHT);
218*c0909341SAndroid Build Coastguard Worker
219*c0909341SAndroid Build Coastguard Worker // Copy more pixels if we don't have to pad them
220*c0909341SAndroid Build Coastguard Worker unit_w += 3 * have_left + 3 * have_right;
221*c0909341SAndroid Build Coastguard Worker uint8_t *dst_l = dst + 3 * !have_left;
222*c0909341SAndroid Build Coastguard Worker p -= 3 * have_left;
223*c0909341SAndroid Build Coastguard Worker lpf -= 3 * have_left;
224*c0909341SAndroid Build Coastguard Worker
225*c0909341SAndroid Build Coastguard Worker if (edges & LR_HAVE_TOP) {
226*c0909341SAndroid Build Coastguard Worker // Copy previous loop filtered rows
227*c0909341SAndroid Build Coastguard Worker const uint8_t *const above_1 = lpf;
228*c0909341SAndroid Build Coastguard Worker const uint8_t *const above_2 = above_1 + PXSTRIDE(stride);
229*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l, above_1, unit_w);
230*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l + REST_UNIT_STRIDE, above_1, unit_w);
231*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l + 2 * REST_UNIT_STRIDE, above_2, unit_w);
232*c0909341SAndroid Build Coastguard Worker } else {
233*c0909341SAndroid Build Coastguard Worker // Pad with first row
234*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l, p, unit_w);
235*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l + REST_UNIT_STRIDE, p, unit_w);
236*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l + 2 * REST_UNIT_STRIDE, p, unit_w);
237*c0909341SAndroid Build Coastguard Worker if (have_left) {
238*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l, &left[0][1], 3);
239*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l + REST_UNIT_STRIDE, &left[0][1], 3);
240*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_l + 2 * REST_UNIT_STRIDE, &left[0][1], 3);
241*c0909341SAndroid Build Coastguard Worker }
242*c0909341SAndroid Build Coastguard Worker }
243*c0909341SAndroid Build Coastguard Worker
244*c0909341SAndroid Build Coastguard Worker uint8_t *dst_tl = dst_l + 3 * REST_UNIT_STRIDE;
245*c0909341SAndroid Build Coastguard Worker if (edges & LR_HAVE_BOTTOM) {
246*c0909341SAndroid Build Coastguard Worker // Copy next loop filtered rows
247*c0909341SAndroid Build Coastguard Worker const uint8_t *const below_1 = lpf + 6 * PXSTRIDE(stride);
248*c0909341SAndroid Build Coastguard Worker const uint8_t *const below_2 = below_1 + PXSTRIDE(stride);
249*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + stripe_h * REST_UNIT_STRIDE, below_1, unit_w);
250*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + (stripe_h + 1) * REST_UNIT_STRIDE, below_2, unit_w);
251*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + (stripe_h + 2) * REST_UNIT_STRIDE, below_2, unit_w);
252*c0909341SAndroid Build Coastguard Worker } else {
253*c0909341SAndroid Build Coastguard Worker // Pad with last row
254*c0909341SAndroid Build Coastguard Worker const uint8_t *const src = p + (stripe_h - 1) * PXSTRIDE(stride);
255*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + stripe_h * REST_UNIT_STRIDE, src, unit_w);
256*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + (stripe_h + 1) * REST_UNIT_STRIDE, src, unit_w);
257*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + (stripe_h + 2) * REST_UNIT_STRIDE, src, unit_w);
258*c0909341SAndroid Build Coastguard Worker if (have_left) {
259*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + stripe_h * REST_UNIT_STRIDE, &left[stripe_h - 1][1], 3);
260*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + (stripe_h + 1) * REST_UNIT_STRIDE, &left[stripe_h - 1][1], 3);
261*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + (stripe_h + 2) * REST_UNIT_STRIDE, &left[stripe_h - 1][1], 3);
262*c0909341SAndroid Build Coastguard Worker }
263*c0909341SAndroid Build Coastguard Worker }
264*c0909341SAndroid Build Coastguard Worker
265*c0909341SAndroid Build Coastguard Worker // Inner UNIT_WxSTRIPE_H
266*c0909341SAndroid Build Coastguard Worker for (int j = 0; j < stripe_h; j++) {
267*c0909341SAndroid Build Coastguard Worker pixel_copy(dst_tl + 3 * have_left, p + 3 * have_left, unit_w - 3 * have_left);
268*c0909341SAndroid Build Coastguard Worker dst_tl += REST_UNIT_STRIDE;
269*c0909341SAndroid Build Coastguard Worker p += PXSTRIDE(stride);
270*c0909341SAndroid Build Coastguard Worker }
271*c0909341SAndroid Build Coastguard Worker
272*c0909341SAndroid Build Coastguard Worker if (!have_right) {
273*c0909341SAndroid Build Coastguard Worker uint8_t *pad = dst_l + unit_w;
274*c0909341SAndroid Build Coastguard Worker uint8_t *row_last = &dst_l[unit_w - 1];
275*c0909341SAndroid Build Coastguard Worker // Pad 3x(STRIPE_H+6) with last column
276*c0909341SAndroid Build Coastguard Worker for (int j = 0; j < stripe_h + 6; j++) {
277*c0909341SAndroid Build Coastguard Worker pixel_set(pad, *row_last, 3);
278*c0909341SAndroid Build Coastguard Worker pad += REST_UNIT_STRIDE;
279*c0909341SAndroid Build Coastguard Worker row_last += REST_UNIT_STRIDE;
280*c0909341SAndroid Build Coastguard Worker }
281*c0909341SAndroid Build Coastguard Worker }
282*c0909341SAndroid Build Coastguard Worker
283*c0909341SAndroid Build Coastguard Worker if (!have_left) {
284*c0909341SAndroid Build Coastguard Worker // Pad 3x(STRIPE_H+6) with first column
285*c0909341SAndroid Build Coastguard Worker for (int j = 0; j < stripe_h + 6; j++) {
286*c0909341SAndroid Build Coastguard Worker pixel_set(dst, *dst_l, 3);
287*c0909341SAndroid Build Coastguard Worker dst += REST_UNIT_STRIDE;
288*c0909341SAndroid Build Coastguard Worker dst_l += REST_UNIT_STRIDE;
289*c0909341SAndroid Build Coastguard Worker }
290*c0909341SAndroid Build Coastguard Worker } else {
291*c0909341SAndroid Build Coastguard Worker dst += 3 * REST_UNIT_STRIDE;
292*c0909341SAndroid Build Coastguard Worker for (int j = 0; j < stripe_h; j++) {
293*c0909341SAndroid Build Coastguard Worker pixel_copy(dst, &left[j][1], 3);
294*c0909341SAndroid Build Coastguard Worker dst += REST_UNIT_STRIDE;
295*c0909341SAndroid Build Coastguard Worker }
296*c0909341SAndroid Build Coastguard Worker }
297*c0909341SAndroid Build Coastguard Worker }
298*c0909341SAndroid Build Coastguard Worker
299*c0909341SAndroid Build Coastguard Worker // FIXME Could split into luma and chroma specific functions,
300*c0909341SAndroid Build Coastguard Worker // (since first and last tops are always 0 for chroma)
301*c0909341SAndroid Build Coastguard Worker // FIXME Could implement a version that requires less temporary memory
302*c0909341SAndroid Build Coastguard Worker // (should be possible to implement with only 6 rows of temp storage)
dav1d_wiener_filter_vsx(uint8_t * p,const ptrdiff_t stride,const uint8_t (* const left)[4],const uint8_t * lpf,const int w,const int h,const LooprestorationParams * const params,const enum LrEdgeFlags edges)303*c0909341SAndroid Build Coastguard Worker void dav1d_wiener_filter_vsx(uint8_t *p, const ptrdiff_t stride,
304*c0909341SAndroid Build Coastguard Worker const uint8_t (*const left)[4],
305*c0909341SAndroid Build Coastguard Worker const uint8_t *lpf,
306*c0909341SAndroid Build Coastguard Worker const int w, const int h,
307*c0909341SAndroid Build Coastguard Worker const LooprestorationParams *const params,
308*c0909341SAndroid Build Coastguard Worker const enum LrEdgeFlags edges)
309*c0909341SAndroid Build Coastguard Worker {
310*c0909341SAndroid Build Coastguard Worker const int16_t (*const filter)[8] = params->filter;
311*c0909341SAndroid Build Coastguard Worker
312*c0909341SAndroid Build Coastguard Worker // Wiener filtering is applied to a maximum stripe height of 64 + 3 pixels
313*c0909341SAndroid Build Coastguard Worker // of padding above and below
314*c0909341SAndroid Build Coastguard Worker ALIGN_STK_16(uint8_t, tmp, 70 /*(64 + 3 + 3)*/ * REST_UNIT_STRIDE,);
315*c0909341SAndroid Build Coastguard Worker padding(tmp, p, stride, left, lpf, w, h, edges);
316*c0909341SAndroid Build Coastguard Worker ALIGN_STK_16(int32_t, hor, 70 /*(64 + 3 + 3)*/ * REST_UNIT_STRIDE + 64,);
317*c0909341SAndroid Build Coastguard Worker
318*c0909341SAndroid Build Coastguard Worker wiener_filter_h_vsx(hor, tmp, filter[0], w, h);
319*c0909341SAndroid Build Coastguard Worker wiener_filter_v_vsx(p, stride, hor, filter[1], w, h);
320*c0909341SAndroid Build Coastguard Worker }
321*c0909341SAndroid Build Coastguard Worker #endif
322