777 lines
18 KiB
C
777 lines
18 KiB
C
/*
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
/*
|
|
** GLW_IMP.C
|
|
**
|
|
** This file contains ALL Win32 specific stuff having to do with the
|
|
** OpenGL refresh. When a port is being made the following functions
|
|
** must be implemented by the port:
|
|
**
|
|
** GLimp_EndFrame
|
|
** GLimp_Init
|
|
** GLimp_Shutdown
|
|
**
|
|
*/
|
|
#include <assert.h>
|
|
#include <windows.h>
|
|
#include "launch_api.h"
|
|
#include "r_glimp.h"
|
|
#include "glw_win.h"
|
|
|
|
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE|WS_SYSMENU)
|
|
#define VID_NUM_MODES (int)( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
|
|
|
|
|
|
extern stdlib_api_t com; // engine toolbox
|
|
#define Host_Error com.error
|
|
int GLimp_InitGL (void);
|
|
|
|
glwstate_t glw_state;
|
|
|
|
/*
|
|
** VID_GetModeInfo
|
|
*/
|
|
typedef struct vidmode_s
|
|
{
|
|
int width, height;
|
|
bool wideScreen;
|
|
} vidmode_t;
|
|
|
|
vidmode_t vid_modes[] =
|
|
{
|
|
// { 320, 240, false },
|
|
// { 400, 300, false },
|
|
// { 512, 384, false },
|
|
{ 640, 480, false },
|
|
{ 800, 600, false },
|
|
{ 960, 720, false },
|
|
{ 1024, 768, false },
|
|
{ 1152, 864, false },
|
|
{ 1280, 800, false },
|
|
{ 1280, 960, false },
|
|
{ 1280, 1024, false },
|
|
{ 1600, 1200, false },
|
|
{ 2048, 1536, false },
|
|
|
|
{ 856, 480, true },
|
|
{ 1024, 576, true },
|
|
{ 1440, 900, true },
|
|
{ 1680, 1050, true },
|
|
{ 1920, 1200, true },
|
|
{ 2560, 1600, true },
|
|
|
|
{ 2400, 600, false },
|
|
{ 3072, 768, false },
|
|
{ 3840, 720, false },
|
|
{ 3840, 1024, false },
|
|
{ 4800, 1200, false },
|
|
{ 6144, 1536, false }
|
|
};
|
|
|
|
bool VID_GetModeInfo( int *width, int *height, bool *wideScreen, int mode )
|
|
{
|
|
if( mode < -1 || mode >= VID_NUM_MODES )
|
|
return false;
|
|
|
|
if( mode == -1 )
|
|
{
|
|
*width = 640;
|
|
*height = 480;
|
|
*wideScreen = false;
|
|
}
|
|
else
|
|
{
|
|
*width = vid_modes[mode].width;
|
|
*height = vid_modes[mode].height;
|
|
*wideScreen = vid_modes[mode].wideScreen;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool VerifyDriver( void )
|
|
{
|
|
char buffer[1024];
|
|
|
|
com.strncpy( buffer, pglGetString( GL_RENDERER ), sizeof(buffer) );
|
|
com.strlwr( buffer, buffer );
|
|
if ( strcmp( buffer, "gdi generic" ) == 0 )
|
|
if ( !glw_state.mcd_accelerated )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
** VID_CreateWindow
|
|
*/
|
|
#define WINDOW_CLASS_NAME "Xash3D""WndClass"
|
|
|
|
bool VID_CreateWindow( int width, int height, bool fullscreen )
|
|
{
|
|
WNDCLASS wc;
|
|
RECT r;
|
|
cvar_t *vid_xpos, *vid_ypos;
|
|
int stylebits;
|
|
int x, y, w, h;
|
|
int exstyle;
|
|
|
|
/* Register the frame class */
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = (WNDPROC)glw_state.wndproc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = glw_state.hInstance;
|
|
wc.hIcon = LoadIcon( glw_state.hInstance, MAKEINTRESOURCE( 101 ) );
|
|
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
|
|
wc.lpszMenuName = 0;
|
|
wc.lpszClassName = WINDOW_CLASS_NAME;
|
|
|
|
if (!RegisterClass (&wc) )
|
|
Host_Error ("Couldn't register window class\n");
|
|
|
|
if (fullscreen)
|
|
{
|
|
exstyle = WS_EX_TOPMOST;
|
|
stylebits = (WS_POPUP|WS_VISIBLE);
|
|
}
|
|
else
|
|
{
|
|
exstyle = 0;
|
|
stylebits = WINDOW_STYLE;
|
|
}
|
|
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = width;
|
|
r.bottom = height;
|
|
|
|
AdjustWindowRect (&r, stylebits, FALSE);
|
|
|
|
w = r.right - r.left;
|
|
h = r.bottom - r.top;
|
|
|
|
if (fullscreen)
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
}
|
|
else
|
|
{
|
|
vid_xpos = Cvar_Get( "r_xpos", "3", CVAR_ARCHIVE, "window position by horizontal" );
|
|
vid_ypos = Cvar_Get( "r_ypos", "22", CVAR_ARCHIVE, "window position by vertical" );
|
|
x = vid_xpos->integer;
|
|
y = vid_ypos->integer;
|
|
}
|
|
|
|
glw_state.hWnd = CreateWindowEx (
|
|
exstyle,
|
|
WINDOW_CLASS_NAME,
|
|
"Xash3D",
|
|
stylebits,
|
|
x, y, w, h,
|
|
NULL,
|
|
NULL,
|
|
glw_state.hInstance,
|
|
NULL);
|
|
|
|
if (!glw_state.hWnd)
|
|
Host_Error ("Couldn't create window\n");
|
|
|
|
ShowWindow( glw_state.hWnd, SW_SHOW );
|
|
UpdateWindow( glw_state.hWnd );
|
|
|
|
// init all the gl stuff for the window
|
|
if (!GLimp_InitGL ())
|
|
{
|
|
MsgDev ( D_ERROR, "VID_CreateWindow() - GLimp_InitGL failed\n");
|
|
return false;
|
|
}
|
|
|
|
SetForegroundWindow( glw_state.hWnd );
|
|
SetFocus( glw_state.hWnd );
|
|
|
|
// let the sound and input subsystems know about the new window
|
|
Cvar_FullSet( "width", va( "%i", width ), CVAR_READ_ONLY );
|
|
Cvar_FullSet( "height", va( "%i", height ), CVAR_READ_ONLY );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
** GLimp_SetMode
|
|
*/
|
|
int GLimp_SetMode( int mode, bool fullscreen )
|
|
{
|
|
int width, height;
|
|
bool wideScreen;
|
|
const char *win_fs[] = { "W", "FS" };
|
|
|
|
Msg ( "Initializing OpenGL display\n");
|
|
|
|
Msg ( "...setting mode %d:", mode );
|
|
|
|
if ( !VID_GetModeInfo( &width, &height, &wideScreen, mode ) )
|
|
{
|
|
Msg ( " invalid mode\n" );
|
|
return rserr_invalid_mode;
|
|
}
|
|
|
|
Msg ( " %d %d %s\n", width, height, win_fs[fullscreen] );
|
|
|
|
// destroy the existing window
|
|
if (glw_state.hWnd)
|
|
{
|
|
GLimp_Shutdown ();
|
|
}
|
|
|
|
// do a CDS if needed
|
|
if ( fullscreen )
|
|
{
|
|
DEVMODE dm;
|
|
|
|
Msg ( "...attempting fullscreen\n" );
|
|
|
|
memset( &dm, 0, sizeof( dm ) );
|
|
|
|
dm.dmSize = sizeof( dm );
|
|
|
|
dm.dmPelsWidth = width;
|
|
dm.dmPelsHeight = height;
|
|
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
|
|
if ( r_colorbits->integer != 0 )
|
|
{
|
|
dm.dmBitsPerPel = r_colorbits->integer;
|
|
dm.dmFields |= DM_BITSPERPEL;
|
|
Msg ( "...using r_bitdepth of %d\n", dm.dmBitsPerPel );
|
|
}
|
|
else
|
|
{
|
|
HDC hdc = GetDC( NULL );
|
|
int bitspixel = GetDeviceCaps( hdc, BITSPIXEL );
|
|
|
|
Msg ( "...using desktop display depth of %d\n", bitspixel );
|
|
|
|
ReleaseDC( 0, hdc );
|
|
}
|
|
|
|
if ( vid_displayfrequency->integer > 0 )
|
|
{
|
|
dm.dmFields |= DM_DISPLAYFREQUENCY;
|
|
dm.dmDisplayFrequency = vid_displayfrequency->integer;
|
|
Msg ( "...using display frequency %i\n", dm.dmDisplayFrequency );
|
|
}
|
|
|
|
Msg ( "...calling CDS: " );
|
|
if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL )
|
|
{
|
|
glState.width = width;
|
|
glState.height = height;
|
|
glState.fullScreen = true;
|
|
|
|
// tell engine about screen sizes
|
|
Cvar_FullSet( "width", va( "%i", width ), CVAR_READ_ONLY );
|
|
Cvar_FullSet( "height", va( "%i", height ), CVAR_READ_ONLY );
|
|
|
|
Msg ( "ok\n" );
|
|
|
|
if ( !VID_CreateWindow (width, height, true) )
|
|
return rserr_invalid_mode;
|
|
|
|
return rserr_ok;
|
|
}
|
|
else
|
|
{
|
|
glState.width = width;
|
|
glState.height = height;
|
|
|
|
// tell engine about screen sizes
|
|
Cvar_FullSet( "width", va( "%i", width ), CVAR_READ_ONLY );
|
|
Cvar_FullSet( "height", va( "%i", height ), CVAR_READ_ONLY );
|
|
|
|
Msg ( "failed\n" );
|
|
|
|
Msg ( "...calling CDS assuming dual monitors:" );
|
|
|
|
dm.dmPelsWidth = width * 2;
|
|
dm.dmPelsHeight = height;
|
|
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
|
|
if ( r_colorbits->integer != 0 )
|
|
{
|
|
dm.dmBitsPerPel = r_colorbits->integer;
|
|
dm.dmFields |= DM_BITSPERPEL;
|
|
Msg ( "...using r_bitdepth of %d\n", dm.dmBitsPerPel );
|
|
}
|
|
|
|
if ( vid_displayfrequency->integer > 0 )
|
|
{
|
|
dm.dmFields |= DM_DISPLAYFREQUENCY;
|
|
dm.dmDisplayFrequency = vid_displayfrequency->integer;
|
|
Msg ( "...using display frequency %i\n", dm.dmDisplayFrequency );
|
|
}
|
|
|
|
/*
|
|
** our first CDS failed, so maybe we're running on some weird dual monitor
|
|
** system
|
|
*/
|
|
if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
|
|
{
|
|
Msg ( " failed\n" );
|
|
|
|
Msg ( "...setting windowed mode\n" );
|
|
|
|
ChangeDisplaySettings( 0, 0 );
|
|
|
|
glState.width = width;
|
|
glState.height = height;
|
|
glState.fullScreen = false;
|
|
|
|
// tell engine about screen sizes
|
|
Cvar_FullSet( "width", va( "%i", width ), CVAR_READ_ONLY );
|
|
Cvar_FullSet( "height", va( "%i", height ), CVAR_READ_ONLY );
|
|
|
|
if ( !VID_CreateWindow (width, height, false) )
|
|
return rserr_invalid_mode;
|
|
return rserr_invalid_fullscreen;
|
|
}
|
|
else
|
|
{
|
|
Msg ( " ok\n" );
|
|
if ( !VID_CreateWindow (width, height, true) )
|
|
return rserr_invalid_mode;
|
|
|
|
glState.fullScreen = true;
|
|
return rserr_ok;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Msg ( "...setting windowed mode\n" );
|
|
|
|
ChangeDisplaySettings( 0, 0 );
|
|
|
|
glState.width = width;
|
|
glState.height = height;
|
|
glState.fullScreen = false;
|
|
|
|
// tell engine about screen sizes
|
|
Cvar_FullSet( "width", va( "%i", width ), CVAR_READ_ONLY );
|
|
Cvar_FullSet( "height", va( "%i", height ), CVAR_READ_ONLY );
|
|
|
|
if ( !VID_CreateWindow (width, height, false) )
|
|
return rserr_invalid_mode;
|
|
}
|
|
|
|
return rserr_ok;
|
|
}
|
|
|
|
/*
|
|
** GLimp_Shutdown
|
|
**
|
|
** This routine does all OS specific shutdown procedures for the OpenGL
|
|
** subsystem. Under OpenGL this means NULLing out the current DC and
|
|
** HGLRC, deleting the rendering context, and releasing the DC acquired
|
|
** for the window. The state structure is also nulled out.
|
|
**
|
|
*/
|
|
void GLimp_Shutdown( void )
|
|
{
|
|
if ( pwglMakeCurrent && !pwglMakeCurrent( NULL, NULL ) )
|
|
Msg ( "ref_gl::R_Shutdown() - wglMakeCurrent failed\n");
|
|
if ( glw_state.hGLRC )
|
|
{
|
|
if ( pwglDeleteContext && !pwglDeleteContext( glw_state.hGLRC ) )
|
|
Msg ( "ref_gl::R_Shutdown() - wglDeleteContext failed\n");
|
|
glw_state.hGLRC = NULL;
|
|
}
|
|
if (glw_state.hDC)
|
|
{
|
|
if ( !ReleaseDC( glw_state.hWnd, glw_state.hDC ) )
|
|
Msg ( "ref_gl::R_Shutdown() - ReleaseDC failed\n" );
|
|
glw_state.hDC = NULL;
|
|
}
|
|
if (glw_state.hWnd)
|
|
{
|
|
ShowWindow ( glw_state.hWnd, SW_HIDE );
|
|
DestroyWindow ( glw_state.hWnd );
|
|
glw_state.hWnd = NULL;
|
|
}
|
|
|
|
UnregisterClass (WINDOW_CLASS_NAME, glw_state.hInstance);
|
|
|
|
if( glState.fullScreen ) {
|
|
ChangeDisplaySettings( 0, 0 );
|
|
glState.fullScreen = false;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** GLimp_Init
|
|
**
|
|
** This routine is responsible for initializing the OS specific portions
|
|
** of OpenGL. Under Win32 this means dealing with the pixelformats and
|
|
** doing the wgl interface stuff.
|
|
*/
|
|
int GLimp_Init( void *hinstance, void *wndproc )
|
|
{
|
|
#define OSR2_BUILD_NUMBER 1111
|
|
|
|
OSVERSIONINFO vinfo;
|
|
|
|
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
|
|
|
glw_state.allowdisplaydepthchange = false;
|
|
|
|
if ( GetVersionEx( &vinfo) )
|
|
{
|
|
if ( vinfo.dwMajorVersion > 4 )
|
|
{
|
|
glw_state.allowdisplaydepthchange = true;
|
|
}
|
|
else if ( vinfo.dwMajorVersion == 4 )
|
|
{
|
|
if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
glw_state.allowdisplaydepthchange = true;
|
|
}
|
|
else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
|
{
|
|
if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
|
|
{
|
|
glw_state.allowdisplaydepthchange = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Msg ( "GLimp_Init() - GetVersionEx failed\n" );
|
|
return false;
|
|
}
|
|
|
|
glw_state.hInstance = ( HINSTANCE ) hinstance;
|
|
glw_state.wndproc = wndproc;
|
|
|
|
return true;
|
|
}
|
|
|
|
int GLimp_InitGL (void)
|
|
{
|
|
PIXELFORMATDESCRIPTOR pfd =
|
|
{
|
|
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
|
|
1, // version number
|
|
PFD_DRAW_TO_WINDOW | // support window
|
|
PFD_SUPPORT_OPENGL | // support OpenGL
|
|
PFD_DOUBLEBUFFER, // double buffered
|
|
PFD_TYPE_RGBA, // RGBA type
|
|
32, // 32-bit color depth
|
|
0, 0, 0, 0, 0, 0, // color bits ignored
|
|
0, // no alpha buffer
|
|
0, // shift bit ignored
|
|
0, // no accumulation buffer
|
|
0, 0, 0, 0, // accum bits ignored
|
|
24, // 32-bit z-buffer
|
|
0, // no stencil buffer
|
|
0, // no auxiliary buffer
|
|
PFD_MAIN_PLANE, // main layer
|
|
0, // reserved
|
|
0, 0, 0 // layer masks ignored
|
|
};
|
|
int pixelformat;
|
|
cvar_t *stereo;
|
|
cvar_t *stencil;
|
|
|
|
stereo = Cvar_Get( "cl_stereo", "0", 0, "enable stereo rendering" );
|
|
|
|
stencil = Cvar_Get( "r_stencilbits", "0", 0, "pixelformat stencil bits (0 - auto)" );
|
|
pfd.cStencilBits = max( 0, stencil->integer );
|
|
|
|
if ( pfd.cStencilBits != 0 )
|
|
glState.stencilEnabled = true;
|
|
else
|
|
glState.stencilEnabled = false;
|
|
|
|
/*
|
|
** set PFD_STEREO if necessary
|
|
*/
|
|
if ( stereo->integer != 0 )
|
|
{
|
|
Msg ( "...attempting to use stereo\n" );
|
|
pfd.dwFlags |= PFD_STEREO;
|
|
glState.stereoEnabled = true;
|
|
}
|
|
else
|
|
{
|
|
glState.stereoEnabled = false;
|
|
}
|
|
|
|
/*
|
|
** figure out if we're running on a minidriver or not
|
|
*/
|
|
if ( strstr( gl_driver->string, "opengl32" ) != 0 )
|
|
glw_state.minidriver = false;
|
|
else
|
|
glw_state.minidriver = true;
|
|
|
|
/*
|
|
** Get a DC for the specified window
|
|
*/
|
|
if ( glw_state.hDC != NULL )
|
|
Msg ( "GLimp_Init() - non-NULL DC exists\n" );
|
|
|
|
if ( ( glw_state.hDC = GetDC( glw_state.hWnd ) ) == NULL )
|
|
{
|
|
Msg ( "GLimp_Init() - GetDC failed\n" );
|
|
return false;
|
|
}
|
|
|
|
if ( glw_state.minidriver )
|
|
{
|
|
if ( (pixelformat = pwglChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
|
|
{
|
|
Msg ( "GLimp_Init() - pwglChoosePixelFormat failed\n");
|
|
return false;
|
|
}
|
|
if ( pwglSetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
|
|
{
|
|
Msg ( "GLimp_Init() - pwglSetPixelFormat failed\n");
|
|
return false;
|
|
}
|
|
pwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
|
|
}
|
|
else
|
|
{
|
|
if ( ( pixelformat = ChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
|
|
{
|
|
Msg ( "GLimp_Init() - ChoosePixelFormat failed\n");
|
|
return false;
|
|
}
|
|
if ( SetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
|
|
{
|
|
Msg ( "GLimp_Init() - SetPixelFormat failed\n");
|
|
return false;
|
|
}
|
|
DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
|
|
|
|
if ( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) )
|
|
{
|
|
extern cvar_t *r_allow_software;
|
|
|
|
if ( r_allow_software->integer )
|
|
glw_state.mcd_accelerated = true;
|
|
else
|
|
glw_state.mcd_accelerated = false;
|
|
}
|
|
else
|
|
{
|
|
glw_state.mcd_accelerated = true;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** report if stereo is desired but unavailable
|
|
*/
|
|
if ( !( pfd.dwFlags & PFD_STEREO ) && ( stereo->integer != 0 ) )
|
|
{
|
|
Msg ( "...failed to select stereo pixel format\n" );
|
|
Cvar_SetValue( "cl_stereo", 0 );
|
|
glState.stereoEnabled = false;
|
|
}
|
|
|
|
/*
|
|
** startup the OpenGL subsystem by creating a context and making
|
|
** it current
|
|
*/
|
|
if ( ( glw_state.hGLRC = pwglCreateContext( glw_state.hDC ) ) == 0 )
|
|
{
|
|
Msg ( "GLimp_Init() - pwglCreateContext failed\n");
|
|
goto fail;
|
|
}
|
|
|
|
if ( !pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) )
|
|
{
|
|
Msg ( "GLimp_Init() - pwglMakeCurrent failed\n");
|
|
goto fail;
|
|
}
|
|
|
|
if ( !VerifyDriver() )
|
|
{
|
|
Msg ( "GLimp_Init() - no hardware acceleration detected\n" );
|
|
goto fail;
|
|
}
|
|
|
|
/*
|
|
** print out PFD specifics
|
|
*/
|
|
Msg ( "GL PFD: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", ( int ) pfd.cColorBits, ( int ) pfd.cDepthBits, ( int )pfd.cStencilBits );
|
|
|
|
return true;
|
|
|
|
fail:
|
|
if ( glw_state.hGLRC )
|
|
{
|
|
pwglDeleteContext( glw_state.hGLRC );
|
|
glw_state.hGLRC = NULL;
|
|
}
|
|
|
|
if ( glw_state.hDC )
|
|
{
|
|
ReleaseDC( glw_state.hWnd, glw_state.hDC );
|
|
glw_state.hDC = NULL;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
** GLimp_UpdateGammaRamp
|
|
*/
|
|
bool GLimp_GetGammaRamp( size_t stride, unsigned short *ramp )
|
|
{
|
|
if( pwglGetDeviceGammaRamp3DFX ) {
|
|
if( pwglGetDeviceGammaRamp3DFX( glw_state.hDC, ramp ) )
|
|
return true;
|
|
}
|
|
|
|
if( GetDeviceGammaRamp ( glw_state.hDC, ramp ) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
** GLimp_SetGammaRamp
|
|
*/
|
|
void GLimp_SetGammaRamp( size_t stride, unsigned short *ramp )
|
|
{
|
|
if( pwglGetDeviceGammaRamp3DFX )
|
|
pwglSetDeviceGammaRamp3DFX( glw_state.hDC, ramp );
|
|
else
|
|
SetDeviceGammaRamp( glw_state.hDC, ramp );
|
|
}
|
|
/*
|
|
=================
|
|
RB_CheckForErrors
|
|
=================
|
|
*/
|
|
|
|
void R_CheckForErrors( const char *filename, const int fileline )
|
|
{
|
|
int err;
|
|
char *str;
|
|
|
|
if((err = pglGetError()) == GL_NO_ERROR )
|
|
return;
|
|
|
|
switch( err )
|
|
{
|
|
case GL_STACK_OVERFLOW:
|
|
str = "GL_STACK_OVERFLOW";
|
|
break;
|
|
case GL_STACK_UNDERFLOW:
|
|
str = "GL_STACK_UNDERFLOW";
|
|
break;
|
|
case GL_INVALID_ENUM:
|
|
str = "GL_INVALID_ENUM";
|
|
break;
|
|
case GL_INVALID_VALUE:
|
|
str = "GL_INVALID_VALUE";
|
|
break;
|
|
case GL_INVALID_OPERATION:
|
|
str = "GL_INVALID_OPERATION";
|
|
break;
|
|
case GL_OUT_OF_MEMORY:
|
|
str = "GL_OUT_OF_MEMORY";
|
|
break;
|
|
default:
|
|
str = "UNKNOWN ERROR";
|
|
break;
|
|
}
|
|
Host_Error( "R_CheckForErrors: %s (called at %s:%i)\n", str, filename, fileline );
|
|
}
|
|
|
|
/*
|
|
** GLimp_BeginFrame
|
|
*/
|
|
void GLimp_BeginFrame( void )
|
|
{
|
|
if ( r_colorbits->modified )
|
|
{
|
|
if ( r_colorbits->integer != 0 && !glw_state.allowdisplaydepthchange )
|
|
{
|
|
Cvar_SetValue( "r_colorbits", 0 );
|
|
Msg ( "r_colorbits requires Win95 OSR2.x or WinNT 4.x\n" );
|
|
}
|
|
r_colorbits->modified = false;
|
|
}
|
|
|
|
if ( glState.cameraSeparation < 0 && glState.stereoEnabled )
|
|
{
|
|
pglDrawBuffer( GL_BACK_LEFT );
|
|
}
|
|
else if ( glState.cameraSeparation > 0 && glState.stereoEnabled )
|
|
{
|
|
pglDrawBuffer( GL_BACK_RIGHT );
|
|
}
|
|
else
|
|
{
|
|
pglDrawBuffer( GL_BACK );
|
|
}
|
|
}
|
|
|
|
/*
|
|
** GLimp_EndFrame
|
|
**
|
|
** Responsible for doing a swapbuffers and possibly for other stuff
|
|
** as yet to be determined. Probably better not to make this a GLimp
|
|
** function and instead do a call to GLimp_SwapBuffers.
|
|
*/
|
|
void GLimp_EndFrame (void)
|
|
{
|
|
R_CheckForErrors( __FILE__, __LINE__ );
|
|
|
|
if ( com.stricmp( gl_drawbuffer->string, "GL_BACK" ) == 0 )
|
|
{
|
|
if ( !pwglSwapBuffers( glw_state.hDC ) )
|
|
Host_Error( "GLimp_EndFrame() - SwapBuffers() failed!\n" );
|
|
}
|
|
}
|
|
|
|
/*
|
|
** GLimp_AppActivate
|
|
*/
|
|
void GLimp_AppActivate( bool active )
|
|
{
|
|
if ( active )
|
|
{
|
|
SetForegroundWindow( glw_state.hWnd );
|
|
ShowWindow( glw_state.hWnd, SW_RESTORE );
|
|
}
|
|
else
|
|
{
|
|
if ( vid_fullscreen->integer )
|
|
ShowWindow( glw_state.hWnd, SW_MINIMIZE );
|
|
}
|
|
}
|