mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 04:31:34 -10:00
509 lines
18 KiB
C++
509 lines
18 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "globalincs/pstypes.h"
|
|
#include "graphics/gropengl.h"
|
|
#include "graphics/gropenglextension.h"
|
|
#include "graphics/gropengltexture.h"
|
|
#include "cmdline/cmdline.h"
|
|
#include "ddsutils/ddsutils.h"
|
|
#include "popup/popup.h"
|
|
|
|
#include "osapi/outwnd.h"
|
|
|
|
|
|
|
|
char *OGL_extension_string = NULL;
|
|
|
|
// ogl_extension is:
|
|
// - required for game flag
|
|
// - enabled flag
|
|
// - number of extensions to check for
|
|
// - extension name(s) (max is 3 variants)
|
|
// - number of functions that extension needs/wants
|
|
// - function names that extension needs (max is 20)
|
|
|
|
// OpenGL extensions that we will want to use
|
|
ogl_extension GL_Extensions[NUM_OGL_EXTENSIONS] =
|
|
{
|
|
// allows for per vertex fog coordinate
|
|
{ false, false, 1, { "GL_EXT_fog_coord" }, 2, {
|
|
"glFogCoordfEXT", "glFogCoordPointerEXT" } },
|
|
|
|
// provides multiple texture units for rendering more than one texture in a single pass
|
|
// (NOTE: this was included in OpenGL 1.2.1 standard, but we still need to check for it or require > 1.2 OGL)
|
|
{ true, false, 1, { "GL_ARB_multitexture" } , 3, {
|
|
"glMultiTexCoord2fARB", "glActiveTextureARB", "glClientActiveTextureARB" } },
|
|
|
|
// "ADD" function for texture environment
|
|
{ true, false, 2, { "GL_ARB_texture_env_add", "GL_EXT_texture_env_add" }, 0, { NULL } },
|
|
|
|
// framework for using compressed textures (doesn't provide actual compression formats we use)
|
|
{ false, false, 1, { "GL_ARB_texture_compression" }, 3, {
|
|
"glCompressedTexImage2D", "glCompressedTexSubImage2D", "glGetCompressedTexImageARB" } },
|
|
|
|
// S3TC texture compression/decompression support (DXT? encoded DDS images)
|
|
{ false, false, 1, { "GL_EXT_texture_compression_s3tc" }, 0, { NULL } },
|
|
|
|
// allows for setting of anisotropic filter (for mipmap texture filtering)
|
|
{ false, false, 1, { "GL_EXT_texture_filter_anisotropic" }, 0, { NULL } },
|
|
|
|
// provides app support to control how distance is calculated in fog computations
|
|
// { false, false, 1, { "GL_NV_fog_distance" }, 0, { NULL } },
|
|
|
|
// specify RGB values for secondary color
|
|
// { false, false, 1, { "GL_EXT_secondary_color" }, 2, {
|
|
// "glSecondaryColor3fvEXT", "glSecondaryColor3ubvEXT" } },
|
|
|
|
// "COMBINE" function for texture environment, these two are basically the same
|
|
{ false, false, 2, { "GL_ARB_texture_env_combine", "GL_EXT_texture_env_combine" }, 0, { NULL } },
|
|
|
|
// lock a vertex array buffer so that OGL can transform it just once with multiple draws
|
|
{ false, false, 1, { "GL_EXT_compiled_vertex_array" }, 2, {
|
|
"glLockArraysEXT", "glUnlockArraysEXT" } },
|
|
|
|
// allows for row major order matrices rather than the standard column major order
|
|
// { true, false, 1, { "GL_ARB_transpose_matrix" }, 2, {
|
|
// "glLoadTransposeMatrixfARB", "glMultTransposeMatrixfARB" } },
|
|
|
|
// this is obsolete with OGL 1.2, which is why the function name is the standard, but we check for the orginal extension name
|
|
{ true, false, 1, { "GL_EXT_draw_range_elements" }, 1, {
|
|
"glDrawRangeElements" } },
|
|
|
|
// extra texture wrap repeat mode
|
|
{ false, false, 1, { "GL_ARB_texture_mirrored_repeat" }, 0, { NULL } },
|
|
|
|
// allows for non-power-of-two textures, but without any cost to normal functionality or usage
|
|
{ false, false, 1, { "GL_ARB_texture_non_power_of_two" }, 0, { NULL } },
|
|
|
|
// creates buffer objects (cached in hi-speed video card memory) for vertex data
|
|
{ false, false, 1, { "GL_ARB_vertex_buffer_object" }, 6, {
|
|
"glBindBufferARB", "glDeleteBuffersARB", "glGenBuffersARB", "glBufferDataARB",
|
|
"glMapBufferARB", "glUnmapBufferARB" } },
|
|
|
|
// allows pixel data to use buffer objects
|
|
{ false, false, 2, { "GL_ARB_pixel_buffer_object", "GL_EXT_pixel_buffer_object" }, 7, {
|
|
"glBindBufferARB", "glDeleteBuffersARB", "glGenBuffersARB", "glBufferDataARB",
|
|
"glBufferSubDataARB", "glMapBufferARB", "glUnmapBufferARB" } },
|
|
|
|
// make me some mipmaps!
|
|
{ false, false, 1, { "GL_SGIS_generate_mipmap" }, 0, { NULL } },
|
|
|
|
// framebuffer object gives us render-to-texture support, among other things
|
|
{ false, false, 1, { "GL_EXT_framebuffer_object" }, 16, {
|
|
"glIsRenderbufferEXT", "glBindRenderbufferEXT", "glDeleteRenderbuffersEXT", "glGenRenderbuffersEXT",
|
|
"glRenderbufferStorageEXT", "glGetRenderbufferParameterivEXT", "glIsFramebufferEXT", "glBindFramebufferEXT",
|
|
"glDeleteFramebuffersEXT", "glGenFramebuffersEXT", "glCheckFramebufferStatusEXT", "glFramebufferTexture2DEXT",
|
|
"glFramebufferRenderbufferEXT", "glGetFramebufferAttachmentParameterivEXT", "glGenerateMipmapEXT", "glDrawBuffers" } },
|
|
|
|
// these next three are almost exactly the same, just different stages of naming.
|
|
// allows for non-power-of-textures, but at a cost of functionality
|
|
// (NOTE: the EXT version is usually found only on the Mac)
|
|
{ false, false, 3, { "GL_ARB_texture_rectangle", "GL_EXT_texture_rectangle", "GL_NV_texture_rectangle" }, 0, { NULL } },
|
|
|
|
// for BGRA rather than RGBA support (it's faster in most cases)
|
|
{ true, false, 1, { "GL_EXT_bgra" }, 0, { NULL } },
|
|
|
|
// cube map support (for environment maps, normal maps, bump maps, etc.)
|
|
{ false, false, 2, { "GL_ARB_texture_cube_map", "GL_EXT_texture_cube_map" }, 0, { NULL } },
|
|
|
|
// apply bias to level-of-detail lamda
|
|
{ false, false, 1, { "GL_EXT_texture_lod_bias" }, 0, { NULL } },
|
|
|
|
// point sprites (for particles)
|
|
{ false, false, 2, { "GL_ARB_point_sprite", "NV_point_sprite" }, 0, { NULL } },
|
|
|
|
// OpenGL Shading Language support. If this is present, then GL_ARB_shader_objects, GL_ARB_fragment_shader
|
|
// and GL_ARB_vertex_shader should also be available.
|
|
{ false, false, 1, { "GL_ARB_shading_language_100" }, 0, { NULL } },
|
|
|
|
// shader objects and program object management
|
|
{ false, false, 1, { "GL_ARB_shader_objects" }, 19, { "glDeleteObjectARB", "glCreateShaderObjectARB", "glShaderSourceARB",
|
|
"glCompileShaderARB", "glGetObjectParameterivARB", "glGetInfoLogARB", "glCreateProgramObjectARB",
|
|
"glAttachObjectARB", "glLinkProgramARB", "glUseProgramObjectARB", "glValidateProgramARB", "glGetUniformLocationARB",
|
|
"glGetUniformivARB", "glUniform1fARB", "glUniform2fARB", "glUniform3fARB", "glUniform4fARB", "glUniform1iARB", "glUniformMatrix4fvARB" } },
|
|
|
|
// programmable vertex level processing
|
|
// some of functions are provided by GL_ARB_vertex_program
|
|
{ false, false, 1, { "GL_ARB_vertex_shader" }, 4, { "glEnableVertexAttribArrayARB", "glDisableVertexAttribArrayARB",
|
|
"glGetAttribLocationARB", "glVertexAttribPointerARB" } },
|
|
|
|
// programmable fragment level processing
|
|
{ false, false, 1, { "GL_ARB_fragment_shader" }, 0, { NULL } },
|
|
|
|
// shader version 3.0 detection extensions (if any of these extensions exist then we should have a SM3.0 compatible card, hopefully)
|
|
{ false, false, 3, { "GL_ARB_shader_texture_lod", "GL_NV_vertex_program3", "GL_ATI_shader_texture_lod" }, 0, { NULL } },
|
|
|
|
{ false, false, 1, { "GL_ARB_texture_float" }, 0, { NULL } },
|
|
|
|
{ false, false, 1, { "GL_ARB_draw_elements_base_vertex" }, 4, { "glDrawElementsBaseVertex", "glDrawRangeElementsBaseVertex",
|
|
"glDrawElementsInstancedBaseVertex", "glMultiDrawElementsBaseVertex" } },
|
|
|
|
{ false, false, 1, {"GL_EXT_framebuffer_blit" }, 1, { "glBlitFramebufferEXT" } },
|
|
|
|
// geometry shaders
|
|
{ false, false, 1, { "GL_EXT_geometry_shader4" }, 2, { "glProgramParameteriEXT", "glFramebufferTextureEXT" } },
|
|
|
|
// array textures
|
|
{ false, false, 1, { "GL_EXT_texture_array" }, 1, { "glTexImage3D" } },
|
|
|
|
{ false, false, 1, { "GL_ARB_uniform_buffer_object" }, 7, { "glGetUniformIndices", "glGetActiveUniformsiv", "glGetActiveUniformName",
|
|
"glGetUniformBlockIndex", "glGetActiveUniformBlockiv", "glGetActiveUniformBlockName", "glUniformBlockBinding" } },
|
|
|
|
{ false, false, 1, { "GL_EXT_transform_feedback" }, 7, { "glBeginTransformFeedbackEXT", "glEndTransformFeedbackEXT", "glBindBufferRangeEXT",
|
|
"glBindBufferOffsetEXT", "glBindBufferBaseEXT", "glTransformFeedbackVaryingsEXT", "glGetTransformFeedbackVaryingEXT" } },
|
|
|
|
{ false, false, 1, { "GL_ARB_draw_instanced" }, 2, { "glDrawArraysInstancedARB", "glDrawElementsInstancedARB" } },
|
|
|
|
{ false, false, 1, { "GL_ARB_texture_buffer_object" }, 1, { "glTexBufferARB" } }
|
|
};
|
|
|
|
// ogl_funcion is:
|
|
// - function name
|
|
// - pointer for extension
|
|
|
|
// All of the OpenGL functions that the extensions need
|
|
ogl_function GL_Functions[NUM_OGL_FUNCTIONS] =
|
|
{
|
|
{ "glFogCoordfEXT", 0 },
|
|
{ "glFogCoordPointerEXT", 0 },
|
|
{ "glMultiTexCoord2fARB", 0 },
|
|
{ "glActiveTextureARB", 0 },
|
|
{ "glClientActiveTextureARB", 0 },
|
|
{ "glCompressedTexImage2D", 0 },
|
|
{ "glCompressedTexSubImage2D", 0 },
|
|
{ "glGetCompressedTexImageARB", 0 },
|
|
// { "glSecondaryColor3fvEXT", 0 },
|
|
// { "glSecondaryColor3ubvEXT", 0 },
|
|
{ "glLockArraysEXT", 0 },
|
|
{ "glUnlockArraysEXT", 0 },
|
|
// { "glLoadTransposeMatrixfARB", 0 },
|
|
// { "glMultTransposeMatrixfARB", 0 },
|
|
{ "glDrawRangeElements", 0 },
|
|
{ "glBindBufferARB", 0 },
|
|
{ "glDeleteBuffersARB", 0 },
|
|
{ "glGenBuffersARB", 0 },
|
|
{ "glBufferDataARB", 0 },
|
|
{ "glBufferSubDataARB", 0 },
|
|
{ "glMapBufferARB", 0 },
|
|
{ "glUnmapBufferARB", 0 },
|
|
{ "glIsRenderbufferEXT", 0 },
|
|
{ "glBindRenderbufferEXT", 0 },
|
|
{ "glDeleteRenderbuffersEXT", 0 },
|
|
{ "glGenRenderbuffersEXT", 0 },
|
|
{ "glRenderbufferStorageEXT", 0 },
|
|
{ "glGetRenderbufferParameterivEXT", 0 },
|
|
{ "glIsFramebufferEXT", 0 },
|
|
{ "glBindFramebufferEXT", 0 },
|
|
{ "glDeleteFramebuffersEXT", 0 },
|
|
{ "glGenFramebuffersEXT", 0 },
|
|
{ "glCheckFramebufferStatusEXT", 0 },
|
|
{ "glFramebufferTexture2DEXT", 0 },
|
|
{ "glFramebufferRenderbufferEXT", 0 },
|
|
{ "glGetFramebufferAttachmentParameterivEXT", 0 },
|
|
{ "glGenerateMipmapEXT", 0 },
|
|
{ "glDeleteObjectARB", 0 },
|
|
{ "glCreateShaderObjectARB", 0 },
|
|
{ "glShaderSourceARB", 0 },
|
|
{ "glCompileShaderARB", 0 },
|
|
{ "glGetObjectParameterivARB", 0 },
|
|
{ "glGetInfoLogARB", 0 },
|
|
{ "glCreateProgramObjectARB", 0 },
|
|
{ "glAttachObjectARB", 0 },
|
|
{ "glLinkProgramARB", 0 },
|
|
{ "glUseProgramObjectARB", 0 },
|
|
{ "glValidateProgramARB", 0 },
|
|
{ "glEnableVertexAttribArrayARB", 0 },
|
|
{ "glDisableVertexAttribArrayARB", 0 },
|
|
{ "glGetAttribLocationARB", 0 },
|
|
{ "glVertexAttribPointerARB", 0 },
|
|
{ "glGetUniformLocationARB", 0 },
|
|
{ "glGetUniformivARB", 0 },
|
|
{ "glUniform1fARB", 0 },
|
|
{ "glUniform2fARB", 0 },
|
|
{ "glUniform3fARB", 0 },
|
|
{ "glUniform4fARB", 0 },
|
|
{ "glUniform3fvARB", 0 },
|
|
{ "glUniform4fvARB", 0 },
|
|
{ "glUniform1iARB", 0 },
|
|
{ "glUniformMatrix4fvARB", 0 },
|
|
{ "glDrawBuffers", 0 },
|
|
{ "glDrawElementsBaseVertex", 0 },
|
|
{ "glDrawRangeElementsBaseVertex", 0 },
|
|
{ "glDrawElementsInstancedBaseVertex", 0 },
|
|
{ "glMultiDrawElementsBaseVertex", 0 },
|
|
{ "glBlitFramebufferEXT", 0},
|
|
{ "glProgramParameteriEXT", 0 },
|
|
{ "glTexImage3D", 0 },
|
|
{ "glFramebufferTextureEXT", 0 },
|
|
{ "glGetUniformIndices", 0 },
|
|
{ "glGetActiveUniformsiv", 0 },
|
|
{ "glGetActiveUniformName", 0 },
|
|
{ "glGetUniformBlockIndex", 0 },
|
|
{ "glGetActiveUniformBlockiv", 0 },
|
|
{ "glGetActiveUniformBlockName", 0 },
|
|
{ "glUniformBlockBinding", 0 },
|
|
{ "glBeginTransformFeedbackEXT", 0 },
|
|
{ "glEndTransformFeedbackEXT", 0 },
|
|
{ "glBindBufferRangeEXT", 0 },
|
|
{ "glBindBufferOffsetEXT", 0 },
|
|
{ "glBindBufferBaseEXT", 0 },
|
|
{ "glTransformFeedbackVaryingsEXT", 0 },
|
|
{ "glGetTransformFeedbackVaryingEXT", 0 },
|
|
{ "glDrawArraysInstancedARB", 0 },
|
|
{ "glDrawElementsInstancedARB", 0 },
|
|
{ "glTexBufferARB", 0 }
|
|
};
|
|
|
|
// special extensions (only special functions are supported at the moment)
|
|
ogl_function GL_EXT_Special[NUM_OGL_EXT_SPECIAL] = {
|
|
{ "wglSwapIntervalEXT", 0 },
|
|
{ "glXSwapIntervalSGI", 0 }
|
|
};
|
|
|
|
|
|
#ifdef _WIN32
|
|
#define GET_PROC_ADDRESS(x) wglGetProcAddress((x))
|
|
#else
|
|
#define GET_PROC_ADDRESS(x) SDL_GL_GetProcAddress((x))
|
|
#endif
|
|
|
|
//tries to find a certain extension
|
|
static inline int opengl_find_extension(const char *ext_to_find)
|
|
{
|
|
if (OGL_extension_string == NULL)
|
|
return 0;
|
|
|
|
return ( strstr(OGL_extension_string, ext_to_find) != NULL );
|
|
}
|
|
|
|
// these extensions may not be listed the normal way so we don't check the extension string for them
|
|
static int opengl_get_extensions_special()
|
|
{
|
|
int i, num_found = 0;
|
|
ogl_function *func = NULL;
|
|
|
|
for (i = 0; i < NUM_OGL_EXT_SPECIAL; i++) {
|
|
func = &GL_EXT_Special[i];
|
|
|
|
Assert( func->function_name != NULL );
|
|
|
|
func->function_ptr = (ptr_u)GET_PROC_ADDRESS(func->function_name);
|
|
|
|
if (func->function_ptr) {
|
|
mprintf((" Found special extension function \"%s\".\n", func->function_name));
|
|
num_found++;
|
|
}
|
|
}
|
|
|
|
return num_found;
|
|
}
|
|
|
|
ogl_function *get_ogl_function( const char *name )
|
|
{
|
|
if (name == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (int i = 0; i < NUM_OGL_FUNCTIONS; i++) {
|
|
if ( !strcmp(GL_Functions[i].function_name, name) ) {
|
|
return &GL_Functions[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//finds OGL extension functions
|
|
//returns number found
|
|
int opengl_get_extensions()
|
|
{
|
|
int i, j, k, num_found = 0;
|
|
ogl_extension *ext = NULL;
|
|
ogl_function *func = NULL;
|
|
|
|
OGL_extension_string = (char*)glGetString(GL_EXTENSIONS);
|
|
|
|
for (i = 0; i < NUM_OGL_EXTENSIONS; i++) {
|
|
ext = &GL_Extensions[i];
|
|
k = 0;
|
|
|
|
while ( !ext->enabled && (k < ext->num_extensions) ) {
|
|
if ( opengl_find_extension(ext->extension_name[k]) ) {
|
|
// some extensions do not have functions
|
|
if (!ext->num_functions) {
|
|
mprintf((" Using extension \"%s\".\n", ext->extension_name[k]));
|
|
ext->enabled = 1;
|
|
num_found++;
|
|
goto Next;
|
|
}
|
|
|
|
// we do have functions so check any/all of them
|
|
for (j = 0; j < ext->num_functions; j++) {
|
|
func = get_ogl_function( ext->function_names[j] );
|
|
|
|
if (func == NULL)
|
|
break;
|
|
|
|
if ( !func->function_ptr )
|
|
func->function_ptr = (ptr_u)GET_PROC_ADDRESS(func->function_name);
|
|
|
|
if ( !func->function_ptr )
|
|
break;
|
|
}
|
|
|
|
if ( j != ext->num_functions ) {
|
|
mprintf((" Found extension \"%s\", but can't find the required function \"%s()\". Extension will be disabled!\n", ext->extension_name[k], ext->function_names[j]));
|
|
|
|
if (ext->required_to_run)
|
|
Error( LOCATION, "The required OpenGL extension '%s' is not fully supported by your current driver version or graphics card.\n", ext->extension_name[k] );
|
|
} else {
|
|
mprintf((" Using extension \"%s\".\n", ext->extension_name[k]));
|
|
ext->enabled = 1;
|
|
num_found++;
|
|
}
|
|
} else {
|
|
// only report if unable to find when we have checked all available extension name variants
|
|
if ( k+1 >= ext->num_extensions ) {
|
|
mprintf((" Unable to find extension \"%s\".\n", ext->extension_name[k]));
|
|
|
|
if (ext->required_to_run)
|
|
Error( LOCATION, "The required OpenGL extension '%s' is not supported by your current driver version or graphics card.\n", ext->extension_name[k] );
|
|
}
|
|
}
|
|
|
|
// now move the the next extension name
|
|
Next:
|
|
k++;
|
|
}
|
|
}
|
|
|
|
num_found += opengl_get_extensions_special();
|
|
|
|
mprintf(( "\n" ));
|
|
|
|
return num_found;
|
|
}
|
|
|
|
|
|
extern int OGL_fogmode;
|
|
|
|
void opengl_extensions_init()
|
|
{
|
|
opengl_get_extensions();
|
|
|
|
// if S3TC compression is found, then "GL_ARB_texture_compression" must be an extension
|
|
Use_compressed_textures = Is_Extension_Enabled(OGL_EXT_TEXTURE_COMPRESSION_S3TC);
|
|
Texture_compression_available = Is_Extension_Enabled(OGL_ARB_TEXTURE_COMPRESSION);
|
|
// Swifty put this in, but it's not doing anything. Once he uses it, he can uncomment it.
|
|
//int use_base_vertex = Is_Extension_Enabled(OGL_ARB_DRAW_ELEMENTS_BASE_VERTEX);
|
|
|
|
//allow VBOs to be used
|
|
if ( !Cmdline_nohtl && !Cmdline_novbo && Is_Extension_Enabled(OGL_ARB_VERTEX_BUFFER_OBJECT) ) {
|
|
Use_VBOs = 1;
|
|
}
|
|
|
|
if ( !Cmdline_no_pbo && Is_Extension_Enabled(OGL_ARB_PIXEL_BUFFER_OBJECT) ) {
|
|
Use_PBOs = 1;
|
|
}
|
|
|
|
// setup the best fog function found
|
|
if ( !Fred_running ) {
|
|
if ( Is_Extension_Enabled(OGL_EXT_FOG_COORD) ) {
|
|
OGL_fogmode = 2;
|
|
} else {
|
|
OGL_fogmode = 1;
|
|
}
|
|
}
|
|
|
|
// if we can't do cubemaps then turn off Cmdline_env
|
|
if ( !(Is_Extension_Enabled(OGL_ARB_TEXTURE_CUBE_MAP) && Is_Extension_Enabled(OGL_ARB_TEXTURE_ENV_COMBINE)) ) {
|
|
Cmdline_env = 0;
|
|
}
|
|
|
|
if ( !(Is_Extension_Enabled(OGL_EXT_GEOMETRY_SHADER4) && Is_Extension_Enabled(OGL_EXT_TEXTURE_ARRAY) && Is_Extension_Enabled(OGL_ARB_DRAW_ELEMENTS_BASE_VERTEX)) ) {
|
|
Cmdline_shadow_quality = 0;
|
|
mprintf((" No hardware support for shadow mapping. Shadows will be disabled. \n"));
|
|
#ifdef NDEBUG
|
|
popup(0, 1, POPUP_OK, "No hardware support for shadow mapping. Shadows will be disabled.\n");
|
|
#endif
|
|
}
|
|
|
|
if ( !Cmdline_noglsl && Is_Extension_Enabled(OGL_ARB_SHADER_OBJECTS) && Is_Extension_Enabled(OGL_ARB_FRAGMENT_SHADER)
|
|
&& Is_Extension_Enabled(OGL_ARB_VERTEX_SHADER) ) {
|
|
int ver = 0, major = 0, minor = 0;
|
|
const char *glsl_ver = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB);
|
|
|
|
sscanf(glsl_ver, "%d.%d", &major, &minor);
|
|
ver = (major * 100) + minor;
|
|
|
|
// SM 4.0 compatible or better
|
|
if (ver >= 400) {
|
|
Use_GLSL = 4;
|
|
}
|
|
// SM 3.0 compatible
|
|
else if ( ver >= 130 ) {
|
|
Use_GLSL = 3;
|
|
}
|
|
// SM 2.0 compatible
|
|
else if (ver >= 120) {
|
|
Use_GLSL = 2;
|
|
}
|
|
// we require GLSL 1.20 or higher
|
|
else if (ver < 110) {
|
|
Use_GLSL = 0;
|
|
mprintf((" OpenGL Shading Language version %s is not sufficient to use GLSL mode in FSO. Defaulting to fixed-function renderer.\n", glGetString(GL_SHADING_LANGUAGE_VERSION_ARB) ));
|
|
#ifdef NDEBUG
|
|
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "GLSL support not available on this GPU. Disabling shader support and defaulting to fixed-function rendering.\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// can't have this stuff without GLSL support
|
|
if ( !Use_GLSL ) {
|
|
Cmdline_normal = 0;
|
|
Cmdline_height = 0;
|
|
Cmdline_postprocess = 0;
|
|
Cmdline_shadow_quality = 0;
|
|
Cmdline_no_deferred_lighting = 1;
|
|
}
|
|
|
|
if ( Use_GLSL < 2 || !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || !Is_Extension_Enabled(OGL_ARB_FLOATING_POINT_TEXTURES) ) {
|
|
mprintf((" No hardware support for deferred lighting. Deferred lighting will be disabled. \n"));
|
|
Cmdline_no_deferred_lighting = 1;
|
|
Cmdline_no_batching = true;
|
|
}
|
|
|
|
if (Use_GLSL) {
|
|
GLint max_texture_units;
|
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &max_texture_units);
|
|
|
|
// we need enough texture slots for this stuff to work
|
|
|
|
if (max_texture_units < 6) {
|
|
mprintf(( "Not enough texture units for height map support. We need at least 6, we found %d.\n", max_texture_units ));
|
|
Cmdline_height = 0;
|
|
} else if (max_texture_units < 5) {
|
|
mprintf(( "Not enough texture units for height and normal map support. We need at least 5, we found %d.\n", max_texture_units ));
|
|
Cmdline_normal = 0;
|
|
Cmdline_height = 0;
|
|
} else if (max_texture_units < 4) {
|
|
mprintf(( "Not enough texture units found for GLSL support. We need at least 4, we found %d.\n", max_texture_units ));
|
|
Use_GLSL = 0;
|
|
}
|
|
}
|
|
}
|