From ced3473020151f27582bf723459e0ae3c0e23e6a Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Fri, 18 Nov 2022 21:28:52 +0200 Subject: [PATCH] zero-copy QX11Data::copyXImageToQImage() for some cases Signed-off-by: Ivailo Monev --- src/gui/image/qimage.h | 1 + src/gui/image/qpixmap.cpp | 5 +++-- src/gui/kernel/qt_x11.cpp | 24 ++++++++++++++---------- src/gui/kernel/qt_x11_p.h | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 908470ceb..2426e97ae 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -197,6 +197,7 @@ private: friend class QSpanData; friend class QPngHandler; friend class QKatHandler; + friend class QX11Data; #if !defined(QT_NO_DATASTREAM) friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QImage &); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QImage &); diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 1e8e16cac..eee8ac4b4 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1455,8 +1455,9 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap) if (image.depth() == 1) { image.setColorTable(monoColorTable()); } - QX11Data::copyXImageToQImage(ximage, image); - XDestroyImage(ximage); + bool freedata = false; + QX11Data::copyXImageToQImage(ximage, image, &freedata); + QX11Data::destroyXImage(ximage, freedata); return QPixmap::fromImage(image); } diff --git a/src/gui/kernel/qt_x11.cpp b/src/gui/kernel/qt_x11.cpp index 1f76e7cd0..9bf66e306 100644 --- a/src/gui/kernel/qt_x11.cpp +++ b/src/gui/kernel/qt_x11.cpp @@ -21,6 +21,7 @@ #include "qcolor.h" #include "qimage.h" +#include "qimage_p.h" #include "qdrawhelper_p.h" #include "qt_x11_p.h" #include "qx11info_x11.h" @@ -115,15 +116,7 @@ void QX11Data::copyQImageToXImage(const QImage &image, XImage *ximage, bool *fre } } -void QX11Data::destroyXImage(XImage *ximage, const bool freedata) -{ - if (!freedata) { - ximage->data = nullptr; - } - XDestroyImage(ximage); -} - -void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image) +void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image, bool *freedata) { Q_ASSERT(ximage); Q_ASSERT(ximage->width == image.width()); @@ -134,6 +127,7 @@ void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image) if (samedepth && samebyteorder) { switch (image.format()) { case QImage::Format_RGB32: { + *freedata = true; uchar *imagedata = image.bits(); const int imagebpl = image.bytesPerLine(); for (int h = 0; h < ximage->height; h++) { @@ -150,7 +144,8 @@ void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image) case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: case QImage::Format_RGB16: { - ::memcpy(image.bits(), ximage->data, image.byteCount()); + *freedata = false; + image.d->data = (uchar*)ximage->data; return; } default: { @@ -159,6 +154,7 @@ void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image) } } + *freedata = true; if (image.depth() == 1) { for (int h = 0; h < ximage->height; h++) { for (int w = 0; w < ximage->width; w++) { @@ -176,6 +172,14 @@ void QX11Data::copyXImageToQImage(XImage *ximage, QImage &image) } } +void QX11Data::destroyXImage(XImage *ximage, const bool freedata) +{ + if (!freedata) { + ximage->data = nullptr; + } + XDestroyImage(ximage); +} + uint QX11Data::XColorPixel(const int screen, const QColor &color) { Display* x11display = QX11Info::display(); diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 7af451e88..79b332ea5 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -235,8 +235,8 @@ struct QX11Data Colormap colormap; static void copyQImageToXImage(const QImage &image, XImage *ximage, bool *freedata); + static void copyXImageToQImage(XImage *ximage, QImage &image, bool *freedata); static void destroyXImage(XImage *ximage, const bool freedata); - static void copyXImageToQImage(XImage *ximage, QImage &image); static uint XColorPixel(const int screen, const QColor &color); -- 2.11.0