rem: bool display, h, v;
context: status_t SET_DISPLAY_MODE(display_mode *mode_to_set) {	/* BOUNDS WARNING:	 * It's impossible to deviate whatever small amount in a display_mode if the lower	 * and upper limits are the same!	 * Besides:	 * BeOS (tested R5.0.3PE) is failing BWindowScreen::SetFrameBuffer() if PROPOSEMODE	 * returns B_BAD_VALUE!	 * Which means PROPOSEMODE should not return that on anything except on	 * deviations for:	 * display_mode.virtual_width;	 * display_mode.virtual_height;	 * display_mode.timing.h_display;	 * display_mode.timing.v_display;	 * So:	 * We don't use bounds here by making sure bounds and target are the same struct!	 * (See the call to PROPOSE_DISPLAY_MODE below) */	display_mode /*bounds,*/ target;	uint8 colour_depth1 = 32;	status_t result;	uint32 startadd,startadd_right;	bool display, h, v;//	bool crt1, crt2, cross;	/* Adjust mode to valid one and fail if invalid */	target /*= bounds*/ = *mode_to_set;	/* show the mode bits */	LOG(1, ("SETMODE: (ENTER) initial modeflags: $%08x\n", target.flags));	LOG(1, ("SETMODE: requested target pixelclock %dkHz\n",  target.timing.pixel_clock));	LOG(1, ("SETMODE: requested virtual_width %d, virtual_height %d\n",										target.virtual_width, target.virtual_height));	/* See BOUNDS WARNING above... */	if (PROPOSE_DISPLAY_MODE(&target, &target, &target) == B_ERROR)	return B_ERROR;	/* if not dualhead capable card clear dualhead flags */	if (!(target.flags & DUALHEAD_CAPABLE))	{		target.flags &= ~DUALHEAD_BITS;	}	/* if not TVout capable card clear TVout flags */	if (!(target.flags & TV_CAPABLE))	{		target.flags &= ~TV_BITS;	}	LOG(1, ("SETMODE: (CONT.) validated command modeflags: $%08x\n", target.flags));	/* make sure a possible 3D add-on will block rendering and re-initialize itself.	 * note: update in _this_ order only */	/* SET_DISPLAY_MODE will reset this flag when it's done. */	si->engine.threeD.mode_changing = true;	/* every 3D add-on will reset this bit-flag when it's done. */	si->engine.threeD.newmode = 0xffffffff;	/* every 3D clone needs to reclaim a slot.	 * note: this also cleans up reserved channels for killed 3D clones.. */	si->engine.threeD.clones = 0x00000000;	/* disable interrupts using the kernel driver */	interrupt_enable(false);	/* disable TVout if supported */	if (si->ps.tvout) BT_stop_tvout();	/* find current DPMS state, then turn off screen(s) */	head1_dpms_fetch(&display, &h, &v);	head1_dpms(false, false, false);	if (si->ps.secondary_head) head2_dpms(false, false, false);	if (si->ps.tvout) BT_dpms(false);	/*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/	startadd = (uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer;	/* calculate and set new mode bytes_per_row */	nv_general_validate_pic_size (&target, &si->fbc.bytes_per_row, &si->acc_mode);	/*Perform the very long mode switch!*/	if (target.flags & DUALHEAD_BITS) /*if some dualhead mode*/	{		uint8 colour_depth2 = colour_depth1;		/* init display mode for secondary head */				display_mode target2 = target;		LOG(1,("SETMODE: setting DUALHEAD mode\n"));		/* validate flags for secondary TVout */		//fixme: remove or block on autodetect fail. (is now shutoff)		if ((0) && (target2.flags & TV_BITS))		{			target.flags &= ~TV_BITS;//still needed for some routines...			target2.flags &= ~TV_BITS;			LOG(1,("SETMODE: blocking TVout: no TVout cable connected!\n"));		}		/* detect which connectors have a CRT connected */		//fixme: 'hot-plugging' for analog monitors removed: remove code as well;		//or make it work with digital panels connected as well.//		crt1 = nv_dac_crt_connected();//		crt2 = nv_dac2_crt_connected();		/* connect outputs 'straight-through' *///		if (crt1)//		{			/* connector1 is used as primary output *///			cross = false;//		}//		else//		{//			if (crt2)				/* connector2 is used as primary output *///				cross = true;//			else				/* no CRT detected: assume connector1 is used as primary output *///				cross = false;//		}		/* set output connectors assignment if possible */		if ((target.flags & DUALHEAD_BITS) == DUALHEAD_SWITCH)			/* invert output assignment in switch mode */			nv_general_head_select(true);		else			nv_general_head_select(false);		/* set the pixel clock PLL(s) */		LOG(8,("SETMODE: target clock %dkHz\n",target.timing.pixel_clock));		if (head1_set_pix_pll(target) == B_ERROR)			LOG(8,("SETMODE: error setting pixel clock (internal DAC)\n"));		/* we do not need to set the pixelclock here for a head that's in TVout mode */		if (!(target2.flags & TV_BITS))		{			LOG(8,("SETMODE: target2 clock %dkHz\n",target2.timing.pixel_clock));			if (head2_set_pix_pll(target2) == B_ERROR)				LOG(8,("SETMODE: error setting pixel clock (DAC2)\n"));		}		/*set the colour depth for CRTC1 and the DAC */		switch(target.space)		{		case B_CMAP8:			colour_depth1 =  8;			head1_mode(BPP8, 1.0);			head1_depth(BPP8);			break;		case B_RGB15_LITTLE:			colour_depth1 = 16;			head1_mode(BPP15, 1.0);			head1_depth(BPP15);			break;		case B_RGB16_LITTLE:			colour_depth1 = 16;			head1_mode(BPP16, 1.0);			head1_depth(BPP16);			break;		case B_RGB32_LITTLE:			colour_depth1 = 32;			head1_mode(BPP32, 1.0);			head1_depth(BPP32);			break;		}		/*set the colour depth for CRTC2 and DAC2 */		switch(target2.space)		{		case B_CMAP8:			colour_depth2 =  8;			head2_mode(BPP8, 1.0);			head2_depth(BPP8);			break;		case B_RGB15_LITTLE:			colour_depth2 = 16;			head2_mode(BPP15, 1.0);			head2_depth(BPP15);			break;		case B_RGB16_LITTLE:			colour_depth2 = 16;			head2_mode(BPP16, 1.0);			head2_depth(BPP16);			break;		case B_RGB32_LITTLE:			colour_depth2 = 32;			head2_mode(BPP32, 1.0);			head2_depth(BPP32);			break;		}		/* check if we are doing interlaced TVout mode */		//fixme: we don't support interlaced mode?		si->interlaced_tv_mode = false;/*		if ((target2.flags & TV_BITS) && (si->ps.card_type >= G450))			si->interlaced_tv_mode = true;*/		/*set the display(s) pitches*/		head1_set_display_pitch ();		//fixme: seperate for real dualhead modes:		//we need a secondary si->fbc!		head2_set_display_pitch ();		/*work out where the "right" screen starts*/		startadd_right = startadd + (target.timing.h_display * (colour_depth1 >> 3));		/* Tell card what memory to display */		switch (target.flags & DUALHEAD_BITS)		{		case DUALHEAD_ON:		case DUALHEAD_SWITCH:			head1_set_display_start(startadd,colour_depth1);			head2_set_display_start(startadd_right,colour_depth2);			break;		case DUALHEAD_CLONE:			head1_set_display_start(startadd,colour_depth1);			head2_set_display_start(startadd,colour_depth2);			break;		}		/* set the timing */		head1_set_timing(target);		/* we do not need to setup CRTC2 here for a head that's in TVout mode */		if (!(target2.flags & TV_BITS))	result = head2_set_timing(target2);		/* TVout support: setup CRTC2 and it's pixelclock */		if (si->ps.tvout && (target2.flags & TV_BITS)) BT_setmode(target2);	}	else /* single head mode */	{		status_t status;		int colour_mode = BPP32;		/* connect output */		if (si->ps.secondary_head)		{			/* detect which connectors have a CRT connected */			//fixme: 'hot-plugging' for analog monitors removed: remove code as well;			//or make it work with digital panels connected as well.//			crt1 = nv_dac_crt_connected();//			crt2 = nv_dac2_crt_connected();			/* connect outputs 'straight-through' *///			if (crt1)//			{				/* connector1 is used as primary output *///				cross = false;//			}//			else//			{//				if (crt2)					/* connector2 is used as primary output *///					cross = true;//				else					/* no CRT detected: assume connector1 is used as primary output *///					cross = false;//			}			/* set output connectors assignment if possible */			nv_general_head_select(false);		}		switch(target.space)		{		case B_CMAP8:        colour_depth1 =  8; colour_mode = BPP8;  break;		case B_RGB15_LITTLE: colour_depth1 = 16; colour_mode = BPP15; break;		case B_RGB16_LITTLE: colour_depth1 = 16; colour_mode = BPP16; break;		case B_RGB32_LITTLE: colour_depth1 = 32; colour_mode = BPP32; break;		default:			LOG(8,("SETMODE: Invalid singlehead colour depth 0x%08x\n", target.space));			return B_ERROR;		}		/* set the pixel clock PLL */		status = head1_set_pix_pll(target);		if (status==B_ERROR)			LOG(8,("CRTC: error setting pixel clock (internal DAC)\n"));		/* set the colour depth for CRTC1 and the DAC */		/* first set the colordepth */		head1_depth(colour_mode);		/* then(!) program the PAL (<8bit colordepth does not support 8bit PAL) */		head1_mode(colour_mode,1.0);		/* set the display pitch */		head1_set_display_pitch();		/* tell the card what memory to display */		head1_set_display_start(startadd,colour_depth1);		/* set the timing */		if (!(target.flags & TV_BITS)) head1_set_timing(target);		/* TVout support: setup CRTC and it's pixelclock */		if (si->ps.tvout && (target.flags & TV_BITS)) BT_setmode(target);		//fixme: shut-off the videoPLL if it exists...	}	/* update driver's mode store */	si->dm = target;	/* update FIFO data fetching according to mode */	nv_crtc_update_fifo();	/* turn screen one on */	head1_dpms(display, h, v);	/* turn screen two on if a dualhead mode is active */	if (target.flags & DUALHEAD_BITS) head2_dpms(display,h,v);	/* turn TVout on if this is a TVout mode */	if (target.flags & TV_BITS) BT_dpms(true);	/* set up acceleration for this mode */	/* note:	 * Maybe later we can forget about non-DMA mode (depends on 3D acceleration	 * attempts). */	if (!si->settings.dma_acc)		nv_acc_init();	else		nv_acc_init_dma();	/* set up overlay unit for this mode */	nv_bes_init();	/* note freemem range */	/* first free adress follows hardcursor and workspace */	si->engine.threeD.mem_low = si->fbc.bytes_per_row * si->dm.virtual_height;	if (si->settings.hardcursor) si->engine.threeD.mem_low += 2048;	/* last free adress is end-of-ram minus max space needed for overlay bitmaps */	//fixme possible:	//if overlay buffers are allocated subtract buffersize from mem_high;	//only allocate overlay buffers if 3D is not in use. (block overlay during 3D)	si->engine.threeD.mem_high = si->ps.memory_size - 1;	/* don't touch the DMA acceleration engine command buffer if it exists */	/* note:	 * the buffer is 32kB in size. Keep some extra distance for safety (faulty apps). */	if (si->settings.dma_acc)	{		if (si->ps.card_arch < NV40A)		{			/* keeping 32kB distance from the DMA buffer */			si->engine.threeD.mem_high -= (64 * 1024);		}		else		{			/* 416kB distance is just OK: keeping another 64kB distance for safety;			 * confirmed for NV43. */			/* note:			 * if you get too close to the DMA command buffer on NV40 and NV43 at			 * least (both confirmed), the source DMA instance will mess-up for			 * at least engine cmd NV_IMAGE_BLIT and NV12_IMAGE_BLIT. */			si->engine.threeD.mem_high -= (512 * 1024);		}	}	si->engine.threeD.mem_high -= (MAXBUFFERS * 1024 * 1024 * 2); /* see overlay.c file */	LOG(1,("SETMODE: booted since %f mS\n", system_time()/1000.0));	/* enable interrupts using the kernel driver */	interrupt_enable(true);	/* make sure a possible 3D add-on will re-initialize itself by signalling ready */	si->engine.threeD.mode_changing = false;	/* optimize memory-access if needed *///	head1_mem_priority(colour_depth1);	/* Tune RAM CAS-latency if needed. Must be done *here*! */	nv_set_cas_latency();	return B_OK;}