diff options
Diffstat (limited to 'src/plugins/platforms')
12 files changed, 165 insertions, 129 deletions
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(); |