mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-11 04:31:35 -10:00
git-svn-id: svn://svn.icculus.org/fs2open/trunk/fs2_open@4128 387891d4-d844-0410-90c0-e4c51a9137d3
405 lines
15 KiB
C++
405 lines
15 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.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/Graphics/GrOpenGLExtension.cpp $
|
|
* $Revision: 1.18 $
|
|
* $Date: 2007-04-13 00:31:58 $
|
|
* $Author: taylor $
|
|
*
|
|
* source for extension implementation in OpenGL
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 1.17 2007/01/07 13:08:12 taylor
|
|
* clean up extension list and comment out the things that we don't use
|
|
*
|
|
* Revision 1.16 2006/08/09 14:42:24 taylor
|
|
* fix for setting of texture lod bias
|
|
*
|
|
* Revision 1.15 2006/05/13 07:29:52 taylor
|
|
* OpenGL envmap support
|
|
* newer OpenGL extension support
|
|
* add GL_ARB_texture_rectangle support for non-power-of-2 textures as interface graphics
|
|
* add cubemap reading and writing support to DDS loader
|
|
* fix bug in DDS loader that made compressed images with mipmaps use more memory than they really required
|
|
* add support for a default envmap named "cubemap.dds"
|
|
* new mission flag "$Environment Map:" to use a pre-existing envmap
|
|
* minor cleanup of compiler warning messages
|
|
* get rid of wasteful math from gr_set_proj_matrix()
|
|
* remove extra gr_set_*_matrix() calls from starfield.cpp as there was no longer a reason for them to be there
|
|
* clean up bmpman flags in reguards to cubemaps and render targets
|
|
* disable D3D envmap code until it can be upgraded to current level of code
|
|
* remove bumpmap code from OpenGL stuff (sorry but it was getting in the way, if it was more than copy-paste it would be worth keeping)
|
|
* replace gluPerspective() call with glFrustum() call, it's a lot less math this way and saves the extra function call
|
|
*
|
|
* Revision 1.14 2006/03/22 18:14:52 taylor
|
|
* if -mipmap is used with -img2dds to then have compressed image also contain mipmaps
|
|
* use nicest hints for texture compression, should improve quality a little
|
|
* when reporting compressed sizes to debug log make ani size be total, not per frame
|
|
*
|
|
* Revision 1.13 2006/02/24 07:35:48 taylor
|
|
* add v-sync support for OGL (I skimmped on this a bit but will go back to do something better, "special" extension wise, at a later date)
|
|
*
|
|
* Revision 1.12 2005/12/28 22:28:44 taylor
|
|
* add support for glCompressedTexSubImage2D(), we don't use it yet but there is nothing wrong with adding it already
|
|
* better support for mipmaps and mipmap filtering
|
|
* add reg option "TextureFilter" to set bilinear or trilinear filter
|
|
* clean up bitmap_id/bitmap_handle/texture_handle madness that made things difficult to understand
|
|
* small fix for using 24-bit images on 16-bit bpp visual (untested)
|
|
*
|
|
* Revision 1.11 2005/12/08 15:10:07 taylor
|
|
* add APPLE_client_storage support to improve texture performance and reduce memory usage a tiny bit on OS X
|
|
*
|
|
* Revision 1.10 2005/11/13 06:44:18 taylor
|
|
* small bit of EFF cleanup
|
|
* add -img2dds support
|
|
* cleanup some D3D stuff (missing a lot since the old code is so unstable I couldn't get it working like I wanted)
|
|
* some minor OGL cleanup and small performance changes
|
|
* converge the various pcx_read_bitmap* functions into one
|
|
* cleanup/rename/remove some cmdline options
|
|
*
|
|
* Revision 1.9 2005/06/19 02:37:02 taylor
|
|
* general cleanup, remove some old code
|
|
* speed up gr_opengl_flip() just a tad
|
|
* inverted gamma slider fix that Sticks made to D3D
|
|
* possible fix for ATI green screens
|
|
* move opengl_check_for_errors() out of gropentnl so we can use it everywhere
|
|
* fix logged OGL info from debug builds to be a little more readable
|
|
* if an extension is found but required function is not then fail
|
|
* try to optimize glDrawRangeElements so we are not rendering more than the card is optimized for
|
|
* some 2d matrix usage checks
|
|
*
|
|
* Revision 1.8 2005/05/12 17:49:12 taylor
|
|
* use vm_malloc(), vm_free(), vm_realloc(), vm_strdup() rather than system named macros
|
|
* fixes various problems and is past time to make the switch
|
|
*
|
|
* Revision 1.7 2005/04/13 23:24:21 phreak
|
|
* Updated the message of a required extension that hasn't been found.
|
|
* It was referencing the old Glide engine.
|
|
*
|
|
* Revision 1.6 2005/02/04 23:29:31 taylor
|
|
* merge with Linux/OSX tree - p0204-3
|
|
*
|
|
* Revision 1.5 2005/01/21 08:25:14 taylor
|
|
* fill in gr_opengl_set_texture_addressing()
|
|
* add support for non-power-of-two textures for cards that have it
|
|
* temporary crash fix from multiple mipmap levels in uncompressed formats
|
|
*
|
|
* Revision 1.4 2004/10/31 21:45:13 taylor
|
|
* Linux tree merge, single array for VBOs/HTL
|
|
*
|
|
* Revision 1.3 2004/07/26 20:47:32 Kazan
|
|
* remove MCD complete
|
|
*
|
|
* Revision 1.2 2004/07/12 16:32:48 Kazan
|
|
* MCD - define _MCD_CHECK to use memory tracking
|
|
*
|
|
* Revision 1.1 2004/05/24 07:25:32 taylor
|
|
* filename case change
|
|
*
|
|
* Revision 2.3 2004/04/13 01:55:41 phreak
|
|
* put in the correct fields for the CVS comments to register
|
|
* fixed a glowmap problem that occured when rendering glowmapped and non-glowmapped ships
|
|
*
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "globalincs/pstypes.h"
|
|
#include "graphics/gropengl.h"
|
|
#include "graphics/gropenglextension.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 15)
|
|
|
|
// 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" }, 6, {
|
|
"glBindBufferARB", "glDeleteBuffersARB", "glGenBuffersARB", "glBufferDataARB",
|
|
"glMapBufferARB", "glUnmapBufferARB" } },
|
|
|
|
// Mac-only extension that allows use of system copy of texture to avoid an additional API copy
|
|
// { false, 0, 1, { "GL_APPLE_client_storage" }, 0, { NULL } },
|
|
|
|
// 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" }, 15, {
|
|
"glIsRenderbufferEXT", "glBindRenderbufferEXT", "glDeleteRenderbuffersEXT", "glGenRenderbuffersEXT",
|
|
"glRenderbufferStorageEXT", "glGetRenderbufferParameterivEXT", "glIsFramebufferEXT", "glBindFramebufferEXT",
|
|
"glDeleteFramebuffersEXT", "glGenFramebuffersEXT", "glCheckFramebufferStatusEXT", "glFramebufferTexture2DEXT",
|
|
"glFramebufferRenderbufferEXT", "glGetFramebufferAttachmentParameterivEXT", "glGenerateMipmapEXT" } },
|
|
|
|
// 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 } }
|
|
};
|
|
|
|
// 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 },
|
|
{ "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 }
|
|
};
|
|
|
|
// 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;
|
|
}
|