diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-11 08:48:27 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-04-11 09:12:36 +0200 |
commit | f34e73a16a3d757057e007874cb5008f16e20f02 (patch) | |
tree | bcc228617cf240773fd09daac1a1a2614b552b68 /src/plugins/platforms/xcb | |
parent | 5380808453728a354ae28aae76e85ac448245cf1 (diff) | |
parent | b9d386f2ccd69c7f6a766a6d90a6024eeb48e90a (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
src/corelib/kernel/qobject.cpp
src/gui/painting/qpaintengine_raster.cpp
Change-Id: I74e1779832f43d033708dcfd6b666c7b4f0111fb
Diffstat (limited to 'src/plugins/platforms/xcb')
17 files changed, 274 insertions, 170 deletions
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp index f2ea56b45a..59401d2ce7 100644 --- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp @@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(QT_XCB_GLINTEGRATION, "qt.xcb.glintegration") +Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl") QXcbGlIntegration::QXcbGlIntegration() { diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h index 6cc96d39be..719d2ace90 100644 --- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h @@ -50,7 +50,7 @@ class QPlatformOffscreenSurface; class QOffscreenSurface; class QXcbNativeInterfaceHandler; -Q_XCB_EXPORT Q_DECLARE_LOGGING_CATEGORY(QT_XCB_GLINTEGRATION) +Q_XCB_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaGl) class Q_XCB_EXPORT QXcbGlIntegration { 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 29f92a1049..079f0466dc 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp @@ -51,7 +51,7 @@ QXcbEglIntegration::QXcbEglIntegration() : m_connection(Q_NULLPTR) , m_egl_display(EGL_NO_DISPLAY) { - qCDebug(QT_XCB_GLINTEGRATION) << "Xcb EGL gl-integration created"; + qCDebug(lcQpaGl) << "Xcb EGL gl-integration created"; } QXcbEglIntegration::~QXcbEglIntegration() @@ -69,13 +69,13 @@ bool QXcbEglIntegration::initialize(QXcbConnection *connection) bool success = eglInitialize(m_egl_display, &major, &minor); if (!success) { m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - qCDebug(QT_XCB_GLINTEGRATION) << "Xcb EGL gl-integration retrying with display" << m_egl_display; + qCDebug(lcQpaGl) << "Xcb EGL gl-integration retrying with display" << m_egl_display; success = eglInitialize(m_egl_display, &major, &minor); } m_native_interface_handler.reset(new QXcbEglNativeInterfaceHandler(connection->nativeInterface())); - qCDebug(QT_XCB_GLINTEGRATION) << "Xcb EGL gl-integration successfully initialized"; + qCDebug(lcQpaGl) << "Xcb EGL gl-integration successfully initialized"; return success; } @@ -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 3e963ccaa8..d536121521 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -93,7 +93,7 @@ QXcbGlxIntegration::QXcbGlxIntegration() : m_connection(Q_NULLPTR) , m_glx_first_event(0) { - qCDebug(QT_XCB_GLINTEGRATION) << "Xcb GLX gl-integration created"; + qCDebug(lcQpaGl) << "Xcb GLX gl-integration created"; } QXcbGlxIntegration::~QXcbGlxIntegration() @@ -118,7 +118,7 @@ bool QXcbGlxIntegration::initialize(QXcbConnection *connection) xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection->xcb_connection(), xglx_query_cookie, &error); if (!xglx_query || error) { - qCWarning(QT_XCB_GLINTEGRATION) << "QXcbConnection: Failed to initialize GLX"; + qCWarning(lcQpaGl) << "QXcbConnection: Failed to initialize GLX"; free(error); return false; } @@ -127,7 +127,7 @@ bool QXcbGlxIntegration::initialize(QXcbConnection *connection) m_native_interface_handler.reset(new QXcbGlxNativeInterfaceHandler(connection->nativeInterface())); - qCDebug(QT_XCB_GLINTEGRATION) << "Xcb GLX gl-integration successfully initialized"; + qCDebug(lcQpaGl) << "Xcb GLX gl-integration successfully initialized"; return true; } @@ -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/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 8f0f683d04..9fa9db158b 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -58,6 +58,7 @@ #include <QtGui/private/qhighdpiscaling_p.h> #include <qpa/qplatformgraphicsbuffer.h> #include <private/qimage_p.h> +#include <qendian.h> #include <algorithm> QT_BEGIN_NAMESPACE @@ -107,6 +108,7 @@ private: // do a server-side copy on expose instead of sending the pixels every time xcb_pixmap_t m_xcb_pixmap; QRegion m_pendingFlush; + QByteArray m_flushBuffer; bool m_hasAlpha; }; @@ -287,11 +289,84 @@ void QXcbShmImage::ensureGC(xcb_drawable_t dst) } } +static inline void copy_unswapped(char *dst, int dstBytesPerLine, const QImage &img, const QRect &rect) +{ + const uchar *srcData = img.constBits(); + const int srcBytesPerLine = img.bytesPerLine(); + + const int leftOffset = rect.left() * img.depth() >> 3; + const int bottom = rect.bottom() + 1; + + for (int yy = rect.top(); yy < bottom; ++yy) { + const uchar *src = srcData + yy * srcBytesPerLine + leftOffset; + ::memmove(dst, src, dstBytesPerLine); + dst += dstBytesPerLine; + } +} + +template <class Pixel> +static inline void copy_swapped(Pixel *dst, const QImage &img, const QRect &rect) +{ + const uchar *srcData = img.constBits(); + const int srcBytesPerLine = img.bytesPerLine(); + + const int left = rect.left(); + const int right = rect.right() + 1; + const int bottom = rect.bottom() + 1; + + for (int yy = rect.top(); yy < bottom; ++yy) { + const Pixel *src = reinterpret_cast<const Pixel *>(srcData + yy * srcBytesPerLine) + left; + + for (int xx = left; xx < right; ++xx) + *dst++ = qbswap<Pixel>(*src++); + } +} + +static QImage native_sub_image(QByteArray *buffer, const QImage &src, int x, int y, int w, int h, bool swap) +{ + const QRect rect(x, y, w, h); + + if (!swap && src.rect() == rect) + return src; + + const int dstStride = w * src.depth() >> 3; + buffer->resize(h * dstStride); + + if (swap) { + switch (src.depth()) { + case 32: + copy_swapped(reinterpret_cast<quint32 *>(buffer->data()), src, rect); + break; + case 16: + copy_swapped(reinterpret_cast<quint16 *>(buffer->data()), src, rect); + break; + } + } else { + copy_unswapped(buffer->data(), dstStride, src, rect); + } + + return QImage(reinterpret_cast<const uchar *>(buffer->constData()), w, h, dstStride, src.format()); +} + void QXcbShmImage::flushPixmap(const QRegion ®ion) { const QVector<QRect> rects = m_pendingFlush.intersected(region).rects(); m_pendingFlush -= region; + xcb_image_t xcb_subimage; + memset(&xcb_subimage, 0, sizeof(xcb_image_t)); + + xcb_subimage.format = m_xcb_image->format; + xcb_subimage.scanline_pad = m_xcb_image->scanline_pad; + xcb_subimage.depth = m_xcb_image->depth; + xcb_subimage.bpp = m_xcb_image->bpp; + xcb_subimage.unit = m_xcb_image->unit; + xcb_subimage.plane_mask = m_xcb_image->plane_mask; + xcb_subimage.byte_order = (xcb_image_order_t) connection()->setup()->image_byte_order; + xcb_subimage.bit_order = m_xcb_image->bit_order; + + const bool needsByteSwap = xcb_subimage.byte_order != m_xcb_image->byte_order; + for (const QRect &rect : rects) { // We must make sure that each request is not larger than max_req_size. // Each request takes req_size + m_xcb_image->stride * height bytes. @@ -308,37 +383,29 @@ void QXcbShmImage::flushPixmap(const QRegion ®ion) // larger than the server's maximum request size and stuff breaks. // To work around that, we upload the image in chunks where each chunk // is small enough for a single request. - int src_x = rect.x(); - int src_y = rect.y(); - int target_x = rect.x(); - int target_y = rect.y(); - int width = rect.width(); + const int x = rect.x(); + int y = rect.y(); + const int width = rect.width(); int height = rect.height(); while (height > 0) { - int rows = std::min(height, rows_per_put); + const int rows = std::min(height, rows_per_put); + const QImage subImage = native_sub_image(&m_flushBuffer, m_qimage, x, y, width, rows, needsByteSwap); - xcb_image_t *subimage = xcb_image_subimage(m_xcb_image, src_x, src_y, width, rows, - 0, 0, 0); - - // Convert the image to the native byte order. - xcb_image_t *native_subimage = xcb_image_native(xcb_connection(), subimage, 1); + xcb_subimage.width = width; + xcb_subimage.height = rows; + xcb_subimage.data = const_cast<uint8_t *>(subImage.constBits()); + xcb_image_annotate(&xcb_subimage); xcb_image_put(xcb_connection(), m_xcb_pixmap, m_gc, - native_subimage, - target_x, - target_y, + &xcb_subimage, + x, + y, 0); - if (native_subimage != subimage) - xcb_image_destroy(native_subimage); - - xcb_image_destroy(subimage); - - src_y += rows; - target_y += rows; + y += rows; height -= rows; } } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 4fee772cd6..cb222842db 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -644,7 +644,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra glIntegrationNames << QStringLiteral("xcb_glx") << QStringLiteral("xcb_egl"); QString glIntegrationName = QString::fromLocal8Bit(qgetenv("QT_XCB_GL_INTEGRATION")); if (!glIntegrationName.isEmpty()) { - qCDebug(QT_XCB_GLINTEGRATION) << "QT_XCB_GL_INTEGRATION is set to" << glIntegrationName; + qCDebug(lcQpaGl) << "QT_XCB_GL_INTEGRATION is set to" << glIntegrationName; if (glIntegrationName != QLatin1String("none")) { glIntegrationNames.removeAll(glIntegrationName); glIntegrationNames.prepend(glIntegrationName); @@ -653,17 +653,19 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra } } - qCDebug(QT_XCB_GLINTEGRATION) << "Choosing xcb gl-integration based on following priority\n" << glIntegrationNames; - for (int i = 0; i < glIntegrationNames.size() && !m_glIntegration; i++) { - m_glIntegration = QXcbGlIntegrationFactory::create(glIntegrationNames.at(i)); - if (m_glIntegration && !m_glIntegration->initialize(this)) { - qCDebug(QT_XCB_GLINTEGRATION) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i); - delete m_glIntegration; - m_glIntegration = Q_NULLPTR; + if (!glIntegrationNames.isEmpty()) { + qCDebug(lcQpaGl) << "Choosing xcb gl-integration based on following priority\n" << glIntegrationNames; + for (int i = 0; i < glIntegrationNames.size() && !m_glIntegration; i++) { + m_glIntegration = QXcbGlIntegrationFactory::create(glIntegrationNames.at(i)); + if (m_glIntegration && !m_glIntegration->initialize(this)) { + qCDebug(lcQpaGl) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i); + delete m_glIntegration; + m_glIntegration = Q_NULLPTR; + } } + if (!m_glIntegration) + qCDebug(lcQpaGl) << "Failed to create xcb gl-integration"; } - if (!m_glIntegration) - qCDebug(QT_XCB_GLINTEGRATION) << "Failed to create xcb gl-integration"; sync(); } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index a16e24061c..48912e0520 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -1002,7 +1002,6 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const Q_ASSERT(shiftMod < 32); Q_ASSERT(altMod < 32); Q_ASSERT(controlMod < 32); - Q_ASSERT(metaMod < 32); xkb_mod_mask_t depressed; int qtKey = 0; @@ -1023,7 +1022,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const depressed |= (1 << shiftMod); if (neededMods & Qt::ControlModifier) depressed |= (1 << controlMod); - if (neededMods & Qt::MetaModifier) + if (metaMod < 32 && neededMods & Qt::MetaModifier) depressed |= (1 << metaMod); xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, 0, 0, lockedLayout); sym = xkb_state_key_get_one_sym(kb_state, keycode); 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 a426e04721..b0b21a5be4 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()) @@ -2830,3 +2792,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(); |