78809305dec86f2e8750d7c7e29cb6b36250d167
[platform/upstream/ffmpeg.git] / libavfilter / x86 / vf_ssim.asm
1 ;*****************************************************************************
2 ;* x86-optimized functions for ssim filter
3 ;*
4 ;* Copyright (C) 2015 Ronald S. Bultje <rsbultje@gmail.com>
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg 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 GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "libavutil/x86/x86util.asm"
24
25 SECTION_RODATA
26
27 pw_1: times 8 dw 1
28 ssim_c1: times 4 dd 416 ;(.01*.01*255*255*64 + .5)
29 ssim_c2: times 4 dd 235963 ;(.03*.03*255*255*64*63 + .5)
30
31 SECTION .text
32
33 %macro SSIM_4X4_LINE 1
34 %if ARCH_X86_64
35 cglobal ssim_4x4_line, 6, 8, %1, buf, buf_stride, ref, ref_stride, sums, w, buf_stride3, ref_stride3
36 %else
37 cglobal ssim_4x4_line, 5, 7, %1, buf, buf_stride, ref, ref_stride, sums, buf_stride3, ref_stride3
38 %define wd r5mp
39 %endif
40     lea     ref_stride3q, [ref_strideq*3]
41     lea     buf_stride3q, [buf_strideq*3]
42 %if notcpuflag(xop)
43     pxor              m7, m7
44     mova             m15, [pw_1]
45 %endif
46
47 .loop:
48 %if cpuflag(xop)
49     pmovzxbw          m0, [bufq+buf_strideq*0]
50     pmovzxbw          m1, [refq+ref_strideq*0]
51     pmaddwd           m4, m0, m0
52     pmaddwd           m6, m0, m1
53     pmovzxbw          m2, [bufq+buf_strideq*1]
54     vpmadcswd         m4, m1, m1, m4
55     pmovzxbw          m3, [refq+ref_strideq*1]
56     paddw             m0, m2
57     vpmadcswd         m4, m2, m2, m4
58     vpmadcswd         m6, m2, m3, m6
59     paddw             m1, m3
60     vpmadcswd         m4, m3, m3, m4
61
62     pmovzxbw          m2, [bufq+buf_strideq*2]
63     pmovzxbw          m3, [refq+ref_strideq*2]
64     vpmadcswd         m4, m2, m2, m4
65     vpmadcswd         m6, m2, m3, m6
66     pmovzxbw          m5, [bufq+buf_stride3q]
67     pmovzxbw          m7, [refq+ref_stride3q]
68     vpmadcswd         m4, m3, m3, m4
69     vpmadcswd         m6, m5, m7, m6
70     paddw             m0, m2
71     paddw             m1, m3
72     vpmadcswd         m4, m5, m5, m4
73     paddw             m0, m5
74     paddw             m1, m7
75     vpmadcswd         m4, m7, m7, m4
76 %else
77     movh              m0, [bufq+buf_strideq*0]  ; a1
78     movh              m1, [refq+ref_strideq*0]  ; b1
79     movh              m2, [bufq+buf_strideq*1]  ; a2
80     movh              m3, [refq+ref_strideq*1]  ; b2
81     punpcklbw         m0, m7                    ; s1 [word]
82     punpcklbw         m1, m7                    ; s2 [word]
83     punpcklbw         m2, m7                    ; s1 [word]
84     punpcklbw         m3, m7                    ; s2 [word]
85     pmaddwd           m4, m0, m0                ; a1 * a1
86     pmaddwd           m5, m1, m1                ; b1 * b1
87     pmaddwd           m8, m2, m2                ; a2 * a2
88     pmaddwd           m9, m3, m3                ; b2 * b2
89     paddd             m4, m5                    ; ss
90     paddd             m8, m9                    ; ss
91     pmaddwd           m6, m0, m1                ; a1 * b1 = ss12
92     pmaddwd           m5, m2, m3                ; a2 * b2 = ss12
93     paddw             m0, m2
94     paddw             m1, m3
95     paddd             m6, m5                    ; s12
96     paddd             m4, m8                    ; ss
97
98     movh              m2, [bufq+buf_strideq*2]  ; a3
99     movh              m3, [refq+ref_strideq*2]  ; b3
100     movh              m5, [bufq+buf_stride3q]   ; a4
101     movh              m8, [refq+ref_stride3q]   ; b4
102     punpcklbw         m2, m7                    ; s1 [word]
103     punpcklbw         m3, m7                    ; s2 [word]
104     punpcklbw         m5, m7                    ; s1 [word]
105     punpcklbw         m8, m7                    ; s2 [word]
106     pmaddwd           m9, m2, m2                ; a3 * a3
107     pmaddwd          m10, m3, m3                ; b3 * b3
108     pmaddwd          m12, m5, m5                ; a4 * a4
109     pmaddwd          m13, m8, m8                ; b4 * b4
110     pmaddwd          m11, m2, m3                ; a3 * b3 = ss12
111     pmaddwd          m14, m5, m8                ; a4 * b4 = ss12
112     paddd             m9, m10
113     paddd            m12, m13
114     paddw             m0, m2
115     paddw             m1, m3
116     paddw             m0, m5
117     paddw             m1, m8
118     paddd             m6, m11
119     paddd             m4, m9
120     paddd             m6, m14
121     paddd             m4, m12
122 %endif
123
124     ; m0 = [word] s1 a,a,a,a,b,b,b,b
125     ; m1 = [word] s2 a,a,a,a,b,b,b,b
126     ; m4 = [dword] ss a,a,b,b
127     ; m6 = [dword] s12 a,a,b,b
128
129 %if cpuflag(xop)
130     vphaddwq          m0, m0                    ; [dword] s1  a, 0, b, 0
131     vphaddwq          m1, m1                    ; [dword] s2  a, 0, b, 0
132     vphadddq          m4, m4                    ; [dword] ss  a, 0, b, 0
133     vphadddq          m6, m6                    ; [dword] s12 a, 0, b, 0
134     punpckhdq     m2, m0, m1                    ; [dword] s1  b, s2 b, 0, 0
135     punpckldq         m0, m1                    ; [dword] s1  a, s2 a, 0, 0
136     punpckhdq     m3, m4, m6                    ; [dword] ss  b, s12 b, 0, 0
137     punpckldq         m4, m6                    ; [dword] ss  a, s12 a, 0, 0
138     punpcklqdq    m1, m2, m3                    ; [dword] b s1, s2, ss, s12
139     punpcklqdq        m0, m4                    ; [dword] a s1, s2, ss, s12
140 %else
141     pmaddwd           m0, m15                   ; [dword] s1 a,a,b,b
142     pmaddwd           m1, m15                   ; [dword] s2 a,a,b,b
143     phaddd            m0, m4                    ; [dword] s1 a, b, ss a, b
144     phaddd            m1, m6                    ; [dword] s2 a, b, s12 a, b
145     punpckhdq     m2, m0, m1                    ; [dword] ss a, s12 a, ss b, s12 b
146     punpckldq         m0, m1                    ; [dword] s1 a, s2 a, s1 b, s2 b
147     punpckhqdq    m1, m0, m2                    ; [dword] b s1, s2, ss, s12
148     punpcklqdq        m0, m2                    ; [dword] a s1, s2, ss, s12
149 %endif
150
151     mova  [sumsq+     0], m0
152     mova  [sumsq+mmsize], m1
153
154     add             bufq, mmsize/2
155     add             refq, mmsize/2
156     add            sumsq, mmsize*2
157     sub               wd, mmsize/8
158     jg .loop
159     RET
160 %endmacro
161
162 %if ARCH_X86_64
163 INIT_XMM ssse3
164 SSIM_4X4_LINE 16
165 %endif
166 %if HAVE_XOP_EXTERNAL
167 INIT_XMM xop
168 SSIM_4X4_LINE 8
169 %endif
170
171 INIT_XMM sse4
172 cglobal ssim_end_line, 3, 3, 7, sum0, sum1, w
173     pxor              m0, m0
174     pxor              m6, m6
175 .loop:
176     mova              m1, [sum0q+mmsize*0]
177     mova              m2, [sum0q+mmsize*1]
178     mova              m3, [sum0q+mmsize*2]
179     mova              m4, [sum0q+mmsize*3]
180     paddd             m1, [sum1q+mmsize*0]
181     paddd             m2, [sum1q+mmsize*1]
182     paddd             m3, [sum1q+mmsize*2]
183     paddd             m4, [sum1q+mmsize*3]
184     paddd             m1, m2
185     paddd             m2, m3
186     paddd             m3, m4
187     paddd             m4, [sum0q+mmsize*4]
188     paddd             m4, [sum1q+mmsize*4]
189     TRANSPOSE4x4D      1, 2, 3, 4, 5
190
191     ; m1 = fs1, m2 = fs2, m3 = fss, m4 = fs12
192     pslld             m3, 6
193     pslld             m4, 6
194     pmulld            m5, m1, m2                ; fs1 * fs2
195     pmulld            m1, m1                    ; fs1 * fs1
196     pmulld            m2, m2                    ; fs2 * fs2
197     psubd             m3, m1
198     psubd             m4, m5                    ; covariance
199     psubd             m3, m2                    ; variance
200
201     ; m1 = fs1 * fs1, m2 = fs2 * fs2, m3 = variance, m4 = covariance, m5 = fs1 * fs2
202     paddd             m4, m4                    ; 2 * covariance
203     paddd             m5, m5                    ; 2 * fs1 * fs2
204     paddd             m1, m2                    ; fs1 * fs1 + fs2 * fs2
205     paddd             m3, [ssim_c2]             ; variance + ssim_c2
206     paddd             m4, [ssim_c2]             ; 2 * covariance + ssim_c2
207     paddd             m5, [ssim_c1]             ; 2 * fs1 * fs2 + ssim_c1
208     paddd             m1, [ssim_c1]             ; fs1 * fs1 + fs2 * fs2 + ssim_c1
209
210     ; convert to float
211     cvtdq2ps          m3, m3
212     cvtdq2ps          m4, m4
213     cvtdq2ps          m5, m5
214     cvtdq2ps          m1, m1
215     mulps             m4, m5
216     mulps             m3, m1
217     divps             m4, m3                    ; ssim_endl
218     mova              m5, m4
219     cvtps2pd          m3, m5
220     movhlps           m5, m5
221     cvtps2pd          m5, m5
222     addpd             m0, m3                    ; ssim
223     addpd             m6, m5                    ; ssim
224     add            sum0q, mmsize*4
225     add            sum1q, mmsize*4
226     sub               wd, 4
227     jg .loop
228
229     ; subpd the ones we added too much
230     test              wd, wd
231     jz .end
232     add               wd, 4
233     test              wd, 3
234     jz .skip3
235     test              wd, 2
236     jz .skip2
237     test              wd, 1
238     jz .skip1
239 .skip3:
240     psrldq            m5, 8
241     subpd             m6, m5
242     jmp .end
243 .skip2:
244     psrldq            m5, 8
245     subpd             m6, m5
246     subpd             m0, m3
247     jmp .end
248 .skip1:
249     psrldq            m3, 16
250     subpd             m6, m5
251
252 .end:
253     addpd             m0, m6
254     movhlps           m4, m0
255     addpd             m0, m4
256 %if ARCH_X86_32
257     movsd            r0m, m0
258     fld        qword r0m
259 %endif
260     RET