I have a new patch that is compatible with older and newer versions of OpenGL, compatibility and core profile. Some notes:
The code has two branches, one for < GL 3.0, and one for GL 3.0+. We determine which branch to choose at runtime, because we don't know what GL version the end user will be linking against. We can't call glGetStringi directly because it is only available in GL 3.0+, so we use glXGetProcAddressARB to acquire the address of glGetStringi and to see if it is available. It will be available if the user links against a GL library that is 3.0+, but will not work if the context is < 3.0, therefore we also check the running GL version. I made sure the program doesn't crash if any GL functions return a NULL pointer, even when they shouldn't according to current specs. This patch no longer needs the GL_GLEXT_PROTOTYPES definition. -Brandon
Most SOIL functions crash if OpenGL context is 3.2+ core profile. SOIL calls glGetString with a value that is no longer valid, and then sends the returned null pointer to strstr. This patch checks the OpenGL version at runtime, and uses a glGetString function that is appropriate and available. It doesn't crash if, for whatever reason, glGetString returns a null pointer. Index: libsoil-1.07~20080707.dfsg/src/SOIL.c =================================================================== --- libsoil-1.07~20080707.dfsg.orig/src/SOIL.c 2013-10-24 15:18:46.936902676 -0700 +++ libsoil-1.07~20080707.dfsg/src/SOIL.c 2013-10-24 15:39:57.018491568 -0700 @@ -80,6 +80,7 @@ #define SOIL_RGBA_S3TC_DXT5 0x83F3 typedef void (APIENTRY * P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data); P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC soilGlCompressedTexImage2D = NULL; +typedef const GLubyte* (APIENTRY * P_SOIL_GLGETSTRINGIPROC) (GLenum name, GLuint index); unsigned int SOIL_direct_load_DDS( const char *filename, unsigned int reuse_texture_ID, @@ -1870,16 +1871,50 @@ return tex_ID; } +static int SOIL_internal_has_OGL_capability(const char * cap) +{ + int i; + GLint num_ext; + const GLubyte * ext_string; + int major_version; + + const GLubyte * ver_string = glGetString(GL_VERSION); + if (ver_string) + major_version = atoi((const char *) ver_string); + else + major_version = 0; + + P_SOIL_GLGETSTRINGIPROC soilGlGetStringi = + (P_SOIL_GLGETSTRINGIPROC) glXGetProcAddressARB((const GLubyte *) "glGetStringi"); + + if (major_version >= 3 && soilGlGetStringi) { + // OpenGL 3.0+ + glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext); + for (i = 0; i < num_ext; i++) { + ext_string = soilGlGetStringi(GL_EXTENSIONS, i); + if (ext_string && !strcmp((const char *) ext_string, cap)) { + return GL_TRUE; + } + } + } + else { + // OpenGL < 3.0 + ext_string = glGetString(GL_EXTENSIONS); + if (ext_string && strstr((const char *) ext_string, cap)) { + return GL_TRUE; + } + } + return GL_FALSE; +} + +// GL_ARB_texture_non_power_of_two is a core feature in OpenGL 2.0 int query_NPOT_capability( void ) { /* check for the capability */ if( has_NPOT_capability == SOIL_CAPABILITY_UNKNOWN ) { /* we haven't yet checked for the capability, do so */ - if( - (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), - "GL_ARB_texture_non_power_of_two" ) ) - ) + if( !SOIL_internal_has_OGL_capability( "GL_ARB_texture_non_power_of_two" )) { /* not there, flag the failure */ has_NPOT_capability = SOIL_CAPABILITY_NONE; @@ -1893,22 +1928,16 @@ return has_NPOT_capability; } +// GL_ARB_texture_rectangle is a core feature in OpenGL 3.1 int query_tex_rectangle_capability( void ) { /* check for the capability */ if( has_tex_rectangle_capability == SOIL_CAPABILITY_UNKNOWN ) { /* we haven't yet checked for the capability, do so */ - if( - (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), - "GL_ARB_texture_rectangle" ) ) - && - (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), - "GL_EXT_texture_rectangle" ) ) - && - (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), - "GL_NV_texture_rectangle" ) ) - ) + if( !SOIL_internal_has_OGL_capability( "GL_ARB_texture_rectangle" ) && + !SOIL_internal_has_OGL_capability( "GL_EXT_texture_rectangle" ) && + !SOIL_internal_has_OGL_capability( "GL_NV_texture_rectangle" ) ) { /* not there, flag the failure */ has_tex_rectangle_capability = SOIL_CAPABILITY_NONE; @@ -1922,19 +1951,15 @@ return has_tex_rectangle_capability; } +// GL_ARB_texture_cube_map is a core feature in OpenGL 1.3 int query_cubemap_capability( void ) { /* check for the capability */ if( has_cubemap_capability == SOIL_CAPABILITY_UNKNOWN ) { /* we haven't yet checked for the capability, do so */ - if( - (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), - "GL_ARB_texture_cube_map" ) ) - && - (NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ), - "GL_EXT_texture_cube_map" ) ) - ) + if( !SOIL_internal_has_OGL_capability( "GL_ARB_texture_cube_map" ) && + !SOIL_internal_has_OGL_capability( "GL_EXT_texture_cube_map" ) ) { /* not there, flag the failure */ has_cubemap_capability = SOIL_CAPABILITY_NONE; @@ -1948,15 +1973,15 @@ return has_cubemap_capability; } +// GL_EXT_texture_compression_s3tc does not appear to be a core feature in any +// version of OpenGL up to 4.4 int query_DXT_capability( void ) { /* check for the capability */ if( has_DXT_capability == SOIL_CAPABILITY_UNKNOWN ) { /* we haven't yet checked for the capability, do so */ - if( NULL == strstr( - (char const*)glGetString( GL_EXTENSIONS ), - "GL_EXT_texture_compression_s3tc" ) ) + if( !SOIL_internal_has_OGL_capability( "GL_EXT_texture_compression_s3tc" ) ) { /* not there, flag the failure */ has_DXT_capability = SOIL_CAPABILITY_NONE;