]> git.sesse.net Git - x264/blob - common/rectangle.h
Slightly faster mbtree asm
[x264] / common / rectangle.h
1 /*****************************************************************************
2  * rectangle.h: h264 encoder library
3  *****************************************************************************
4  * Copyright (C) 2010 Fiona Glaser <fiona@x264.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
19  *****************************************************************************/
20
21 /* This function should only be called with constant w / h / s arguments! */
22 static ALWAYS_INLINE void x264_macroblock_cache_rect( void *dst, int w, int h, int s, uint32_t v )
23 {
24     uint8_t *d = dst;
25     uint16_t v2 = s == 2 ? v : v * 0x101;
26     uint32_t v4 = s == 4 ? v : s == 2 ? v * 0x10001 : v * 0x1010101;
27     uint64_t v8 = v4 + ((uint64_t)v4 << 32);
28     s *= 8;
29
30     if( w == 2 )
31     {
32         M16( d+s*0 ) = v2;
33         if( h == 1 ) return;
34         M16( d+s*1 ) = v2;
35         if( h == 2 ) return;
36         M16( d+s*2 ) = v2;
37         M16( d+s*3 ) = v2;
38     }
39     else if( w == 4 )
40     {
41         M32( d+s*0 ) = v4;
42         if( h == 1 ) return;
43         M32( d+s*1 ) = v4;
44         if( h == 2 ) return;
45         M32( d+s*2 ) = v4;
46         M32( d+s*3 ) = v4;
47     }
48     else if( w == 8 )
49     {
50         if( WORD_SIZE == 8 )
51         {
52             M64( d+s*0 ) = v8;
53             if( h == 1 ) return;
54             M64( d+s*1 ) = v8;
55             if( h == 2 ) return;
56             M64( d+s*2 ) = v8;
57             M64( d+s*3 ) = v8;
58         }
59         else
60         {
61             M32( d+s*0+0 ) = v4;
62             M32( d+s*0+4 ) = v4;
63             if( h == 1 ) return;
64             M32( d+s*1+0 ) = v4;
65             M32( d+s*1+4 ) = v4;
66             if( h == 2 ) return;
67             M32( d+s*2+0 ) = v4;
68             M32( d+s*2+4 ) = v4;
69             M32( d+s*3+0 ) = v4;
70             M32( d+s*3+4 ) = v4;
71         }
72     }
73     else if( w == 16 )
74     {
75         /* height 1, width 16 doesn't occur */
76         assert( h != 1 );
77         if( WORD_SIZE == 8 )
78         {
79             do
80             {
81                 M64( d+s*0+0 ) = v8;
82                 M64( d+s*0+8 ) = v8;
83                 M64( d+s*1+0 ) = v8;
84                 M64( d+s*1+8 ) = v8;
85                 h -= 2;
86                 d += s*2;
87             } while( h );
88         }
89         else
90         {
91             do
92             {
93                 M32( d+ 0 ) = v4;
94                 M32( d+ 4 ) = v4;
95                 M32( d+ 8 ) = v4;
96                 M32( d+12 ) = v4;
97                 d += s;
98             } while( --h );
99         }
100     }
101     else
102         assert(0);
103 }
104
105 extern void (*x264_cache_mv_func_table[10])(void *, uint32_t);\
106 extern void (*x264_cache_mvd_func_table[10])(void *, uint32_t);\
107 extern void (*x264_cache_ref_func_table[10])(void *, uint32_t);\
108
109 #define x264_macroblock_cache_mv_ptr( a, x, y, w, h, l, mv ) x264_macroblock_cache_mv( a, x, y, w, h, l, M32( mv ) )
110 static ALWAYS_INLINE void x264_macroblock_cache_mv( x264_t *h, int x, int y, int width, int height, int i_list, uint32_t mv )
111 {
112     void *mv_cache = &h->mb.cache.mv[i_list][X264_SCAN8_0+x+8*y];
113     if( x264_nonconstant_p( width ) || x264_nonconstant_p( height ) )
114         x264_cache_mv_func_table[width + (height<<1)-3]( mv_cache, mv );
115     else
116         x264_macroblock_cache_rect( mv_cache, width*4, height, 4, mv );
117 }
118 static ALWAYS_INLINE void x264_macroblock_cache_mvd( x264_t *h, int x, int y, int width, int height, int i_list, uint16_t mvd )
119 {
120     void *mvd_cache = &h->mb.cache.mvd[i_list][X264_SCAN8_0+x+8*y];
121     if( x264_nonconstant_p( width ) || x264_nonconstant_p( height ) )
122         x264_cache_mvd_func_table[width + (height<<1)-3]( mvd_cache, mvd );
123     else
124         x264_macroblock_cache_rect( mvd_cache, width*2, height, 2, mvd );
125 }
126 static ALWAYS_INLINE void x264_macroblock_cache_ref( x264_t *h, int x, int y, int width, int height, int i_list, uint8_t ref )
127 {
128     void *ref_cache = &h->mb.cache.ref[i_list][X264_SCAN8_0+x+8*y];
129     if( x264_nonconstant_p( width ) || x264_nonconstant_p( height ) )
130         x264_cache_ref_func_table[width + (height<<1)-3]( ref_cache, ref );
131     else
132         x264_macroblock_cache_rect( ref_cache, width, height, 1, ref );
133 }
134 static ALWAYS_INLINE void x264_macroblock_cache_skip( x264_t *h, int x, int y, int width, int height, int b_skip )
135 {
136     x264_macroblock_cache_rect( &h->mb.cache.skip[X264_SCAN8_0+x+8*y], width, height, 1, b_skip );
137 }
138 static ALWAYS_INLINE void x264_macroblock_cache_intra8x8_pred( x264_t *h, int x, int y, int i_mode )
139 {
140     x264_macroblock_cache_rect( &h->mb.cache.intra4x4_pred_mode[X264_SCAN8_0+x+8*y], 2, 2, 1, i_mode );
141 }