diff options
author | José Fonseca <jfonseca@vmware.com> | 2015-01-05 19:59:59 +0000 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2015-01-05 19:59:59 +0000 |
commit | a44df7a4fb533e904e4092ca6d67c4cfdf90dab6 (patch) | |
tree | 18522c244ab4fdb25b23664de650159088381217 /helpers | |
parent | 0396fa0d2efe03b336bfb82ff288ae32badec3ac (diff) |
glretrace: Move the logic to determine the current context profile into glprofile module.
As it will be useful elsewhere.
Diffstat (limited to 'helpers')
-rw-r--r-- | helpers/glprofile.cpp | 163 | ||||
-rw-r--r-- | helpers/glprofile.hpp | 17 |
2 files changed, 178 insertions, 2 deletions
diff --git a/helpers/glprofile.cpp b/helpers/glprofile.cpp index b893adfb..0cfcaa45 100644 --- a/helpers/glprofile.cpp +++ b/helpers/glprofile.cpp @@ -26,6 +26,11 @@ #include "glprofile.hpp" +#include <assert.h> + +#include "os.hpp" +#include "glproc.hpp" + namespace glprofile { @@ -45,4 +50,162 @@ operator << (std::ostream &os, const Profile & profile) { } +static inline bool +isDigit(char c) { + return c >= '0' && c <= '9'; +} + + +static unsigned +parseNumber(const char * & p) +{ + unsigned n = 0; + char c = *p; + while (isDigit(c)) { + unsigned digit = c - '0'; + n *= 10; + n += digit; + ++p; + c = *p; + } + return n; +} + + +/* + * Parse API and version numbers from a GL_VERSION string. + * + * OpenGL 2.1 specification states that GL_VERSION string is laid out as + * + * <version number><space><vendor-specific information> + * + * Where <version number> is either of the form <major number>.<minor number> + * or <major number>.<minor number>.<release number>, where the numbers all + * have one or more digits. The release number and vendor specific + * information are optional. + * + * OpenGL ES 1.x specification states that GL_VERSION is laid out as + * + * "OpenGL ES-XX 1.x" XX={CM,CL} + * + * OpenGL ES 2 and 3 specifications state that GL_VERSION is laid out as + * + * "OpenGL ES N.M vendor-specific information" + */ +static Profile +parseVersion(const char *version) +{ + Profile profile(API_GL, 0, 0, false); + + const char *p = version; + + if (p[0] == 'O' && + p[1] == 'p' && + p[2] == 'e' && + p[3] == 'n' && + p[4] == 'G' && + p[5] == 'L' && + p[6] == ' ' && + p[7] == 'E' && + p[8] == 'S') { + p += 9; + + profile.api = API_GLES; + + // skip `-{CM,CL}` + if (*p == '-') { + ++p; + while (*p != ' ') { + if (*p == '\0') { + goto malformed; + } + ++p; + } + } + + // skip white-space + while (*p == ' ') { + if (*p == '\0') { + goto malformed; + } + ++p; + } + } + + if (!isDigit(*p)) { + goto malformed; + } + + profile.major = parseNumber(p); + if (*p++ == '.' && + isDigit(*p)) { + profile.minor = parseNumber(p); + } else { + goto malformed; + } + + return profile; + +malformed: + os::log("warning: malformed GL_VERSION (\"%s\")\n", version); + return profile; +} + + +/* + * Get the profile of the current context. + */ +Profile +getCurrentContextProfile(void) +{ + Profile profile(API_GL, 0, 0, false); + + assert(parseVersion("3.0 Mesa 10.3.2") == Profile(API_GL, 3, 0)); + assert(parseVersion("3.3 (Core Profile) Mesa 10.3.2") == Profile(API_GL, 3, 3)); + assert(parseVersion("4.4.0 NVIDIA 331.89") == Profile(API_GL, 4, 4)); + assert(parseVersion("OpenGL ES 3.0 Mesa 10.3.2") == Profile(API_GLES, 3, 0)); + + const char *version = (const char *)_glGetString(GL_VERSION); + if (!version) { + os::log("warning: null GL_VERSION\n"); + return profile; + } + + // Parse the version string. + profile = parseVersion(version); + + if (profile.major >= 3) { + /* + * From OpenGL and OpenGL ES version 3 onwards, the GL version may also + * be queried via GL_MAJOR VERSION and GL_MINOR_VERSION, which should + * match the major number and minor number in GL_VERSION string, so use + * it to check we parsed the versions correcly. + */ + + GLint majorVersion = 0; + _glGetIntegerv(GL_MAJOR_VERSION, &majorVersion); + GLint minorVersion = 0; + _glGetIntegerv(GL_MINOR_VERSION, &minorVersion); + + if (majorVersion != profile.major || + minorVersion != profile.minor) { + os::log("apitrace: warning: OpenGL context version mismatch (GL_VERSION=\"%s\", but GL_MAJOR/MINOR_VERSION=%u.%u)\n", + version, majorVersion, minorVersion); + } + } + + if (profile.api == API_GL && + profile.versionGreaterOrEqual(3, 2)) { + GLint profileMask = 0; + _glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMask); + if (profileMask & GL_CONTEXT_CORE_PROFILE_BIT) { + profile.core = true; + } + } + + return profile; + +} + + } /* namespace glprofile */ diff --git a/helpers/glprofile.hpp b/helpers/glprofile.hpp index e8d9edbd..dc35400b 100644 --- a/helpers/glprofile.hpp +++ b/helpers/glprofile.hpp @@ -67,10 +67,19 @@ struct Profile { // Comparison operator, mainly for use in std::map inline bool + operator == (const Profile & other) const { + return major == other.major && + minor == other.minor && + api == other.api && + core == other.core; + } + + // Comparison operator, mainly for use in std::map + inline bool operator < (const Profile & other) const { - return api < other.api || - major < other.major || + return major < other.major || minor < other.minor || + api < other.api || core < other.core; } }; @@ -80,6 +89,10 @@ std::ostream & operator << (std::ostream &os, const Profile & profile); +Profile +getCurrentContextProfile(void); + + } /* namespace glprofile */ |