769 lines
26 KiB
C
769 lines
26 KiB
C
//=======================================================================
|
|
// Copyright XashXT Group 2007 ©
|
|
// r_opengl.c - openg32.dll handler
|
|
//=======================================================================
|
|
|
|
#include "gl_local.h"
|
|
|
|
glwstate_t glw_state;
|
|
|
|
#define num_vidmodes ((int)(sizeof(vidmode) / sizeof(vidmode[0])) - 1)
|
|
|
|
typedef struct vidmode_s
|
|
{
|
|
const char *desc;
|
|
int width;
|
|
int height;
|
|
float pixelheight;
|
|
} vidmode_t;
|
|
|
|
vidmode_t vidmode[] =
|
|
{
|
|
{"Mode 0: 4x3", 640, 480, 1 },
|
|
{"Mode 1: 4x3", 800, 600, 1 },
|
|
{"Mode 2: 4x3", 1024, 768, 1 },
|
|
{"Mode 3: 4x3", 1152, 864, 1 },
|
|
{"Mode 4: 4x3", 1280, 960, 1 },
|
|
{"Mode 5: 4x3", 1400, 1050, 1 },
|
|
{"Mode 6: 4x3", 1600, 1200, 1 },
|
|
{"Mode 7: 4x3", 1920, 1440, 1 },
|
|
{"Mode 8: 4x3", 2048, 1536, 1 },
|
|
{"Mode 9: 14x9", 840, 540, 1 },
|
|
{"Mode 10: 14x9", 1680, 1080, 1 },
|
|
{"Mode 11: 16x9", 640, 360, 1 },
|
|
{"Mode 12: 16x9", 683, 384, 1 },
|
|
{"Mode 13: 16x9", 960, 540, 1 },
|
|
{"Mode 14: 16x9", 1280, 720, 1 },
|
|
{"Mode 15: 16x9", 1366, 768, 1 },
|
|
{"Mode 16: 16x9", 1920, 1080, 1 },
|
|
{"Mode 17: 16x9", 2560, 1440, 1 },
|
|
{"Mode 18: NTSC", 360, 240, 1.125 },
|
|
{"Mode 19: NTSC", 720, 480, 1.125 },
|
|
{"Mode 20: PAL ", 360, 283, 0.9545 },
|
|
{"Mode 21: PAL ", 720, 566, 0.9545 },
|
|
{NULL, 0, 0, 0 },
|
|
};
|
|
|
|
static dllfunc_t wgl_funcs[] =
|
|
{
|
|
{"wglChoosePixelFormat", (void **) &pwglChoosePixelFormat},
|
|
{"wglDescribePixelFormat", (void **) &pwglDescribePixelFormat},
|
|
{"wglGetPixelFormat", (void **) &pwglGetPixelFormat},
|
|
{"wglSetPixelFormat", (void **) &pwglSetPixelFormat},
|
|
{"wglSwapBuffers", (void **) &pwglSwapBuffers},
|
|
{"wglCreateContext", (void **) &pwglCreateContext},
|
|
{"wglDeleteContext", (void **) &pwglDeleteContext},
|
|
{"wglGetProcAddress", (void **) &pwglGetProcAddress},
|
|
{"wglMakeCurrent", (void **) &pwglMakeCurrent},
|
|
{"wglGetCurrentContext", (void **) &pwglGetCurrentContext},
|
|
{"wglGetCurrentDC", (void **) &pwglGetCurrentDC},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t wglswapintervalfuncs[] =
|
|
{
|
|
{"wglSwapIntervalEXT", (void **) &pwglSwapIntervalEXT},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t opengl_110funcs[] =
|
|
{
|
|
{"glClearColor", (void **) &pglClearColor},
|
|
{"glClear", (void **) &pglClear},
|
|
{"glAlphaFunc", (void **) &pglAlphaFunc},
|
|
{"glBlendFunc", (void **) &pglBlendFunc},
|
|
{"glCullFace", (void **) &pglCullFace},
|
|
{"glDrawBuffer", (void **) &pglDrawBuffer},
|
|
{"glReadBuffer", (void **) &pglReadBuffer},
|
|
{"glEnable", (void **) &pglEnable},
|
|
{"glDisable", (void **) &pglDisable},
|
|
{"glEnableClientState", (void **) &pglEnableClientState},
|
|
{"glDisableClientState", (void **) &pglDisableClientState},
|
|
{"glGetBooleanv", (void **) &pglGetBooleanv},
|
|
{"glGetDoublev", (void **) &pglGetDoublev},
|
|
{"glGetFloatv", (void **) &pglGetFloatv},
|
|
{"glGetIntegerv", (void **) &pglGetIntegerv},
|
|
{"glGetError", (void **) &pglGetError},
|
|
{"glGetString", (void **) &pglGetString},
|
|
{"glFinish", (void **) &pglFinish},
|
|
{"glFlush", (void **) &pglFlush},
|
|
{"glClearDepth", (void **) &pglClearDepth},
|
|
{"glDepthFunc", (void **) &pglDepthFunc},
|
|
{"glDepthMask", (void **) &pglDepthMask},
|
|
{"glDepthRange", (void **) &pglDepthRange},
|
|
{"glDrawElements", (void **) &pglDrawElements},
|
|
{"glColorMask", (void **) &pglColorMask},
|
|
{"glVertexPointer", (void **) &pglVertexPointer},
|
|
{"glNormalPointer", (void **) &pglNormalPointer},
|
|
{"glColorPointer", (void **) &pglColorPointer},
|
|
{"glTexCoordPointer", (void **) &pglTexCoordPointer},
|
|
{"glArrayElement", (void **) &pglArrayElement},
|
|
{"glColor3f", (void **) &pglColor3f},
|
|
{"glColor3fv", (void **) &pglColor3fv},
|
|
{"glColor4f", (void **) &pglColor4f},
|
|
{"glColor4fv", (void **) &pglColor4fv},
|
|
{"glColor4ubv", (void **) &pglColor4ubv},
|
|
{"glTexCoord1f", (void **) &pglTexCoord1f},
|
|
{"glTexCoord2f", (void **) &pglTexCoord2f},
|
|
{"glTexCoord3f", (void **) &pglTexCoord3f},
|
|
{"glTexCoord4f", (void **) &pglTexCoord4f},
|
|
{"glTexGenf", (void **) &pglTexGenf},
|
|
{"glTexGenfv", (void **) &pglTexGenfv},
|
|
{"glVertex2f", (void **) &pglVertex2f},
|
|
{"glVertex3f", (void **) &pglVertex3f},
|
|
{"glVertex3fv", (void **) &pglVertex3fv},
|
|
{"glBegin", (void **) &pglBegin},
|
|
{"glEnd", (void **) &pglEnd},
|
|
{"glLineWidth", (void**) &pglLineWidth},
|
|
{"glPointSize", (void**) &pglPointSize},
|
|
{"glMatrixMode", (void **) &pglMatrixMode},
|
|
{"glOrtho", (void **) &pglOrtho},
|
|
{"glFrustum", (void **) &pglFrustum},
|
|
{"glViewport", (void **) &pglViewport},
|
|
{"glPushMatrix", (void **) &pglPushMatrix},
|
|
{"glPopMatrix", (void **) &pglPopMatrix},
|
|
{"glLoadIdentity", (void **) &pglLoadIdentity},
|
|
{"glLoadMatrixd", (void **) &pglLoadMatrixd},
|
|
{"glLoadMatrixf", (void **) &pglLoadMatrixf},
|
|
{"glMultMatrixd", (void **) &pglMultMatrixd},
|
|
{"glMultMatrixf", (void **) &pglMultMatrixf},
|
|
{"glRotated", (void **) &pglRotated},
|
|
{"glRotatef", (void **) &pglRotatef},
|
|
{"glScaled", (void **) &pglScaled},
|
|
{"glScalef", (void **) &pglScalef},
|
|
{"glTranslated", (void **) &pglTranslated},
|
|
{"glTranslatef", (void **) &pglTranslatef},
|
|
{"glReadPixels", (void **) &pglReadPixels},
|
|
{"glStencilFunc", (void **) &pglStencilFunc},
|
|
{"glStencilMask", (void **) &pglStencilMask},
|
|
{"glStencilOp", (void **) &pglStencilOp},
|
|
{"glClearStencil", (void **) &pglClearStencil},
|
|
{"glTexEnvf", (void **) &pglTexEnvf},
|
|
{"glTexEnvfv", (void **) &pglTexEnvfv},
|
|
{"glTexEnvi", (void **) &pglTexEnvi},
|
|
{"glTexParameterf", (void **) &pglTexParameterf},
|
|
{"glTexParameterfv", (void **) &pglTexParameterfv},
|
|
{"glTexParameteri", (void **) &pglTexParameteri},
|
|
{"glHint", (void **) &pglHint},
|
|
{"glPixelStoref", (void **) &pglPixelStoref},
|
|
{"glPixelStorei", (void **) &pglPixelStorei},
|
|
{"glGenTextures", (void **) &pglGenTextures},
|
|
{"glDeleteTextures", (void **) &pglDeleteTextures},
|
|
{"glBindTexture", (void **) &pglBindTexture},
|
|
{"glTexImage1D", (void **) &pglTexImage1D},
|
|
{"glTexImage2D", (void **) &pglTexImage2D},
|
|
{"glTexSubImage1D", (void **) &pglTexSubImage1D},
|
|
{"glTexSubImage2D", (void **) &pglTexSubImage2D},
|
|
{"glCopyTexImage1D", (void **) &pglCopyTexImage1D},
|
|
{"glCopyTexImage2D", (void **) &pglCopyTexImage2D},
|
|
{"glCopyTexSubImage1D", (void **) &pglCopyTexSubImage1D},
|
|
{"glCopyTexSubImage2D", (void **) &pglCopyTexSubImage2D},
|
|
{"glScissor", (void **) &pglScissor},
|
|
{"glPolygonOffset", (void **) &pglPolygonOffset},
|
|
{"glPolygonMode", (void **) &pglPolygonMode},
|
|
{"glPolygonStipple", (void **) &pglPolygonStipple},
|
|
{"glClipPlane", (void **) &pglClipPlane},
|
|
{"glGetClipPlane", (void **) &pglGetClipPlane},
|
|
{"glShadeModel", (void **) &pglShadeModel},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t pointparametersfunc[] =
|
|
{
|
|
{"glPointParameterfEXT", (void **) &pglPointParameterfEXT},
|
|
{"glPointParameterfvEXT", (void **) &pglPointParameterfvEXT},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t drawrangeelementsfuncs[] =
|
|
{
|
|
{"glDrawRangeElements", (void **) &pglDrawRangeElements},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t drawrangeelementsextfuncs[] =
|
|
{
|
|
{"glDrawRangeElementsEXT", (void **) &pglDrawRangeElementsEXT},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t multitexturefuncs[] =
|
|
{
|
|
{"glMultiTexCoord1fARB", (void **) &pglMultiTexCoord1f},
|
|
{"glMultiTexCoord2fARB", (void **) &pglMultiTexCoord2f},
|
|
{"glMultiTexCoord3fARB", (void **) &pglMultiTexCoord3f},
|
|
{"glMultiTexCoord4fARB", (void **) &pglMultiTexCoord4f},
|
|
{"glActiveTextureARB", (void **) &pglActiveTextureARB},
|
|
{"glClientActiveTextureARB", (void **) &pglClientActiveTexture},
|
|
{"glClientActiveTextureARB", (void **) &pglClientActiveTextureARB},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t compiledvertexarrayfuncs[] =
|
|
{
|
|
{"glLockArraysEXT", (void **) &pglLockArraysEXT},
|
|
{"glUnlockArraysEXT", (void **) &pglUnlockArraysEXT},
|
|
{"glDrawArrays", (void **) &pglDrawArrays},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t texture3dextfuncs[] =
|
|
{
|
|
{"glTexImage3DEXT", (void **) &pglTexImage3D},
|
|
{"glTexSubImage3DEXT", (void **) &pglTexSubImage3D},
|
|
{"glCopyTexSubImage3DEXT", (void **) &pglCopyTexSubImage3D},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t atiseparatestencilfuncs[] =
|
|
{
|
|
{"glStencilOpSeparateATI", (void **) &pglStencilOpSeparate},
|
|
{"glStencilFuncSeparateATI", (void **) &pglStencilFuncSeparate},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t gl2separatestencilfuncs[] =
|
|
{
|
|
{"glStencilOpSeparate", (void **) &pglStencilOpSeparate},
|
|
{"glStencilFuncSeparate", (void **) &pglStencilFuncSeparate},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t stenciltwosidefuncs[] =
|
|
{
|
|
{"glActiveStencilFaceEXT", (void **) &pglActiveStencilFaceEXT},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t blendequationfuncs[] =
|
|
{
|
|
{"glBlendEquationEXT", (void **) &pglBlendEquationEXT},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t shaderobjectsfuncs[] =
|
|
{
|
|
{"glDeleteObjectARB", (void **) &pglDeleteObjectARB},
|
|
{"glGetHandleARB", (void **) &pglGetHandleARB},
|
|
{"glDetachObjectARB", (void **) &pglDetachObjectARB},
|
|
{"glCreateShaderObjectARB", (void **) &pglCreateShaderObjectARB},
|
|
{"glShaderSourceARB", (void **) &pglShaderSourceARB},
|
|
{"glCompileShaderARB", (void **) &pglCompileShaderARB},
|
|
{"glCreateProgramObjectARB", (void **) &pglCreateProgramObjectARB},
|
|
{"glAttachObjectARB", (void **) &pglAttachObjectARB},
|
|
{"glLinkProgramARB", (void **) &pglLinkProgramARB},
|
|
{"glUseProgramObjectARB", (void **) &pglUseProgramObjectARB},
|
|
{"glValidateProgramARB", (void **) &pglValidateProgramARB},
|
|
{"glUniform1fARB", (void **) &pglUniform1fARB},
|
|
{"glUniform2fARB", (void **) &pglUniform2fARB},
|
|
{"glUniform3fARB", (void **) &pglUniform3fARB},
|
|
{"glUniform4fARB", (void **) &pglUniform4fARB},
|
|
{"glUniform1iARB", (void **) &pglUniform1iARB},
|
|
{"glUniform2iARB", (void **) &pglUniform2iARB},
|
|
{"glUniform3iARB", (void **) &pglUniform3iARB},
|
|
{"glUniform4iARB", (void **) &pglUniform4iARB},
|
|
{"glUniform1fvARB", (void **) &pglUniform1fvARB},
|
|
{"glUniform2fvARB", (void **) &pglUniform2fvARB},
|
|
{"glUniform3fvARB", (void **) &pglUniform3fvARB},
|
|
{"glUniform4fvARB", (void **) &pglUniform4fvARB},
|
|
{"glUniform1ivARB", (void **) &pglUniform1ivARB},
|
|
{"glUniform2ivARB", (void **) &pglUniform2ivARB},
|
|
{"glUniform3ivARB", (void **) &pglUniform3ivARB},
|
|
{"glUniform4ivARB", (void **) &pglUniform4ivARB},
|
|
{"glUniformMatrix2fvARB", (void **) &pglUniformMatrix2fvARB},
|
|
{"glUniformMatrix3fvARB", (void **) &pglUniformMatrix3fvARB},
|
|
{"glUniformMatrix4fvARB", (void **) &pglUniformMatrix4fvARB},
|
|
{"glGetObjectParameterfvARB", (void **) &pglGetObjectParameterfvARB},
|
|
{"glGetObjectParameterivARB", (void **) &pglGetObjectParameterivARB},
|
|
{"glGetInfoLogARB", (void **) &pglGetInfoLogARB},
|
|
{"glGetAttachedObjectsARB", (void **) &pglGetAttachedObjectsARB},
|
|
{"glGetUniformLocationARB", (void **) &pglGetUniformLocationARB},
|
|
{"glGetActiveUniformARB", (void **) &pglGetActiveUniformARB},
|
|
{"glGetUniformfvARB", (void **) &pglGetUniformfvARB},
|
|
{"glGetUniformivARB", (void **) &pglGetUniformivARB},
|
|
{"glGetShaderSourceARB", (void **) &pglGetShaderSourceARB},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t vertexshaderfuncs[] =
|
|
{
|
|
{"glVertexAttribPointerARB", (void **) &pglVertexAttribPointerARB},
|
|
{"glEnableVertexAttribArrayARB", (void **) &pglEnableVertexAttribArrayARB},
|
|
{"glDisableVertexAttribArrayARB", (void **) &pglDisableVertexAttribArrayARB},
|
|
{"glBindAttribLocationARB", (void **) &pglBindAttribLocationARB},
|
|
{"glGetActiveAttribARB", (void **) &pglGetActiveAttribARB},
|
|
{"glGetAttribLocationARB", (void **) &pglGetAttribLocationARB},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t vbofuncs[] =
|
|
{
|
|
{"glBindBufferARB" , (void **) &pglBindBufferARB},
|
|
{"glDeleteBuffersARB" , (void **) &pglDeleteBuffersARB},
|
|
{"glGenBuffersARB" , (void **) &pglGenBuffersARB},
|
|
{"glIsBufferARB" , (void **) &pglIsBufferARB},
|
|
{"glMapBufferARB" , (void **) &pglMapBufferARB},
|
|
{"glUnmapBufferARB" , (void **) &pglUnmapBufferARB},
|
|
{"glBufferDataARB" , (void **) &pglBufferDataARB},
|
|
{"glBufferSubDataARB" , (void **) &pglBufferSubDataARB},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static dllfunc_t texturecompressionfuncs[] =
|
|
{
|
|
{"glCompressedTexImage3DARB", (void **) &pglCompressedTexImage3DARB},
|
|
{"glCompressedTexImage2DARB", (void **) &pglCompressedTexImage2DARB},
|
|
{"glCompressedTexImage1DARB", (void **) &pglCompressedTexImage1DARB},
|
|
{"glCompressedTexSubImage3DARB", (void **) &pglCompressedTexSubImage3DARB},
|
|
{"glCompressedTexSubImage2DARB", (void **) &pglCompressedTexSubImage2DARB},
|
|
{"glCompressedTexSubImage1DARB", (void **) &pglCompressedTexSubImage1DARB},
|
|
{"glGetCompressedTexImageARB", (void **) &pglGetCompressedTexImage},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, NULL, NULL, NULL, true, 0 };
|
|
|
|
bool R_DeleteContext( void )
|
|
{
|
|
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;
|
|
}
|
|
|
|
bool R_SetPixelformat( void )
|
|
{
|
|
long flags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_DOUBLEBUFFER;
|
|
int pixelformat;
|
|
|
|
PIXELFORMATDESCRIPTOR pfd =
|
|
{
|
|
sizeof(PIXELFORMATDESCRIPTOR),// size of this pfd
|
|
1, // version number
|
|
flags, // support window|OpenGL|generic accel|double buffer
|
|
PFD_TYPE_RGBA, // RGBA type
|
|
24, // 24-bit color depth
|
|
8, 0, 8, 0, 8, 0, // color bits set to 32
|
|
8, 0, // alpha bit 8
|
|
0, // no accumulation buffer
|
|
0, 0, 0, 0, // accum bits ignored
|
|
32, // 32-bit z-buffer
|
|
8, // 8-bit stencil buffer
|
|
0, // no auxiliary buffer
|
|
PFD_MAIN_PLANE, // main layer
|
|
0, // reserved
|
|
0, 0, 0 // layer masks ignored
|
|
};
|
|
|
|
Sys_LoadLibrary( &opengl_dll ); // load opengl32.dll
|
|
if( !opengl_dll.link ) return false;
|
|
|
|
if(( glw_state.hDC = GetDC( glw_state.hWnd )) == NULL )
|
|
return false;
|
|
|
|
glw_state.minidriver = false;
|
|
if( glw_state.minidriver )
|
|
{
|
|
if(!(pixelformat = pwglChoosePixelFormat( glw_state.hDC, &pfd)))
|
|
return false;
|
|
if(!(pwglSetPixelFormat( glw_state.hDC, pixelformat, &pfd)))
|
|
return false;
|
|
pwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
|
|
}
|
|
else
|
|
{
|
|
if(!( pixelformat = ChoosePixelFormat( glw_state.hDC, &pfd )))
|
|
return false;
|
|
if(!(SetPixelFormat( glw_state.hDC, pixelformat, &pfd )))
|
|
return false;
|
|
DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
|
|
}
|
|
|
|
if(!(glw_state.hGLRC = pwglCreateContext( glw_state.hDC )))
|
|
return R_DeleteContext();
|
|
if(!(pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC )))
|
|
return R_DeleteContext();
|
|
|
|
// print out PFD specifics
|
|
MsgDev(D_NOTE, "GL PFD: color(%d-bits) Z(%d-bit)\n", ( int )pfd.cColorBits, ( int )pfd.cDepthBits );
|
|
|
|
// init gamma ramp
|
|
ZeroMemory( gl_config.original_ramp, sizeof(gl_config.original_ramp));
|
|
GetDeviceGammaRamp( glw_state.hDC, gl_config.original_ramp );
|
|
vid_gamma->modified = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
void R_Free_OpenGL( void )
|
|
{
|
|
SetDeviceGammaRamp( glw_state.hDC, gl_config.original_ramp );
|
|
|
|
if( pwglMakeCurrent ) pwglMakeCurrent( NULL, NULL );
|
|
if( glw_state.hGLRC )
|
|
{
|
|
if( pwglDeleteContext ) pwglDeleteContext( glw_state.hGLRC );
|
|
glw_state.hGLRC = NULL;
|
|
}
|
|
if( glw_state.hDC )
|
|
{
|
|
ReleaseDC( glw_state.hWnd, glw_state.hDC );
|
|
glw_state.hDC = NULL;
|
|
}
|
|
if( glw_state.hWnd )
|
|
{
|
|
DestroyWindow ( glw_state.hWnd );
|
|
glw_state.hWnd = NULL;
|
|
}
|
|
UnregisterClass( "Xash Window", glw_state.hInst );
|
|
|
|
if( gl_state.fullscreen )
|
|
{
|
|
ChangeDisplaySettings( 0, 0 );
|
|
gl_state.fullscreen = false;
|
|
}
|
|
Sys_FreeLibrary( &opengl_dll );
|
|
|
|
// now all extensions are disabled
|
|
memset( gl_config.extension, 0, sizeof(gl_config.extension[0]) * R_EXTCOUNT);
|
|
}
|
|
|
|
void R_SaveVideoMode( int vid_mode )
|
|
{
|
|
int i = bound(0, vid_mode, num_vidmodes); // check range
|
|
|
|
Cvar_SetValue("width", vidmode[i].width );
|
|
Cvar_SetValue("height", vidmode[i].height );
|
|
Cvar_SetValue("r_mode", i ); // merge if out of bounds
|
|
MsgDev(D_NOTE, "Set: %s [%dx%d]\n", vidmode[i].desc, vidmode[i].width, vidmode[i].height );
|
|
}
|
|
|
|
bool R_CreateWindow( int width, int height, bool fullscreen )
|
|
{
|
|
WNDCLASS wc;
|
|
RECT rect;
|
|
cvar_t *r_xpos, *r_ypos;
|
|
int stylebits = WINDOW_STYLE;
|
|
int x = 0, y = 0, w, h;
|
|
int exstyle = 0;
|
|
static char wndname[128];
|
|
|
|
com.strcpy( wndname, GI->title );
|
|
|
|
// register the frame class
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = (WNDPROC)glw_state.wndproc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = glw_state.hInst;
|
|
wc.hIcon = LoadIcon( glw_state.hInst, MAKEINTRESOURCE( 101 ));
|
|
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
|
wc.hbrBackground = (void *)COLOR_3DSHADOW;
|
|
wc.lpszClassName = "Xash Window";
|
|
wc.lpszMenuName = 0;
|
|
|
|
if(!RegisterClass( &wc ))
|
|
{
|
|
MsgDev( D_ERROR, "R_CreateWindow: couldn't register window class %s\n" "Xash Window" );
|
|
return false;
|
|
}
|
|
|
|
if( fullscreen )
|
|
{
|
|
exstyle = WS_EX_TOPMOST;
|
|
stylebits = WS_POPUP | WS_VISIBLE;
|
|
}
|
|
|
|
rect.left = 0;
|
|
rect.top = 0;
|
|
rect.right = width;
|
|
rect.bottom = height;
|
|
|
|
AdjustWindowRect( &rect, stylebits, FALSE );
|
|
w = rect.right - rect.left;
|
|
h = rect.bottom - rect.top;
|
|
|
|
if( !fullscreen )
|
|
{
|
|
r_xpos = Cvar_Get( "r_xpos", "3", CVAR_ARCHIVE, "window position by horizontal" );
|
|
r_ypos = Cvar_Get( "r_ypos", "22", CVAR_ARCHIVE, "window position by vertical" );
|
|
x = r_xpos->integer;
|
|
y = r_ypos->integer;
|
|
}
|
|
|
|
glw_state.hWnd = CreateWindowEx( exstyle, "Xash Window", wndname, stylebits, x, y, w, h, NULL, NULL, glw_state.hInst, NULL );
|
|
|
|
if( !glw_state.hWnd )
|
|
{
|
|
MsgDev( D_ERROR, "R_CreateWindow: couldn't create window %s\n", wndname );
|
|
return false;
|
|
}
|
|
|
|
ShowWindow( glw_state.hWnd, SW_SHOW );
|
|
UpdateWindow( glw_state.hWnd );
|
|
|
|
// init all the gl stuff for the window
|
|
if(!R_SetPixelformat())
|
|
{
|
|
MsgDev( D_ERROR, "OpenGL driver not installed\n" );
|
|
return false;
|
|
}
|
|
|
|
SetForegroundWindow( glw_state.hWnd );
|
|
SetFocus( glw_state.hWnd );
|
|
return true;
|
|
}
|
|
|
|
rserr_t R_ChangeDisplaySettings( int vid_mode, bool fullscreen )
|
|
{
|
|
int width, height;
|
|
|
|
R_SaveVideoMode( vid_mode );
|
|
|
|
width = r_width->integer;
|
|
height = r_height->integer;
|
|
|
|
// destroy the existing window
|
|
if( glw_state.hWnd ) R_Free_OpenGL();
|
|
|
|
// do a CDS if needed
|
|
if( fullscreen )
|
|
{
|
|
DEVMODE dm;
|
|
|
|
ZeroMemory( &dm, sizeof( dm ));
|
|
dm.dmSize = sizeof( dm );
|
|
dm.dmPelsWidth = width;
|
|
dm.dmPelsHeight = height;
|
|
dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
|
|
|
|
if(ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL)
|
|
{
|
|
gl_state.fullscreen = true;
|
|
if(!R_CreateWindow( width, height, true ))
|
|
return rserr_invalid_mode;
|
|
return rserr_ok;
|
|
}
|
|
else
|
|
{
|
|
dm.dmPelsWidth = width * 2;
|
|
dm.dmPelsHeight = height;
|
|
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
if( gl_bitdepth->value != 0 )
|
|
{
|
|
dm.dmBitsPerPel = gl_bitdepth->value;
|
|
dm.dmFields |= DM_BITSPERPEL;
|
|
}
|
|
|
|
// our first CDS failed, so maybe we're running on some weird dual monitor system
|
|
if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
|
|
{
|
|
ChangeDisplaySettings( 0, 0 );
|
|
gl_state.fullscreen = false;
|
|
if(!R_CreateWindow( width, height, false ))
|
|
return rserr_invalid_mode;
|
|
return rserr_invalid_fullscreen;
|
|
}
|
|
else
|
|
{
|
|
if(!R_CreateWindow( width, height, true ))
|
|
return rserr_invalid_mode;
|
|
gl_state.fullscreen = true;
|
|
return rserr_ok;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ChangeDisplaySettings( 0, 0 );
|
|
gl_state.fullscreen = false;
|
|
if(!R_CreateWindow( width, height, false ))
|
|
return rserr_invalid_mode;
|
|
}
|
|
return rserr_ok;
|
|
}
|
|
|
|
/*
|
|
==================
|
|
R_Init_OpenGL
|
|
==================
|
|
*/
|
|
bool R_Init_OpenGL( void )
|
|
{
|
|
rserr_t err;
|
|
bool fullscreen;
|
|
|
|
fullscreen = r_fullscreen->integer;
|
|
r_fullscreen->modified = false;
|
|
r_mode->modified = false;
|
|
|
|
if(( err = R_ChangeDisplaySettings( r_mode->integer, fullscreen )) == rserr_ok )
|
|
{
|
|
gl_state.prev_mode = r_mode->integer;
|
|
}
|
|
else
|
|
{
|
|
if( err == rserr_invalid_fullscreen )
|
|
{
|
|
Cvar_SetValue( "fullscreen", 0 );
|
|
r_fullscreen->modified = false;
|
|
MsgDev( D_ERROR, "R_SetMode: fullscreen unavailable in this mode\n" );
|
|
if(( err = R_ChangeDisplaySettings( r_mode->integer, false )) == rserr_ok )
|
|
return true;
|
|
}
|
|
else if( err == rserr_invalid_mode )
|
|
{
|
|
Cvar_SetValue( "r_mode", gl_state.prev_mode );
|
|
r_mode->modified = false;
|
|
MsgDev( D_ERROR, "R_SetMode: invalid mode\n" );
|
|
}
|
|
// try setting it back to something safe
|
|
if(( err = R_ChangeDisplaySettings( gl_state.prev_mode, false )) != rserr_ok )
|
|
{
|
|
MsgDev( D_ERROR, "R_SetMode: could not revert to safe mode\n" );
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
R_CheckForErrors
|
|
=================
|
|
*/
|
|
void R_CheckForErrors( void )
|
|
{
|
|
int err;
|
|
char *str;
|
|
|
|
if( !r_check_errors->integer )
|
|
return;
|
|
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", str );
|
|
}
|
|
|
|
void R_EndFrame( void )
|
|
{
|
|
if( stricmp( gl_drawbuffer->string, "GL_BACK" ) == 0 )
|
|
{
|
|
if( !pwglSwapBuffers( glw_state.hDC ) )
|
|
Host_Error("GLimp_EndFrame() - SwapBuffers() failed!\n" );
|
|
}
|
|
}
|
|
|
|
void R_InitExtensions( void )
|
|
{
|
|
// initialize gl extensions
|
|
GL_CheckExtension( "OpenGL 1.1.0", opengl_110funcs, NULL, R_OPENGL_110 );
|
|
|
|
// get our various GL strings
|
|
gl_config.vendor_string = pglGetString( GL_VENDOR );
|
|
gl_config.renderer_string = pglGetString( GL_RENDERER );
|
|
gl_config.version_string = pglGetString( GL_VERSION );
|
|
gl_config.extensions_string = pglGetString( GL_EXTENSIONS );
|
|
MsgDev( D_INFO, "Video: %s\n", gl_config.renderer_string );
|
|
|
|
GL_CheckExtension( "WGL_EXT_swap_control", wglswapintervalfuncs, NULL, R_WGL_SWAPCONTROL );
|
|
GL_CheckExtension( "glDrawRangeElements", drawrangeelementsfuncs, "gl_drawrangeelments", R_DRAWRANGEELMENTS );
|
|
if(!GL_Support( R_DRAWRANGEELMENTS )) GL_CheckExtension("GL_EXT_draw_range_elements", drawrangeelementsextfuncs, "gl_drawrangeelments", R_DRAWRANGEELMENTS );
|
|
|
|
// multitexture
|
|
GL_CheckExtension("GL_ARB_multitexture", multitexturefuncs, "gl_arb_multitexture", R_ARB_MULTITEXTURE );
|
|
if(GL_Support( R_ARB_MULTITEXTURE ))
|
|
{
|
|
pglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &gl_state.textureunits );
|
|
GL_CheckExtension( "GL_ARB_texture_env_combine", NULL, "gl_texture_env_combine", R_COMBINE_EXT );
|
|
if(!GL_Support( R_COMBINE_EXT )) GL_CheckExtension("GL_EXT_texture_env_combine", NULL, "gl_texture_env_combine", R_COMBINE_EXT );
|
|
if(GL_Support( R_COMBINE_EXT )) GL_CheckExtension( "GL_ARB_texture_env_dot3", NULL, "gl_texture_env_dot3", R_DOT3_ARB_EXT );
|
|
GL_TEXTURE0 = GL_TEXTURE0_ARB;
|
|
GL_TEXTURE1 = GL_TEXTURE1_ARB;
|
|
}
|
|
|
|
// 3d texture support
|
|
GL_CheckExtension( "GL_EXT_texture3D", texture3dextfuncs, "gl_texture_3d", R_TEXTURE_3D_EXT );
|
|
if(GL_Support( R_TEXTURE_3D_EXT ))
|
|
{
|
|
pglGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &gl_state.max_3d_texture_size );
|
|
if( gl_state.max_3d_texture_size < 32 )
|
|
{
|
|
GL_SetExtension( R_TEXTURE_3D_EXT, false );
|
|
MsgDev( D_ERROR, "GL_EXT_texture3D reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n" );
|
|
}
|
|
}
|
|
|
|
// hardware cubemaps
|
|
GL_CheckExtension( "GL_ARB_texture_cube_map", NULL, "gl_texture_cubemap", R_TEXTURECUBEMAP_EXT );
|
|
if(GL_Support( R_TEXTURECUBEMAP_EXT )) pglGetIntegerv( GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &gl_state.max_cubemap_texture_size );
|
|
|
|
// point particles extension
|
|
GL_CheckExtension( "GL_EXT_point_parameters", pointparametersfunc, NULL, R_EXT_POINTPARAMETERS );
|
|
|
|
GL_CheckExtension( "GL_ARB_texture_non_power_of_two", NULL, "gl_texture_npot", R_ARB_TEXTURE_NPOT_EXT );
|
|
GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, "gl_dds_hardware_support", R_TEXTURE_COMPRESSION_EXT );
|
|
GL_CheckExtension( "GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "gl_cva_support", R_CUSTOM_VERTEX_ARRAY_EXT );
|
|
if(!GL_Support(R_CUSTOM_VERTEX_ARRAY_EXT)) GL_CheckExtension( "GL_SGI_compiled_vertex_array", compiledvertexarrayfuncs, "gl_cva_support", R_CUSTOM_VERTEX_ARRAY_EXT );
|
|
GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, "gl_clamp_to_edge", R_CLAMPTOEDGE_EXT );
|
|
if(!GL_Support( R_CLAMPTOEDGE_EXT )) GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "gl_clamp_to_edge", R_CLAMPTOEDGE_EXT );
|
|
|
|
GL_CheckExtension( "GL_EXT_texture_filter_anisotropic", NULL, "gl_texture_anisotropy", R_ANISOTROPY_EXT );
|
|
if(GL_Support( R_ANISOTROPY_EXT )) pglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_state.max_anisotropy );
|
|
|
|
GL_CheckExtension( "GL_EXT_blend_minmax", blendequationfuncs, "gl_ext_customblend", R_BLEND_MINMAX_EXT );
|
|
GL_CheckExtension( "GL_EXT_blend_subtract", blendequationfuncs, "gl_ext_customblend", R_BLEND_SUBTRACT_EXT );
|
|
|
|
GL_CheckExtension( "glStencilOpSeparate", gl2separatestencilfuncs, "gl_separate_stencil",R_SEPARATESTENCIL_EXT );
|
|
if(!GL_Support( R_SEPARATESTENCIL_EXT )) GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "gl_separate_stencil", R_SEPARATESTENCIL_EXT );
|
|
|
|
GL_CheckExtension( "GL_EXT_stencil_two_side", stenciltwosidefuncs, "gl_stenciltwoside", R_STENCILTWOSIDE_EXT );
|
|
GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", R_ARB_VERTEX_BUFFER_OBJECT_EXT );
|
|
|
|
// we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code
|
|
if( pglDrawRangeElements == NULL ) pglDrawRangeElements = pglDrawRangeElementsEXT;
|
|
|
|
// vp and fp shaders
|
|
GL_CheckExtension( "GL_ARB_shader_objects", shaderobjectsfuncs, "gl_shaderobjects", R_SHADER_OBJECTS_EXT );
|
|
GL_CheckExtension( "GL_ARB_shading_language_100", NULL, "gl_glslprogram", R_SHADER_GLSL100_EXT );
|
|
GL_CheckExtension( "GL_ARB_vertex_shader", vertexshaderfuncs, "gl_vertexshader", R_VERTEX_SHADER_EXT );
|
|
GL_CheckExtension( "GL_ARB_fragment_shader", NULL, "gl_pixelshader", R_FRAGMENT_SHADER_EXT );
|
|
|
|
// rectangle textures support
|
|
if( com.strstr( gl_config.extensions_string, "GL_NV_texture_rectangle" ))
|
|
gl_state.tex_rectangle_type = GL_TEXTURE_RECTANGLE_NV;
|
|
else if( com.strstr( gl_config.extensions_string, "GL_EXT_texture_rectangle" ))
|
|
gl_state.tex_rectangle_type = GL_TEXTURE_RECTANGLE_EXT;
|
|
else gl_state.tex_rectangle_type = 0; // no rectangle
|
|
} |