hevc: SSE2 and SSSE3 loop filters
[ffmpeg.git] / libavcodec / x86 / blockdsp.c
1 /*
2  * This file is part of Libav.
3  *
4  * Libav is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * Libav is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with Libav; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <stdint.h>
20
21 #include "config.h"
22 #include "libavutil/attributes.h"
23 #include "libavutil/internal.h"
24 #include "libavutil/cpu.h"
25 #include "libavutil/x86/asm.h"
26 #include "libavutil/x86/cpu.h"
27 #include "libavcodec/blockdsp.h"
28 #include "libavcodec/version.h"
29
30 #if HAVE_INLINE_ASM
31
32 #define CLEAR_BLOCKS(name, n)                           \
33 static void name(int16_t *blocks)                       \
34 {                                                       \
35     __asm__ volatile (                                  \
36         "pxor %%mm7, %%mm7              \n\t"           \
37         "mov     %1,        %%"REG_a"   \n\t"           \
38         "1:                             \n\t"           \
39         "movq %%mm7,   (%0, %%"REG_a")  \n\t"           \
40         "movq %%mm7,  8(%0, %%"REG_a")  \n\t"           \
41         "movq %%mm7, 16(%0, %%"REG_a")  \n\t"           \
42         "movq %%mm7, 24(%0, %%"REG_a")  \n\t"           \
43         "add    $32, %%"REG_a"          \n\t"           \
44         "js      1b                     \n\t"           \
45         :: "r"(((uint8_t *) blocks) + 128 * n),         \
46            "i"(-128 * n)                                \
47         : "%"REG_a);                                    \
48 }
49 CLEAR_BLOCKS(clear_blocks_mmx, 6)
50 CLEAR_BLOCKS(clear_block_mmx, 1)
51
52 static void clear_block_sse(int16_t *block)
53 {
54     __asm__ volatile (
55         "xorps  %%xmm0, %%xmm0          \n"
56         "movaps %%xmm0,    (%0)         \n"
57         "movaps %%xmm0,  16(%0)         \n"
58         "movaps %%xmm0,  32(%0)         \n"
59         "movaps %%xmm0,  48(%0)         \n"
60         "movaps %%xmm0,  64(%0)         \n"
61         "movaps %%xmm0,  80(%0)         \n"
62         "movaps %%xmm0,  96(%0)         \n"
63         "movaps %%xmm0, 112(%0)         \n"
64         :: "r" (block)
65         : "memory");
66 }
67
68 static void clear_blocks_sse(int16_t *blocks)
69 {
70     __asm__ volatile (
71         "xorps  %%xmm0, %%xmm0              \n"
72         "mov        %1,         %%"REG_a"   \n"
73         "1:                                 \n"
74         "movaps %%xmm0,    (%0, %%"REG_a")  \n"
75         "movaps %%xmm0,  16(%0, %%"REG_a")  \n"
76         "movaps %%xmm0,  32(%0, %%"REG_a")  \n"
77         "movaps %%xmm0,  48(%0, %%"REG_a")  \n"
78         "movaps %%xmm0,  64(%0, %%"REG_a")  \n"
79         "movaps %%xmm0,  80(%0, %%"REG_a")  \n"
80         "movaps %%xmm0,  96(%0, %%"REG_a")  \n"
81         "movaps %%xmm0, 112(%0, %%"REG_a")  \n"
82         "add      $128,         %%"REG_a"   \n"
83         "js         1b                      \n"
84         :: "r"(((uint8_t *) blocks) + 128 * 6), "i"(-128 * 6)
85         : "%"REG_a);
86 }
87
88 #endif /* HAVE_INLINE_ASM */
89
90 #if FF_API_XVMC
91 av_cold void ff_blockdsp_init_x86(BlockDSPContext *c, unsigned high_bit_depth,
92                                   AVCodecContext *avctx)
93 #else
94 av_cold void ff_blockdsp_init_x86(BlockDSPContext *c, unsigned high_bit_depth)
95 #endif /* FF_API_XVMC */
96 {
97 #if HAVE_INLINE_ASM
98     int cpu_flags = av_get_cpu_flags();
99
100     if (!high_bit_depth) {
101         if (INLINE_MMX(cpu_flags)) {
102             c->clear_block  = clear_block_mmx;
103             c->clear_blocks = clear_blocks_mmx;
104         }
105
106 #if FF_API_XVMC
107 FF_DISABLE_DEPRECATION_WARNINGS
108     /* XvMCCreateBlocks() may not allocate 16-byte aligned blocks */
109     if (CONFIG_MPEG_XVMC_DECODER && avctx->xvmc_acceleration > 1)
110         return;
111 FF_ENABLE_DEPRECATION_WARNINGS
112 #endif /* FF_API_XVMC */
113
114         if (INLINE_SSE(cpu_flags)) {
115             c->clear_block  = clear_block_sse;
116             c->clear_blocks = clear_blocks_sse;
117         }
118     }
119 #endif /* HAVE_INLINE_ASM */
120 }