rem: BESW(NV04_OE_STATE, 0x00000000);
context: status_t eng_configure_bes	(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset){	/* yuy2 (4:2:2) colorspace calculations */	/* Note:	 * in BeOS R5.0.3 and DANO:	 * 'ow->offset_xxx' is always 0, so not used;	 * 'ow->width' and 'ow->height' are the output window size: does not change	 * if window is clipping;	 * 'ow->h_start' and 'ow->v_start' are the left-top position of the output	 * window. These values can be negative: this means the window is clipping	 * at the left or the top of the display, respectively. */	/* 'ov' is the view in the source bitmap, so which part of the bitmap is actually	 * displayed on screen. This is used for the 'hardware zoom' function. */ 	/* output window position and clipping info for source buffer */	move_overlay_info moi;	/* calculated BES register values */	uint32 	hiscalv, viscalv;	/* interval representation, used for scaling calculations */	uint16 intrep;	/* inverse scaling factor, used for source positioning */	uint32 ifactor;	/* copy of overlay view which has checked valid values */	overlay_view my_ov;	/**************************************************************************************	 *** copy, check and limit if needed the user-specified view into the intput bitmap ***	 **************************************************************************************/	my_ov = *ov;	/* check for valid 'coordinates' */	if (my_ov.width == 0) my_ov.width++;	if (my_ov.height == 0) my_ov.height++;	if (my_ov.h_start > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))		my_ov.h_start = ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1);	if (((my_ov.h_start + my_ov.width) - 1) > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))		my_ov.width = ((((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1) - my_ov.h_start) + 1);	if (my_ov.v_start > (ob->height - 1))		my_ov.v_start = (ob->height - 1);	if (((my_ov.v_start + my_ov.height) - 1) > (ob->height - 1))		my_ov.height = (((ob->height - 1) - my_ov.v_start) + 1);	LOG(4,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",		my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));	/* save for eng_bes_calc_move_overlay() */	si->overlay.ow = *ow;	si->overlay.ob = *ob;	si->overlay.my_ov = my_ov;	/********************************	 *** setup horizontal scaling ***	 ********************************/	LOG(4,("Overlay: total input picture width = %d, height = %d\n",			(ob->width - si->overlay.myBufInfo[offset].slopspace), ob->height));	LOG(4,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));	/* determine interval representation value, taking zoom into account */	if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)	{		/* horizontal filtering is ON */		if ((my_ov.width == ow->width) | (ow->width < 2))		{			/* no horizontal scaling used, OR destination width < 2 */			intrep = 0;		}		else		{			intrep = 1;		}	}	else	{		/* horizontal filtering is OFF */		if ((ow->width < my_ov.width) & (ow->width >= 2))		{			/* horizontal downscaling used AND destination width >= 2 */			intrep = 1;		}		else		{			intrep = 0;		}	}	LOG(4,("Overlay: horizontal interval representation value is %d\n",intrep));	/* calculate inverse horizontal scaling factor, taking zoom into account */	/* standard scaling formula: */	ifactor = (((uint32)(my_ov.width - intrep)) << 16) / (ow->width - intrep); 	/* correct factor to prevent most-right visible 'line' from distorting */	ifactor -= (1 << 2);	hiscalv = ifactor;	/* save for eng_bes_calc_move_overlay() */	si->overlay.h_ifactor = ifactor;	LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));	/* check scaling factor (and modify if needed) to be within scaling limits */	/* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */	if (hiscalv < 0x00002000)	{		/* (non-inverse) factor too large, set factor to max. valid value */		hiscalv = 0x00002000;		LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / hiscalv));	}	switch (si->ps.card_arch)	{	case NV04A:		/* Riva128-TNT2 series have a 'downscaling' limit of 1.000489		 * (16bit register with 0.11 format value) */		if (hiscalv > 0x0000ffff)		{			/* (non-inverse) factor too small, set factor to min. valid value */			hiscalv = 0x0000ffff;			LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)2048 / (hiscalv >> 5)));		}		break;	case NV30A:	case NV40A:		/* GeForceFX series and up have a downscaling limit of 0.5 (except NV31!) */		if ((hiscalv > (2 << 16)) && (si->ps.card_type != NV31))		{			/* (non-inverse) factor too small, set factor to min. valid value */			hiscalv = (2 << 16);			LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));		}		/* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits!		 * So let it fall through... */		if (si->ps.card_type != NV31) break;	default:		/* the rest has a downscaling limit of 0.125 */		if (hiscalv > (8 << 16))		{			/* (non-inverse) factor too small, set factor to min. valid value */			hiscalv = (8 << 16);			LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)65536 / hiscalv));		}		break;	}	/* AND below is required by hardware */	hiscalv &= 0x001ffffc;	/******************************	 *** setup vertical scaling ***	 ******************************/	/* determine interval representation value, taking zoom into account */	if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)	{		/* vertical filtering is ON */		if ((my_ov.height == ow->height) | (ow->height < 2))		{			/* no vertical scaling used, OR destination height < 2 */			intrep = 0;		}		else		{			intrep = 1;		}	}	else	{		/* vertical filtering is OFF */		if ((ow->height < my_ov.height) & (ow->height >= 2))		{			/* vertical downscaling used AND destination height >= 2 */			intrep = 1;		}		else		{			intrep = 0;		}	}	LOG(4,("Overlay: vertical interval representation value is %d\n",intrep));	/* calculate inverse vertical scaling factor, taking zoom into account */	/* standard scaling formula: */	ifactor = (((uint32)(my_ov.height - intrep)) << 16) / (ow->height - intrep); 	/* correct factor to prevent lowest visible line from distorting */	ifactor -= (1 << 2);	LOG(4,("Overlay: vertical scaling factor is %f\n", (float)65536 / ifactor));	/* preserve ifactor for source positioning calculations later on */	viscalv = ifactor;	/* save for eng_bes_calc_move_overlay() */	si->overlay.v_ifactor = ifactor;	/* check scaling factor (and modify if needed) to be within scaling limits */	/* all cards have a upscaling limit of 8.0 (see official nVidia specsheets) */	if (viscalv < 0x00002000)	{		/* (non-inverse) factor too large, set factor to max. valid value */		viscalv = 0x00002000;		LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / viscalv));	}	switch (si->ps.card_arch)	{	case NV04A:		/* Riva128-TNT2 series have a 'downscaling' limit of 1.000489		 * (16bit register with 0.11 format value) */		if (viscalv > 0x0000ffff)		{			/* (non-inverse) factor too small, set factor to min. valid value */			viscalv = 0x0000ffff;			LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)2048 / (viscalv >> 5)));		}		break;	case NV30A:	case NV40A:		/* GeForceFX series and up have a downscaling limit of 0.5 (except NV31!) */		if ((viscalv > (2 << 16)) && (si->ps.card_type != NV31))		{			/* (non-inverse) factor too small, set factor to min. valid value */			viscalv = (2 << 16);			LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));		}		/* NV31 (confirmed GeForceFX 5600) has NV20A scaling limits!		 * So let it fall through... */		if (si->ps.card_type != NV31) break;	default:		/* the rest has a downscaling limit of 0.125 */		if (viscalv > (8 << 16))		{			/* (non-inverse) factor too small, set factor to min. valid value */			viscalv = (8 << 16);			LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)65536 / viscalv));		}		break;	}	/* AND below is required by hardware */	viscalv &= 0x001ffffc;	/********************************************************************************	 *** setup all edges of output window, setup horizontal and vertical clipping ***	 ********************************************************************************/	eng_bes_calc_move_overlay(&moi);	/*****************************	 *** log color keying info ***	 *****************************/	LOG(4,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",		ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));	LOG(4,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",		ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));	/*****************	 *** log flags ***	 *****************/	LOG(4,("Overlay: ow->flags is $%08x\n",ow->flags));	/* BTW: horizontal and vertical filtering are fixed and turned on for GeForce overlay. */	/*************************************	 *** sync to BES (Back End Scaler) ***	 *************************************/	/* Done in card hardware:	 * double buffered registers + trigger if programming complete feature. */	/**************************************	 *** actually program the registers ***	 **************************************/	if (si->ps.card_arch < NV10A)	{		/* unknown, but needed (otherwise high-res distortions and only half the frames */		BESW(NV04_OE_STATE, 0x00000000);		/* select buffer 0 as active (b16) */		BESW(NV04_SU_STATE, 0x00000000);		/* unknown (no effect?) */		BESW(NV04_RM_STATE, 0x00000000);		/* setup clipped(!) buffer startadress in RAM */		/* RIVA128 - TNT bes doesn't have clipping registers, so no subpixelprecise clipping		 * either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */		/* (program both buffers to prevent sync distortions) */		/* first include 'pixel precise' left clipping... (top clipping was already included) */		moi.a1orgv += ((moi.hsrcstv >> 16) * 2);		/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */		BESW(NV04_0BUFADR, (moi.a1orgv & ~0x03));		BESW(NV04_1BUFADR, (moi.a1orgv & ~0x03));		/* setup buffer source pitch including slopspace (in bytes).		 * Note:		 * source pitch granularity = 16 pixels on the RIVA128 - TNT (so pre-NV10) bes */		/* (program both buffers to prevent sync distortions) */		BESW(NV04_0SRCPTCH, (ob->width * 2));		BESW(NV04_1SRCPTCH, (ob->width * 2));		/* setup output window position */		BESW(NV04_DSTREF, ((moi.vcoordv & 0xffff0000) | ((moi.hcoordv & 0xffff0000) >> 16)));		/* setup output window size */		BESW(NV04_DSTSIZE, (			(((moi.vcoordv & 0x0000ffff) - ((moi.vcoordv & 0xffff0000) >> 16) + 1) << 16) |			((moi.hcoordv & 0x0000ffff) - ((moi.hcoordv & 0xffff0000) >> 16) + 1)			));		/* setup horizontal and vertical scaling */		BESW(NV04_ISCALVH, (((viscalv << 16) >> 5) | (hiscalv >> 5)));		/* enable vertical filtering (b0) */		BESW(NV04_CTRL_V, 0x00000001);		/* enable horizontal filtering (no effect?) */		BESW(NV04_CTRL_H, 0x00000111);		/* enable BES (b0), enable colorkeying (b4), format yuy2 (b8: 0 = ccir) */		BESW(NV04_GENCTRL, 0x00000111);		/* select buffer 1 as active (b16) */		BESW(NV04_SU_STATE, 0x00010000);		/**************************		 *** setup color keying ***		 **************************/		/* setup colorkeying */		switch(si->dm.space)		{		case B_RGB15_LITTLE:			BESW(NV04_COLKEY, (				((ow->blue.value & ow->blue.mask) << 0)   |				((ow->green.value & ow->green.mask) << 5) |				((ow->red.value & ow->red.mask) << 10)    |				((ow->alpha.value & ow->alpha.mask) << 15)				));			break;		case B_RGB16_LITTLE:			BESW(NV04_COLKEY, (				((ow->blue.value & ow->blue.mask) << 0)   |				((ow->green.value & ow->green.mask) << 5) |				((ow->red.value & ow->red.mask) << 11)				/* this space has no alpha bits */				));			break;		case B_CMAP8:		case B_RGB32_LITTLE:		default:			BESW(NV04_COLKEY, (				((ow->blue.value & ow->blue.mask) << 0)   |				((ow->green.value & ow->green.mask) << 8) |				((ow->red.value & ow->red.mask) << 16)    |				((ow->alpha.value & ow->alpha.mask) << 24)				));			break;		}	}	else	{		/* >= NV10A */			/* setup buffer origin: GeForce uses subpixel precise clipping on left and top! (12.4 values) */		BESW(NV10_0SRCREF, ((moi.v1srcstv << 4) & 0xffff0000) | ((moi.hsrcstv >> 12) & 0x0000ffff));		/* setup buffersize */		//fixme if needed: width must be even officially...		BESW(NV10_0SRCSIZE, ((ob->height << 16) | ob->width));		/* setup source pitch including slopspace (in bytes),		 * b16: select YUY2 (0 = YV12), b20: use colorkey, b24: no iturbt_709 (do iturbt_601) */		/* Note:		 * source pitch granularity = 32 pixels on GeForce cards!! */		BESW(NV10_0SRCPTCH, (((ob->width * 2) & 0x0000ffff) | (1 << 16) | (1 << 20) | (0 << 24)));		/* setup output window position */		BESW(NV10_0DSTREF, ((moi.vcoordv & 0xffff0000) | ((moi.hcoordv & 0xffff0000) >> 16)));		/* setup output window size */		BESW(NV10_0DSTSIZE, (			(((moi.vcoordv & 0x0000ffff) - ((moi.vcoordv & 0xffff0000) >> 16) + 1) << 16) |			((moi.hcoordv & 0x0000ffff) - ((moi.hcoordv & 0xffff0000) >> 16) + 1)			));		/* setup horizontal scaling */		BESW(NV10_0ISCALH, (hiscalv << 4));		/* setup vertical scaling */		BESW(NV10_0ISCALV, (viscalv << 4));		/* setup (unclipped!) buffer startadress in RAM */		BESW(NV10_0BUFADR, moi.a1orgv);		/* enable BES (b0 = 0) */		BESW(NV10_GENCTRL, 0x00000000);		/* We only use buffer buffer 0: select it. (0x01 = buffer 0, 0x10 = buffer 1) */		/* This also triggers activation of programmed values (double buffered registers feature) */		BESW(NV10_BUFSEL, 0x00000001);		/**************************		 *** setup color keying ***		 **************************/		/* setup colorkeying */		switch(si->dm.space)		{		case B_RGB15_LITTLE:			BESW(NV10_COLKEY, (				((ow->blue.value & ow->blue.mask) << 0)   |				((ow->green.value & ow->green.mask) << 5) |				((ow->red.value & ow->red.mask) << 10)    |				((ow->alpha.value & ow->alpha.mask) << 15)				));			break;		case B_RGB16_LITTLE:			BESW(NV10_COLKEY, (				((ow->blue.value & ow->blue.mask) << 0)   |				((ow->green.value & ow->green.mask) << 5) |				((ow->red.value & ow->red.mask) << 11)				/* this space has no alpha bits */				));			break;		case B_CMAP8:		case B_RGB32_LITTLE:		default:			BESW(NV10_COLKEY, (				((ow->blue.value & ow->blue.mask) << 0)   |				((ow->green.value & ow->green.mask) << 8) |				((ow->red.value & ow->red.mask) << 16)    |				((ow->alpha.value & ow->alpha.mask) << 24)				));			break;		}	}	/* note that overlay is in use (for eng_bes_move_overlay()) */	si->overlay.active = true;	return B_OK;}