62de824
From b56dbaf5b3247bd8e87e4e856ad845593755c10c Mon Sep 17 00:00:00 2001
62de824
From: =?utf-8?q?Samuel=20R=C3=B8dal?= <samuel.rodal@nokia.com>
62de824
Date: Wed, 28 Sep 2011 15:22:56 +0200
62de824
Subject: [PATCH] Fixed broken window surface flush when depth is 24 and bpp is not 32.
62de824
62de824
Some X servers use a compact representation of 24 depth visuals. In that
62de824
case we can't use the shared memory or XPutImage paths, as Qt's RGB32
62de824
does not match the internal memory layout.
62de824
62de824
Also fixed QPixmap::fromImage() to work in this case to prevent the red
62de824
and blue channels from being swapped.
62de824
62de824
Task-number: QTBUG-21754
62de824
Reviewed-by: Alberto Mardegan
62de824
---
62de824
 src/gui/image/qnativeimage.cpp             |   12 ++++++------
62de824
 src/gui/image/qpixmap_x11.cpp              |   18 +++++++++++++-----
62de824
 src/gui/kernel/qapplication_x11.cpp        |    6 ++++++
62de824
 src/gui/kernel/qt_x11_p.h                  |    2 ++
62de824
 src/gui/painting/qwindowsurface_raster.cpp |    5 +++--
62de824
 5 files changed, 30 insertions(+), 13 deletions(-)
62de824
62de824
diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp
62de824
index aebcbaf..e1382dd 100644
62de824
--- a/src/gui/image/qnativeimage.cpp
62de824
+++ b/src/gui/image/qnativeimage.cpp
62de824
@@ -153,7 +153,12 @@ QImage::Format QNativeImage::systemFormat()
62de824
 QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* isTextBuffer */, QWidget *widget)
62de824
     : xshmimg(0), xshmpm(0)
