1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libtheora/lib/x86_vc/mmxstate.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,176 @@ 1.4 +/******************************************************************** 1.5 + * * 1.6 + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * 1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 1.10 + * * 1.11 + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * 1.12 + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * 1.13 + * * 1.14 + ******************************************************************** 1.15 + 1.16 + function: 1.17 + last mod: $Id: mmxstate.c 17563 2010-10-25 17:40:54Z tterribe $ 1.18 + 1.19 + ********************************************************************/ 1.20 + 1.21 +/*MMX acceleration of complete fragment reconstruction algorithm. 1.22 + Originally written by Rudolf Marek.*/ 1.23 +#include <string.h> 1.24 +#include "x86int.h" 1.25 +#include "mmxloop.h" 1.26 + 1.27 +#if defined(OC_X86_ASM) 1.28 + 1.29 +void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi, 1.30 + int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){ 1.31 + unsigned char *dst; 1.32 + ptrdiff_t frag_buf_off; 1.33 + int ystride; 1.34 + int refi; 1.35 + /*Apply the inverse transform.*/ 1.36 + /*Special case only having a DC component.*/ 1.37 + if(_last_zzi<2){ 1.38 + /*Note that this value must be unsigned, to keep the __asm__ block from 1.39 + sign-extending it when it puts it in a register.*/ 1.40 + ogg_uint16_t p; 1.41 + /*We round this dequant product (and not any of the others) because there's 1.42 + no iDCT rounding.*/ 1.43 + p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5); 1.44 + /*Fill _dct_coeffs with p.*/ 1.45 + __asm{ 1.46 +#define Y eax 1.47 +#define P ecx 1.48 + mov Y,_dct_coeffs 1.49 + movzx P,p 1.50 + lea Y,[Y+128] 1.51 + /*mm0=0000 0000 0000 AAAA*/ 1.52 + movd mm0,P 1.53 + /*mm0=0000 0000 AAAA AAAA*/ 1.54 + punpcklwd mm0,mm0 1.55 + /*mm0=AAAA AAAA AAAA AAAA*/ 1.56 + punpckldq mm0,mm0 1.57 + movq [Y],mm0 1.58 + movq [8+Y],mm0 1.59 + movq [16+Y],mm0 1.60 + movq [24+Y],mm0 1.61 + movq [32+Y],mm0 1.62 + movq [40+Y],mm0 1.63 + movq [48+Y],mm0 1.64 + movq [56+Y],mm0 1.65 + movq [64+Y],mm0 1.66 + movq [72+Y],mm0 1.67 + movq [80+Y],mm0 1.68 + movq [88+Y],mm0 1.69 + movq [96+Y],mm0 1.70 + movq [104+Y],mm0 1.71 + movq [112+Y],mm0 1.72 + movq [120+Y],mm0 1.73 +#undef Y 1.74 +#undef P 1.75 + } 1.76 + } 1.77 + else{ 1.78 + /*Dequantize the DC coefficient.*/ 1.79 + _dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant); 1.80 + oc_idct8x8_mmx(_dct_coeffs+64,_dct_coeffs,_last_zzi); 1.81 + } 1.82 + /*Fill in the target buffer.*/ 1.83 + frag_buf_off=_state->frag_buf_offs[_fragi]; 1.84 + refi=_state->frags[_fragi].refi; 1.85 + ystride=_state->ref_ystride[_pli]; 1.86 + dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off; 1.87 + if(refi==OC_FRAME_SELF)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs+64); 1.88 + else{ 1.89 + const unsigned char *ref; 1.90 + int mvoffsets[2]; 1.91 + ref=_state->ref_frame_data[refi]+frag_buf_off; 1.92 + if(oc_state_get_mv_offsets(_state,mvoffsets,_pli, 1.93 + _state->frag_mvs[_fragi])>1){ 1.94 + oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride, 1.95 + _dct_coeffs+64); 1.96 + } 1.97 + else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs+64); 1.98 + } 1.99 +} 1.100 + 1.101 +/*We copy these entire function to inline the actual MMX routines so that we 1.102 + use only a single indirect call.*/ 1.103 + 1.104 +void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit){ 1.105 + memset(_bv,~(_flimit<<1),8); 1.106 +} 1.107 + 1.108 +/*Apply the loop filter to a given set of fragment rows in the given plane. 1.109 + The filter may be run on the bottom edge, affecting pixels in the next row of 1.110 + fragments, so this row also needs to be available. 1.111 + _bv: The bounding values array. 1.112 + _refi: The index of the frame buffer to filter. 1.113 + _pli: The color plane to filter. 1.114 + _fragy0: The Y coordinate of the first fragment row to filter. 1.115 + _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/ 1.116 +void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state, 1.117 + signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){ 1.118 + const oc_fragment_plane *fplane; 1.119 + const oc_fragment *frags; 1.120 + const ptrdiff_t *frag_buf_offs; 1.121 + unsigned char *ref_frame_data; 1.122 + ptrdiff_t fragi_top; 1.123 + ptrdiff_t fragi_bot; 1.124 + ptrdiff_t fragi0; 1.125 + ptrdiff_t fragi0_end; 1.126 + int ystride; 1.127 + int nhfrags; 1.128 + fplane=_state->fplanes+_pli; 1.129 + nhfrags=fplane->nhfrags; 1.130 + fragi_top=fplane->froffset; 1.131 + fragi_bot=fragi_top+fplane->nfrags; 1.132 + fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags; 1.133 + fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags; 1.134 + ystride=_state->ref_ystride[_pli]; 1.135 + frags=_state->frags; 1.136 + frag_buf_offs=_state->frag_buf_offs; 1.137 + ref_frame_data=_state->ref_frame_data[_refi]; 1.138 + /*The following loops are constructed somewhat non-intuitively on purpose. 1.139 + The main idea is: if a block boundary has at least one coded fragment on 1.140 + it, the filter is applied to it. 1.141 + However, the order that the filters are applied in matters, and VP3 chose 1.142 + the somewhat strange ordering used below.*/ 1.143 + while(fragi0<fragi0_end){ 1.144 + ptrdiff_t fragi; 1.145 + ptrdiff_t fragi_end; 1.146 + fragi=fragi0; 1.147 + fragi_end=fragi+nhfrags; 1.148 + while(fragi<fragi_end){ 1.149 + if(frags[fragi].coded){ 1.150 + unsigned char *ref; 1.151 + ref=ref_frame_data+frag_buf_offs[fragi]; 1.152 +#define PIX eax 1.153 +#define YSTRIDE3 edi 1.154 +#define YSTRIDE ecx 1.155 +#define LL edx 1.156 +#define D esi 1.157 +#define D_WORD si 1.158 + if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,_bv); 1.159 + if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,_bv); 1.160 + if(fragi+1<fragi_end&&!frags[fragi+1].coded){ 1.161 + OC_LOOP_FILTER_H_MMX(ref+8,ystride,_bv); 1.162 + } 1.163 + if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){ 1.164 + OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,_bv); 1.165 + } 1.166 +#undef PIX 1.167 +#undef YSTRIDE3 1.168 +#undef YSTRIDE 1.169 +#undef LL 1.170 +#undef D 1.171 +#undef D_WORD 1.172 + } 1.173 + fragi++; 1.174 + } 1.175 + fragi0+=nhfrags; 1.176 + } 1.177 +} 1.178 + 1.179 +#endif