Skip to content

Commit 9de2c16

Browse files
committed
Fix glGetString
kbranigan#17
1 parent 21ac178 commit 9de2c16

File tree

2 files changed

+75
-38
lines changed

2 files changed

+75
-38
lines changed

src/SOIL.c

+70-33
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,53 @@ int query_DXT_capability( void );
9090
#define SOIL_RGBA_S3TC_DXT5 0x83F3
9191
typedef void (APIENTRY * P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data);
9292
P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC soilGlCompressedTexImage2D = NULL;
93+
typedef const GLubyte* (APIENTRY * P_SOIL_GLGETSTRINGIPROC) (GLenum name, GLuint index);
94+
95+
/**
96+
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=727175
97+
"Most SOIL functions crash if OpenGL context is 3.2+ core profile. SOIL calls
98+
glGetString with a value that is no longer valid, and then sends the returned
99+
null pointer to strstr.
100+
This patch checks the OpenGL version at runtime, and uses a glGetString function
101+
that is appropriate and available. It doesn't crash if, for whatever reason,
102+
glGetString returns a null pointer."
103+
- Thanks to Brandon!
104+
**/
105+
static int SOIL_internal_has_OGL_capability(const char * cap)
106+
{
107+
int i;
108+
GLint num_ext;
109+
const GLubyte * ext_string;
110+
int major_version;
111+
112+
const GLubyte * ver_string = glGetString(GL_VERSION);
113+
if (ver_string)
114+
major_version = atoi((const char *) ver_string);
115+
else
116+
major_version = 0;
117+
118+
P_SOIL_GLGETSTRINGIPROC soilGlGetStringi =
119+
(P_SOIL_GLGETSTRINGIPROC) glXGetProcAddressARB((const GLubyte *) "glGetStringi");
120+
121+
if (major_version >= 3 && soilGlGetStringi) {
122+
// OpenGL 3.0+
123+
glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext);
124+
for (i = 0; i < num_ext; i++) {
125+
ext_string = soilGlGetStringi(GL_EXTENSIONS, i);
126+
if (ext_string && !strcmp((const char *) ext_string, cap)) {
127+
return GL_TRUE;
128+
}
129+
}
130+
}
131+
else {
132+
// OpenGL < 3.0
133+
ext_string = glGetString(GL_EXTENSIONS);
134+
if (ext_string && strstr((const char *) ext_string, cap)) {
135+
return GL_TRUE;
136+
}
137+
}
138+
return GL_FALSE;
139+
}
93140
unsigned int SOIL_direct_load_DDS(
94141
const char *filename,
95142
unsigned int reuse_texture_ID,
@@ -1725,7 +1772,7 @@ unsigned int SOIL_direct_load_DDS_from_memory(
17251772
/* do this for each face of the cubemap! */
17261773
for( cf_target = ogl_target_start; cf_target <= ogl_target_end; ++cf_target )
17271774
{
1728-
if( buffer_index + DDS_full_size <= buffer_length )
1775+
if( buffer_index + DDS_full_size <= (unsigned int)buffer_length )
17291776
{
17301777
unsigned int byte_offset = DDS_main_size;
17311778
memcpy( (void*)DDS_data, (const void*)(&buffer[buffer_index]), DDS_full_size );
@@ -1735,7 +1782,7 @@ unsigned int SOIL_direct_load_DDS_from_memory(
17351782
{
17361783
/* and remember, DXT uncompressed uses BGR(A),
17371784
so swap to RGB(A) for ALL MIPmap levels */
1738-
for( i = 0; i < DDS_full_size; i += block_size )
1785+
for( i = 0; i < (int)DDS_full_size; i += block_size )
17391786
{
17401787
unsigned char temp = DDS_data[i];
17411788
DDS_data[i] = DDS_data[i+2];
@@ -1872,29 +1919,25 @@ unsigned int SOIL_direct_load_DDS(
18721919
}
18731920
/* now try to do the loading */
18741921
tex_ID = SOIL_direct_load_DDS_from_memory(
1875-
(const unsigned char *const)buffer, buffer_length,
1922+
(const unsigned char *const)buffer, (int)buffer_length,
18761923
reuse_texture_ID, flags, loading_as_cubemap );
18771924
SOIL_free_image_data( buffer );
18781925
return tex_ID;
18791926
}
18801927

1928+
// GL_ARB_texture_non_power_of_two is a core feature in OpenGL 2.0
18811929
int query_NPOT_capability( void )
18821930
{
18831931
/* check for the capability */
18841932
if( has_NPOT_capability == SOIL_CAPABILITY_UNKNOWN )
18851933
{
18861934
/* we haven't yet checked for the capability, do so */
1887-
if(
1888-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1889-
"GL_ARB_texture_non_power_of_two" ) )
1890-
&&
1891-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1892-
"GL_OES_texture_npot" ) )
1893-
)
1935+
if (!SOIL_internal_has_OGL_capability("GL_ARB_texture_non_power_of_two"))
18941936
{
18951937
/* not there, flag the failure */
18961938
has_NPOT_capability = SOIL_CAPABILITY_NONE;
1897-
} else
1939+
}
1940+
else
18981941
{
18991942
/* it's there! */
19001943
has_NPOT_capability = SOIL_CAPABILITY_PRESENT;
@@ -1904,26 +1947,21 @@ int query_NPOT_capability( void )
19041947
return has_NPOT_capability;
19051948
}
19061949

1950+
// GL_ARB_texture_rectangle is a core feature in OpenGL 3.1
19071951
int query_tex_rectangle_capability( void )
19081952
{
19091953
/* check for the capability */
19101954
if( has_tex_rectangle_capability == SOIL_CAPABILITY_UNKNOWN )
19111955
{
19121956
/* we haven't yet checked for the capability, do so */
1913-
if(
1914-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1915-
"GL_ARB_texture_rectangle" ) )
1916-
&&
1917-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1918-
"GL_EXT_texture_rectangle" ) )
1919-
&&
1920-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1921-
"GL_NV_texture_rectangle" ) )
1922-
)
1957+
if (!SOIL_internal_has_OGL_capability("GL_ARB_texture_rectangle") &&
1958+
!SOIL_internal_has_OGL_capability("GL_EXT_texture_rectangle") &&
1959+
!SOIL_internal_has_OGL_capability("GL_NV_texture_rectangle"))
19231960
{
19241961
/* not there, flag the failure */
19251962
has_tex_rectangle_capability = SOIL_CAPABILITY_NONE;
1926-
} else
1963+
}
1964+
else
19271965
{
19281966
/* it's there! */
19291967
has_tex_rectangle_capability = SOIL_CAPABILITY_PRESENT;
@@ -1933,26 +1971,24 @@ int query_tex_rectangle_capability( void )
19331971
return has_tex_rectangle_capability;
19341972
}
19351973

