]> git.sesse.net Git - ffmpeg/blob - libswscale/x86/output.asm
Merge commit '58d154922707bfeb873cb3a7476e0f94b17463dd'
[ffmpeg] / libswscale / x86 / output.asm
1 ;******************************************************************************
2 ;* x86-optimized vertical line scaling functions
3 ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com>
4 ;*                    Kieran Kunhya <kieran@kunhya.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 minshort:      times 8 dw 0x8000
28 yuv2yuvX_16_start:  times 4 dd 0x4000 - 0x40000000
29 yuv2yuvX_10_start:  times 4 dd 0x10000
30 yuv2yuvX_9_start:   times 4 dd 0x20000
31 yuv2yuvX_10_upper:  times 8 dw 0x3ff
32 yuv2yuvX_9_upper:   times 8 dw 0x1ff
33 pd_4:          times 4 dd 4
34 pd_4min0x40000:times 4 dd 4 - (0x40000)
35 pw_16:         times 8 dw 16
36 pw_32:         times 8 dw 32
37 pw_512:        times 8 dw 512
38 pw_1024:       times 8 dw 1024
39
40 SECTION .text
41
42 ;-----------------------------------------------------------------------------
43 ; vertical line scaling
44 ;
45 ; void yuv2plane1_<output_size>_<opt>(const int16_t *src, uint8_t *dst, int dstW,
46 ;                                     const uint8_t *dither, int offset)
47 ; and
48 ; void yuv2planeX_<output_size>_<opt>(const int16_t *filter, int filterSize,
49 ;                                     const int16_t **src, uint8_t *dst, int dstW,
50 ;                                     const uint8_t *dither, int offset)
51 ;
52 ; Scale one or $filterSize lines of source data to generate one line of output
53 ; data. The input is 15 bits in int16_t if $output_size is [8,10] and 19 bits in
54 ; int32_t if $output_size is 16. $filter is 12 bits. $filterSize is a multiple
55 ; of 2. $offset is either 0 or 3. $dither holds 8 values.
56 ;-----------------------------------------------------------------------------
57 %macro yuv2planeX_mainloop 2
58 .pixelloop_%2:
59 %assign %%i 0
60     ; the rep here is for the 8-bit output MMX case, where dither covers
61     ; 8 pixels but we can only handle 2 pixels per register, and thus 4
62     ; pixels per iteration. In order to not have to keep track of where
63     ; we are w.r.t. dithering, we unroll the MMX/8-bit loop x2.
64 %if %1 == 8
65 %assign %%repcnt 16/mmsize
66 %else
67 %assign %%repcnt 1
68 %endif
69
70 %rep %%repcnt
71
72 %if %1 == 8
73 %if ARCH_X86_32
74     mova            m2, [rsp+mmsize*(0+%%i)]
75     mova            m1, [rsp+mmsize*(1+%%i)]
76 %else ; x86-64
77     mova            m2,  m8
78     mova            m1,  m_dith
79 %endif ; x86-32/64
80 %else ; %1 == 9/10/16
81     mova            m1, [yuv2yuvX_%1_start]
82     mova            m2,  m1
83 %endif ; %1 == 8/9/10/16
84     movsx     cntr_reg,  fltsizem
85 .filterloop_%2_ %+ %%i:
86     ; input pixels
87     mov             r6, [srcq+gprsize*cntr_reg-2*gprsize]
88 %if %1 == 16
89     mova            m3, [r6+r5*4]
90     mova            m5, [r6+r5*4+mmsize]
91 %else ; %1 == 8/9/10
92     mova            m3, [r6+r5*2]
93 %endif ; %1 == 8/9/10/16
94     mov             r6, [srcq+gprsize*cntr_reg-gprsize]
95 %if %1 == 16
96     mova            m4, [r6+r5*4]
97     mova            m6, [r6+r5*4+mmsize]
98 %else ; %1 == 8/9/10
99     mova            m4, [r6+r5*2]
100 %endif ; %1 == 8/9/10/16
101
102     ; coefficients
103     movd            m0, [filterq+2*cntr_reg-4] ; coeff[0], coeff[1]
104 %if %1 == 16
105     pshuflw         m7,  m0,  0          ; coeff[0]
106     pshuflw         m0,  m0,  0x55       ; coeff[1]
107     pmovsxwd        m7,  m7              ; word -> dword
108     pmovsxwd        m0,  m0              ; word -> dword
109
110     pmulld          m3,  m7
111     pmulld          m5,  m7
112     pmulld          m4,  m0
113     pmulld          m6,  m0
114
115     paddd           m2,  m3
116     paddd           m1,  m5
117     paddd           m2,  m4
118     paddd           m1,  m6
119 %else ; %1 == 10/9/8
120     punpcklwd       m5,  m3,  m4
121     punpckhwd       m3,  m4
122     SPLATD          m0
123
124     pmaddwd         m5,  m0
125     pmaddwd         m3,  m0
126
127     paddd           m2,  m5
128     paddd           m1,  m3
129 %endif ; %1 == 8/9/10/16
130
131     sub       cntr_reg,  2
132     jg .filterloop_%2_ %+ %%i
133
134 %if %1 == 16
135     psrad           m2,  31 - %1
136     psrad           m1,  31 - %1
137 %else ; %1 == 10/9/8
138     psrad           m2,  27 - %1
139     psrad           m1,  27 - %1
140 %endif ; %1 == 8/9/10/16
141
142 %if %1 == 8
143     packssdw        m2,  m1
144     packuswb        m2,  m2
145     movh   [dstq+r5*1],  m2
146 %else ; %1 == 9/10/16
147 %if %1 == 16
148     packssdw        m2,  m1
149     paddw           m2, [minshort]
150 %else ; %1 == 9/10
151 %if cpuflag(sse4)
152     packusdw        m2,  m1
153 %else ; mmxext/sse2
154     packssdw        m2,  m1
155     pmaxsw          m2,  m6
156 %endif ; mmxext/sse2/sse4/avx
157     pminsw          m2, [yuv2yuvX_%1_upper]
158 %endif ; %1 == 9/10/16
159     mov%2   [dstq+r5*2],  m2
160 %endif ; %1 == 8/9/10/16
161
162     add             r5,  mmsize/2
163     sub             wd,  mmsize/2
164
165 %assign %%i %%i+2
166 %endrep
167     jg .pixelloop_%2
168 %endmacro
169
170 %macro yuv2planeX_fn 3
171
172 %if ARCH_X86_32
173 %define cntr_reg fltsizeq
174 %define movsx mov
175 %else
176 %define cntr_reg r7
177 %define movsx movsxd
178 %endif
179
180 cglobal yuv2planeX_%1, %3, 8, %2, filter, fltsize, src, dst, w, dither, offset
181 %if %1 == 8 || %1 == 9 || %1 == 10
182     pxor            m6,  m6
183 %endif ; %1 == 8/9/10
184
185 %if %1 == 8
186 %if ARCH_X86_32
187 %assign pad 0x2c - (stack_offset & 15)
188     SUB             rsp, pad
189 %define m_dith m7
190 %else ; x86-64
191 %define m_dith m9
192 %endif ; x86-32
193
194     ; create registers holding dither
195     movq        m_dith, [ditherq]        ; dither
196     test        offsetd, offsetd
197     jz              .no_rot
198 %if mmsize == 16
199     punpcklqdq  m_dith,  m_dith
200 %endif ; mmsize == 16
201     PALIGNR     m_dith,  m_dith,  3,  m0
202 .no_rot:
203 %if mmsize == 16
204     punpcklbw   m_dith,  m6
205 %if ARCH_X86_64
206     punpcklwd       m8,  m_dith,  m6
207     pslld           m8,  12
208 %else ; x86-32
209     punpcklwd       m5,  m_dith,  m6
210     pslld           m5,  12
211 %endif ; x86-32/64
212     punpckhwd   m_dith,  m6
213     pslld       m_dith,  12
214 %if ARCH_X86_32
215     mova      [rsp+ 0],  m5
216     mova      [rsp+16],  m_dith
217 %endif
218 %else ; mmsize == 8
219     punpcklbw       m5,  m_dith,  m6
220     punpckhbw   m_dith,  m6
221     punpcklwd       m4,  m5,  m6
222     punpckhwd       m5,  m6
223     punpcklwd       m3,  m_dith,  m6
224     punpckhwd   m_dith,  m6
225     pslld           m4,  12
226     pslld           m5,  12
227     pslld           m3,  12
228     pslld       m_dith,  12
229     mova      [rsp+ 0],  m4
230     mova      [rsp+ 8],  m5
231     mova      [rsp+16],  m3
232     mova      [rsp+24],  m_dith
233 %endif ; mmsize == 8/16
234 %endif ; %1 == 8
235
236     xor             r5,  r5
237
238 %if mmsize == 8 || %1 == 8
239     yuv2planeX_mainloop %1, a
240 %else ; mmsize == 16
241     test          dstq, 15
242     jnz .unaligned
243     yuv2planeX_mainloop %1, a
244     REP_RET
245 .unaligned:
246     yuv2planeX_mainloop %1, u
247 %endif ; mmsize == 8/16
248
249 %if %1 == 8
250 %if ARCH_X86_32
251     ADD             rsp, pad
252     RET
253 %else ; x86-64
254     REP_RET
255 %endif ; x86-32/64
256 %else ; %1 == 9/10/16
257     REP_RET
258 %endif ; %1 == 8/9/10/16
259 %endmacro
260
261 %if ARCH_X86_32
262 INIT_MMX mmxext
263 yuv2planeX_fn  8,  0, 7
264 yuv2planeX_fn  9,  0, 5
265 yuv2planeX_fn 10,  0, 5
266 %endif
267
268 INIT_XMM sse2
269 yuv2planeX_fn  8, 10, 7
270 yuv2planeX_fn  9,  7, 5
271 yuv2planeX_fn 10,  7, 5
272
273 INIT_XMM sse4
274 yuv2planeX_fn  8, 10, 7
275 yuv2planeX_fn  9,  7, 5
276 yuv2planeX_fn 10,  7, 5
277 yuv2planeX_fn 16,  8, 5
278
279 %if HAVE_AVX_EXTERNAL
280 INIT_XMM avx
281 yuv2planeX_fn  8, 10, 7
282 yuv2planeX_fn  9,  7, 5
283 yuv2planeX_fn 10,  7, 5
284 %endif
285
286 ; %1=outout-bpc, %2=alignment (u/a)
287 %macro yuv2plane1_mainloop 2
288 .loop_%2:
289 %if %1 == 8
290     paddsw          m0, m2, [srcq+wq*2+mmsize*0]
291     paddsw          m1, m3, [srcq+wq*2+mmsize*1]
292     psraw           m0, 7
293     psraw           m1, 7
294     packuswb        m0, m1
295     mov%2    [dstq+wq], m0
296 %elif %1 == 16
297     paddd           m0, m4, [srcq+wq*4+mmsize*0]
298     paddd           m1, m4, [srcq+wq*4+mmsize*1]
299     paddd           m2, m4, [srcq+wq*4+mmsize*2]
300     paddd           m3, m4, [srcq+wq*4+mmsize*3]
301     psrad           m0, 3
302     psrad           m1, 3
303     psrad           m2, 3
304     psrad           m3, 3
305 %if cpuflag(sse4) ; avx/sse4
306     packusdw        m0, m1
307     packusdw        m2, m3
308 %else ; mmx/sse2
309     packssdw        m0, m1
310     packssdw        m2, m3
311     paddw           m0, m5
312     paddw           m2, m5
313 %endif ; mmx/sse2/sse4/avx
314     mov%2    [dstq+wq*2+mmsize*0], m0
315     mov%2    [dstq+wq*2+mmsize*1], m2
316 %else ; %1 == 9/10
317     paddsw          m0, m2, [srcq+wq*2+mmsize*0]
318     paddsw          m1, m2, [srcq+wq*2+mmsize*1]
319     psraw           m0, 15 - %1
320     psraw           m1, 15 - %1
321     pmaxsw          m0, m4
322     pmaxsw          m1, m4
323     pminsw          m0, m3
324     pminsw          m1, m3
325     mov%2    [dstq+wq*2+mmsize*0], m0
326     mov%2    [dstq+wq*2+mmsize*1], m1
327 %endif
328     add             wq, mmsize
329     jl .loop_%2
330 %endmacro
331
332 %macro yuv2plane1_fn 3
333 cglobal yuv2plane1_%1, %3, %3, %2, src, dst, w, dither, offset
334     movsxdifnidn    wq, wd
335     add             wq, mmsize - 1
336     and             wq, ~(mmsize - 1)
337 %if %1 == 8
338     add           dstq, wq
339 %else ; %1 != 8
340     lea           dstq, [dstq+wq*2]
341 %endif ; %1 == 8
342 %if %1 == 16
343     lea           srcq, [srcq+wq*4]
344 %else ; %1 != 16
345     lea           srcq, [srcq+wq*2]
346 %endif ; %1 == 16
347     neg             wq
348
349 %if %1 == 8
350     pxor            m4, m4               ; zero
351
352     ; create registers holding dither
353     movq            m3, [ditherq]        ; dither
354     test       offsetd, offsetd
355     jz              .no_rot
356 %if mmsize == 16
357     punpcklqdq      m3, m3
358 %endif ; mmsize == 16
359     PALIGNR         m3, m3, 3, m2
360 .no_rot:
361 %if mmsize == 8
362     mova            m2, m3
363     punpckhbw       m3, m4               ; byte->word
364     punpcklbw       m2, m4               ; byte->word
365 %else
366     punpcklbw       m3, m4
367     mova            m2, m3
368 %endif
369 %elif %1 == 9
370     pxor            m4, m4
371     mova            m3, [pw_512]
372     mova            m2, [pw_32]
373 %elif %1 == 10
374     pxor            m4, m4
375     mova            m3, [pw_1024]
376     mova            m2, [pw_16]
377 %else ; %1 == 16
378 %if cpuflag(sse4) ; sse4/avx
379     mova            m4, [pd_4]
380 %else ; mmx/sse2
381     mova            m4, [pd_4min0x40000]
382     mova            m5, [minshort]
383 %endif ; mmx/sse2/sse4/avx
384 %endif ; %1 == ..
385
386     ; actual pixel scaling
387 %if mmsize == 8
388     yuv2plane1_mainloop %1, a
389 %else ; mmsize == 16
390     test          dstq, 15
391     jnz .unaligned
392     yuv2plane1_mainloop %1, a
393     REP_RET
394 .unaligned:
395     yuv2plane1_mainloop %1, u
396 %endif ; mmsize == 8/16
397     REP_RET
398 %endmacro
399
400 %if ARCH_X86_32
401 INIT_MMX mmx
402 yuv2plane1_fn  8, 0, 5
403 yuv2plane1_fn 16, 0, 3
404
405 INIT_MMX mmxext
406 yuv2plane1_fn  9, 0, 3
407 yuv2plane1_fn 10, 0, 3
408 %endif
409
410 INIT_XMM sse2
411 yuv2plane1_fn  8, 5, 5
412 yuv2plane1_fn  9, 5, 3
413 yuv2plane1_fn 10, 5, 3
414 yuv2plane1_fn 16, 6, 3
415
416 INIT_XMM sse4
417 yuv2plane1_fn 16, 5, 3
418
419 %if HAVE_AVX_EXTERNAL
420 INIT_XMM avx
421 yuv2plane1_fn  8, 5, 5
422 yuv2plane1_fn  9, 5, 3
423 yuv2plane1_fn 10, 5, 3
424 yuv2plane1_fn 16, 5, 3
425 %endif