summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-09-28 14:10:10 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-10-07 09:04:38 +0000
commit06089a19e52126bb83016d6a360aaf32c53bed49 (patch)
treee6058ddc96b75ce9f6cf7f8131fe203cf3819a87
parent23d0c77ce86927963ea2b0a31564cfd5189a7539 (diff)
xcb: Unify visual to QImage::Format logic
Make a common function to replace the two existing ones that convert from XCB visuals to QImage format. Change-Id: I2ae08ef4df96df950910a45e71c9d9cd98375b2e Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp144
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp103
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
6 files changed, 114 insertions, 146 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index d53a961b85..de11ecfb6e 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -2070,7 +2070,8 @@ const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
xcb_format_next(&iterator);
}
- return 0;
+ qWarning() << "XCB failed to find an xcb_format_t for depth:" << depth;
+ return nullptr;
}
void QXcbConnection::sync()
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 9fb0d44b74..e259fbf0b4 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -53,39 +53,108 @@ extern "C" {
#undef template
#endif
+#include "qxcbconnection.h"
+#include "qxcbintegration.h"
+
+namespace {
+
+QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask, int blue_mask)
+{
+ if (bits_per_pixel == 32) {
+ switch (depth) {
+ case 32:
+ if (red_mask == 0xff0000 && blue_mask == 0xff)
+ return QImage::Format_ARGB32_Premultiplied;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (red_mask == 0xff && blue_mask == 0xff0000)
+ return QImage::Format_RGBA8888_Premultiplied;
+#else
+ if (red_mask == 0xff000000 && blue_mask == 0xff00)
+ return QImage::Format_RGBA8888_Premultiplied;
+#endif
+ if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
+ return QImage::Format_A2BGR30_Premultiplied;
+ if (red_mask == 0x3ff00000 && blue_mask == 0x3ff)
+ return QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case 30:
+ if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
+ return QImage::Format_BGR30;
+ if (blue_mask == 0x3ff && red_mask == 0x3ff00000)
+ return QImage::Format_RGB30;
+ break;
+ case 24:
+ if (red_mask == 0xff0000 && blue_mask == 0xff)
+ return QImage::Format_RGB32;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (red_mask == 0xff && blue_mask == 0xff0000)
+ return QImage::Format_RGBX8888;
+#else
+ if (red_mask == 0xff000000 && blue_mask == 0xff00)
+ return QImage::Format_RGBX8888;
+#endif
+ break;
+ }
+ } else if (bits_per_pixel == 16) {
+ if (depth == 16 && red_mask == 0xf800 && blue_mask == 0x1f)
+ return QImage::Format_RGB16;
+ if (depth == 15 && red_mask == 0x7c00 && blue_mask == 0x1f)
+ return QImage::Format_RGB555;
+ }
+ return QImage::Format_Invalid;
+}
+
+} // namespace
+
QT_BEGIN_NAMESPACE
-// TODO: Merge with imageFormatForVisual in qxcbwindow.cpp
-QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth,
- const xcb_visualtype_t *visual)
+bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual,
+ QImage::Format *imageFormat, bool *needsRgbSwap)
{
- const xcb_format_t *format = connection->formatForDepth(depth);
+ Q_ASSERT(connection && visual && imageFormat);
+
+ if (needsRgbSwap)
+ *needsRgbSwap = false;
+ *imageFormat = QImage::Format_Invalid;
- if (!visual || !format)
- return QImage::Format_Invalid;
+ if (depth == 8) {
+ if (visual->_class == XCB_VISUAL_CLASS_GRAY_SCALE) {
+ *imageFormat = QImage::Format_Grayscale8;
+ return true;
+ }
+#if QT_CONFIG(xcb_native_painting)
+ if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled()) {
+ *imageFormat = QImage::Format_Indexed8;
+ return true;
+ }
+#endif
+ return false;
+ }
- if (depth == 32 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return QImage::Format_ARGB32_Premultiplied;
+ const xcb_format_t *format = connection->formatForDepth(depth);
+ if (!format)
+ return false;
- if (depth == 30 && format->bits_per_pixel == 32 && visual->red_mask == 0x3ff
- && visual->green_mask == 0x0ffc00 && visual->blue_mask == 0x3ff00000)
- return QImage::Format_BGR30;
+ const bool connectionEndianSwap = connection->imageNeedsEndianSwap();
+ // We swap the masks and see if we can recognize it as a host format
+ const quint32 red_mask = connectionEndianSwap ? qbswap(visual->red_mask) : visual->red_mask;
+ const quint32 blue_mask = connectionEndianSwap ? qbswap(visual->blue_mask) : visual->blue_mask;
- if (depth == 30 && format->bits_per_pixel == 32 && visual->blue_mask == 0x3ff
- && visual->green_mask == 0x0ffc00 && visual->red_mask == 0x3ff00000)
- return QImage::Format_RGB30;
+ *imageFormat = imageFormatForMasks(depth, format->bits_per_pixel, red_mask, blue_mask);
+ if (*imageFormat != QImage::Format_Invalid)
+ return true;
- if (depth == 24 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return QImage::Format_RGB32;
+ if (needsRgbSwap) {
+ *imageFormat = imageFormatForMasks(depth, format->bits_per_pixel, blue_mask, red_mask);
+ if (*imageFormat != QImage::Format_Invalid) {
+ *needsRgbSwap = true;
+ return true;
+ }
+ }
- if (depth == 16 && format->bits_per_pixel == 16 && visual->red_mask == 0xf800
- && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
- return QImage::Format_RGB16;
+ qWarning("Unsupported screen format: depth: %d, bits_per_pixel: %d, red_mask: %x, blue_mask: %x", depth, format->bits_per_pixel, red_mask, blue_mask);
- qWarning("qt_xcb_imageFormatForVisual did not recognize format");
- return QImage::Format_Invalid;
+ return false;
}
QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap,
@@ -105,33 +174,14 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
QPixmap result;
- QImage::Format format = qt_xcb_imageFormatForVisual(connection, depth, visual);
- if (format != QImage::Format_Invalid) {
+ QImage::Format format;
+ bool needsRgbSwap;
+ if (qt_xcb_imageFormatForVisual(connection, depth, visual, &format, &needsRgbSwap)) {
uint32_t bytes_per_line = length / height;
QImage image(const_cast<uint8_t *>(data), width, height, bytes_per_line, format);
- // we may have to swap the byte order
- if (connection->imageNeedsEndianSwap()) {
- if (image.depth() == 16) {
- for (int i = 0; i < image.height(); ++i) {
- ushort *p = reinterpret_cast<ushort *>(image.scanLine(i));
- ushort *end = p + image.width();
- while (p < end) {
- *p = qbswap(*p);
- p++;
- }
- }
- } else if (image.depth() == 32) {
- for (int i = 0; i < image.height(); ++i) {
- uint *p = reinterpret_cast<uint *>(image.scanLine(i));
- uint *end = p + image.width();
- while (p < end) {
- *p = qbswap(*p);
- p++;
- }
- }
- }
- }
+ if (needsRgbSwap)
+ image = std::move(image).rgbSwapped();
// fix-up alpha channel
if (format == QImage::Format_RGB32) {
diff --git a/src/plugins/platforms/xcb/qxcbimage.h b/src/plugins/platforms/xcb/qxcbimage.h
index a9071a45de..d718089ec2 100644
--- a/src/plugins/platforms/xcb/qxcbimage.h
+++ b/src/plugins/platforms/xcb/qxcbimage.h
@@ -48,8 +48,8 @@
QT_BEGIN_NAMESPACE
-QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection,
- uint8_t depth, const xcb_visualtype_t *visual);
+bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual,
+ QImage::Format *imageFormat, bool *needsRgbSwap = nullptr);
QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap,
int width, int height, int depth,
const xcb_visualtype_t *visual);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 45a0f19d98..cdeafa8cba 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -583,7 +583,9 @@ QRect QXcbScreen::availableGeometry() const
QImage::Format QXcbScreen::format() const
{
- return qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual));
+ QImage::Format format;
+ qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual), &format);
+ return format;
}
QDpi QXcbScreen::virtualDpi() const
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index aaca7def99..bce078d657 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -42,7 +42,6 @@
#include <QtDebug>
#include <QMetaEnum>
#include <QScreen>
-#include <QtCore/qendian.h>
#include <QtGui/QIcon>
#include <QtGui/QRegion>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -52,6 +51,7 @@
#include "qxcbscreen.h"
#include "qxcbdrag.h"
#include "qxcbkeyboard.h"
+#include "qxcbimage.h"
#include "qxcbwmsupport.h"
#include "qxcbimage.h"
#include "qxcbnativeinterface.h"
@@ -177,108 +177,23 @@ static inline bool isTransient(const QWindow *w)
|| w->type() == Qt::Popup;
}
-// TODO: Merge with qt_xcb_imageFormatForVisual in qxcbimage.cpp
-QImage::Format QXcbWindow::imageFormatForVisual(const xcb_visualtype_t *visual, bool *rgbSwap) const
+void QXcbWindow::setImageFormatForVisual(const xcb_visualtype_t *visual)
{
- const bool connectionEndianSwap = connection()->imageNeedsEndianSwap();
- // We swap the masks and see if we can recognize it as a host format
- const quint32 red_mask = connectionEndianSwap ? qbswap(visual->red_mask) : visual->red_mask;
- const quint32 blue_mask = connectionEndianSwap ? qbswap(visual->blue_mask) : visual->blue_mask;
-
- if (rgbSwap)
- *rgbSwap = false;
- switch (m_depth) {
- case 32:
- if (blue_mask == 0xff)
- return QImage::Format_ARGB32_Premultiplied;
- if (red_mask == 0x3ff)
- return QImage::Format_A2BGR30_Premultiplied;
- if (blue_mask == 0x3ff)
- return QImage::Format_A2RGB30_Premultiplied;
- if (red_mask == 0xff) {
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- return QImage::Format_RGBA8888_Premultiplied;
-#else
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_ARGB32_Premultiplied;
-#endif
- }
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- if (red_mask == 0xff00 && blue_mask == 0xff000000) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGBA8888_Premultiplied;
- }
-#endif
- break;
- case 30:
- if (red_mask == 0x3ff)
- return QImage::Format_BGR30;
- if (blue_mask == 0x3ff)
- return QImage::Format_RGB30;
- break;
- case 24:
- if (blue_mask == 0xff)
- return QImage::Format_RGB32;
- if (red_mask == 0xff) {
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- return QImage::Format_RGBX8888;
-#else
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGB32;
-#endif
- }
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- if (red_mask == 0xff00 && blue_mask == 0xff000000) {
- *rgbSwap = true;
- return QImage::Format_RGBX8888;
- }
-#endif
- break;
- case 16:
- if (blue_mask == 0x1f)
- return QImage::Format_RGB16;
- if (red_mask == 0x1f) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGB16;
- }
- break;
- case 15:
- if (blue_mask == 0x1f)
- return QImage::Format_RGB555;
- if (red_mask == 0x1f) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGB555;
- }
- break;
-#if QT_CONFIG(xcb_native_painting)
- case 8:
- if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled())
- return QImage::Format_Indexed8;
- break;
-#endif
- default:
- break;
- }
- qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", m_depth, red_mask, blue_mask);
+ if (qt_xcb_imageFormatForVisual(connection(), m_depth, visual, &m_imageFormat, &m_imageRgbSwap))
+ return;
switch (m_depth) {
case 32:
case 24:
qWarning("Using RGB32 fallback, if this works your X11 server is reporting a bad screen format.");
- return QImage::Format_RGB32;
+ m_imageFormat = QImage::Format_RGB32;
+ break;
case 16:
qWarning("Using RGB16 fallback, if this works your X11 server is reporting a bad screen format.");
- return QImage::Format_RGB16;
+ m_imageFormat = QImage::Format_RGB16;
default:
break;
}
-
- return QImage::Format_Invalid;
}
static inline bool positionIncludesFrame(QWindow *w)
@@ -410,7 +325,7 @@ void QXcbWindow::create()
}
if (!visual)
visual = platformScreen->visualForId(m_visualId);
- m_imageFormat = imageFormatForVisual(visual, &m_imageRgbSwap);
+ setImageFormatForVisual(visual);
connection()->addWindowEventListener(m_window, this);
return;
}
@@ -480,7 +395,7 @@ void QXcbWindow::create()
m_visualId = visual->visual_id;
m_depth = platformScreen->depthOfVisual(m_visualId);
- m_imageFormat = imageFormatForVisual(visual, &m_imageRgbSwap);
+ setImageFormatForVisual(visual);
quint32 mask = XCB_CW_BACK_PIXMAP
| XCB_CW_BORDER_PIXEL
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index ebace55328..176f9a234c 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -188,7 +188,7 @@ public Q_SLOTS:
protected:
virtual void resolveFormat(const QSurfaceFormat &format) { m_format = format; }
virtual const xcb_visualtype_t *createVisual();
- QImage::Format imageFormatForVisual(const xcb_visualtype_t *visual, bool *rgbSwap) const;
+ void setImageFormatForVisual(const xcb_visualtype_t *visual);
QXcbScreen *parentScreen();