crash when using a visual with 24 bits per pixel (#749647,QTBUG-21754)

This commit is contained in:
Rex Dieter 2011-10-28 15:27:57 -05:00
parent d5adc58734
commit 62de8242b5
3 changed files with 154 additions and 20 deletions

View File

@ -1,15 +0,0 @@
diff -up qt-everywhere-opensource-src-4.7.0/src/gui/image/qpixmap_x11.cpp.me qt-everywhere-opensource-src-4.7.0/src/gui/image/qpixmap_x11.cpp
--- qt-everywhere-opensource-src-4.7.0/src/gui/image/qpixmap_x11.cpp.me 2010-10-15 22:04:09.000000000 +0200
+++ qt-everywhere-opensource-src-4.7.0/src/gui/image/qpixmap_x11.cpp 2010-10-15 22:04:18.000000000 +0200
@@ -900,9 +900,9 @@ void QX11PixmapData::fromImage(const QIm
case BPP24_888: // 24 bit MSB
CYCLE(
for (int x=0; x<w; x++) {
- *dst++ = qRed (*p);
+ *dst++ = qBlue (*p);
*dst++ = qGreen(*p);
- *dst++ = qBlue (*p++);
+ *dst++ = qRed (*p++);
}
)
break;

View File

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

13
qt.spec
View File

@ -11,7 +11,7 @@ Summary: Qt toolkit
Name: qt
Epoch: 1
Version: 4.8.0
Release: 0.22.rc1%{?dist}
Release: 0.23.rc1%{?dist}
# See LGPL_EXCEPTIONS.txt, LICENSE.GPL3, respectively, for exception details
License: (LGPLv2 with exceptions or GPLv3 with exceptions) and ASL 2.0 and BSD and FTL and MIT
@ -60,9 +60,6 @@ Patch54: qt-everywhere-opensource-src-4.7.0-beta2-mysql_config.patch
# http://bugs.kde.org/show_bug.cgi?id=180051#c22
Patch55: qt-everywhere-opensource-src-4.6.2-cups.patch
# fix 24bit color issue
Patch63: qt-everywhere-opensource-src-4.7.0-bpp24.patch
# Fails to create debug build of Qt projects on mingw (rhbz#653674)
Patch64: qt-everywhere-opensource-src-4.7.1-QTBUG-14467.patch
@ -94,6 +91,9 @@ Patch72: qt-everywhere-opensource-src-4.8.0-QUrl_toLocalFile.patch
Patch73: qt-everywhere-opensource-src-4.8.0-qtwebkit-glib231.patch
# upstream patches
# Applications crash when using a visual with 24 bits per pixel
# https://bugreports.qt.nokia.com/browse/QTBUG-21754
Patch100: qt-everywhere-opensource-src-4.8.0-QTBUG-21754.patch
# security patches
@ -402,7 +402,6 @@ rm -fv mkspecs/linux-g++*/qmake.conf.multilib-optflags
## TODO: upstream me
%patch54 -p1 -b .mysql_config
%patch55 -p1 -b .cups-1
%patch63 -p1 -b .bpp24
%patch64 -p1 -b .QTBUG-14467
%patch65 -p1 -b .qtreeview-kpackagekit-crash
%patch67 -p1 -b .s390
@ -420,6 +419,7 @@ popd
%endif
# upstream patches
%patch100 -p1 -b .QTBUG-21754
# security fixes
@ -1050,6 +1050,9 @@ fi
%changelog
* Fri Oct 28 2011 Rex Dieter <rdieter@fedoraproject.org> 4.8.0-0.23.rc1
- crash when using a visual with 24 bits per pixel (#749647,QTBUG-21754)
* Fri Oct 28 2011 Kevin Kofler <Kevin@tigcc.ticalc.org> 4.8.0-0.22.rc1
- fix FTBFS in QtWebKit's wtf library with GLib 2.31