Skip to content

Commit 55ba31f

Browse files
committed
On linux with --enable-gles, the obtaining of the shader major and minor version had a bug.
The old code assumed <major> '.' <minor> [' ' other stuff ] But on Linux the string being parsed has other stuff at the beginning. This would cause the atoi calls to raise an exception. I solved it with inline C code that handles all cases.
1 parent d85d41b commit 55ba31f

File tree

1 file changed

+67
-7
lines changed

1 file changed

+67
-7
lines changed

src/libprojectM/Renderer/StaticGlShaders.cpp

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "StaticGlShaders.h"
22
#include "projectM-opengl.h"
3+
#include <cstring>
4+
35

46
namespace {
57
// Variants of shaders for GLSL1.2
@@ -770,16 +772,74 @@ StaticGlShaders::StaticGlShaders(bool use_gles) : use_gles_(use_gles) {
770772
}
771773

772774
StaticGlShaders::GlslVersion StaticGlShaders::QueryGlslVersion() {
775+
/* In the linux desktop environment with --use-gles configured, the parsing of the GL_SHADING_LANGUAGE_VERSION
776+
string comes back as "OpenGL ES GLSL ES 3"
777+
And I think this was supposed to be parsing somethign like
778+
"3.10 etc etc"
779+
This caused exceptions to be raised in the std::stoi section;
780+
781+
So - The parsing will look for <anything> <number> ['.' <number>] [<anything else>]
782+
and will default to 3.0 for the version in case of errors
783+
*/
784+
785+
int major = 3; /* 3.0 is default */
786+
int minor = 0;
787+
773788
std::string glsl_version_string = reinterpret_cast<const char *>(
774789
glGetString(GL_SHADING_LANGUAGE_VERSION));
775-
size_t dot_location = glsl_version_string.find('.');
776-
size_t end_location = glsl_version_string.find(' ');
777-
auto major_string = glsl_version_string.substr(0, dot_location);
778-
auto minor_string = glsl_version_string.substr(dot_location + 1,
779-
end_location - dot_location);
780-
int major = std::stoi(major_string);
781-
int minor = std::stoi(minor_string);
782790

791+
size_t version_len = glsl_version_string.length();
792+
/* make a c version of the string and do the conversion to integers manually just for this case */
793+
if (version_len) { // find the number
794+
size_t position = 0;
795+
char *cstr = new char [version_len+1];
796+
797+
strcpy(cstr,glsl_version_string.c_str());
798+
799+
/* scan the anything before the number */
800+
while (position<version_len) {
801+
char ch = cstr[position];
802+
if ((ch >= '0') || (ch <= '9')) {
803+
break;
804+
}
805+
position++;
806+
}
807+
808+
/* scan the first number */
809+
{
810+
int possible_major = 0;
811+
while (position<version_len) {
812+
char ch = cstr[position];
813+
if ((ch >= '0') || (ch <= '9')) {
814+
possible_major = (possible_major * 10) + ch - '0';
815+
}
816+
else if (ch == '.') { /* got the minor */
817+
position++;
818+
int possible_minor = 0;
819+
while (position<version_len) {
820+
if ((ch >= '0') || (ch <= '9')) {
821+
possible_minor = (possible_minor * 10) + ch - '0';
822+
}
823+
else break;
824+
position++;
825+
} /* while scanning the minor version */
826+
if (possible_major) { /* set the minor version only if the major number is valid */
827+
minor = possible_minor;
828+
}
829+
break; // We scanned it
830+
}
831+
else { /* not a number or period */
832+
break;
833+
}
834+
position++;
835+
} /* while scanning the major number */
836+
if (possible_major) {
837+
major = possible_major;
838+
}
839+
} /* scanning block */
840+
delete[] cstr;
841+
} /* if there is a string to parse */
842+
783843
return GlslVersion{major, minor};
784844
}
785845

0 commit comments

Comments
 (0)