diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qglxintegration.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 213 |
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; + } } } |