62de824
 {
62de824
-    if (!X11->use_mitshm) {
62de824
+    QX11Info info = widget->x11Info();
62de824
+
62de824
+    int dd = info.depth();
62de824
+    Visual *vis = (Visual*) info.visual();
62de824
+
62de824
+    if (!X11->use_mitshm || format != QImage::Format_RGB16 && X11->bppForDepth.value(dd) != 32) {
62de824
         image = QImage(width, height, format);
62de824
         // follow good coding practice and set xshminfo attributes, though values not used in this case
62de824
         xshminfo.readOnly = true;
62de824
@@ -163,11 +168,6 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /*
62de824
         return;
62de824
     }
62de824
 
62de824
-    QX11Info info = widget->x11Info();
62de824
-
62de824
-    int dd = info.depth();
62de824
-    Visual *vis = (Visual*) info.visual();
62de824
-
62de824
     xshmimg = XShmCreateImage(X11->display, vis, dd, ZPixmap, 0, &xshminfo, width, height);
62de824
     if (!xshmimg) {
62de824
         qWarning("QNativeImage: Unable to create shared XImage.");
62de824
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
62de824
index 77c2a2a..0e1401c 100644
62de824
--- a/src/gui/image/qpixmap_x11.cpp
62de824
+++ b/src/gui/image/qpixmap_x11.cpp
62de824
@@ -897,12 +897,20 @@ void QX11PixmapData::fromImage(const QImage &img,
62de824
                     }
62de824
                     )
62de824
                     break;
62de824
-            case BPP24_888:                        // 24 bit MSB
62de824
+            case BPP24_888:
62de824
                 CYCLE(
62de824
-                    for (int x=0; x
62de824
-                        *dst++ = qRed  (*p);
62de824
-                        *dst++ = qGreen(*p);
62de824
-                        *dst++ = qBlue (*p++);
62de824
+                    if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
62de824
+                        for (int x=0; x
62de824
+                            *dst++ = qRed  (*p);
62de824
+                            *dst++ = qGreen(*p);
62de824
+                            *dst++ = qBlue (*p++);
62de824
+                        }
62de824
+                    } else {
62de824
+                        for (int x=0; x
62de824
+                            *dst++ = qBlue (*p);
62de824
+                            *dst++ = qGreen(*p);
62de824
+                            *dst++ = qRed  (*p++);
62de824
+                        }
62de824
                     }
62de824
                     )
62de824
                     break;
62de824
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
62de824
index ef8e2b8..408e9ac 100644
62de824
--- a/src/gui/kernel/qapplication_x11.cpp
62de824
+++ b/src/gui/kernel/qapplication_x11.cpp
62de824
@@ -1896,6 +1896,12 @@ void qt_init(QApplicationPrivate *priv, int,
62de824
         X11->defaultScreen = DefaultScreen(X11->display);
62de824
         X11->screenCount = ScreenCount(X11->display);
62de824
 
62de824
+        int formatCount = 0;
62de824
+        XPixmapFormatValues *values = XListPixmapFormats(X11->display, &formatCount);
62de824
+        for (int i = 0; i < formatCount; ++i)
62de824
+            X11->bppForDepth[values[i].depth] = values[i].bits_per_pixel;
62de824
+        XFree(values);
62de824
+
62de824
         X11->screens = new QX11InfoData[X11->screenCount];
62de824
         X11->argbVisuals = new Visual *[X11->screenCount];
62de824
         X11->argbColormaps = new Colormap[X11->screenCount];
62de824
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
62de824
index 72acaf3..fe4a631 100644
62de824
--- a/src/gui/kernel/qt_x11_p.h
62de824
+++ b/src/gui/kernel/qt_x11_p.h
62de824
@@ -54,6 +54,7 @@
62de824
 //
62de824
 
62de824
 #include "QtGui/qwindowdefs.h"
62de824
+#include "QtCore/qhash.h"
62de824
 #include "QtCore/qlist.h"
62de824
 #include "QtCore/qvariant.h"
62de824
 
62de824
@@ -467,6 +468,7 @@ struct QX11Data
62de824
     Colormap *argbColormaps;
62de824
     int screenCount;
62de824
     int defaultScreen;
62de824
+    QHash<int, int> bppForDepth;
62de824
 
62de824
     Time time;
62de824
     Time userTime;
62de824
diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
62de824
index 15ff044..2a25bff 100644
62de824
--- a/src/gui/painting/qwindowsurface_raster.cpp
62de824
+++ b/src/gui/painting/qwindowsurface_raster.cpp
62de824
@@ -254,8 +254,9 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
62de824
     } else
62de824
 #endif
62de824
     {
62de824
+        int depth = widget->x11Info().depth();
62de824
         const QImage &src = d->image->image;
62de824
-        if (src.format() != QImage::Format_RGB32 || widget->x11Info().depth() < 24) {
62de824
+        if (src.format() != QImage::Format_RGB32 || depth < 24 || X11->bppForDepth.value(depth) != 32) {
62de824
             Q_ASSERT(src.depth() >= 16);
62de824
             const QImage sub_src(src.scanLine(br.y()) + br.x() * (uint(src.depth()) / 8),
62de824
                                  br.width(), br.height(), src.bytesPerLine(), src.format());
62de824
@@ -267,7 +268,7 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
62de824
         } else {
62de824
             // qpaintengine_x11.cpp
62de824
             extern void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image, Drawable hd, GC gc, Display *dpy, Visual *visual, int depth);
62de824
-            qt_x11_drawImage(br, wpos, src, widget->handle(), d_ptr->gc, X11->display, (Visual *)widget->x11Info().visual(), widget->x11Info().depth());
62de824
+            qt_x11_drawImage(br, wpos, src, widget->handle(), d_ptr->gc, X11->display, (Visual *)widget->x11Info().visual(), depth);
62de824
         }
62de824
     }
62de824
 
62de824
-- 
62de824
1.6.1
62de824