__asm __volatile(SFENCE:::"memory"); __asm __volatile(EMMS:::"memory");
void SwScale_YV12slice(unsigned char* srcptr[],int stride[], int y, int h,			     uint8_t* dstptr[], int dststride, int dstw, int dstbpp,			     unsigned int s_xinc,unsigned int s_yinc){// scaling factors://static int s_yinc=(vo_dga_src_height<<16)/vo_dga_vp_height;//static int s_xinc=(vo_dga_src_width<<8)/vo_dga_vp_width;unsigned int s_xinc2;static int s_srcypos; // points to the dst Pixels center in the source (0 is the center of pixel 0,0 in src)static int s_ypos;// last horzontally interpolated lines, used to avoid unnecessary calculationsstatic int s_last_ypos;static int s_last_y1pos;static int static_dstw;#ifdef HAVE_MMX2// used to detect a horizontal size changestatic int old_dstw= -1;static int old_s_xinc= -1;#endifint srcWidth= (dstw*s_xinc + 0x8000)>>16;int dstUVw= fullUVIpol ? dstw : dstw/2;#ifdef HAVE_MMX2canMMX2BeUsed= (s_xinc <= 0x10000 && (dstw&31)==0 && (srcWidth&15)==0) ? 1 : 0;#endif// match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst// n-2 is the last chrominance sample available// FIXME this is not perfect, but noone shuld notice the difference, the more correct variant// would be like the vertical one, but that would require some special code for the// first and last pixelif(canMMX2BeUsed) 	s_xinc+= 20;else			s_xinc = ((srcWidth-2)<<16)/(dstw-2) - 20;if(fullUVIpol && !dstbpp==12) 	s_xinc2= s_xinc>>1;else				s_xinc2= s_xinc;  // force calculation of the horizontal interpolation of the first line  if(y==0){	s_last_ypos=-99;	s_last_y1pos=-99;	s_srcypos= s_yinc/2 - 0x8000;	s_ypos=0;#ifdef HAVE_MMX2// cant downscale !!!	if((old_s_xinc != s_xinc || old_dstw!=dstw) && canMMX2BeUsed)	{		uint8_t *fragment;		int imm8OfPShufW1;		int imm8OfPShufW2;		int fragmentLength;		int xpos, xx, xalpha, i;		old_s_xinc= s_xinc;		old_dstw= dstw;		static_dstw= dstw;		// create an optimized horizontal scaling routine		//code fragment		asm volatile(			"jmp 9f				\n\t"		// Begin			"0:				\n\t"			"movq (%%esi), %%mm0		\n\t" //FIXME Alignment			"movq %%mm0, %%mm1		\n\t"			"psrlq $8, %%mm0		\n\t"			"punpcklbw %%mm7, %%mm1	\n\t"			"movq %%mm2, %%mm3		\n\t"			"punpcklbw %%mm7, %%mm0	\n\t"			"addw %%bx, %%cx		\n\t" //2*xalpha += (4*s_xinc)&0xFFFF			"pshufw $0xFF, %%mm1, %%mm1	\n\t"			"1:				\n\t"			"adcl %%edx, %%esi		\n\t" //xx+= (4*s_xinc)>>16 + carry			"pshufw $0xFF, %%mm0, %%mm0	\n\t"			"2:				\n\t"			"psrlw $9, %%mm3		\n\t"			"psubw %%mm1, %%mm0		\n\t"			"pmullw %%mm3, %%mm0		\n\t"			"paddw %%mm6, %%mm2		\n\t" // 2*alpha += xpos&0xFFFF			"psllw $7, %%mm1		\n\t"			"paddw %%mm1, %%mm0		\n\t"			"movq %%mm0, (%%edi, %%eax)	\n\t"			"addl $8, %%eax			\n\t"		// End			"9:				\n\t"//		"int $3\n\t"			"leal 0b, %0			\n\t"			"leal 1b, %1			\n\t"			"leal 2b, %2			\n\t"			"decl %1			\n\t"			"decl %2			\n\t"			"subl %0, %1			\n\t"			"subl %0, %2			\n\t"			"leal 9b, %3			\n\t"			"subl %0, %3			\n\t"			:"=r" (fragment), "=r" (imm8OfPShufW1), "=r" (imm8OfPShufW2),			 "=r" (fragmentLength)		);		xpos= 0; //s_xinc/2 - 0x8000; // difference between pixel centers		/* choose xinc so that all 8 parts fit exactly		   Note: we cannot use just 1 part because it would not fit in the code cache *///		s_xinc2_diff= -((((s_xinc2*(dstw/8))&0xFFFF))/(dstw/8))-10;//		s_xinc_diff= -((((s_xinc*(dstw/8))&0xFFFF))/(dstw/8));#ifdef ALT_ERROR//		s_xinc2_diff+= ((0x10000/(dstw/8)));#endif//		s_xinc_diff= s_xinc2_diff*2;//		s_xinc2+= s_xinc2_diff;//		s_xinc+= s_xinc_diff;//		old_s_xinc= s_xinc;		for(i=0; i<dstw/8; i++)		{			int xx=xpos>>16;			if((i&3) == 0)			{				int a=0;				int b=((xpos+s_xinc)>>16) - xx;				int c=((xpos+s_xinc*2)>>16) - xx;				int d=((xpos+s_xinc*3)>>16) - xx;				memcpy(funnyYCode + fragmentLength*i/4, fragment, fragmentLength);				funnyYCode[fragmentLength*i/4 + imm8OfPShufW1]=				funnyYCode[fragmentLength*i/4 + imm8OfPShufW2]=					a | (b<<2) | (c<<4) | (d<<6);				// if we dont need to read 8 bytes than dont :), reduces the chance of				// crossing a cache line				if(d<3) funnyYCode[fragmentLength*i/4 + 1]= 0x6E;				funnyYCode[fragmentLength*(i+4)/4]= RET;			}			xpos+=s_xinc;		}		xpos= 0; //s_xinc2/2 - 0x10000; // difference between centers of chrom samples		for(i=0; i<dstUVw/8; i++)		{			int xx=xpos>>16;			if((i&3) == 0)			{				int a=0;				int b=((xpos+s_xinc2)>>16) - xx;				int c=((xpos+s_xinc2*2)>>16) - xx;				int d=((xpos+s_xinc2*3)>>16) - xx;				memcpy(funnyUVCode + fragmentLength*i/4, fragment, fragmentLength);				funnyUVCode[fragmentLength*i/4 + imm8OfPShufW1]=				funnyUVCode[fragmentLength*i/4 + imm8OfPShufW2]=					a | (b<<2) | (c<<4) | (d<<6);				// if we dont need to read 8 bytes than dont :), reduces the chance of				// crossing a cache line				if(d<3) funnyUVCode[fragmentLength*i/4 + 1]= 0x6E;				funnyUVCode[fragmentLength*(i+4)/4]= RET;			}			xpos+=s_xinc2;		}//		funnyCode[0]= RET;	}#endif // HAVE_MMX2  } // reset counters  while(1){    unsigned char *dest =dstptr[0]+dststride*s_ypos;    unsigned char *uDest=dstptr[1]+(dststride>>1)*(s_ypos>>1);    unsigned char *vDest=dstptr[2]+(dststride>>1)*(s_ypos>>1);    int y0=(s_srcypos + 0xFFFF)>>16;  // first luminance source line number below the dst line	// points to the dst Pixels center in the source (0 is the center of pixel 0,0 in src)    int srcuvpos= dstbpp==12 ?	s_srcypos + s_yinc/2 - 0x8000 :    				s_srcypos - 0x8000;    int y1=(srcuvpos + 0x1FFFF)>>17; // first chrominance source line number below the dst line    int yalpha=((s_srcypos-1)&0xFFFF)>>4;    int uvalpha=((srcuvpos-1)&0x1FFFF)>>5;    uint16_t *buf0=pix_buf_y[y0&1];		// top line of the interpolated slice    uint16_t *buf1=pix_buf_y[((y0+1)&1)];	// bottom line of the interpolated slice    uint16_t *uvbuf0=pix_buf_uv[y1&1];		// top line of the interpolated slice    uint16_t *uvbuf1=pix_buf_uv[(y1+1)&1];	// bottom line of the interpolated slice    int i;    if(y0>=y+h) break; // FIXME wrong, skips last lines, but they are dupliactes anyway    if((y0&1) && dstbpp==12) uvalpha=-1; // there is no alpha if there is no line    s_ypos++; s_srcypos+=s_yinc;    //only interpolate the src line horizontally if we didnt do it allready	if(s_last_ypos!=y0)	{		unsigned char *src;		// skip if first line has been horiz scaled alleady		if(s_last_ypos != y0-1)		{			// check if first line is before any available src lines			if(y0-1 < y) 	src=srcptr[0]+(0     )*stride[0];			else		src=srcptr[0]+(y0-y-1)*stride[0];			hyscale(buf0, dstw, src, srcWidth, s_xinc);		}		// check if second line is after any available src lines		if(y0-y >= h)	src=srcptr[0]+(h-1)*stride[0];		else		src=srcptr[0]+(y0-y)*stride[0];		// the min() is required to avoid reuseing lines which where not available		s_last_ypos= MIN(y0, y+h-1);		hyscale(buf1, dstw, src, srcWidth, s_xinc);	}//	printf("%d %d %d %d\n", y, y1, s_last_y1pos, h);      // *** horizontal scale U and V lines to temp buffer	if(s_last_y1pos!=y1)	{		uint8_t *src1, *src2;		// skip if first line has been horiz scaled alleady		if(s_last_y1pos != y1-1)		{			// check if first line is before any available src lines			if(y1-y/2-1 < 0)			{				src1= srcptr[1]+(0)*stride[1];				src2= srcptr[2]+(0)*stride[2];			}else{				src1= srcptr[1]+(y1-y/2-1)*stride[1];				src2= srcptr[2]+(y1-y/2-1)*stride[2];			}			hcscale(uvbuf0, dstUVw, src1, src2, srcWidth, s_xinc2);		}		// check if second line is after any available src lines		if(y1 - y/2 >= h/2)		{			src1= srcptr[1]+(h/2-1)*stride[1];			src2= srcptr[2]+(h/2-1)*stride[2];		}else{			src1= srcptr[1]+(y1-y/2)*stride[1];			src2= srcptr[2]+(y1-y/2)*stride[2];		}		hcscale(uvbuf1, dstUVw, src1, src2, srcWidth, s_xinc2);		// the min() is required to avoid reuseing lines which where not available		s_last_y1pos= MIN(y1, y/2+h/2-1);	}	if(dstbpp==12) //YV12		yuv2yuv(buf0, buf1, uvbuf0, uvbuf1, dest, uDest, vDest, dstw, yalpha, uvalpha);	else if(ABS(s_yinc - 0x10000) < 10)		yuv2rgb1(buf0, buf1, uvbuf0, uvbuf1, dest, dstw, yalpha, uvalpha, dstbpp);	else		yuv2rgbX(buf0, buf1, uvbuf0, uvbuf1, dest, dstw, yalpha, uvalpha, dstbpp);#ifdef HAVE_MMX    	b16Dither= b16Dither1;	b16Dither1= b16Dither2;	b16Dither2= b16Dither;	g16Dither= g16Dither1;	g16Dither1= g16Dither2;	g16Dither2= g16Dither;#endif  }__asm __volatile(SFENCE:::"memory");__asm __volatile(EMMS:::"memory");}