From 332816779c42e8a3fed34e9295c09338bc9b4945 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 22 Nov 2019 13:02:31 +0100 Subject: Multithread some QImage routines Use QThreadPool to process QImage smooth-scaling, format conversions, and colorspace transforms multithreaded. Change-Id: Ic142b1fa899f56e7e5099d36ca713701a47b681b Reviewed-by: Lars Knoll --- src/gui/image/qimage.cpp | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) (limited to 'src/gui/image/qimage.cpp') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index ec72180f0d..2646d298e9 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -69,6 +69,11 @@ #include #include +#if QT_CONFIG(thread) +#include "qsemaphore.h" +#include "qthreadpool.h" +#endif + QT_BEGIN_NAMESPACE static inline bool isLocked(QImageData *data) @@ -5024,18 +5029,43 @@ void QImage::applyColorTransform(const QColorTransform &transform) Q_UNREACHABLE(); } + std::function transformSegment; + if (depth() > 32) { - for (int i = 0; i < height(); ++i) { - QRgba64 *scanline = reinterpret_cast(scanLine(i)); - transform.d->apply(scanline, scanline, width(), flags); - } + transformSegment = [&](int yStart, int yEnd) { + for (int y = yStart; y < yEnd; ++y) { + QRgba64 *scanline = reinterpret_cast(scanLine(y)); + transform.d->apply(scanline, scanline, width(), flags); + } + }; } else { - for (int i = 0; i < height(); ++i) { - QRgb *scanline = reinterpret_cast(scanLine(i)); - transform.d->apply(scanline, scanline, width(), flags); - } + transformSegment = [&](int yStart, int yEnd) { + for (int y = yStart; y < yEnd; ++y) { + QRgb *scanline = reinterpret_cast(scanLine(y)); + transform.d->apply(scanline, scanline, width(), flags); + } + }; } +#if QT_CONFIG(thread) + int segments = sizeInBytes() / (1<<16); + segments = std::min(segments, height()); + if (segments > 1) { + QSemaphore semaphore; + int y = 0; + for (int i = 0; i < segments; ++i) { + int yn = (height() - y) / (segments - i); + QThreadPool::globalInstance()->start([&, y, yn]() { + transformSegment(y, y + yn); + semaphore.release(1); + }); + y += yn; + } + semaphore.acquire(segments); + } else +#endif + transformSegment(0, height()); + if (oldFormat != format()) *this = std::move(*this).convertToFormat(oldFormat); } -- cgit v1.2.3