summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp354
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience_p.h8
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp5
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp23
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h7
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp12
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp66
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp165
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h4
14 files changed, 366 insertions, 290 deletions
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 870e746a53..7dc29fae6d 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -40,6 +40,7 @@
// We have to include this before the X11 headers dragged in by
// qglxconvenience_p.h.
#include <QtCore/QByteArray>
+#include <QtCore/QScopedPointer>
#include "qglxconvenience_p.h"
@@ -77,174 +78,182 @@ enum {
QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
{
- QVector<int> spec(48);
- int i = 0;
+ QVector<int> spec;
- spec[i++] = GLX_LEVEL;
- spec[i++] = 0;
- spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit;
+ spec << GLX_LEVEL
+ << 0
- spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT;
+ << GLX_RENDER_TYPE
+ << GLX_RGBA_BIT
- spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize();
- spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize();
- spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize();
- if (format.hasAlpha()) {
- spec[i++] = GLX_ALPHA_SIZE; spec[i++] = format.alphaBufferSize();
- }
+ << GLX_RED_SIZE
+ << qMax(1, format.redBufferSize())
- spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.swapBehavior() != QSurfaceFormat::SingleBuffer ? True : False;
+ << GLX_GREEN_SIZE
+ << qMax(1, format.greenBufferSize())
- spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False;
+ << GLX_BLUE_SIZE
+ << qMax(1, format.blueBufferSize())
- if (format.depthBufferSize() > 0) {
- spec[i++] = GLX_DEPTH_SIZE; spec[i++] = format.depthBufferSize();
- }
+ << GLX_ALPHA_SIZE
+ << qMax(0, format.alphaBufferSize());
- if (format.stencilBufferSize() > 0) {
- spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize();
- }
+ if (format.swapBehavior() != QSurfaceFormat::SingleBuffer)
+ spec << GLX_DOUBLEBUFFER
+ << True;
- if (format.samples() > 1) {
- spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
- spec[i++] = 1;
- spec[i++] = GLX_SAMPLES_ARB;
- spec[i++] = format.samples();
- }
+ if (format.stereo())
+ spec << GLX_STEREO
+ << True;
+
+ if (format.depthBufferSize() != -1)
+ spec << GLX_DEPTH_SIZE
+ << format.depthBufferSize();
+
+ if (format.stencilBufferSize() != -1)
+ spec << GLX_STENCIL_SIZE
+ << format.stencilBufferSize();
+
+ if (format.samples() > 1)
+ spec << GLX_SAMPLE_BUFFERS_ARB
+ << 1
+ << GLX_SAMPLES_ARB
+ << format.samples();
+
+ spec << GLX_DRAWABLE_TYPE
+ << drawableBit
+
+ << XNone;
- spec[i++] = XNone;
return spec;
}
-GLXFBConfig qglx_findConfig(Display *display, int screen , const QSurfaceFormat &format, int drawableBit)
-{
- // Allow forcing LIBGL_ALWAYS_SOFTWARE for Qt 5 applications only.
- // This is most useful with drivers that only support OpenGL 1.
- // We need OpenGL 2, but the user probably doesn't want
- // LIBGL_ALWAYS_SOFTWARE in OpenGL 1 apps.
- static bool checkedForceSoftwareOpenGL = false;
- static bool forceSoftwareOpenGL = false;
- if (!checkedForceSoftwareOpenGL) {
- // If LIBGL_ALWAYS_SOFTWARE is already set, don't mess with it.
- // We want to unset LIBGL_ALWAYS_SOFTWARE at the end so it does not
- // get inherited by other processes, of course only if it wasn't
- // already set before.
- if (!qEnvironmentVariableIsEmpty("QT_XCB_FORCE_SOFTWARE_OPENGL")
- && !qEnvironmentVariableIsSet("LIBGL_ALWAYS_SOFTWARE"))
- forceSoftwareOpenGL = true;
-
- checkedForceSoftwareOpenGL = true;
- }
+namespace {
+struct QXcbSoftwareOpenGLEnforcer {
+ QXcbSoftwareOpenGLEnforcer() {
+ // Allow forcing LIBGL_ALWAYS_SOFTWARE for Qt 5 applications only.
+ // This is most useful with drivers that only support OpenGL 1.
+ // We need OpenGL 2, but the user probably doesn't want
+ // LIBGL_ALWAYS_SOFTWARE in OpenGL 1 apps.
+
+ if (!checkedForceSoftwareOpenGL) {
+ // If LIBGL_ALWAYS_SOFTWARE is already set, don't mess with it.
+ // We want to unset LIBGL_ALWAYS_SOFTWARE at the end so it does not
+ // get inherited by other processes, of course only if it wasn't
+ // already set before.
+ if (!qEnvironmentVariableIsEmpty("QT_XCB_FORCE_SOFTWARE_OPENGL")
+ && !qEnvironmentVariableIsSet("LIBGL_ALWAYS_SOFTWARE"))
+ forceSoftwareOpenGL = true;
+
+ checkedForceSoftwareOpenGL = true;
+ }
- if (forceSoftwareOpenGL)
- qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
+ if (forceSoftwareOpenGL)
+ qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
+ }
- bool reduced = true;
- GLXFBConfig chosenConfig = 0;
- QSurfaceFormat reducedFormat = format;
- while (!chosenConfig && reduced) {
- QVector<int> spec = qglx_buildSpec(reducedFormat, drawableBit);
- int confcount = 0;
- GLXFBConfig *configs;
- configs = glXChooseFBConfig(display, screen,spec.constData(),&confcount);
- if (confcount)
- {
- for (int i = 0; i < confcount; i++) {
- chosenConfig = configs[i];
- // Make sure we try to get an ARGB visual if the format asked for an alpha:
- if (reducedFormat.hasAlpha()) {
- int alphaSize;
- glXGetFBConfigAttrib(display,configs[i],GLX_ALPHA_SIZE,&alphaSize);
- if (alphaSize > 0) {
- XVisualInfo *visual = glXGetVisualFromFBConfig(display, chosenConfig);
- bool hasAlpha = false;
-
-#if !defined(QT_NO_XRENDER)
- XRenderPictFormat *pictFormat = XRenderFindVisualFormat(display, visual->visual);
- hasAlpha = pictFormat->direct.alphaMask > 0;
-#else
- hasAlpha = visual->depth == 32;
-#endif
+ ~QXcbSoftwareOpenGLEnforcer() {
+ // unset LIBGL_ALWAYS_SOFTWARE now so other processes don't inherit it
+ if (forceSoftwareOpenGL)
+ qunsetenv("LIBGL_ALWAYS_SOFTWARE");
+ }
- XFree(visual);
+ static bool checkedForceSoftwareOpenGL;
+ static bool forceSoftwareOpenGL;
+};
- if (hasAlpha)
- break;
- }
- } else {
- break; // Just choose the first in the list if there's no alpha requested
- }
- }
+bool QXcbSoftwareOpenGLEnforcer::checkedForceSoftwareOpenGL = false;
+bool QXcbSoftwareOpenGLEnforcer::forceSoftwareOpenGL = false;
- XFree(configs);
- }
- if (!chosenConfig)
- reducedFormat = qglx_reduceSurfaceFormat(reducedFormat,&reduced);
+template <class T>
+struct QXlibScopedPointerDeleter {
+ static inline void cleanup(T *pointer) {
+ XFree(pointer);
}
+};
- // unset LIBGL_ALWAYS_SOFTWARE now so other processes don't inherit it
- if (forceSoftwareOpenGL)
- qunsetenv("LIBGL_ALWAYS_SOFTWARE");
+template <class T>
+using QXlibPointer = QScopedPointer<T, QXlibScopedPointerDeleter<T>>;
- return chosenConfig;
+template <class T>
+using QXlibArrayPointer = QScopedArrayPointer<T, QXlibScopedPointerDeleter<T>>;
}
-XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format)
+GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format, bool highestPixelFormat, int drawableBit)
{
- Q_ASSERT(format);
+ QXcbSoftwareOpenGLEnforcer softwareOpenGLEnforcer;
- XVisualInfo *visualInfo = 0;
+ GLXFBConfig config = 0;
- GLXFBConfig config = qglx_findConfig(display,screen,*format);
- if (config) {
- visualInfo = glXGetVisualFromFBConfig(display, config);
- qglx_surfaceFormatFromGLXFBConfig(format, display, config);
- }
+ do {
+ const QVector<int> spec = qglx_buildSpec(format, drawableBit);
- // attempt to fall back to glXChooseVisual
- bool reduced = true;
- QSurfaceFormat reducedFormat = *format;
- while (!visualInfo && reduced) {
- QVarLengthArray<int, 13> attribs;
- attribs.append(GLX_RGBA);
-
- if (reducedFormat.redBufferSize() > 0) {
- attribs.append(GLX_RED_SIZE);
- attribs.append(reducedFormat.redBufferSize());
- }
+ int confcount = 0;
+ QXlibArrayPointer<GLXFBConfig> configs(glXChooseFBConfig(display, screen, spec.constData(), &confcount));
- if (reducedFormat.greenBufferSize() > 0) {
- attribs.append(GLX_GREEN_SIZE);
- attribs.append(reducedFormat.greenBufferSize());
+ if (!config && confcount > 0) {
+ config = configs[0];
+ if (highestPixelFormat && !format.hasAlpha())
+ break;
}
- if (reducedFormat.blueBufferSize() > 0) {
- attribs.append(GLX_BLUE_SIZE);
- attribs.append(reducedFormat.blueBufferSize());
- }
+ const int requestedRed = qMax(0, format.redBufferSize());
+ const int requestedGreen = qMax(0, format.greenBufferSize());
+ const int requestedBlue = qMax(0, format.blueBufferSize());
+ const int requestedAlpha = qMax(0, format.alphaBufferSize());
- if (reducedFormat.stencilBufferSize() > 0) {
- attribs.append(GLX_STENCIL_SIZE);
- attribs.append(reducedFormat.stencilBufferSize());
- }
+ for (int i = 0; i < confcount; i++) {
+ GLXFBConfig candidate = configs[i];
+
+ QXlibPointer<XVisualInfo> visual(glXGetVisualFromFBConfig(display, candidate));
- if (reducedFormat.depthBufferSize() > 0) {
- attribs.append(GLX_DEPTH_SIZE);
- attribs.append(reducedFormat.depthBufferSize());
+ const int actualRed = qPopulationCount(visual->red_mask);
+ const int actualGreen = qPopulationCount(visual->green_mask);
+ const int actualBlue = qPopulationCount(visual->blue_mask);
+ const int actualAlpha = visual->depth - actualRed - actualGreen - actualBlue;
+
+ if (requestedRed && actualRed != requestedRed)
+ continue;
+ if (requestedGreen && actualGreen != requestedGreen)
+ continue;
+ if (requestedBlue && actualBlue != requestedBlue)
+ continue;
+ if (requestedAlpha && actualAlpha != requestedAlpha)
+ continue;
+
+ return candidate;
}
+ } while (qglx_reduceFormat(&format));
+
+ return config;
+}
- if (reducedFormat.swapBehavior() != QSurfaceFormat::SingleBuffer)
- attribs.append(GLX_DOUBLEBUFFER);
+XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit)
+{
+ Q_ASSERT(format);
- attribs.append(XNone);
+ XVisualInfo *visualInfo = 0;
- visualInfo = glXChooseVisual(display, screen, attribs.data());
- if (visualInfo)
- *format = reducedFormat;
+ GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit);
+ if (config)
+ visualInfo = glXGetVisualFromFBConfig(display, config);
- reducedFormat = qglx_reduceSurfaceFormat(reducedFormat, &reduced);
+ if (visualInfo) {
+ qglx_surfaceFormatFromGLXFBConfig(format, display, config);
+ return visualInfo;
}
+ // attempt to fall back to glXChooseVisual
+ do {
+ QVector<int> attribs = qglx_buildSpec(*format, drawableBit);
+ visualInfo = glXChooseVisual(display, screen, attribs.data());
+
+ if (visualInfo) {
+ qglx_surfaceFormatFromVisualInfo(format, display, visualInfo);
+ return visualInfo;
+ }
+ } while (qglx_reduceFormat(format));
+
return visualInfo;
}
@@ -318,33 +327,64 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
format->setStereo(stereo);
}
-QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced)
+bool qglx_reduceFormat(QSurfaceFormat *format)
{
- QSurfaceFormat retFormat = format;
- *reduced = true;
-
- if (retFormat.depthBufferSize() >= 32) {
- retFormat.setDepthBufferSize(24);
- } else if (retFormat.depthBufferSize() > 0) {
- retFormat.setDepthBufferSize(0);
- } else if (retFormat.redBufferSize() > 1) {
- retFormat.setRedBufferSize(1);
- } else if (retFormat.greenBufferSize() > 1) {
- retFormat.setGreenBufferSize(1);
- } else if (retFormat.blueBufferSize() > 1) {
- retFormat.setBlueBufferSize(1);
- } else if (retFormat.samples() > 1) {
- retFormat.setSamples(qMin(retFormat.samples() / 2, 16));
- } else if (retFormat.stereo()) {
- retFormat.setStereo(false);
- }else if (retFormat.stencilBufferSize() > 0) {
- retFormat.setStencilBufferSize(0);
- }else if (retFormat.hasAlpha()) {
- retFormat.setAlphaBufferSize(0);
- }else if (retFormat.swapBehavior() != QSurfaceFormat::SingleBuffer) {
- retFormat.setSwapBehavior(QSurfaceFormat::SingleBuffer);
- }else{
- *reduced = false;
+ Q_ASSERT(format);
+
+ if (format->redBufferSize() > 1) {
+ format->setRedBufferSize(1);
+ return true;
+ }
+
+ if (format->greenBufferSize() > 1) {
+ format->setGreenBufferSize(1);
+ return true;
+ }
+
+ if (format->blueBufferSize() > 1) {
+ format->setBlueBufferSize(1);
+ return true;
}
- return retFormat;
+
+ if (format->swapBehavior() != QSurfaceFormat::SingleBuffer){
+ format->setSwapBehavior(QSurfaceFormat::SingleBuffer);
+ return true;
+ }
+
+ if (format->samples() > 1) {
+ format->setSamples(qMin(16, format->samples() / 2));
+ return true;
+ }
+
+ if (format->depthBufferSize() >= 32) {
+ format->setDepthBufferSize(24);
+ return true;
+ }
+
+ if (format->depthBufferSize() > 1) {
+ format->setDepthBufferSize(1);
+ return true;
+ }
+
+ if (format->depthBufferSize() > 0) {
+ format->setDepthBufferSize(0);
+ return true;
+ }
+
+ if (format->hasAlpha()) {
+ format->setAlphaBufferSize(0);
+ return true;
+ }
+
+ if (format->stencilBufferSize() > 1) {
+ format->setStencilBufferSize(1);
+ return true;
+ }
+
+ if (format->stencilBufferSize() > 0) {
+ format->setStencilBufferSize(0);
+ return true;
+ }
+
+ return false;
}
diff --git a/src/platformsupport/glxconvenience/qglxconvenience_p.h b/src/platformsupport/glxconvenience/qglxconvenience_p.h
index 309974f357..d422668584 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience_p.h
+++ b/src/platformsupport/glxconvenience/qglxconvenience_p.h
@@ -57,11 +57,11 @@
#include <X11/Xlib.h>
#include <GL/glx.h>
-XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format);
-GLXFBConfig qglx_findConfig(Display *display, int screen, const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
+QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
+XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit = GLX_WINDOW_BIT);
+GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat = false, int drawableBit = GLX_WINDOW_BIT);
void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config);
void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo);
-QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
-QSurfaceFormat qglx_reduceSurfaceFormat(const QSurfaceFormat &format, bool *reduced);
+bool qglx_reduceFormat(QSurfaceFormat *format);
#endif // QGLXCONVENIENCE_H
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
index f546cda4ad..079f0466dc 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
@@ -87,7 +87,7 @@ QXcbWindow *QXcbEglIntegration::createWindow(QWindow *window) const
QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
- QXcbEglContext *platformContext = new QXcbEglContext(context->format(),
+ QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()),
context->shareHandle(),
eglDisplay(),
screen->connection(),
@@ -98,7 +98,8 @@ QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLC
QPlatformOffscreenSurface *QXcbEglIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
- return new QEGLPbuffer(eglDisplay(), surface->requestedFormat(), surface);
+ QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle());
+ return new QEGLPbuffer(eglDisplay(), screen->surfaceFormatFor(surface->requestedFormat()), surface);
}
void *QXcbEglIntegration::xlib_display() const
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
index 777dfac535..69b7dfbdbf 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
@@ -59,15 +59,19 @@ QXcbEglWindow::~QXcbEglWindow()
eglDestroySurface(m_glIntegration->eglDisplay(), m_surface);
}
-void QXcbEglWindow::resolveFormat()
+void QXcbEglWindow::resolveFormat(const QSurfaceFormat &format)
{
- m_config = q_configFromGLFormat(m_glIntegration->eglDisplay(), window()->requestedFormat(), true);
- m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, m_format);
+ m_config = q_configFromGLFormat(m_glIntegration->eglDisplay(), format);
+ m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, format);
}
-void *QXcbEglWindow::createVisual()
-{
#ifdef XCB_USE_XLIB
+const xcb_visualtype_t *QXcbEglWindow::createVisual()
+{
+ QXcbScreen *scr = xcbScreen();
+ if (!scr)
+ return QXcbWindow::createVisual();
+
Display *xdpy = static_cast<Display *>(m_glIntegration->xlib_display());
VisualID id = QXlibEglIntegration::getCompatibleVisualId(xdpy, m_glIntegration->eglDisplay(), m_config);
@@ -78,11 +82,12 @@ void *QXcbEglWindow::createVisual()
XVisualInfo *visualInfo;
int matchingCount = 0;
visualInfo = XGetVisualInfo(xdpy, VisualIDMask, &visualInfoTemplate, &matchingCount);
- return visualInfo;
-#else
- return QXcbWindow::createVisual();
-#endif
+ const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
+ XFree(visualInfo);
+
+ return xcb_visualtype;
}
+#endif
void QXcbEglWindow::create()
{
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
index f36f53d168..48fc6dce70 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h
@@ -60,8 +60,11 @@ public:
protected:
void create() Q_DECL_OVERRIDE;
- void resolveFormat() Q_DECL_OVERRIDE;
- void *createVisual() Q_DECL_OVERRIDE;
+ void resolveFormat(const QSurfaceFormat &format) Q_DECL_OVERRIDE;
+
+#ifdef XCB_USE_XLIB
+ const xcb_visualtype_t *createVisual() Q_DECL_OVERRIDE;
+#endif
private:
QXcbEglIntegration *m_glIntegration;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index 4290ec54fc..5580f81a7a 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -715,8 +715,8 @@ bool QGLXContext::supportsThreading()
QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
: QPlatformOffscreenSurface(offscreenSurface)
- , m_format(offscreenSurface->requestedFormat())
, m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
+ , m_format(m_screen->surfaceFormatFor(offscreenSurface->requestedFormat()))
, m_pbuffer(0)
{
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
index f00d96e6d5..bf1f1b324b 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
@@ -106,8 +106,8 @@ public:
GLXPbuffer pbuffer() const { return m_pbuffer; }
private:
- QSurfaceFormat m_format;
QXcbScreen *m_screen;
+ QSurfaceFormat m_format;
GLXPbuffer m_pbuffer;
};
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index a3668df59a..d536121521 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -189,7 +189,7 @@ QXcbWindow *QXcbGlxIntegration::createWindow(QWindow *window) const
QPlatformOpenGLContext *QXcbGlxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
- QGLXContext *platformContext = new QGLXContext(screen, context->format(),
+ QGLXContext *platformContext = new QGLXContext(screen, screen->surfaceFormatFor(context->format()),
context->shareHandle(), context->nativeHandle());
context->setNativeHandle(platformContext->nativeHandle());
return platformContext;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
index 36503f4a7c..8ae83b8084 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
@@ -53,17 +53,15 @@ QXcbGlxWindow::~QXcbGlxWindow()
{
}
-void QXcbGlxWindow::resolveFormat()
-{
- m_format = window()->requestedFormat(); //qglx_findVisualInfo sets the resovled format
-}
-
-void *QXcbGlxWindow::createVisual()
+const xcb_visualtype_t *QXcbGlxWindow::createVisual()
{
QXcbScreen *scr = xcbScreen();
if (!scr)
return Q_NULLPTR;
- return qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format);
+ XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format);
+ const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
+ XFree(visualInfo);
+ return xcb_visualtype;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h
index 1954f972f1..9519245130 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h
@@ -52,8 +52,7 @@ public:
~QXcbGlxWindow();
protected:
- void resolveFormat() Q_DECL_OVERRIDE;
- void *createVisual() Q_DECL_OVERRIDE;
+ const xcb_visualtype_t *createVisual() Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 67a9b2f190..4cb1b29152 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -47,6 +47,7 @@
#include <stdio.h>
#include <QDebug>
+#include <QtAlgorithms>
#include <qpa/qwindowsysteminterface.h>
#include <private/qmath_p.h>
@@ -359,6 +360,69 @@ void QXcbScreen::windowShown(QXcbWindow *window)
}
}
+QSurfaceFormat QXcbScreen::surfaceFormatFor(const QSurfaceFormat &format) const
+{
+ const xcb_visualid_t xcb_visualid = connection()->hasDefaultVisualId() ? connection()->defaultVisualId()
+ : screen()->root_visual;
+ const xcb_visualtype_t *xcb_visualtype = visualForId(xcb_visualid);
+
+ const int redSize = qPopulationCount(xcb_visualtype->red_mask);
+ const int greenSize = qPopulationCount(xcb_visualtype->green_mask);
+ const int blueSize = qPopulationCount(xcb_visualtype->blue_mask);
+
+ QSurfaceFormat result = format;
+
+ if (result.redBufferSize() < 0)
+ result.setRedBufferSize(redSize);
+
+ if (result.greenBufferSize() < 0)
+ result.setGreenBufferSize(greenSize);
+
+ if (result.blueBufferSize() < 0)
+ result.setBlueBufferSize(blueSize);
+
+ return result;
+}
+
+const xcb_visualtype_t *QXcbScreen::visualForFormat(const QSurfaceFormat &format) const
+{
+ QVector<const xcb_visualtype_t *> candidates;
+
+ for (auto ii = m_visuals.constBegin(); ii != m_visuals.constEnd(); ++ii) {
+ const xcb_visualtype_t &xcb_visualtype = ii.value();
+
+ const int redSize = qPopulationCount(xcb_visualtype.red_mask);
+ const int greenSize = qPopulationCount(xcb_visualtype.green_mask);
+ const int blueSize = qPopulationCount(xcb_visualtype.blue_mask);
+ const int alphaSize = depthOfVisual(xcb_visualtype.visual_id) - redSize - greenSize - blueSize;
+
+ if (format.redBufferSize() != -1 && redSize != format.redBufferSize())
+ continue;
+
+ if (format.greenBufferSize() != -1 && greenSize != format.greenBufferSize())
+ continue;
+
+ if (format.blueBufferSize() != -1 && blueSize != format.blueBufferSize())
+ continue;
+
+ if (format.alphaBufferSize() != -1 && alphaSize != format.alphaBufferSize())
+ continue;
+
+ candidates.append(&xcb_visualtype);
+ }
+
+ if (candidates.isEmpty())
+ return nullptr;
+
+ // Try to find a RGB visual rather than e.g. BGR or GBR
+ for (const xcb_visualtype_t *candidate : qAsConst(candidates))
+ if (qCountTrailingZeroBits(candidate->blue_mask) == 0)
+ return candidate;
+
+ // Did not find anything we like, just grab the first one and hope for the best
+ return candidates.first();
+}
+
void QXcbScreen::sendStartupMessage(const QByteArray &message) const
{
xcb_window_t rootWindow = root();
@@ -403,7 +467,7 @@ quint8 QXcbScreen::depthOfVisual(xcb_visualid_t visualid) const
QImage::Format QXcbScreen::format() const
{
- return QImage::Format_RGB32;
+ return qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual));
}
QDpi QXcbScreen::virtualDpi() const
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 30c5073459..8716af29b5 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -155,6 +155,9 @@ public:
QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; }
+ QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const;
+
+ const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const;
const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
quint8 depthOfVisual(xcb_visualid_t) const;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 13eecbfb4f..a97420380c 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -382,18 +382,6 @@ void QXcbWindow::create()
return;
}
- const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK;
- const quint32 values[] = {
- // XCB_CW_BACK_PIXMAP
- XCB_NONE,
- // XCB_CW_OVERRIDE_REDIRECT
- type == Qt::Popup || type == Qt::ToolTip || (window()->flags() & Qt::BypassWindowManagerHint),
- // XCB_CW_SAVE_UNDER
- type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
- // XCB_CW_EVENT_MASK
- defaultEventMask
- };
-
// Parameters to XCreateWindow() are frame corner + inner size.
// This fits in case position policy is frame inclusive. There is
// currently no way to implement it for frame-exclusive geometries.
@@ -424,108 +412,76 @@ void QXcbWindow::create()
}
}
- resolveFormat();
-
-#ifdef XCB_USE_XLIB
- if (window()->surfaceType() != QSurface::RasterSurface
- && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
- XVisualInfo *visualInfo = Q_NULLPTR;
- if (connection()->hasDefaultVisualId())
- visualInfo = CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(this);
- if (!visualInfo)
- visualInfo = static_cast<XVisualInfo *>(createVisual());
-
- if (Q_UNLIKELY(!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface))
- qFatal("Could not initialize OpenGL");
-
- if (!visualInfo && window()->surfaceType() == QSurface::RasterGLSurface) {
- qWarning("Could not initialize OpenGL for RasterGLSurface, reverting to RasterSurface.");
- window()->setSurfaceType(QSurface::RasterSurface);
- }
-
- if (visualInfo) {
- m_depth = visualInfo->depth;
- m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask, &m_imageRgbSwap);
- Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
+ resolveFormat(platformScreen->surfaceFormatFor(window()->requestedFormat()));
- XSetWindowAttributes a;
- a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), platformScreen->screenNumber());
- a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), platformScreen->screenNumber());
- a.colormap = cmap;
+ const xcb_visualtype_t *visual = Q_NULLPTR;
- m_visualId = visualInfo->visualid;
+ if (connection()->hasDefaultVisualId()) {
+ visual = platformScreen->visualForId(connection()->defaultVisualId());
+ if (!visual)
+ qWarning() << "Failed to use requested visual id.";
+ }
- m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, rect.x(), rect.y(), rect.width(), rect.height(),
- 0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWBackPixel|CWBorderPixel|CWColormap, &a);
+ if (!visual)
+ visual = createVisual();
- XFree(visualInfo);
- }
+ if (!visual) {
+ qWarning() << "Falling back to using screens root_visual.";
+ visual = platformScreen->visualForId(platformScreen->screen()->root_visual);
}
-#endif
- if (!m_window)
- {
- m_window = xcb_generate_id(xcb_connection());
- m_visualId = UINT_MAX;
- const xcb_visualtype_t *visual = Q_NULLPTR;
- m_depth = platformScreen->screen()->root_depth;
+ Q_ASSERT(visual);
- uint32_t mask = 0;
- uint32_t values[3];
+ m_visualId = visual->visual_id;
+ m_depth = platformScreen->depthOfVisual(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
+ xcb_colormap_t colormap = 0;
- if (connection()->hasDefaultVisualId()) {
- m_visualId = connection()->defaultVisualId();
- visual = platformScreen->visualForId(m_visualId);
- }
+ quint32 mask = XCB_CW_BACK_PIXMAP
+ | XCB_CW_BORDER_PIXEL
+ | XCB_CW_BIT_GRAVITY
+ | XCB_CW_OVERRIDE_REDIRECT
+ | XCB_CW_SAVE_UNDER
+ | XCB_CW_EVENT_MASK;
- if (!visual) {
- if (connection()->hasDefaultVisualId())
- qWarning("Failed to use default visual id. Falling back to using screens root_visual");
-
- m_visualId = platformScreen->screen()->root_visual;
-
- if (m_format.alphaBufferSize() == 8) {
- xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen());
- while (depthIter.rem) {
- if (depthIter.data->depth == 32) {
- xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data);
- if (visualIter.rem) {
- m_visualId = visualIter.data->visual_id;
- m_depth = 32;
- uint32_t colormap = xcb_generate_id(xcb_connection());
- xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap,
- xcb_parent_id, m_visualId);
- mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
- values[0] = platformScreen->screen()->white_pixel;
- values[1] = platformScreen->screen()->black_pixel;
- values[2] = colormap;
- break;
- }
- }
- xcb_depth_next(&depthIter);
- }
- }
+ static const bool haveOpenGL = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL);
- visual = platformScreen->visualForId(m_visualId);
- }
+ if ((window()->supportsOpenGL() && haveOpenGL) || m_format.hasAlpha()) {
+ colormap = xcb_generate_id(xcb_connection());
+ Q_XCB_CALL(xcb_create_colormap(xcb_connection(),
+ XCB_COLORMAP_ALLOC_NONE,
+ colormap,
+ xcb_parent_id,
+ m_visualId));
- m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- m_depth,
- m_window, // window id
- xcb_parent_id, // parent window id
- rect.x(),
- rect.y(),
- rect.width(),
- rect.height(),
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- m_visualId, // visual
- mask,
- values));
+ mask |= XCB_CW_COLORMAP;
}
+ quint32 values[] = {
+ XCB_BACK_PIXMAP_NONE,
+ platformScreen->screen()->black_pixel,
+ XCB_GRAVITY_NORTH_WEST,
+ type == Qt::Popup || type == Qt::ToolTip || (window()->flags() & Qt::BypassWindowManagerHint),
+ type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
+ defaultEventMask,
+ colormap
+ };
+
+ m_window = xcb_generate_id(xcb_connection());
+ Q_XCB_CALL(xcb_create_window(xcb_connection(),
+ m_depth,
+ m_window, // window id
+ xcb_parent_id, // parent window id
+ rect.x(),
+ rect.y(),
+ rect.width(),
+ rect.height(),
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ m_visualId, // visual
+ mask,
+ values));
+
connection()->addWindowEventListener(m_window, this);
Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
@@ -2560,6 +2516,12 @@ void QXcbWindow::updateSyncRequestCounter()
}
}
+const xcb_visualtype_t *QXcbWindow::createVisual()
+{
+ return xcbScreen() ? xcbScreen()->visualForFormat(m_format)
+ : nullptr;
+}
+
bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
{
if (grab && !connection()->canGrab())
@@ -2831,3 +2793,4 @@ QXcbScreen *QXcbWindow::xcbScreen() const
}
QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 7b70dc2ef8..9ad0153ca2 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -182,8 +182,8 @@ public Q_SLOTS:
void updateSyncRequestCounter();
protected:
- virtual void resolveFormat() { m_format = window()->requestedFormat(); }
- virtual void *createVisual() { return Q_NULLPTR; }
+ virtual void resolveFormat(const QSurfaceFormat &format) { m_format = format; }
+ virtual const xcb_visualtype_t *createVisual();
QXcbScreen *parentScreen();