1974+
// GL_ARB_texture_cube_map is a core feature in OpenGL 1.3
19361975
int query_cubemap_capability( void )
19371976
{
19381977
/* check for the capability */
19391978
if( has_cubemap_capability == SOIL_CAPABILITY_UNKNOWN )
19401979
{
19411980
/* we haven't yet checked for the capability, do so */
1942-
if(
1943-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1944-
"GL_ARB_texture_cube_map" ) )
1945-
&&
1946-
(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1947-
"GL_EXT_texture_cube_map" ) )
1981+
if (!SOIL_internal_has_OGL_capability("GL_ARB_texture_cube_map") &&
1982+
!SOIL_internal_has_OGL_capability("GL_EXT_texture_cube_map")
19481983
#ifdef GL_ES_VERSION_2_0
19491984
&& (0) /* GL ES 2.0 supports cubemaps, always enable */
19501985
#endif
19511986
)
19521987
{
19531988
/* not there, flag the failure */
19541989
has_cubemap_capability = SOIL_CAPABILITY_NONE;
1955-
} else
1990+
}
1991+
else
19561992
{
19571993
/* it's there! */
19581994
has_cubemap_capability = SOIL_CAPABILITY_PRESENT;
@@ -1962,19 +1998,20 @@ int query_cubemap_capability( void )
19621998
return has_cubemap_capability;
19631999
}
19642000

2001+
// GL_EXT_texture_compression_s3tc does not appear to be a core feature in any
2002+
// version of OpenGL up to 4.4
19652003
int query_DXT_capability( void )
19662004
{
19672005
/* check for the capability */
19682006
if( has_DXT_capability == SOIL_CAPABILITY_UNKNOWN )
19692007
{
19702008
/* we haven't yet checked for the capability, do so */
1971-
if( NULL == strstr(
1972-
(char const*)glGetString( GL_EXTENSIONS ),
1973-
"GL_EXT_texture_compression_s3tc" ) )
2009+
if (!SOIL_internal_has_OGL_capability("GL_EXT_texture_compression_s3tc"))
19742010
{
19752011
/* not there, flag the failure */
19762012
has_DXT_capability = SOIL_CAPABILITY_NONE;
1977-
} else
2013+
}
2014+
else
19782015
{
19792016
/* and find the address of the extension function */
19802017
P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC ext_addr = NULL;

src/image_helper.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ find_max_RGBE
322322
for( i = width * height; i > 0; --i )
323323
{
324324
/* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
325-
float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
325+
float scale = (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
326326
for( j = 0; j < 3; ++j )
327327
{
328328
if( img[j] * scale > max_val )
@@ -363,14 +363,14 @@ RGBE_to_RGBdivA
363363
/* decode this pixel, and find the max */
364364
float r,g,b,e, m;
365365
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
366-
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
366+
e = scale * (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
367367
r = e * img[0];
368368
g = e * img[1];
369369
b = e * img[2];
370370
m = (r > g) ? r : g;
371371
m = (b > m) ? b : m;
372372
/* and encode it into RGBdivA */
373-
iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f;
373+
iv = (m != 0.0f) ? (int)(255.0f / m) : 1;
374374
iv = (iv < 1) ? 1 : iv;
375375
img[3] = (iv > 255) ? 255 : iv;
376376
iv = (int)(img[3] * r + 0.5f);
@@ -412,14 +412,14 @@ RGBE_to_RGBdivA2
412412
/* decode this pixel, and find the max */
413413
float r,g,b,e, m;
414414
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
415-
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
415+
e = scale * (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
416416
r = e * img[0];
417417
g = e * img[1];
418418
b = e * img[2];
419419
m = (r > g) ? r : g;
420420
m = (b > m) ? b : m;
421421
/* and encode it into RGBdivA */
422-
iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f;
422+
iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1;
423423
iv = (iv < 1) ? 1 : iv;
424424
img[3] = (iv > 255) ? 255 : iv;
425425
iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);

0 commit comments

Comments
 (0)