summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qplatformopenglcontext.cpp34
-rw-r--r--src/gui/kernel/qplatformopenglcontext.h2
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp2
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp77
4 files changed, 107 insertions, 8 deletions
diff --git a/src/gui/kernel/qplatformopenglcontext.cpp b/src/gui/kernel/qplatformopenglcontext.cpp
index ed8ab09479..8e6a9da562 100644
--- a/src/gui/kernel/qplatformopenglcontext.cpp
+++ b/src/gui/kernel/qplatformopenglcontext.cpp
@@ -118,4 +118,38 @@ void QPlatformOpenGLContext::setContext(QOpenGLContext *context)
d->context = context;
}
+bool QPlatformOpenGLContext::parseOpenGLVersion(const QString& versionString, int &major, int &minor)
+{
+ bool majorOk = false;
+ bool minorOk = false;
+ QStringList parts = versionString.split(QLatin1Char(' '));
+ if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
+ if (parts.size() >= 3) {
+ QStringList versionParts = parts.at(2).split(QLatin1Char('.'));
+ if (versionParts.size() >= 2) {
+ major = versionParts.at(0).toInt(&majorOk);
+ minor = versionParts.at(1).toInt(&minorOk);
+ } else {
+ qWarning("Unrecognized OpenGL ES version");
+ }
+ } else {
+ // If < 3 parts to the name, it is an unrecognised OpenGL ES
+ qWarning("Unrecognised OpenGL ES version");
+ }
+ } else {
+ // Not OpenGL ES, but regular OpenGL, the version numbers are first in the string
+ QStringList versionParts = parts.at(0).split(QLatin1Char('.'));
+ if (versionParts.size() >= 2) {
+ major = versionParts.at(0).toInt(&majorOk);
+ minor = versionParts.at(1).toInt(&minorOk);
+ } else {
+ qWarning("Unrecognized OpenGL version");
+ }
+ }
+
+ if (!majorOk || !minorOk)
+ qWarning("Unrecognized OpenGL version");
+ return (majorOk && minorOk);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformopenglcontext.h b/src/gui/kernel/qplatformopenglcontext.h
index ffdfaba15e..bed83b0913 100644
--- a/src/gui/kernel/qplatformopenglcontext.h
+++ b/src/gui/kernel/qplatformopenglcontext.h
@@ -88,6 +88,8 @@ public:
QOpenGLContext *context() const;
+ static bool parseOpenGLVersion(const QString& versionString, int &major, int &minor);
+
private:
friend class QOpenGLContext;
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index a11af43671..ca5c1cb39d 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -210,6 +210,8 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f
attribs.append(XNone);
visualInfo = glXChooseVisual(display, screen, attribs.data());
+ if (visualInfo)
+ *format = reducedFormat;
reducedFormat = qglx_reduceSurfaceFormat(reducedFormat, &reduced);
}
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index d1a21c9c4f..089bca8a63 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -74,7 +74,6 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
#endif
-
QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
: QPlatformOpenGLContext()
, m_screen(screen)
@@ -86,18 +85,22 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),format);
+ XVisualInfo *visualInfo = 0;
+ Window window = 0; // Temporary window used to query OpenGL context
if (config) {
// Resolve entry point for glXCreateContextAttribsARB
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
+ // Use glXCreateContextAttribsARB if is available
if (glXCreateContextAttribsARB != 0) {
QVector<int> contextAttributes;
contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << m_format.majorVersion()
<< GLX_CONTEXT_MINOR_VERSION_ARB << m_format.minorVersion();
+ // If asking for OpenGL 3.2 or newer we should also specify a profile
if (m_format.majorVersion() > 3 || (m_format.majorVersion() == 3 && m_format.minorVersion() > 1)) {
if (m_format.profile() == QSurfaceFormat::CoreProfile) {
contextAttributes << GLX_CONTEXT_FLAGS_ARB << GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
@@ -129,14 +132,17 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
}
}
- if (m_context) {
+ // Get the basic surface format details
+ if (m_context)
m_format = qglx_surfaceFormatFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context);
- m_format.setMajorVersion(format.majorVersion());
- m_format.setMinorVersion(format.minorVersion());
- m_format.setProfile(format.profile());
- }
+
+ // Used for creating the temporary window
+ visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
+ if (!visualInfo)
+ qFatal("Could not initialize GLX");
} else {
- XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), screen->screenNumber(), &m_format);
+ // Note that m_format gets updated with the used surface format
+ visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(screen), screen->screenNumber(), &m_format);
if (!visualInfo)
qFatal("Could not initialize GLX");
m_context = glXCreateContext(DISPLAY_FROM_XCB(screen), visualInfo, m_shareContext, true);
@@ -145,8 +151,63 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
m_shareContext = 0;
m_context = glXCreateContext(DISPLAY_FROM_XCB(screen), visualInfo, 0, true);
}
- XFree(visualInfo);
}
+
+ // Create a temporary window so that we can make the new context current
+ Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone);
+ XSetWindowAttributes a;
+ a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
+ a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
+ a.colormap = cmap;
+
+ window = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(),
+ 0, 0, 100, 100,
+ 0, visualInfo->depth, InputOutput, visualInfo->visual,
+ CWBackPixel|CWBorderPixel|CWColormap, &a);
+
+ XFree(visualInfo);
+
+ // Query the OpenGL version and profile
+ if (m_context && window) {
+ glXMakeCurrent(DISPLAY_FROM_XCB(screen), window, m_context);
+
+ int major = 0, minor = 0;
+ QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
+ if (parseOpenGLVersion(versionString, major, minor)) {
+ m_format.setMajorVersion(major);
+ m_format.setMinorVersion(minor);
+ }
+
+ // If we have OpenGL 3.2 or newer we also need to query the profile in use
+ if (m_format.majorVersion() > 3 || (m_format.majorVersion() == 3 && m_format.minorVersion() > 1)) {
+ // nVidia drivers have a bug where querying GL_CONTEXT_PROFILE_MASK always returns 0.
+ // In this case let's assume that we got the profile that we asked for since nvidia implements
+ // both Core and Compatibility profiles
+ if (versionString.contains(QStringLiteral("NVIDIA"))) {
+ m_format.setProfile(format.profile());
+ } else {
+ GLint profileMask;
+ glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profileMask);
+ switch (profileMask) {
+ case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
+ m_format.setProfile(QSurfaceFormat::CoreProfile);
+ break;
+
+ case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
+ default:
+ m_format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ }
+ }
+ } else {
+ m_format.setProfile(QSurfaceFormat::NoProfile);
+ }
+
+ // Make our context non-current
+ glXMakeCurrent(DISPLAY_FROM_XCB(screen), 0, 0);
+ }
+
+ // Destroy our temporary window
+ XDestroyWindow(DISPLAY_FROM_XCB(screen), window);
}
QGLXContext::~QGLXContext()