/* * 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 #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; }