static void GLW_CreateGLWnd( void )
{
	int x, y, w, h;
	HWND hParent;
	float aspect;
	DWORD s, es;
	skinDef_t *skin;

	int refresh = 0;
	int colorDepth = 0;

	WinVars_t *winVars = (WinVars_t*)ri.PlatformGetVars();

	if( winVars->hWnd )
		return;

	x = 0;
	y = 0;

	if( r_fullscreen->integer )
	{
		int mode_id;

		char * res = r_fsmode->string;
		w = atoi( COM_Parse( &res ) );
		h = atoi( COM_Parse( &res ) );
		aspect = (float)w / (float)h;

		sql_prepare( &com_db, "SELECT x, y FROM monitors SEARCH dev_name ?" );
		sql_bindtext( &com_db, 1, r_fsmonitor->string );
		if( sql_step( &com_db ) )
		{
			x = sql_columnasint( &com_db, 0 );
			y = sql_columnasint( &com_db, 1 );
		}
		sql_done( &com_db );

		//find the settings mode id
		mode_id = -1;
		sql_prepare( &com_db, "SELECT id FROM fsmodes SEARCH dev_name ?1 WHERE w=?2 AND h=?3" );
		sql_bindtext( &com_db, 1, r_fsmonitor->string );
		sql_bindint( &com_db, 2, w );
		sql_bindint( &com_db, 3, h );
		if( sql_step( &com_db ) )
			mode_id = sql_columnasint( &com_db, 0 );
		sql_done( &com_db );

		//get a matching color mode
		sql_prepare( &com_db, "SELECT bpp FROM fsmodes_ext SEARCH id ?1" );
		sql_bindint( &com_db, 1, mode_id );

		while( sql_step( &com_db ) )
		{
			int bpp = sql_columnasint( &com_db, 0 );
			if( r_colorbits->integer )
			{
				if( bpp == r_colorbits->integer )
				{
					//take an exact match
					colorDepth = bpp;
					break;
				}

				if( bpp > r_colorbits->integer )
				{
					if( colorDepth < r_colorbits->integer || bpp < colorDepth )
						//if we must go over, take the smallest value that goes over
						colorDepth = bpp;
				}
				else if( bpp > colorDepth )
					colorDepth = bpp;
			}
			else if( bpp > colorDepth )
				colorDepth = bpp;
		}

		sql_done( &com_db );

		//get a matching refresh rate
		sql_prepare( &com_db, "SELECT hz FROM fsmodes_ext SEARCH id ?1 WHERE bpp=?2" );
		sql_bindint( &com_db, 1, mode_id );
		sql_bindint( &com_db, 2, colorDepth );

		while( sql_step( &com_db ) )
		{
			int hz = sql_columnasint( &com_db, 0 );
			if( r_displayRefresh->integer )
			{
				if( hz == r_displayRefresh->integer )
				{
					//take an exact match
					refresh = hz;
					break;
				}

				if( hz > r_displayRefresh->integer )
				{
					if( refresh < r_displayRefresh->integer || hz < refresh )
						//if we must go over, take the smallest value that goes over
						refresh = hz;
				}
				else if( hz > refresh )
					refresh = hz;
			}
			else if( hz > refresh )
				//take the highest refresh rate
				refresh = hz;
		}

		sql_done( &com_db );
	}
	else
	{
		if( !R_GetModeInfo( &w, &h, &aspect, r_mode->integer ) )
		{
			//fall back to special modes
			w = 0;
			h = 0;
		}
	}

	/*
		Clean out old display mode changes.

		Note that we *don't* skip this when we're going back into fullscreen
		as it tends to produce some aweful bugs on some Windows installations.
	*/
	if( glw_state.cdsFullscreen )
		ChangeDisplaySettings( NULL, 0 );

	//window style bits
	es = 0;
	s = 0;

	skin = NULL;

	if( r_fullscreen->integer )
	{
		//go into full screen mode

		RECT rc;
		HMONITOR monitor;
		MONITORINFOEX monitorInfo;

		hParent = 0;

		//make sure we're set up for multimon goodness
		if( winVars->hWndHost )
		{
			GetWindowRect( winVars->hWndHost, &rc );
		}
		else
		{
			rc.left = x;
			rc.top = y;
			rc.right = x + w;
			rc.bottom = y + h;
		}

		monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );

		monitorInfo.cbSize = sizeof( monitorInfo );
		GetMonitorInfo( monitor, (LPMONITORINFO)&monitorInfo );

		//if we got an invalid mode then use desktop resolution
		if( w == 0 )
			w = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
		if( h == 0 )
			h = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;

		//change that monitor's display size to <w, h>
		//set the window rect to cover the display
		//skip the festival of desktop flickering if not changing resolution
		if( (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left) != w ||
			(monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top) != h )
		{
			DEVMODE dm;
			memset( &dm, 0, sizeof( dm ) );

			dm.dmSize = sizeof( dm );
			
			dm.dmPelsWidth = w;
			dm.dmPelsHeight = h;
			dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;

			if( refresh != 0 )
			{
				dm.dmDisplayFrequency = refresh;
				dm.dmFields |= DM_DISPLAYFREQUENCY;
			}

			if( colorDepth != 0 )
			{
				dm.dmBitsPerPel = colorDepth;
				dm.dmFields |= DM_BITSPERPEL;
			}

			if( ChangeDisplaySettingsEx( monitorInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL )
				!= DISP_CHANGE_SUCCESSFUL )
			{
				//try again without color bits and frequency
				dm.dmFields &= ~(DM_BITSPERPEL | DM_DISPLAYFREQUENCY);
				dm.dmBitsPerPel = 0;
				dm.dmDisplayFrequency = 0;

				if( ChangeDisplaySettingsEx( monitorInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL )
					!= DISP_CHANGE_SUCCESSFUL )
					//failed...
					ri.Printf( PRINT_WARNING, "Invalid fullscreen resolution, running at desktop resolution" );
			}
		}

		//get the new monitor info
		monitorInfo.cbSize = sizeof( monitorInfo );
		GetMonitorInfo( monitor, (LPMONITORINFO)&monitorInfo );

		x = monitorInfo.rcMonitor.left;
		y = monitorInfo.rcMonitor.top;
		w = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
		h = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;

		s = WS_POPUP;
		es = WS_EX_APPWINDOW | WS_EX_TOPMOST;

		glw_state.cdsFullscreen = qtrue;
	}
	else if( winVars->hWndHost )
	{
		RECT rc;

		hParent = winVars->hWndHost;

		GetClientRect( winVars->hWndHost, &rc );
		x = rc.left;
		y = rc.top;
		w = rc.right - rc.left;
		h = rc.bottom - rc.top;

		s = WS_CHILD;
		es = WS_EX_NOPARENTNOTIFY;
	}
	else
	{
		RECT rc;
		HMONITOR monitor;
		MONITORINFO monitorInfo;
		qboolean usedefault = qfalse;

		if( w == 0 )
			w = 640;
		if( h == 0 )
			h = 480;

		vid_xpos = ri.Cvar_Get( "vid_xpos", va("%d",CW_USEDEFAULT), CVAR_ARCHIVE );
		vid_ypos = ri.Cvar_Get( "vid_ypos", "0", CVAR_ARCHIVE );

		x = vid_xpos->integer;
		y = vid_ypos->integer;

		if ( x == CW_USEDEFAULT ) {
			x = 0;
			usedefault = qtrue;
		}

		rc.left = x;
		rc.top = y;
		rc.right = x + w;
		rc.bottom = y + h;

		hParent = 0;

		if( r_skin->string[0] )
			skin = Skin_Load( r_skin->string );
		
		//account for the border frame
		if( skin )
		{
			s = WS_POPUP;
			es = WS_EX_APPWINDOW;

			Skin_AdjustWindowRect( &rc, skin );
			AdjustWindowRectEx( &rc, s, FALSE, es );
		}
		else
		{
			s = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER | WS_CAPTION;
			es = WS_EX_APPWINDOW;

			AdjustWindowRectEx( &rc, s, FALSE, es );
		}

		x = rc.left;
		y = rc.top;
		w = rc.right - rc.left;
		h = rc.bottom - rc.top;

		//constrain to a monitor
		//this is important as we can't get a
		//pixel format if we're entirely off screen
		monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST );

		monitorInfo.cbSize = sizeof( monitorInfo );
		GetMonitorInfo( monitor, &monitorInfo );

		//if we're not actually intersecting the monitor
		//(shoved off of the screen I guess) move back onto it

		if( x > monitorInfo.rcWork.right )
			//left window edge past right screen edge
			x = monitorInfo.rcWork.right - w;
		if( x + w < monitorInfo.rcWork.left )
			//right window edge past left screen edge
			x = monitorInfo.rcWork.left;

		if( y > monitorInfo.rcWork.bottom )
			//top window edge past bottom screen edge
			y = monitorInfo.rcWork.bottom - h;
		if( y + h < monitorInfo.rcWork.top )
			//bottom window edge past top screen edge
			y = monitorInfo.rcWork.top;

		glw_state.cdsFullscreen = qfalse;


		if ( usedefault ) {
			x = monitorInfo.rcMonitor.left + ((monitorInfo.rcMonitor.right-monitorInfo.rcMonitor.left)-w)/2;
			y = monitorInfo.rcMonitor.top + ((monitorInfo.rcMonitor.bottom-monitorInfo.rcMonitor.top)-h)/2;
		}
	}

	winVars->hWnd = NULL;

	if( skin )
	{
		Skin_RegisterClass();
		winVars->hWnd = Skin_CreateWnd( skin, x, y, w, h );
	}
	
	if( !winVars->hWnd )
	{
		GLW_RegisterClass();
		winVars->hWnd = CreateWindowEx( es, WINDOW_CLASS_NAME, WINDOW_CAPTION,
			s, x, y, w, h, hParent, NULL, winVars->hInstance, NULL );
	}

	//the window now owns the skin and will free it

	if( !winVars->hWnd )
		ri.Error( ERR_FATAL, "GLW: could not create window" );

	SetWindowPos( winVars->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );

	ShowWindow( winVars->hWnd, SW_SHOWNORMAL );
	SetFocus( winVars->hWnd );

	//get the window to draw once (get rid of graphical clutter)
	UpdateWindow( winVars->hWnd );

	//fire up the GL
	glw_state.hDC = GetDC( winVars->hWnd );
	if( !glw_state.hDC )
		ri.Error( ERR_FATAL, "GLW: could not get window DC" );

	//set up the pixel format
	{
		int pixelFormat;
		PIXELFORMATDESCRIPTOR pfd;

		GLW_CreatePFD( &pfd );
		pixelFormat = GLW_ChoosePFDEx( &pfd );

		if( !pixelFormat )
		{
			pixelFormat = GLW_ChoosePFD( glw_state.hDC, &pfd );
			glConfig.fsaaSamples = 1;
		}

		if( !pixelFormat )
			ri.Error( ERR_FATAL, "GLW: no valid pixel format" );

		pfd.nSize = sizeof( pfd );
		DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( pfd ), &pfd );
		if( !SetPixelFormat( glw_state.hDC, pixelFormat, &pfd ) )
			ri.Error( ERR_FATAL, "GLW: could not set pixel format" );

		glConfig.colorBits = pfd.cColorBits;
		glConfig.depthBits = pfd.cDepthBits;
		glConfig.stencilBits = pfd.cStencilBits;
		glConfig.stereoEnabled = (pfd.dwFlags & PFD_STEREO) ? qtrue : qfalse;

		ri.Printf( PRINT_ALL, "Using Pixel Format %i\n", pixelFormat );
	}
		
	glw_state.hGLRC = wglCreateContext( glw_state.hDC );
	if( !glw_state.hGLRC || !wglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) )
		ri.Error( ERR_FATAL, "GLW: could not initialize GL" );

	GLW_CheckExtensions();

	//R_PerfInit();

	{
		//get the actual sizes, in case Windows constrained our window
		RECT rc;
		GetClientRect( winVars->hWnd, &rc );
		w = rc.right - rc.left;
		h = rc.bottom - rc.top;

		//fill in some glConfig stuff which *will* be referenced
		//by various subsystem init functions (i.e. Cg, bloom)
		glConfig.vidWidth = w;
		glConfig.vidHeight = h;
		glConfig.windowAspect = aspect;
	}

	glConfig.deviceSupportsGamma = qfalse;
	glConfig.isFullscreen = glw_state.cdsFullscreen ? qtrue : qfalse;

	glConfig.xscale = glConfig.vidWidth / 640.0f;
	glConfig.yscale = glConfig.vidHeight / 480.0f;

	if( glConfig.vidWidth * 480 > glConfig.vidHeight * 640 )
	{
		// wide screen
		glConfig.xscale	= glConfig.yscale;
		glConfig.xbias	= ((float)glConfig.vidWidth - (640.0F * glConfig.xscale)) * 0.5F;
	}
	else
	{
		// no wide screen
		glConfig.xbias	= 0.0f;
	}
}
Example #2
0
/*
** - get a DC if one doesn't exist
** - create an HGLRC if one doesn't exist
*/
static qbool GLW_InitDriver( int colorbits )
{
	int		tpfd;
	int		depthbits, stencilbits;
	static PIXELFORMATDESCRIPTOR pfd;		// save between frames since 'tr' gets cleared

	ri.Printf( PRINT_DEVELOPER, "Initializing OpenGL driver\n" );

	//
	// get a DC for our window if we don't already have one allocated
	//
	if ( glw_state.hDC == NULL )
	{
		if ( ( glw_state.hDC = GetDC( g_wv.hWnd ) ) == NULL )
		{
			ri.Printf( PRINT_ALL, "...Get DC failed\n" );
			return qfalse;
		}
		ri.Printf( PRINT_DEVELOPER, "...Get DC succeeded\n" );
	}

	if ( colorbits == 0 )
	{
		colorbits = glw_state.desktopBPP;
	}

	//
	// implicitly assume Z-buffer depth == desktop color depth
	//
	if ( r_depthbits->integer == 0 ) {
		if ( colorbits > 16 ) {
			depthbits = 24;
		} else {
			depthbits = 16;
		}
	} else {
		depthbits = r_depthbits->integer;
	}

	//
	// do not allow stencil if Z-buffer depth likely won't contain it
	//
	stencilbits = r_stencilbits->integer;
	if ( depthbits < 24 )
	{
		stencilbits = 0;
	}

	//
	// make two attempts to set the PIXELFORMAT
	//

	//
	// first attempt: r_colorbits, depthbits, and r_stencilbits
	//
	if ( !glw_state.pixelFormatSet )
	{
		GLW_CreatePFD( &pfd, colorbits, depthbits, stencilbits, (qbool)r_stereo->integer );
		if ( ( tpfd = GLW_MakeContext( &pfd ) ) != TRY_PFD_SUCCESS )
		{
			if ( tpfd == TRY_PFD_FAIL_HARD )
			{
				ri.Printf( PRINT_WARNING, "...failed hard\n" );
				return qfalse;
			}

			//
			// punt if we've already tried the desktop bit depth and no stencil bits
			//
			if ( ( r_colorbits->integer == glw_state.desktopBPP ) && !stencilbits )
			{
				ReleaseDC( g_wv.hWnd, glw_state.hDC );
				glw_state.hDC = NULL;
				ri.Printf( PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n" );
				return qfalse;
			}

			//
			// second attempt: desktop's color bits and no stencil
			//
			if ( colorbits > glw_state.desktopBPP )
				colorbits = glw_state.desktopBPP;

			GLW_CreatePFD( &pfd, colorbits, depthbits, 0, (qbool)r_stereo->integer );
			if ( GLW_MakeContext( &pfd ) != TRY_PFD_SUCCESS )
			{
				if ( glw_state.hDC )
				{
					ReleaseDC( g_wv.hWnd, glw_state.hDC );
					glw_state.hDC = NULL;
				}
				ri.Printf( PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n" );
				return qfalse;
			}
		}

		// report if stereo is desired but unavailable
		//
		if ( r_stereo->integer && !( pfd.dwFlags & PFD_STEREO ) )
		{
			ri.Printf( PRINT_ALL, "...failed to select stereo pixel format\n" );
			glConfig.stereoEnabled = qfalse;
		}
	}

	// store PFD specifics
	//
	glConfig.colorBits = ( int ) pfd.cColorBits;
	glConfig.depthBits = ( int ) pfd.cDepthBits;
	glConfig.stencilBits = ( int ) pfd.cStencilBits;

	return qtrue;
}
Example #3
0
//	- get a DC if one doesn't exist
//	- create an HGLRC if one doesn't exist
static bool GLW_InitDriver( int colorbits ) {
	static PIXELFORMATDESCRIPTOR pfd;		// save between frames since 'tr' gets cleared

	common->Printf( "Initializing OpenGL driver\n" );

	//
	// get a DC for our window if we don't already have one allocated
	//
	if ( maindc == NULL ) {
		common->Printf( "...getting DC: " );

		if ( ( maindc = GetDC( GMainWindow ) ) == NULL ) {
			common->Printf( "failed\n" );
			return false;
		}
		common->Printf( "succeeded\n" );
	}

	if ( colorbits == 0 ) {
		colorbits = desktopBitsPixel;
	}

	//
	// implicitly assume Z-buffer depth == desktop color depth
	//
	int depthbits;
	if ( r_depthbits->integer == 0 ) {
		if ( colorbits > 16 ) {
			depthbits = 24;
		} else {
			depthbits = 16;
		}
	} else {
		depthbits = r_depthbits->integer;
	}

	//
	// do not allow stencil if Z-buffer depth likely won't contain it
	//
	int stencilbits = r_stencilbits->integer;
	if ( depthbits < 24 ) {
		stencilbits = 0;
	}

	//
	// make two attempts to set the PIXELFORMAT
	//

	//
	// first attempt: r_colorbits, depthbits, and r_stencilbits
	//
	if ( !pixelFormatSet ) {
		GLW_CreatePFD( &pfd, colorbits, depthbits, stencilbits, !!r_stereo->integer );
		int tpfd = GLW_MakeContext( &pfd );
		if ( tpfd != TRY_PFD_SUCCESS ) {
			if ( tpfd == TRY_PFD_FAIL_HARD ) {
				if ( maindc ) {
					ReleaseDC( GMainWindow, maindc );
					maindc = NULL;
				}

				common->Printf( S_COLOR_YELLOW "...failed hard\n" );
				return false;
			}

			//
			// punt if we've already tried the desktop bit depth and no stencil bits
			//
			if ( ( r_colorbits->integer == desktopBitsPixel ) && ( stencilbits == 0 ) ) {
				if ( maindc ) {
					ReleaseDC( GMainWindow, maindc );
					maindc = NULL;
				}

				common->Printf( "...failed to find an appropriate PIXELFORMAT\n" );

				return false;
			}

			//
			// second attempt: desktop's color bits and no stencil
			//
			if ( colorbits > desktopBitsPixel ) {
				colorbits = desktopBitsPixel;
			}
			GLW_CreatePFD( &pfd, colorbits, depthbits, 0, !!r_stereo->integer );
			if ( GLW_MakeContext( &pfd ) != TRY_PFD_SUCCESS ) {
				if ( maindc ) {
					ReleaseDC( GMainWindow, maindc );
					maindc = NULL;
				}

				common->Printf( "...failed to find an appropriate PIXELFORMAT\n" );

				return false;
			}
		}

		//
		//	Report if stereo is desired but unavailable.
		//
		if ( !( pfd.dwFlags & PFD_STEREO ) && ( r_stereo->integer != 0 ) ) {
			common->Printf( "...failed to select stereo pixel format\n" );
			glConfig.stereoEnabled = false;
		}
	}

	//
	//	Store PFD specifics.
	//
	glConfig.colorBits = ( int )pfd.cColorBits;
	glConfig.depthBits = ( int )pfd.cDepthBits;
	glConfig.stencilBits = ( int )pfd.cStencilBits;

	return true;
}