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>
This commit is contained in:
parent
84100c9085
commit
394249616c
@ -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()
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -90,8 +90,8 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QXcbIntegration::QXcbIntegration(const QStringList ¶meters)
|
||||
: 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 ¶meters)
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user