summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp6
-rw-r--r--src/corelib/thread/qthreadpool.cpp22
-rw-r--r--src/corelib/thread/qthreadpool_p.h2
-rw-r--r--src/gui/configure.cmake12
-rw-r--r--src/gui/image/qimage.cpp12
-rw-r--r--src/gui/image/qimage_conversions.cpp29
-rw-r--r--src/gui/kernel/qguiapplication.cpp44
-rw-r--r--src/gui/kernel/qguiapplication_p.h3
-rw-r--r--src/gui/painting/qdrawhelper.cpp10
-rw-r--r--src/gui/painting/qimagescale.cpp7
-rw-r--r--src/gui/painting/qimagescale_lsx.cpp7
-rw-r--r--src/gui/painting/qimagescale_neon.cpp8
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp7
13 files changed, 97 insertions, 72 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 0f1de6b97cd..2bff9468824 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -930,10 +930,8 @@ QCoreApplication::~QCoreApplication()
#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
QThreadPool *globalThreadPool = nullptr;
- QThreadPool *guiThreadPool = nullptr;
QT_TRY {
globalThreadPool = QThreadPool::globalInstance();
- guiThreadPool = QThreadPoolPrivate::qtGuiInstance();
} QT_CATCH (...) {
// swallow the exception, since destructors shouldn't throw
}
@@ -941,10 +939,6 @@ QCoreApplication::~QCoreApplication()
globalThreadPool->waitForDone();
delete globalThreadPool;
}
- if (guiThreadPool) {
- guiThreadPool->waitForDone();
- delete guiThreadPool;
- }
#endif
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index 62e3773af95..f326ed21229 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -475,28 +475,6 @@ QThreadPool *QThreadPool::globalInstance()
}
/*!
- Returns the QThreadPool instance for Qt Gui.
- \internal
-*/
-QThreadPool *QThreadPoolPrivate::qtGuiInstance()
-{
- Q_CONSTINIT static QPointer<QThreadPool> guiInstance;
- Q_CONSTINIT static QBasicMutex theMutex;
- const static bool runtime_disable = qEnvironmentVariableIsSet("QT_NO_GUI_THREADPOOL");
- if (runtime_disable)
- return nullptr;
- const QMutexLocker locker(&theMutex);
- if (guiInstance.isNull() && !QCoreApplication::closingDown()) {
- guiInstance = new QThreadPool();
- // Limit max thread to avoid too many parallel threads.
- // We are not optimized for much more than 4 or 8 threads.
- if (guiInstance && guiInstance->maxThreadCount() > 4)
- guiInstance->setMaxThreadCount(qBound(4, guiInstance->maxThreadCount() / 2, 8));
- }
- return guiInstance;
-}
-
-/*!
Reserves a thread and uses it to run \a runnable, unless this thread will
make the current thread count exceed maxThreadCount(). In that case,
\a runnable is added to a run queue instead. The \a priority argument can
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index 284cf21e4fd..eac078cad88 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -133,8 +133,6 @@ public:
void stealAndRunRunnable(QRunnable *runnable);
void deletePageIfFinished(QueuePage *page);
- static QThreadPool *qtGuiInstance();
-
mutable QMutex mutex;
QSet<QThreadPoolThread *> allThreads;
QQueue<QThreadPoolThread *> waitingThreads;
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index 7889445976b..b7eb37e8a8c 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -1271,6 +1271,14 @@ qt_feature("raster-fp" PRIVATE
PURPOSE "Internal painting support for floating point rasterization."
CONDITION NOT VXWORKS # QTBUG-115777
)
+
+qt_feature("qtgui-threadpool" PRIVATE
+ SECTION "Painting"
+ LABEL "Multi-threaded image and painting helpers"
+ PURPOSE "Multi-threaded image transforms and QPainter fills."
+ CONDITION QT_FEATURE_thread AND NOT WASM
+)
+
qt_feature("undocommand" PUBLIC
SECTION "Utilities"
LABEL "QUndoCommand"
@@ -1344,6 +1352,10 @@ qt_configure_add_summary_entry(ARGS "vulkan")
qt_configure_add_summary_entry(ARGS "metal")
qt_configure_add_summary_entry(ARGS "graphicsframecapture")
qt_configure_add_summary_entry(ARGS "sessionmanager")
+qt_configure_add_summary_entry(
+ ARGS "qtgui-threadpool"
+ CONDITION QT_FEATURE_thread
+)
qt_configure_end_summary_section() # end of "Qt Gui" section
qt_configure_add_summary_section(NAME "Features used by QPA backends")
qt_configure_add_summary_entry(ARGS "evdev")
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index b18952fc12f..06ae65e3f63 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -35,7 +35,7 @@
#include <private/qimage_p.h>
#include <private/qfont_p.h>
-#if QT_CONFIG(thread)
+#if QT_CONFIG(qtgui_threadpool)
#include <qsemaphore.h>
#include <qthreadpool.h>
#include <private/qthreadpool_p.h>
@@ -4908,7 +4908,7 @@ QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Q
}
// Otherwise only use it when the scaling factor demands it, or the image is large enough to scale multi-threaded
if (nonpaintable_scale_xform
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
|| (ws * hs) >= (1<<20)
#endif
) {
@@ -5328,10 +5328,10 @@ void QImage::applyColorTransform(const QColorTransform &transform)
};
}
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(width()) * height()) >> 16;
segments = std::min(segments, height());
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -5818,10 +5818,10 @@ QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format
}
}
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(width()) * height()) >> 16;
segments = std::min(segments, height());
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 5f300afd5f5..c1a700fddfb 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -17,11 +17,6 @@
#include <qsemaphore.h>
#include <qthreadpool.h>
#include <private/qthreadpool_p.h>
-#ifdef Q_OS_WASM
-// WebAssembly has threads; however we can't block the main thread.
-#else
-#define QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
-#endif
#endif
#include <QtCore/q20utility.h>
@@ -212,11 +207,11 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
}
};
-#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -267,11 +262,11 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
destData += dest->bytes_per_line;
}
};
-#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -321,11 +316,11 @@ void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::I
destData += dest->bytes_per_line;
}
};
-#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -434,10 +429,10 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
destData += params.bytesPerLine;
}
};
-#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -527,10 +522,10 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
destData += params.bytesPerLine;
}
};
-#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -621,10 +616,10 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
destData += params.bytesPerLine;
}
};
-#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 2a5a4933907..1e44ac83361 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -99,6 +99,10 @@
#include <private/qvulkandefaultinstance_p.h>
#endif
+#if QT_CONFIG(thread)
+#include <QtCore/QThreadPool>
+#endif
+
#include <qtgui_tracepoints_p.h>
#include <private/qtools_p.h>
@@ -686,6 +690,20 @@ QGuiApplication::~QGuiApplication()
d->cursor_list.clear();
#endif
+#if QT_CONFIG(qtgui_threadpool)
+ // Synchronize and stop the gui thread pool threads.
+ QThreadPool *guiThreadPool = nullptr;
+ QT_TRY {
+ guiThreadPool = QGuiApplicationPrivate::qtGuiThreadPool();
+ } QT_CATCH (...) {
+ // swallow the exception, since destructors shouldn't throw
+ }
+ if (guiThreadPool) {
+ guiThreadPool->waitForDone();
+ delete guiThreadPool;
+ }
+#endif
+
delete QGuiApplicationPrivate::app_icon;
QGuiApplicationPrivate::app_icon = nullptr;
delete QGuiApplicationPrivate::platform_name;
@@ -4553,6 +4571,32 @@ QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
}
/*!
+ Returns the QThreadPool instance for Qt Gui.
+ \internal
+*/
+QThreadPool *QGuiApplicationPrivate::qtGuiThreadPool()
+{
+#if QT_CONFIG(qtgui_threadpool)
+ Q_CONSTINIT static QPointer<QThreadPool> guiInstance;
+ Q_CONSTINIT static QBasicMutex theMutex;
+ const static bool runtime_disable = qEnvironmentVariableIsSet("QT_NO_GUI_THREADPOOL");
+ if (runtime_disable)
+ return nullptr;
+ const QMutexLocker locker(&theMutex);
+ if (guiInstance.isNull() && !QCoreApplication::closingDown()) {
+ guiInstance = new QThreadPool();
+ // Limit max thread to avoid too many parallel threads.
+ // We are not optimized for much more than 4 or 8 threads.
+ if (guiInstance && guiInstance->maxThreadCount() > 4)
+ guiInstance->setMaxThreadCount(qBound(4, guiInstance->maxThreadCount() / 2, 8));
+ }
+ return guiInstance;
+#else
+ return nullptr;
+#endif
+}
+
+/*!
\fn template <typename QNativeInterface> QNativeInterface *QGuiApplication::nativeInterface() const
Returns a native interface of the given type for the application.
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 45eac1c2654..2bdbc2463be 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -57,6 +57,7 @@ class QActionPrivate;
#if QT_CONFIG(shortcut)
class QShortcutPrivate;
#endif
+class QThreadPool;
class Q_GUI_EXPORT QGuiApplicationPrivate : public QCoreApplicationPrivate
{
@@ -337,6 +338,8 @@ public:
static QEvent::Type contextMenuEventType();
+ static QThreadPool *qtGuiThreadPool();
+
protected:
virtual void handleThemeChanged();
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 8beb299fab4..92d3ad8d821 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -27,11 +27,7 @@
#include <qloggingcategory.h>
#include <qmath.h>
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#define QT_USE_THREAD_PARALLEL_FILLS
-#endif
-
-#if defined(QT_USE_THREAD_PARALLEL_FILLS)
+#if QT_CONFIG(qtgui_threadpool)
#include <qsemaphore.h>
#include <qthreadpool.h>
#include <private/qthreadpool_p.h>
@@ -3963,10 +3959,10 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b
// -------------------- blend methods ---------------------
-#if defined(QT_USE_THREAD_PARALLEL_FILLS)
+#if QT_CONFIG(qtgui_threadpool)
#define QT_THREAD_PARALLEL_FILLS(function) \
const int segments = (count + 32) / 64; \
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance(); \
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool(); \
if (segments > 1 && qPixelLayouts[data->rasterBuffer->format].bpp >= QPixelLayout::BPP8 \
&& threadPool && !threadPool->contains(QThread::currentThread())) { \
QSemaphore semaphore; \
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 1b1f2e8b8c8..1bbfcf07a0a 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -10,9 +10,10 @@
#include "qrgba64_p.h"
#include "qrgbafloat.h"
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qguiapplication_p.h>
#include <private/qthreadpool_p.h>
#endif
@@ -284,10 +285,10 @@ void qt_qimageScaleAARGBA_down_xy_neon(QImageScaleInfo *isi, unsigned int *dest,
template<typename T>
static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, const T &scaleSection)
{
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_lsx.cpp b/src/gui/painting/qimagescale_lsx.cpp
index c128b014b8c..6ec856c6f3b 100644
--- a/src/gui/painting/qimagescale_lsx.cpp
+++ b/src/gui/painting/qimagescale_lsx.cpp
@@ -6,8 +6,9 @@
#include <private/qdrawhelper_loongarch64_p.h>
#include <private/qsimd_p.h>
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
#include <qsemaphore.h>
+#include <private/qguiapplication_p.h>
#include <private/qthreadpool_p.h>
#endif
@@ -20,10 +21,10 @@ using namespace QImageScale;
template<typename T>
static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, const T &scaleSection)
{
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_neon.cpp b/src/gui/painting/qimagescale_neon.cpp
index 074b8198626..1fc1070dc0d 100644
--- a/src/gui/painting/qimagescale_neon.cpp
+++ b/src/gui/painting/qimagescale_neon.cpp
@@ -3,11 +3,13 @@
#include "qimagescale_p.h"
#include "qimage.h"
+#include <private/qtguiglobal_p.h>
#include <private/qsimd_p.h>
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qguiapplication_p.h>
#include <private/qthreadpool_p.h>
#endif
@@ -20,10 +22,10 @@ using namespace QImageScale;
template<typename T>
static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, const T &scaleSection)
{
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
index 982e533a32a..5d4c3a4e7c2 100644
--- a/src/gui/painting/qimagescale_sse4.cpp
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -6,9 +6,10 @@
#include <private/qdrawhelper_x86_p.h>
#include <private/qsimd_p.h>
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qguiapplication_p.h>
#include <private/qthreadpool_p.h>
#endif
@@ -21,10 +22,10 @@ using namespace QImageScale;
template<typename T>
static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, const T &scaleSection)
{
-#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#if QT_CONFIG(qtgui_threadpool)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;