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