1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12#include "vpx_config.h"
13#include "vp8/common/loopfilter.h"
14
15#define prototype_loopfilter(sym) \
16    void sym(unsigned char *src, int pitch, const unsigned char *blimit,\
17             const unsigned char *limit, const unsigned char *thresh, int count)
18
19#define prototype_loopfilter_nc(sym) \
20    void sym(unsigned char *src, int pitch, const unsigned char *blimit,\
21             const unsigned char *limit, const unsigned char *thresh)
22
23#define prototype_simple_loopfilter(sym) \
24    void sym(unsigned char *y, int ystride, const unsigned char *blimit)
25
26prototype_loopfilter(vp8_mbloop_filter_vertical_edge_mmx);
27prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_mmx);
28prototype_loopfilter(vp8_loop_filter_vertical_edge_mmx);
29prototype_loopfilter(vp8_loop_filter_horizontal_edge_mmx);
30prototype_simple_loopfilter(vp8_loop_filter_simple_horizontal_edge_mmx);
31prototype_simple_loopfilter(vp8_loop_filter_simple_vertical_edge_mmx);
32
33#if HAVE_SSE2 && ARCH_X86_64
34prototype_loopfilter(vp8_loop_filter_bv_y_sse2);
35prototype_loopfilter(vp8_loop_filter_bh_y_sse2);
36#else
37prototype_loopfilter_nc(vp8_loop_filter_vertical_edge_sse2);
38prototype_loopfilter_nc(vp8_loop_filter_horizontal_edge_sse2);
39#endif
40prototype_loopfilter_nc(vp8_mbloop_filter_vertical_edge_sse2);
41prototype_loopfilter_nc(vp8_mbloop_filter_horizontal_edge_sse2);
42
43extern loop_filter_uvfunction vp8_loop_filter_horizontal_edge_uv_sse2;
44extern loop_filter_uvfunction vp8_loop_filter_vertical_edge_uv_sse2;
45extern loop_filter_uvfunction vp8_mbloop_filter_horizontal_edge_uv_sse2;
46extern loop_filter_uvfunction vp8_mbloop_filter_vertical_edge_uv_sse2;
47
48#if HAVE_MMX
49/* Horizontal MB filtering */
50void vp8_loop_filter_mbh_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
51                             int y_stride, int uv_stride, loop_filter_info *lfi)
52{
53    vp8_mbloop_filter_horizontal_edge_mmx(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
54
55    if (u_ptr)
56        vp8_mbloop_filter_horizontal_edge_mmx(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
57
58    if (v_ptr)
59        vp8_mbloop_filter_horizontal_edge_mmx(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
60}
61
62
63/* Vertical MB Filtering */
64void vp8_loop_filter_mbv_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
65                             int y_stride, int uv_stride, loop_filter_info *lfi)
66{
67    vp8_mbloop_filter_vertical_edge_mmx(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
68
69    if (u_ptr)
70        vp8_mbloop_filter_vertical_edge_mmx(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
71
72    if (v_ptr)
73        vp8_mbloop_filter_vertical_edge_mmx(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
74}
75
76
77/* Horizontal B Filtering */
78void vp8_loop_filter_bh_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
79                            int y_stride, int uv_stride, loop_filter_info *lfi)
80{
81    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
82    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
83    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
84
85    if (u_ptr)
86        vp8_loop_filter_horizontal_edge_mmx(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
87
88    if (v_ptr)
89        vp8_loop_filter_horizontal_edge_mmx(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
90}
91
92
93void vp8_loop_filter_bhs_mmx(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
94{
95    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 4 * y_stride, y_stride, blimit);
96    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 8 * y_stride, y_stride, blimit);
97    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 12 * y_stride, y_stride, blimit);
98}
99
100
101/* Vertical B Filtering */
102void vp8_loop_filter_bv_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
103                            int y_stride, int uv_stride, loop_filter_info *lfi)
104{
105    vp8_loop_filter_vertical_edge_mmx(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
106    vp8_loop_filter_vertical_edge_mmx(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
107    vp8_loop_filter_vertical_edge_mmx(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
108
109    if (u_ptr)
110        vp8_loop_filter_vertical_edge_mmx(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
111
112    if (v_ptr)
113        vp8_loop_filter_vertical_edge_mmx(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
114}
115
116
117void vp8_loop_filter_bvs_mmx(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
118{
119    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 4, y_stride, blimit);
120    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 8, y_stride, blimit);
121    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 12, y_stride, blimit);
122}
123#endif
124
125
126/* Horizontal MB filtering */
127#if HAVE_SSE2
128void vp8_loop_filter_mbh_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
129                              int y_stride, int uv_stride, loop_filter_info *lfi)
130{
131    vp8_mbloop_filter_horizontal_edge_sse2(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr);
132
133    if (u_ptr)
134        vp8_mbloop_filter_horizontal_edge_uv_sse2(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, v_ptr);
135}
136
137
138/* Vertical MB Filtering */
139void vp8_loop_filter_mbv_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
140                              int y_stride, int uv_stride, loop_filter_info *lfi)
141{
142    vp8_mbloop_filter_vertical_edge_sse2(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr);
143
144    if (u_ptr)
145        vp8_mbloop_filter_vertical_edge_uv_sse2(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, v_ptr);
146}
147
148
149/* Horizontal B Filtering */
150void vp8_loop_filter_bh_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
151                             int y_stride, int uv_stride, loop_filter_info *lfi)
152{
153#if ARCH_X86_64
154    vp8_loop_filter_bh_y_sse2(y_ptr, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
155#else
156    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
157    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
158    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
159#endif
160
161    if (u_ptr)
162        vp8_loop_filter_horizontal_edge_uv_sse2(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, v_ptr + 4 * uv_stride);
163}
164
165
166void vp8_loop_filter_bhs_sse2(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
167{
168    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 4 * y_stride, y_stride, blimit);
169    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 8 * y_stride, y_stride, blimit);
170    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 12 * y_stride, y_stride, blimit);
171}
172
173
174/* Vertical B Filtering */
175void vp8_loop_filter_bv_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
176                             int y_stride, int uv_stride, loop_filter_info *lfi)
177{
178#if ARCH_X86_64
179    vp8_loop_filter_bv_y_sse2(y_ptr, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
180#else
181    vp8_loop_filter_vertical_edge_sse2(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
182    vp8_loop_filter_vertical_edge_sse2(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
183    vp8_loop_filter_vertical_edge_sse2(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr);
184#endif
185
186    if (u_ptr)
187        vp8_loop_filter_vertical_edge_uv_sse2(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, v_ptr + 4);
188}
189
190
191void vp8_loop_filter_bvs_sse2(unsigned char *y_ptr, int y_stride, const unsigned char *blimit)
192{
193    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 4, y_stride, blimit);
194    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 8, y_stride, blimit);
195    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 12, y_stride, blimit);
196}
197
198#endif
199