summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qglxintegration.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb/qglxintegration.cpp')
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp213
1 files changed, 54 insertions, 159 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 2b18ecf7a4..5efac6ce12 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -105,57 +105,6 @@ static Window createDummyWindow(QXcbScreen *screen, GLXFBConfig config)
return window;
}
-// Per-window data for active OpenGL contexts.
-struct QOpenGLContextData
-{
- QOpenGLContextData(Display *display, Window window, GLXContext context)
- : m_display(display),
- m_window(window),
- m_context(context)
- {}
-
- QOpenGLContextData()
- : m_display(0),
- m_window(0),
- m_context(0)
- {}
-
- Display *m_display;
- Window m_window;
- GLXContext m_context;
-};
-
-static inline QOpenGLContextData currentOpenGLContextData()
-{
- QOpenGLContextData result;
- result.m_display = glXGetCurrentDisplay();
- result.m_window = glXGetCurrentDrawable();
- result.m_context = glXGetCurrentContext();
- return result;
-}
-
-static inline QOpenGLContextData createDummyWindowOpenGLContextData(QXcbScreen *screen)
-{
- QOpenGLContextData result;
- result.m_display = DISPLAY_FROM_XCB(screen);
-
- QSurfaceFormat format;
- GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen), screen->screenNumber(), format);
- if (config) {
- result.m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, 0, true);
- result.m_window = createDummyWindow(screen, config);
- } else {
- XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(screen), screen->screenNumber(), &format);
- if (!visualInfo)
- qFatal("Could not initialize GLX");
- result.m_context = glXCreateContext(DISPLAY_FROM_XCB(screen), visualInfo, 0, true);
- result.m_window = createDummyWindow(screen, visualInfo);
- XFree(visualInfo);
- }
-
- return result;
-}
-
static inline QByteArray getGlString(GLenum param)
{
if (const GLubyte *s = glGetString(param))
@@ -203,70 +152,7 @@ static void updateFormatFromContext(QSurfaceFormat &format)
format.setProfile(QSurfaceFormat::CompatibilityProfile);
}
-/*!
- \class QOpenGLTemporaryContext
- \brief A temporary context that can be instantiated on the stack.
-
- Functions like glGetString() only work if there is a current GL context.
-
- \internal
- \ingroup qt-lighthouse-xcb
-*/
-class QOpenGLTemporaryContext
-{
- Q_DISABLE_COPY(QOpenGLTemporaryContext)
-public:
- QOpenGLTemporaryContext(QXcbScreen *screen);
- ~QOpenGLTemporaryContext();
-
-private:
- const QOpenGLContextData m_previous;
- const QOpenGLContextData m_current;
-};
-
-QOpenGLTemporaryContext::QOpenGLTemporaryContext(QXcbScreen *screen)
- : m_previous(currentOpenGLContextData()),
- m_current(createDummyWindowOpenGLContextData(screen))
-{
- // Make our temporary context current on our temporary window
- glXMakeCurrent(m_current.m_display, m_current.m_window, m_current.m_context);
-}
-
-QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
-{
- // Restore the previous context if possible, otherwise just release our temporary context
- if (m_previous.m_display)
- glXMakeCurrent(m_previous.m_display, m_previous.m_window, m_previous.m_context);
- else
- glXMakeCurrent(m_current.m_display, 0, 0);
-
- // Destroy our temporary window
- XDestroyWindow(m_current.m_display, m_current.m_window);
-
- // Finally destroy our temporary context itself
- glXDestroyContext(m_current.m_display, m_current.m_context);
-}
-
-QOpenGLDefaultContextInfo::QOpenGLDefaultContextInfo()
- : vendor(getGlString(GL_VENDOR)),
- renderer(getGlString(GL_RENDERER))
-{
- updateFormatFromContext(format);
-}
-
-QOpenGLDefaultContextInfo *QOpenGLDefaultContextInfo::create(QXcbScreen *screen)
-{
- // We need a current context for getGLString() to work. To have
- // the QOpenGLDefaultContextInfo contain the latest supported
- // context version, we rely upon the QOpenGLTemporaryContext to
- // correctly obtain a context with the latest version
- QScopedPointer<QOpenGLTemporaryContext> temporaryContext(new QOpenGLTemporaryContext(screen));
- QOpenGLDefaultContextInfo *result = new QOpenGLDefaultContextInfo;
- return result;
-}
-
-
-QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share, QOpenGLDefaultContextInfo *defaultContextInfo)
+QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
: QPlatformOpenGLContext()
, m_screen(screen)
, m_context(0)
@@ -294,51 +180,60 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber())).split(' ');
bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
- // Use glXCreateContextAttribsARB if is available
+ // Use glXCreateContextAttribsARB if available
if (glxExt.contains("GLX_ARB_create_context") && glXCreateContextAttribsARB != 0) {
- // We limit the requested version by the version of the static context as
- // glXCreateContextAttribsARB fails and returns NULL if the requested context
- // version is not supported. This means that we will get the closest supported
- // context format that that which was requested and is supported by the driver
- const int maxSupportedVersion = (defaultContextInfo->format.majorVersion() << 8)
- + defaultContextInfo->format.minorVersion();
- const int requestedVersion = qMin((m_format.majorVersion() << 8) + m_format.minorVersion(),
- maxSupportedVersion);
- const int majorVersion = requestedVersion >> 8;
- const int minorVersion = requestedVersion & 0xFF;
-
- QVector<int> contextAttributes;
- contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion
- << GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion;
-
- // If asking for OpenGL 3.2 or newer we should also specify a profile
- if (supportsProfiles && (m_format.majorVersion() > 3 || (m_format.majorVersion() == 3 && m_format.minorVersion() > 1))) {
- if (m_format.profile() == QSurfaceFormat::CoreProfile)
- contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
- else
- contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
- }
-
- int flags = 0;
-
- if (m_format.testOption(QSurfaceFormat::DebugContext))
- flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
-
- // A forward-compatible context may be requested for 3.0 and later
- if (m_format.majorVersion() >= 3 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions))
- flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
-
- if (flags != 0)
- contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags;
-
- contextAttributes << None;
-
- m_context = glXCreateContextAttribsARB(DISPLAY_FROM_XCB(screen), config, m_shareContext, true, contextAttributes.data());
- if (!m_context && m_shareContext) {
- // re-try without a shared glx context
- m_context = glXCreateContextAttribsARB(DISPLAY_FROM_XCB(screen), config, 0, true, contextAttributes.data());
- if (m_context)
- m_shareContext = 0;
+ // Try to create an OpenGL context for each known OpenGL version in descending
+ // order from the requested version.
+ const int requestedVersion = format.majorVersion() * 10 + qMin(format.minorVersion(), 9);
+
+ QVector<int> glVersions;
+ if (requestedVersion > 43)
+ glVersions << requestedVersion;
+
+ // Don't bother with versions below 2.0
+ glVersions << 43 << 42 << 41 << 40 << 33 << 32 << 31 << 30 << 21 << 20;
+
+ for (int i = 0; !m_context && i < glVersions.count(); i++) {
+ const int version = glVersions[i];
+ if (version > requestedVersion)
+ continue;
+
+ const int majorVersion = version / 10;
+ const int minorVersion = version % 10;
+
+ QVector<int> contextAttributes;
+ contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion
+ << GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion;
+
+ // If asking for OpenGL 3.2 or newer we should also specify a profile
+ if (version >= 32 && supportsProfiles) {
+ if (m_format.profile() == QSurfaceFormat::CoreProfile)
+ contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ else
+ contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+
+ int flags = 0;
+
+ if (m_format.testOption(QSurfaceFormat::DebugContext))
+ flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
+
+ // A forward-compatible context may be requested for 3.0 and later
+ if (version >= 30 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions))
+ flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+
+ if (flags != 0)
+ contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags;
+
+ contextAttributes << None;
+
+ m_context = glXCreateContextAttribsARB(DISPLAY_FROM_XCB(screen), config, m_shareContext, true, contextAttributes.data());
+ if (!m_context && m_shareContext) {
+ // re-try without a shared glx context
+ m_context = glXCreateContextAttribsARB(DISPLAY_FROM_XCB(screen), config, 0, true, contextAttributes.data());
+ if (m_context)
+ m_shareContext = 0;
+ }
}
}