diff options
author | Louai Al-Khanji <louai.al-khanji@theqtcompany.com> | 2016-03-03 14:16:29 -0800 |
---|---|---|
committer | Louai Al-Khanji <louai.al-khanji@theqtcompany.com> | 2016-04-09 05:17:27 +0000 |
commit | 5f39a0ef8d037ed8d1fa19d5514308ed4a2ca161 (patch) | |
tree | a9d0d69ba8add9ef11384a577ec5f9692aeed709 /src/plugins/platforms/xcb/qxcbscreen.cpp | |
parent | 89034600939bbfe241ba3d6136abf7bb6961db52 (diff) |
X11: Better support non-32bit visuals
This patch improves support for non-32bit screen configurations on X. The
patch mostly touches the xcb platform plugin but the changes to the glx
convenience functions do affect e.g. the offscreen plugin as well.
Since QWindow instances are now by default of type RasterGL instead of
Raster the majority of all windows are in fact instances of QXcbGlxWindow.
This means that the eventual QSurfaceFormat that we use is chosen based on
the available OpenGL configurations. Here the GLX config resolution code
did not do a very good job in trying to find the closest match relative to
the requested QSurfaceFormat, instead preferring higher bit depths.
This is an issue since many configurations support 32-bit windows even
if the screen itself has a root window with depth 16. In particular,
servers supporting both GLX and Render are very likely to have such
visuals. Particularly affected are remote X connections - even if the
application itself makes no use of OpenGL at all!
The changes introduced by this patch are as follows:
1. Improve the GLX visual selection logic
2. Improve the xcb visual selection logic
3. Remove duplicated visual lookup for OpenGL-enabled windows
4. Configure the default QSurfaceFormat to match the primary screen depth
Change-Id: Id1c176359e63a4581410e20350db5ac2c083e1cf
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbscreen.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.cpp | 66 |
1 files changed, 65 insertions, 1 deletions
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 |