summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2012-09-27 15:24:34 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-03 17:22:03 +0200
commit394249616cbb4c0861a032d33f846f85e2801677 (patch)
treed1b7b2b44041be92bbc47f3419866a823ed381c6
parent84100c9085ddc30368582d02a4229d44622f85e2 (diff)
OpenGL: Don't request a context version higher than is supported
The function wglCreateContextAttribsARB will fail if we request a context version higher than is supported. We therefore upper-bound the requested version by the version of the static context. This results in context creation succeeding and having the closest possible match to the requested format. The xcb qpa plugin is modified to operate similarly to the windows plugin in that it now creates a "static" context which is used to limit the versions of contexts requested by the user. Change-Id: I277ad7cc82edfdf7b9d8502ad921c8175feb1a4a Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
-rw-r--r--src/gui/kernel/qopenglcontext.cpp10
-rw-r--r--src/gui/kernel/qplatformopenglcontext.cpp10
-rw-r--r--src/gui/kernel/qplatformopenglcontext.h2
-rw-r--r--src/opengl/qgl.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp17
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp262
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h15
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp27
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h13
10 files changed, 300 insertions, 68 deletions
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 3106b4cd91..6c006ab8b3 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -297,10 +297,18 @@ void QOpenGLContext::setScreen(QScreen *screen)
The current configuration includes the format, the share context, and the
screen.
+ If the OpenGL implementation on your system does not support the requested
+ version of OpenGL context, then QOpenGLContext will try to create the closest
+ matching version. The actual created context properties can be queried
+ using the QSurfaceFormat returned by the format() function. For example, if
+ you request a context that supports OpenGL 4.3 Core profile but the driver
+ and/or hardware only supports version 3.2 Core profile contexts then you will
+ get a 3.2 Core profile context.
+
Returns true if the native context was successfully created and is ready to
be used with makeCurrent(), swapBuffers(), etc.
- \sa makeCurrent(), destroy()
+ \sa makeCurrent(), destroy(), format()
*/
bool QOpenGLContext::create()
{
diff --git a/src/gui/kernel/qplatformopenglcontext.cpp b/src/gui/kernel/qplatformopenglcontext.cpp
index 8e6a9da562..f2d6f6199c 100644
--- a/src/gui/kernel/qplatformopenglcontext.cpp
+++ b/src/gui/kernel/qplatformopenglcontext.cpp
@@ -118,14 +118,14 @@ void QPlatformOpenGLContext::setContext(QOpenGLContext *context)
d->context = context;
}
-bool QPlatformOpenGLContext::parseOpenGLVersion(const QString& versionString, int &major, int &minor)
+bool QPlatformOpenGLContext::parseOpenGLVersion(const QByteArray &versionString, int &major, int &minor)
{
bool majorOk = false;
bool minorOk = false;
- QStringList parts = versionString.split(QLatin1Char(' '));
- if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
+ QList<QByteArray> parts = versionString.split(' ');
+ if (versionString.startsWith(QByteArrayLiteral("OpenGL ES"))) {
if (parts.size() >= 3) {
- QStringList versionParts = parts.at(2).split(QLatin1Char('.'));
+ QList<QByteArray> versionParts = parts.at(2).split('.');
if (versionParts.size() >= 2) {
major = versionParts.at(0).toInt(&majorOk);
minor = versionParts.at(1).toInt(&minorOk);
@@ -138,7 +138,7 @@ bool QPlatformOpenGLContext::parseOpenGLVersion(const QString& versionString, in
}
} else {
// Not OpenGL ES, but regular OpenGL, the version numbers are first in the string
- QStringList versionParts = parts.at(0).split(QLatin1Char('.'));
+ QList<QByteArray> versionParts = parts.at(0).split('.');
if (versionParts.size() >= 2) {
major = versionParts.at(0).toInt(&majorOk);
minor = versionParts.at(1).toInt(&minorOk);
diff --git a/src/gui/kernel/qplatformopenglcontext.h b/src/gui/kernel/qplatformopenglcontext.h
index bed83b0913..e64dad64c2 100644
--- a/src/gui/kernel/qplatformopenglcontext.h
+++ b/src/gui/kernel/qplatformopenglcontext.h
@@ -88,7 +88,7 @@ public:
QOpenGLContext *context() const;
- static bool parseOpenGLVersion(const QString& versionString, int &major, int &minor);
+ static bool parseOpenGLVersion(const QByteArray &versionString, int &major, int &minor);
private:
friend class QOpenGLContext;
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 147a823431..9b456f6a64 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -3002,6 +3002,14 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex
specified in the constructor; otherwise returns false (i.e. the
context is invalid).
+ If the OpenGL implementation on your system does not support the requested
+ version of OpenGL context, then QGLContext will try to create the closest
+ matching version. The actual created context properties can be queried
+ using the QGLFormat returned by the format() function. For example, if
+ you request a context that supports OpenGL 4.3 Core profile but the driver
+ and/or hardware only supports version 3.2 Core profile contexts then you will
+ get a 3.2 Core profile context.
+
After successful creation, format() returns the set of features of
the created GL rendering context.
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 45e344416d..1c9a7d36f5 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -562,12 +562,21 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
int attributes[attribSize];
int attribIndex = 0;
qFill(attributes, attributes + attribSize, int(0));
- const int requestedVersion = (format.majorVersion() << 8) + format.minorVersion();
+
+ // We limit the requested version by the version of the static context as
+ // wglCreateContextAttribsARB 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 requestedVersion = qMin((format.majorVersion() << 8) + format.minorVersion(),
+ staticContext.defaultFormat.version);
+ const int majorVersion = requestedVersion >> 8;
+ const int minorVersion = requestedVersion & 0xFF;
+
if (requestedVersion > 0x0101) {
attributes[attribIndex++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
- attributes[attribIndex++] = format.majorVersion();
+ attributes[attribIndex++] = majorVersion;
attributes[attribIndex++] = WGL_CONTEXT_MINOR_VERSION_ARB;
- attributes[attribIndex++] = format.minorVersion();
+ attributes[attribIndex++] = minorVersion;
}
if (requestedVersion >= 0x0300) {
attributes[attribIndex++] = WGL_CONTEXT_FLAGS_ARB;
@@ -594,7 +603,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
}
if (QWindowsContext::verboseGL)
qDebug("%s: Creating context version %d.%d with %d attributes",
- __FUNCTION__, format.majorVersion(), format.minorVersion(), attribIndex / 2);
+ __FUNCTION__, majorVersion, minorVersion, attribIndex / 2);
const HGLRC result =
staticContext.wglCreateContextAttribsARB(hdc, shared, attributes);
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 089bca8a63..8c300d6c19 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -74,7 +74,197 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
#endif
-QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+static Window createDummyWindow(QXcbScreen *screen, XVisualInfo *visualInfo)
+{
+ 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 window = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(),
+ 0, 0, 100, 100,
+ 0, visualInfo->depth, InputOutput, visualInfo->visual,
+ CWBackPixel|CWBorderPixel|CWColormap, &a);
+ return window;
+}
+
+static Window createDummyWindow(QXcbScreen *screen, GLXFBConfig config)
+{
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
+ if (!visualInfo)
+ qFatal("Could not initialize GLX");
+ Window window = createDummyWindow(screen, visualInfo);
+ XFree(visualInfo);
+ 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))
+ return QByteArray(reinterpret_cast<const char*>(s));
+ return QByteArray();
+}
+
+static void updateFormatFromContext(QSurfaceFormat &format)
+{
+ // Update the version, profile, and context bit of the format
+ int major = 0, minor = 0;
+ QByteArray versionString(getGlString(GL_VERSION));
+ if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
+ format.setMajorVersion(major);
+ format.setMinorVersion(minor);
+ }
+
+ const int version = (major << 8) + minor;
+ if (version < 0x0300) {
+ format.setProfile(QSurfaceFormat::NoProfile);
+ format.setOption(QSurfaceFormat::DeprecatedFunctions);
+ return;
+ }
+
+ // Version 3.0 onwards - check if it includes deprecated functionality or is
+ // a debug context
+ GLint value = 0;
+ glGetIntegerv(GL_CONTEXT_FLAGS, &value);
+ if (value & ~GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
+ format.setOption(QSurfaceFormat::DeprecatedFunctions);
+ if (value & GLX_CONTEXT_DEBUG_BIT_ARB)
+ format.setOption(QSurfaceFormat::DebugContext);
+ if (version < 0x0302)
+ return;
+
+ // Version 3.2 and newer have a profile
+ value = 0;
+ glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
+ switch (value) {
+ case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ break;
+ case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ break;
+ default:
+ format.setProfile(QSurfaceFormat::NoProfile);
+ break;
+ }
+}
+
+/*!
+ \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)
: QPlatformOpenGLContext()
, m_screen(screen)
, m_context(0)
@@ -95,10 +285,20 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
// Use glXCreateContextAttribsARB if is available
if (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((format.majorVersion() << 8) + format.minorVersion(),
+ maxSupportedVersion);
+ const int majorVersion = requestedVersion >> 8;
+ const int minorVersion = requestedVersion & 0xFF;
QVector<int> contextAttributes;
- contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << m_format.majorVersion()
- << GLX_CONTEXT_MINOR_VERSION_ARB << m_format.minorVersion();
+ 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 (m_format.majorVersion() > 3 || (m_format.majorVersion() == 3 && m_format.minorVersion() > 1)) {
@@ -136,10 +336,8 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
if (m_context)
m_format = qglx_surfaceFormatFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context);
- // Used for creating the temporary window
- visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
- if (!visualInfo)
- qFatal("Could not initialize GLX");
+ // Create a temporary window so that we can make the new context current
+ window = createDummyWindow(screen, config);
} else {
// Note that m_format gets updated with the used surface format
visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(screen), screen->screenNumber(), &m_format);
@@ -151,56 +349,16 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
m_shareContext = 0;
m_context = glXCreateContext(DISPLAY_FROM_XCB(screen), visualInfo, 0, true);
}
- }
-
- // 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);
+ // Create a temporary window so that we can make the new context current
+ window = createDummyWindow(screen, visualInfo);
+ 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);
- }
+ updateFormatFromContext(m_format);
// Make our context non-current
glXMakeCurrent(DISPLAY_FROM_XCB(screen), 0, 0);
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index f8afb2db77..b8285c965a 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -54,10 +54,23 @@
QT_BEGIN_NAMESPACE
+class QOpenGLDefaultContextInfo
+{
+ Q_DISABLE_COPY(QOpenGLDefaultContextInfo)
+ QOpenGLDefaultContextInfo();
+public:
+ static QOpenGLDefaultContextInfo *create(QXcbScreen *screen);
+
+ const QByteArray vendor;
+ const QByteArray renderer;
+ QSurfaceFormat format;
+};
+
+
class QGLXContext : public QPlatformOpenGLContext
{
public:
- QGLXContext(QXcbScreen *xd, const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ QGLXContext(QXcbScreen *xd, const QSurfaceFormat &format, QPlatformOpenGLContext *share, QOpenGLDefaultContextInfo *defaultContextInfo);
~QGLXContext();
bool makeCurrent(QPlatformSurface *surface);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 76534cf5c4..401739f7d5 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -224,11 +224,13 @@ void QXcbConnection::updateScreens()
// Now activeScreens is the complete set of screens which are active at this time.
// Delete any existing screens which are not in activeScreens
- for (int i = m_screens.count() - 1; i >= 0; --i)
+ for (int i = m_screens.count() - 1; i >= 0; --i) {
if (!activeScreens.contains(m_screens[i])) {
+ ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->removeDefaultOpenGLContextInfo(m_screens[i]);
delete m_screens[i];
m_screens.removeAt(i);
}
+ }
// Add any new screens, and make sure the primary screen comes first
// since it is used by QGuiApplication::primaryScreen()
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 8784046560..029a6de17f 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -90,8 +90,8 @@
QT_BEGIN_NAMESPACE
QXcbIntegration::QXcbIntegration(const QStringList &parameters)
- : m_eventDispatcher(createUnixEventDispatcher()),
- m_services(new QGenericUnixServices)
+ : m_eventDispatcher(createUnixEventDispatcher())
+ , m_services(new QGenericUnixServices)
{
QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher);
@@ -119,6 +119,7 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
QXcbIntegration::~QXcbIntegration()
{
+ qDeleteAll(m_defaultContextInfos);
qDeleteAll(m_connections);
}
@@ -176,7 +177,14 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
{
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
#if defined(XCB_USE_GLX)
- return new QGLXContext(screen, context->format(), context->shareHandle());
+ QOpenGLDefaultContextInfo *defaultContextInfo;
+ if (m_defaultContextInfos.contains(screen)) {
+ defaultContextInfo = m_defaultContextInfos.value(screen);
+ } else {
+ defaultContextInfo = QOpenGLDefaultContextInfo::create(screen);
+ m_defaultContextInfos.insert(screen, defaultContextInfo);
+ }
+ return new QGLXContext(screen, context->format(), context->shareHandle(), defaultContextInfo);
#elif defined(XCB_USE_EGL)
return new QEGLXcbPlatformContext(context->format(), context->shareHandle(),
screen->connection()->egl_display(), screen->connection());
@@ -274,4 +282,17 @@ QPlatformTheme *QXcbIntegration::createPlatformTheme(const QString &name) const
return QGenericUnixTheme::createUnixTheme(name);
}
+/*!
+ Called by QXcbConnection prior to a QQnxScreen being deleted.
+
+ Destroys and cleans up any default OpenGL context info for this screen.
+*/
+void QXcbIntegration::removeDefaultOpenGLContextInfo(QXcbScreen *screen)
+{
+ if (!m_defaultContextInfos.contains(screen))
+ return;
+ QOpenGLDefaultContextInfo* info = m_defaultContextInfos.take(screen);
+ delete info;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 7f7c52372c..669a0d00f6 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -51,6 +51,11 @@ class QXcbConnection;
class QAbstractEventDispatcher;
class QXcbNativeInterface;
+#if !defined(QT_NO_OPENGL) && defined(XCB_USE_GLX)
+class QOpenGLDefaultContextInfo;
+class QXcbScreen;
+#endif
+
class QXcbIntegration : public QPlatformIntegration
{
public:
@@ -92,6 +97,10 @@ public:
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
+#if !defined(QT_NO_OPENGL) && defined(XCB_USE_GLX)
+ void removeDefaultOpenGLContextInfo(QXcbScreen *screen);
+#endif
+
private:
QList<QXcbConnection *> m_connections;
@@ -101,6 +110,10 @@ private:
QScopedPointer<QPlatformInputContext> m_inputContext;
QAbstractEventDispatcher *m_eventDispatcher;
+#if !defined(QT_NO_OPENGL) && defined(XCB_USE_GLX)
+ mutable QHash<QXcbScreen *, QOpenGLDefaultContextInfo *> m_defaultContextInfos;
+#endif
+
#ifndef QT_NO_ACCESSIBILITY
QScopedPointer<QPlatformAccessibility> m_accessibility;
#endif