summaryrefslogtreecommitdiff
path: root/helpers
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2015-01-05 19:59:59 +0000
committerJosé Fonseca <jfonseca@vmware.com>2015-01-05 19:59:59 +0000
commita44df7a4fb533e904e4092ca6d67c4cfdf90dab6 (patch)
tree18522c244ab4fdb25b23664de650159088381217 /helpers
parent0396fa0d2efe03b336bfb82ff288ae32badec3ac (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.cpp163
-rw-r--r--helpers/glprofile.hpp17
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 */