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;

Reply via email to