static void GLimp_InitExtensions( void ) { if ( !r_allowExtensions->integer ) { Com_Printf ("*** IGNORING OPENGL EXTENSIONS ***\n" ); g_bDynamicGlowSupported = false; ri->Cvar_Set( "r_DynamicGlow","0" ); return; } Com_Printf ("Initializing OpenGL extensions\n" ); // Select our tc scheme GLW_InitTextureCompression(); // GL_EXT_texture_env_add glConfig.textureEnvAddAvailable = qfalse; if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) ) { if ( r_ext_texture_env_add->integer ) { glConfig.textureEnvAddAvailable = qtrue; Com_Printf ("...using GL_EXT_texture_env_add\n" ); } else { glConfig.textureEnvAddAvailable = qfalse; Com_Printf ("...ignoring GL_EXT_texture_env_add\n" ); } } else { Com_Printf ("...GL_EXT_texture_env_add not found\n" ); } // GL_EXT_texture_filter_anisotropic glConfig.maxTextureFilterAnisotropy = 0; if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) ) { #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF //can't include glext.h here ... sigh qglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxTextureFilterAnisotropy ); Com_Printf ("...GL_EXT_texture_filter_anisotropic available\n" ); if ( r_ext_texture_filter_anisotropic->integer>1 ) { Com_Printf ("...using GL_EXT_texture_filter_anisotropic\n" ); } else { Com_Printf ("...ignoring GL_EXT_texture_filter_anisotropic\n" ); } ri->Cvar_SetValue( "r_ext_texture_filter_anisotropic_avail", glConfig.maxTextureFilterAnisotropy ); if ( r_ext_texture_filter_anisotropic->value > glConfig.maxTextureFilterAnisotropy ) { ri->Cvar_SetValue( "r_ext_texture_filter_anisotropic_avail", glConfig.maxTextureFilterAnisotropy ); } } else { Com_Printf ("...GL_EXT_texture_filter_anisotropic not found\n" ); ri->Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "0" ); } // GL_EXT_clamp_to_edge glConfig.clampToEdgeAvailable = qfalse; if ( strstr( glConfig.extensions_string, "GL_EXT_texture_edge_clamp" ) ) { glConfig.clampToEdgeAvailable = qtrue; Com_Printf ("...Using GL_EXT_texture_edge_clamp\n" ); } // GL_ARB_multitexture qglMultiTexCoord2fARB = NULL; qglActiveTextureARB = NULL; qglClientActiveTextureARB = NULL; if ( strstr( glConfig.extensions_string, "GL_ARB_multitexture" ) ) { if ( r_ext_multitexture->integer ) { qglMultiTexCoord2fARB = ( PFNGLMULTITEXCOORD2FARBPROC ) SDL_GL_GetProcAddress( "glMultiTexCoord2fARB" ); qglActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC ) SDL_GL_GetProcAddress( "glActiveTextureARB" ); qglClientActiveTextureARB = ( PFNGLCLIENTACTIVETEXTUREARBPROC ) SDL_GL_GetProcAddress( "glClientActiveTextureARB" ); if ( qglActiveTextureARB ) { qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures ); if ( glConfig.maxActiveTextures > 1 ) { Com_Printf ("...using GL_ARB_multitexture\n" ); } else { qglMultiTexCoord2fARB = NULL; qglActiveTextureARB = NULL; qglClientActiveTextureARB = NULL; Com_Printf ("...not using GL_ARB_multitexture, < 2 texture units\n" ); } } } else { Com_Printf ("...ignoring GL_ARB_multitexture\n" ); } } else { Com_Printf ("...GL_ARB_multitexture not found\n" ); } // GL_EXT_compiled_vertex_array qglLockArraysEXT = NULL; qglUnlockArraysEXT = NULL; if ( strstr( glConfig.extensions_string, "GL_EXT_compiled_vertex_array" ) ) { if ( r_ext_compiled_vertex_array->integer ) { Com_Printf ("...using GL_EXT_compiled_vertex_array\n" ); qglLockArraysEXT = ( void ( APIENTRY * )( int, int ) ) SDL_GL_GetProcAddress( "glLockArraysEXT" ); qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) SDL_GL_GetProcAddress( "glUnlockArraysEXT" ); if (!qglLockArraysEXT || !qglUnlockArraysEXT) { Com_Error (ERR_FATAL, "bad getprocaddress"); } } else { Com_Printf ("...ignoring GL_EXT_compiled_vertex_array\n" ); } } else { Com_Printf ("...GL_EXT_compiled_vertex_array not found\n" ); } qglPointParameterfEXT = NULL; qglPointParameterfvEXT = NULL; //3d textures -rww qglTexImage3DEXT = NULL; qglTexSubImage3DEXT = NULL; if ( strstr( glConfig.extensions_string, "GL_EXT_point_parameters" ) ) { if ( r_ext_compiled_vertex_array->integer ) { Com_Printf ("...using GL_EXT_point_parameters\n" ); qglPointParameterfEXT = ( void ( APIENTRY * )( GLenum, GLfloat) ) SDL_GL_GetProcAddress( "glPointParameterfEXT" ); qglPointParameterfvEXT = ( void ( APIENTRY * )( GLenum, GLfloat *) ) SDL_GL_GetProcAddress( "glPointParameterfvEXT" ); //3d textures -rww qglTexImage3DEXT = (void ( APIENTRY * ) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *) ) SDL_GL_GetProcAddress( "glTexImage3DEXT" ); qglTexSubImage3DEXT = (void ( APIENTRY * ) (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *) ) SDL_GL_GetProcAddress( "glTexSubImage3DEXT" ); if (!qglPointParameterfEXT || !qglPointParameterfvEXT) { Com_Error (ERR_FATAL, "bad getprocaddress"); } } else { Com_Printf ("...ignoring GL_EXT_point_parameters\n" ); } } else { Com_Printf ("...GL_EXT_point_parameters not found\n" ); } bool bNVRegisterCombiners = false; // Register Combiners. if ( strstr( glConfig.extensions_string, "GL_NV_register_combiners" ) ) { // NOTE: This extension requires multitexture support (over 2 units). if ( glConfig.maxActiveTextures >= 2 ) { bNVRegisterCombiners = true; // Register Combiners function pointer address load. - AReis // NOTE: VV guys will _definetly_ not be able to use regcoms. Pixel Shaders are just as good though :-) // NOTE: Also, this is an nVidia specific extension (of course), so fragment shaders would serve the same purpose // if we needed some kind of fragment/pixel manipulation support. qglCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC)SDL_GL_GetProcAddress( "glCombinerParameterfvNV" ); qglCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC)SDL_GL_GetProcAddress( "glCombinerParameterivNV" ); qglCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC)SDL_GL_GetProcAddress( "glCombinerParameterfNV" ); qglCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC)SDL_GL_GetProcAddress( "glCombinerParameteriNV" ); qglCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC)SDL_GL_GetProcAddress( "glCombinerInputNV" ); qglCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC)SDL_GL_GetProcAddress( "glCombinerOutputNV" ); qglFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC)SDL_GL_GetProcAddress( "glFinalCombinerInputNV" ); qglGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)SDL_GL_GetProcAddress( "glGetCombinerInputParameterfvNV" ); qglGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)SDL_GL_GetProcAddress( "glGetCombinerInputParameterivNV" ); qglGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)SDL_GL_GetProcAddress( "glGetCombinerOutputParameterfvNV" ); qglGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)SDL_GL_GetProcAddress( "glGetCombinerOutputParameterivNV" ); qglGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)SDL_GL_GetProcAddress( "glGetFinalCombinerInputParameterfvNV" ); qglGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)SDL_GL_GetProcAddress( "glGetFinalCombinerInputParameterivNV" ); // Validate the functions we need. if ( !qglCombinerParameterfvNV || !qglCombinerParameterivNV || !qglCombinerParameterfNV || !qglCombinerParameteriNV || !qglCombinerInputNV || !qglCombinerOutputNV || !qglFinalCombinerInputNV || !qglGetCombinerInputParameterfvNV || !qglGetCombinerInputParameterivNV || !qglGetCombinerOutputParameterfvNV || !qglGetCombinerOutputParameterivNV || !qglGetFinalCombinerInputParameterfvNV || !qglGetFinalCombinerInputParameterivNV ) { bNVRegisterCombiners = false; qglCombinerParameterfvNV = NULL; qglCombinerParameteriNV = NULL; Com_Printf ("...GL_NV_register_combiners failed\n" ); } } else { bNVRegisterCombiners = false; Com_Printf ("...ignoring GL_NV_register_combiners\n" ); } } else { bNVRegisterCombiners = false; Com_Printf ("...GL_NV_register_combiners not found\n" ); } // NOTE: Vertex and Fragment Programs are very dependant on each other - this is actually a // good thing! So, just check to see which we support (one or the other) and load the shared // function pointers. ARB rocks! // Vertex Programs. bool bARBVertexProgram = false; if ( strstr( glConfig.extensions_string, "GL_ARB_vertex_program" ) ) { bARBVertexProgram = true; } else { bARBVertexProgram = false; Com_Printf ("...GL_ARB_vertex_program not found\n" ); } // Fragment Programs. bool bARBFragmentProgram = false; if ( strstr( glConfig.extensions_string, "GL_ARB_fragment_program" ) ) { bARBFragmentProgram = true; } else { bARBFragmentProgram = false; Com_Printf ("...GL_ARB_fragment_program not found\n" ); } // If we support one or the other, load the shared function pointers. if ( bARBVertexProgram || bARBFragmentProgram ) { qglProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) SDL_GL_GetProcAddress("glProgramStringARB"); qglBindProgramARB = (PFNGLBINDPROGRAMARBPROC) SDL_GL_GetProcAddress("glBindProgramARB"); qglDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) SDL_GL_GetProcAddress("glDeleteProgramsARB"); qglGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) SDL_GL_GetProcAddress("glGenProgramsARB"); qglProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4dARB"); qglProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4dvARB"); qglProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4fARB"); qglProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4fvARB"); qglProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4dARB"); qglProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4dvARB"); qglProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4fARB"); qglProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4fvARB"); qglGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) SDL_GL_GetProcAddress("glGetProgramEnvParameterdvARB"); qglGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetProgramEnvParameterfvARB"); qglGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) SDL_GL_GetProcAddress("glGetProgramLocalParameterdvARB"); qglGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetProgramLocalParameterfvARB"); qglGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) SDL_GL_GetProcAddress("glGetProgramivARB"); qglGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) SDL_GL_GetProcAddress("glGetProgramStringARB"); qglIsProgramARB = (PFNGLISPROGRAMARBPROC) SDL_GL_GetProcAddress("glIsProgramARB"); // Validate the functions we need. if ( !qglProgramStringARB || !qglBindProgramARB || !qglDeleteProgramsARB || !qglGenProgramsARB || !qglProgramEnvParameter4dARB || !qglProgramEnvParameter4dvARB || !qglProgramEnvParameter4fARB || !qglProgramEnvParameter4fvARB || !qglProgramLocalParameter4dARB || !qglProgramLocalParameter4dvARB || !qglProgramLocalParameter4fARB || !qglProgramLocalParameter4fvARB || !qglGetProgramEnvParameterdvARB || !qglGetProgramEnvParameterfvARB || !qglGetProgramLocalParameterdvARB || !qglGetProgramLocalParameterfvARB || !qglGetProgramivARB || !qglGetProgramStringARB || !qglIsProgramARB ) { bARBVertexProgram = false; bARBFragmentProgram = false; qglGenProgramsARB = NULL; //clear ptrs that get checked qglProgramEnvParameter4fARB = NULL; Com_Printf ("...ignoring GL_ARB_vertex_program\n" ); Com_Printf ("...ignoring GL_ARB_fragment_program\n" ); } } // Figure out which texture rectangle extension to use. bool bTexRectSupported = false; if ( Q_stricmpn( glConfig.vendor_string, "ATI Technologies",16 )==0 && Q_stricmpn( glConfig.version_string, "1.3.3",5 )==0 && glConfig.version_string[5] < '9' ) //1.3.34 and 1.3.37 and 1.3.38 are broken for sure, 1.3.39 is not { g_bTextureRectangleHack = true; } if ( strstr( glConfig.extensions_string, "GL_NV_texture_rectangle" ) || strstr( glConfig.extensions_string, "GL_EXT_texture_rectangle" ) ) { bTexRectSupported = true; } // Find out how many general combiners they have. #define GL_MAX_GENERAL_COMBINERS_NV 0x854D GLint iNumGeneralCombiners = 0; if(bNVRegisterCombiners) qglGetIntegerv( GL_MAX_GENERAL_COMBINERS_NV, &iNumGeneralCombiners ); // Only allow dynamic glows/flares if they have the hardware if ( bTexRectSupported && bARBVertexProgram && qglActiveTextureARB && glConfig.maxActiveTextures >= 4 && ( ( bNVRegisterCombiners && iNumGeneralCombiners >= 2 ) || bARBFragmentProgram ) ) { g_bDynamicGlowSupported = true; // this would overwrite any achived setting gwg // Cvar_Set( "r_DynamicGlow", "1" ); } else { g_bDynamicGlowSupported = false; ri->Cvar_Set( "r_DynamicGlow","0" ); } }
static void SetFinalProjection( void ) { float xmin, xmax, ymin, ymax; float width, height, depth; float zNear, zFar, zProj, stereoSep; float dx, dy; vec2_t pixelJitter, eyeJitter; // // set up projection matrix // zNear = r_znear->value; zFar = backEnd.viewParms.zFar; zProj = r_zproj->value; stereoSep = r_stereoSeparation->value / 100.0f; ymax = zNear * tan( backEnd.viewParms.fovY * M_PI / 360.0f ); ymin = -ymax; xmax = zNear * tan( backEnd.viewParms.fovX * M_PI / 360.0f ); xmin = -xmax; width = xmax - xmin; height = ymax - ymin; depth = zFar - zNear; pixelJitter[0] = pixelJitter[1] = 0; eyeJitter[0] = eyeJitter[1] = 0; /* Jitter the view */ if ( stereoSep <= 0.0f) { R_MME_JitterView( pixelJitter, eyeJitter ); } else if ( stereoSep > 0.0f) { R_MME_JitterViewStereo( pixelJitter, eyeJitter ); } dx = ( pixelJitter[0]*width ) / backEnd.viewParms.viewportWidth; dy = ( pixelJitter[1]*height ) / backEnd.viewParms.viewportHeight; dx += eyeJitter[0]; dy += eyeJitter[1]; xmin += dx; xmax += dx; ymin += dy; ymax += dy; qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); qglGetFloatv(GL_PROJECTION_MATRIX, backEnd.viewParms.projectionMatrix ); qglPopMatrix(); backEnd.viewParms.projectionMatrix[0] = 2 * zNear / width; backEnd.viewParms.projectionMatrix[4] = 0; backEnd.viewParms.projectionMatrix[8] = ( xmax + xmin + 2 * stereoSep ) / width; // normally 0 backEnd.viewParms.projectionMatrix[12] = 2 * zProj * stereoSep / width; backEnd.viewParms.projectionMatrix[1] = 0; backEnd.viewParms.projectionMatrix[5] = 2 * zNear / height; backEnd.viewParms.projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0 backEnd.viewParms.projectionMatrix[13] = 0; backEnd.viewParms.projectionMatrix[2] = 0; backEnd.viewParms.projectionMatrix[6] = 0; backEnd.viewParms.projectionMatrix[10] = -( zFar + zNear ) / depth; backEnd.viewParms.projectionMatrix[14] = -2 * zFar * zNear / depth; backEnd.viewParms.projectionMatrix[3] = 0; backEnd.viewParms.projectionMatrix[7] = 0; backEnd.viewParms.projectionMatrix[11] = -1; backEnd.viewParms.projectionMatrix[15] = 0; }
/* ** GLW_InitExtensions */ static void GLimp_InitExtensions( void ) { if ( !r_allowExtensions->integer ) { Com_Printf ("*** IGNORING OPENGL EXTENSIONS ***\n" ); g_bDynamicGlowSupported = false; Cvar_Set( "r_DynamicGlow","0" ); return; } Com_Printf ("Initializing OpenGL extensions\n" ); // Select our tc scheme GLW_InitTextureCompression(); // GL_EXT_texture_env_add glConfig.textureEnvAddAvailable = qfalse; if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) ) { if ( r_ext_texture_env_add->integer ) { glConfig.textureEnvAddAvailable = qtrue; Com_Printf ("...using GL_EXT_texture_env_add\n" ); } else { glConfig.textureEnvAddAvailable = qfalse; Com_Printf ("...ignoring GL_EXT_texture_env_add\n" ); } } else { Com_Printf ("...GL_EXT_texture_env_add not found\n" ); } // GL_EXT_texture_filter_anisotropic glConfig.maxTextureFilterAnisotropy = 0; if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) ) { #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF //can't include glext.h here ... sigh qglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxTextureFilterAnisotropy ); Com_Printf ("...GL_EXT_texture_filter_anisotropic available\n" ); if ( r_ext_texture_filter_anisotropic->integer>1 ) { Com_Printf ("...using GL_EXT_texture_filter_anisotropic\n" ); } else { Com_Printf ("...ignoring GL_EXT_texture_filter_anisotropic\n" ); } Cvar_Set( "r_ext_texture_filter_anisotropic_avail", va("%f",glConfig.maxTextureFilterAnisotropy) ); if ( r_ext_texture_filter_anisotropic->value > glConfig.maxTextureFilterAnisotropy ) { Cvar_Set( "r_ext_texture_filter_anisotropic", va("%f",glConfig.maxTextureFilterAnisotropy) ); } } else { Com_Printf ("...GL_EXT_texture_filter_anisotropic not found\n" ); Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "0" ); } // GL_EXT_clamp_to_edge glConfig.clampToEdgeAvailable = qfalse; if ( strstr( glConfig.extensions_string, "GL_EXT_texture_edge_clamp" ) ) { glConfig.clampToEdgeAvailable = qtrue; Com_Printf ("...Using GL_EXT_texture_edge_clamp\n" ); } #if 0 // WGL_EXT_swap_control qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) SDL_GL_GetProcAddress( "wglSwapIntervalEXT" ); if ( qwglSwapIntervalEXT ) { Com_Printf ("...using WGL_EXT_swap_control\n" ); r_swapInterval->modified = qtrue; // force a set next frame } else { Com_Printf ("...WGL_EXT_swap_control not found\n" ); } #endif // GL_ARB_multitexture qglMultiTexCoord2fARB = NULL; qglActiveTextureARB = NULL; qglClientActiveTextureARB = NULL; if ( strstr( glConfig.extensions_string, "GL_ARB_multitexture" ) ) { if ( r_ext_multitexture->integer ) { qglMultiTexCoord2fARB = ( PFNGLMULTITEXCOORD2FARBPROC ) SDL_GL_GetProcAddress( "glMultiTexCoord2fARB" ); qglActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC ) SDL_GL_GetProcAddress( "glActiveTextureARB" ); qglClientActiveTextureARB = ( PFNGLCLIENTACTIVETEXTUREARBPROC ) SDL_GL_GetProcAddress( "glClientActiveTextureARB" ); if ( qglActiveTextureARB ) { qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures ); if ( glConfig.maxActiveTextures > 1 ) { Com_Printf ("...using GL_ARB_multitexture\n" ); } else { qglMultiTexCoord2fARB = NULL; qglActiveTextureARB = NULL; qglClientActiveTextureARB = NULL; Com_Printf ("...not using GL_ARB_multitexture, < 2 texture units\n" ); } } } else { Com_Printf ("...ignoring GL_ARB_multitexture\n" ); } } else { Com_Printf ("...GL_ARB_multitexture not found\n" ); } // GL_EXT_compiled_vertex_array qglLockArraysEXT = NULL; qglUnlockArraysEXT = NULL; if ( strstr( glConfig.extensions_string, "GL_EXT_compiled_vertex_array" ) ) { if ( r_ext_compiled_vertex_array->integer ) { Com_Printf ("...using GL_EXT_compiled_vertex_array\n" ); qglLockArraysEXT = ( void ( APIENTRY * )( int, int ) ) SDL_GL_GetProcAddress( "glLockArraysEXT" ); qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) SDL_GL_GetProcAddress( "glUnlockArraysEXT" ); if (!qglLockArraysEXT || !qglUnlockArraysEXT) { Com_Error (ERR_FATAL, "bad getprocaddress"); } } else { Com_Printf ("...ignoring GL_EXT_compiled_vertex_array\n" ); } } else { Com_Printf ("...GL_EXT_compiled_vertex_array not found\n" ); } qglPointParameterfEXT = NULL; qglPointParameterfvEXT = NULL; //3d textures -rww qglTexImage3DEXT = NULL; qglTexSubImage3DEXT = NULL; if ( strstr( glConfig.extensions_string, "GL_EXT_point_parameters" ) ) { if ( r_ext_compiled_vertex_array->integer || 1) { Com_Printf ("...using GL_EXT_point_parameters\n" ); qglPointParameterfEXT = ( void ( APIENTRY * )( GLenum, GLfloat) ) SDL_GL_GetProcAddress( "glPointParameterfEXT" ); qglPointParameterfvEXT = ( void ( APIENTRY * )( GLenum, GLfloat *) ) SDL_GL_GetProcAddress( "glPointParameterfvEXT" ); //3d textures -rww qglTexImage3DEXT = (void ( APIENTRY * ) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *) ) SDL_GL_GetProcAddress( "glTexImage3DEXT" ); qglTexSubImage3DEXT = (void ( APIENTRY * ) (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *) ) SDL_GL_GetProcAddress( "glTexSubImage3DEXT" ); if (!qglPointParameterfEXT || !qglPointParameterfvEXT) { Com_Error (ERR_FATAL, "bad getprocaddress"); } } else { Com_Printf ("...ignoring GL_EXT_point_parameters\n" ); } } else { Com_Printf ("...GL_EXT_point_parameters not found\n" ); } bool bNVRegisterCombiners = false; // Register Combiners. if ( strstr( glConfig.extensions_string, "GL_NV_register_combiners" ) ) { // NOTE: This extension requires multitexture support (over 2 units). if ( glConfig.maxActiveTextures >= 2 ) { bNVRegisterCombiners = true; // Register Combiners function pointer address load. - AReis // NOTE: VV guys will _definetly_ not be able to use regcoms. Pixel Shaders are just as good though :-) // NOTE: Also, this is an nVidia specific extension (of course), so fragment shaders would serve the same purpose // if we needed some kind of fragment/pixel manipulation support. qglCombinerParameterfvNV = ( PFNGLCOMBINERPARAMETERFVNV ) SDL_GL_GetProcAddress( "glCombinerParameterfvNV" ); qglCombinerParameterivNV = ( PFNGLCOMBINERPARAMETERIVNV ) SDL_GL_GetProcAddress( "glCombinerParameterivNV" ); qglCombinerParameterfNV = ( PFNGLCOMBINERPARAMETERFNV ) SDL_GL_GetProcAddress( "glCombinerParameterfNV" ); qglCombinerParameteriNV = ( PFNGLCOMBINERPARAMETERINV ) SDL_GL_GetProcAddress( "glCombinerParameteriNV" ); qglCombinerInputNV = ( PFNGLCOMBINERINPUTNV ) SDL_GL_GetProcAddress( "glCombinerInputNV" ); qglCombinerOutputNV = ( PFNGLCOMBINEROUTPUTNV ) SDL_GL_GetProcAddress( "glCombinerOutputNV" ); qglFinalCombinerInputNV = ( PFNGLFINALCOMBINERINPUTNV ) SDL_GL_GetProcAddress( "glFinalCombinerInputNV" ); qglGetCombinerInputParameterfvNV = ( PFNGLGETCOMBINERINPUTPARAMETERFVNV ) SDL_GL_GetProcAddress( "glGetCombinerInputParameterfvNV" ); qglGetCombinerInputParameterivNV = ( PFNGLGETCOMBINERINPUTPARAMETERIVNV ) SDL_GL_GetProcAddress( "glGetCombinerInputParameterivNV" ); qglGetCombinerOutputParameterfvNV = ( PFNGLGETCOMBINEROUTPUTPARAMETERFVNV ) SDL_GL_GetProcAddress( "glGetCombinerOutputParameterfvNV" ); qglGetCombinerOutputParameterivNV = ( PFNGLGETCOMBINEROUTPUTPARAMETERIVNV ) SDL_GL_GetProcAddress( "glGetCombinerOutputParameterivNV" ); qglGetFinalCombinerInputParameterfvNV = ( PFNGLGETFINALCOMBINERINPUTPARAMETERFVNV ) SDL_GL_GetProcAddress( "glGetFinalCombinerInputParameterfvNV" ); qglGetFinalCombinerInputParameterivNV = ( PFNGLGETFINALCOMBINERINPUTPARAMETERIVNV ) SDL_GL_GetProcAddress( "glGetFinalCombinerInputParameterivNV" ); // Validate the functions we need. if ( !qglCombinerParameterfvNV || !qglCombinerParameterivNV || !qglCombinerParameterfNV || !qglCombinerParameteriNV || !qglCombinerInputNV || !qglCombinerOutputNV || !qglFinalCombinerInputNV || !qglGetCombinerInputParameterfvNV || !qglGetCombinerInputParameterivNV || !qglGetCombinerOutputParameterfvNV || !qglGetCombinerOutputParameterivNV || !qglGetFinalCombinerInputParameterfvNV || !qglGetFinalCombinerInputParameterivNV ) { bNVRegisterCombiners = false; qglCombinerParameterfvNV = NULL; qglCombinerParameteriNV = NULL; Com_Printf ("...GL_NV_register_combiners failed\n" ); } } else { bNVRegisterCombiners = false; Com_Printf ("...ignoring GL_NV_register_combiners\n" ); } } else { bNVRegisterCombiners = false; Com_Printf ("...GL_NV_register_combiners not found\n" ); } // NOTE: Vertex and Fragment Programs are very dependant on each other - this is actually a // good thing! So, just check to see which we support (one or the other) and load the shared // function pointers. ARB rocks! // Vertex Programs. bool bARBVertexProgram = false; if ( strstr( glConfig.extensions_string, "GL_ARB_vertex_program" ) ) { bARBVertexProgram = true; } else { bARBVertexProgram = false; Com_Printf ("...GL_ARB_vertex_program not found\n" ); } // Fragment Programs. bool bARBFragmentProgram = false; if ( strstr( glConfig.extensions_string, "GL_ARB_fragment_program" ) ) { bARBFragmentProgram = true; } else { bARBFragmentProgram = false; Com_Printf ("...GL_ARB_fragment_program not found\n" ); } // If we support one or the other, load the shared function pointers. if ( bARBVertexProgram || bARBFragmentProgram ) { qglProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) SDL_GL_GetProcAddress("glProgramStringARB"); qglBindProgramARB = (PFNGLBINDPROGRAMARBPROC) SDL_GL_GetProcAddress("glBindProgramARB"); qglDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) SDL_GL_GetProcAddress("glDeleteProgramsARB"); qglGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) SDL_GL_GetProcAddress("glGenProgramsARB"); qglProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4dARB"); qglProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4dvARB"); qglProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4fARB"); qglProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) SDL_GL_GetProcAddress("glProgramEnvParameter4fvARB"); qglProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4dARB"); qglProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4dvARB"); qglProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4fARB"); qglProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) SDL_GL_GetProcAddress("glProgramLocalParameter4fvARB"); qglGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) SDL_GL_GetProcAddress("glGetProgramEnvParameterdvARB"); qglGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetProgramEnvParameterfvARB"); qglGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) SDL_GL_GetProcAddress("glGetProgramLocalParameterdvARB"); qglGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetProgramLocalParameterfvARB"); qglGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) SDL_GL_GetProcAddress("glGetProgramivARB"); qglGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) SDL_GL_GetProcAddress("glGetProgramStringARB"); qglIsProgramARB = (PFNGLISPROGRAMARBPROC) SDL_GL_GetProcAddress("glIsProgramARB"); // Validate the functions we need. if ( !qglProgramStringARB || !qglBindProgramARB || !qglDeleteProgramsARB || !qglGenProgramsARB || !qglProgramEnvParameter4dARB || !qglProgramEnvParameter4dvARB || !qglProgramEnvParameter4fARB || !qglProgramEnvParameter4fvARB || !qglProgramLocalParameter4dARB || !qglProgramLocalParameter4dvARB || !qglProgramLocalParameter4fARB || !qglProgramLocalParameter4fvARB || !qglGetProgramEnvParameterdvARB || !qglGetProgramEnvParameterfvARB || !qglGetProgramLocalParameterdvARB || !qglGetProgramLocalParameterfvARB || !qglGetProgramivARB || !qglGetProgramStringARB || !qglIsProgramARB ) { bARBVertexProgram = false; bARBFragmentProgram = false; qglGenProgramsARB = NULL; //clear ptrs that get checked qglProgramEnvParameter4fARB = NULL; Com_Printf ("...ignoring GL_ARB_vertex_program\n" ); Com_Printf ("...ignoring GL_ARB_fragment_program\n" ); } } // Figure out which texture rectangle extension to use. bool bTexRectSupported = false; if ( Q_strnicmp( glConfig.vendor_string, "ATI Technologies",16 )==0 && Q_strnicmp( glConfig.version_string, "1.3.3",5 )==0 && glConfig.version_string[5] < '9' ) //1.3.34 and 1.3.37 and 1.3.38 are broken for sure, 1.3.39 is not { g_bTextureRectangleHack = true; } if ( strstr( glConfig.extensions_string, "GL_NV_texture_rectangle" ) || strstr( glConfig.extensions_string, "GL_EXT_texture_rectangle" ) ) { bTexRectSupported = true; } #if 0 // OK, so not so good to put this here, but no one else uses it!!! -AReis typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); PFNWGLGETEXTENSIONSSTRINGARBPROC qwglGetExtensionsStringARB; qwglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) SDL_GL_GetProcAddress("wglGetExtensionsStringARB"); const char *wglExtensions = NULL; #endif bool bHasPixelFormat = false; bool bHasRenderTexture = false; #if 0 // Get the WGL extensions string. if ( qwglGetExtensionsStringARB ) { wglExtensions = qwglGetExtensionsStringARB( glw_state.hDC ); } // This externsion is used to get the wgl extension string. if ( wglExtensions ) { // Pixel Format. if ( strstr( wglExtensions, "WGL_ARB_pixel_format" ) ) { qwglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) SDL_GL_GetProcAddress("wglGetPixelFormatAttribivARB"); qwglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC) SDL_GL_GetProcAddress("wglGetPixelFormatAttribfvARB"); qwglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) SDL_GL_GetProcAddress("wglChoosePixelFormatARB"); // Validate the functions we need. if ( !qwglGetPixelFormatAttribivARB || !qwglGetPixelFormatAttribfvARB || !qwglChoosePixelFormatARB ) { Com_Printf ("...ignoring WGL_ARB_pixel_format\n" ); } else { bHasPixelFormat = true; } } else { Com_Printf ("...ignoring WGL_ARB_pixel_format\n" ); } // Offscreen pixel-buffer. // NOTE: VV guys can use the equivelant SetRenderTarget() with the correct texture surfaces. bool bWGLARBPbuffer = false; if ( strstr( wglExtensions, "WGL_ARB_pbuffer" ) && bHasPixelFormat ) { bWGLARBPbuffer = true; qwglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) SDL_GL_GetProcAddress("wglCreatePbufferARB"); qwglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC) SDL_GL_GetProcAddress("wglGetPbufferDCARB"); qwglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC) SDL_GL_GetProcAddress("wglReleasePbufferDCARB"); qwglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC) SDL_GL_GetProcAddress("wglDestroyPbufferARB"); qwglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC) SDL_GL_GetProcAddress("wglQueryPbufferARB"); // Validate the functions we need. if ( !qwglCreatePbufferARB || !qwglGetPbufferDCARB || !qwglReleasePbufferDCARB || !qwglDestroyPbufferARB || !qwglQueryPbufferARB ) { bWGLARBPbuffer = false; Com_Printf ("...WGL_ARB_pbuffer failed\n" ); } } else { bWGLARBPbuffer = false; Com_Printf ("...WGL_ARB_pbuffer not found\n" ); } // Render-Texture (requires pbuffer ext (and it's dependancies of course). if ( strstr( wglExtensions, "WGL_ARB_render_texture" ) && bWGLARBPbuffer ) { qwglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC) SDL_GL_GetProcAddress("wglBindTexImageARB"); qwglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC) SDL_GL_GetProcAddress("wglReleaseTexImageARB"); qwglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC) SDL_GL_GetProcAddress("wglSetPbufferAttribARB"); // Validate the functions we need. if ( !qwglCreatePbufferARB || !qwglGetPbufferDCARB || !qwglReleasePbufferDCARB || !qwglDestroyPbufferARB || !qwglQueryPbufferARB ) { Com_Printf ("...ignoring WGL_ARB_render_texture\n" ); } else { bHasRenderTexture = true; } } else { Com_Printf ("...ignoring WGL_ARB_render_texture\n" ); } } #endif // Find out how many general combiners they have. #define GL_MAX_GENERAL_COMBINERS_NV 0x854D GLint iNumGeneralCombiners = 0; qglGetIntegerv( GL_MAX_GENERAL_COMBINERS_NV, &iNumGeneralCombiners ); // Only allow dynamic glows/flares if they have the hardware if ( bTexRectSupported && bARBVertexProgram && bHasRenderTexture && qglActiveTextureARB && glConfig.maxActiveTextures >= 4 && ( ( bNVRegisterCombiners && iNumGeneralCombiners >= 2 ) || bARBFragmentProgram ) ) { g_bDynamicGlowSupported = true; // this would overwrite any achived setting gwg // Cvar_Set( "r_DynamicGlow", "1" ); } else { g_bDynamicGlowSupported = false; Cvar_Set( "r_DynamicGlow","0" ); } }
/* ** GLW_InitExtensions */ static void GLW_InitExtensions( void ) { // Select our tc scheme GLW_InitTextureCompression(); // GL_EXT_texture_env_add glConfig.textureEnvAddAvailable = qfalse; if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) ) { glConfig.textureEnvAddAvailable = qtrue; } // GL_EXT_texture_filter_anisotropic glConfig.maxTextureFilterAnisotropy = 0; if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) ) { qglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxTextureFilterAnisotropy ); Com_Printf ("...GL_EXT_texture_filter_anisotropic available\n" ); if ( r_ext_texture_filter_anisotropic->integer>1 ) { Com_Printf ("...using GL_EXT_texture_filter_anisotropic\n" ); } else { Com_Printf ("...ignoring GL_EXT_texture_filter_anisotropic\n" ); } Cvar_Set( "r_ext_texture_filter_anisotropic_avail", va("%f",glConfig.maxTextureFilterAnisotropy) ); if ( r_ext_texture_filter_anisotropic->value > glConfig.maxTextureFilterAnisotropy ) { Cvar_Set( "r_ext_texture_filter_anisotropic", va("%f",glConfig.maxTextureFilterAnisotropy) ); } } else { Com_Printf ("...GL_EXT_texture_filter_anisotropic not found\n" ); Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "0" ); } // GL_EXT_clamp_to_edge glConfig.clampToEdgeAvailable = qfalse; if ( strstr( glConfig.extensions_string, "GL_EXT_texture_edge_clamp" ) ) { glConfig.clampToEdgeAvailable = qtrue; } // GL_ARB_multitexture if ( strstr( glConfig.extensions_string, "GL_ARB_multitexture" ) ) { if ( qglActiveTextureARB ) { qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures ); if ( glConfig.maxActiveTextures < 2 ) { qglMultiTexCoord2fARB = NULL; qglActiveTextureARB = NULL; qglClientActiveTextureARB = NULL; } } } }