diff options
18 files changed, 419 insertions, 44 deletions
diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf index a18396876d..dbbccd0445 100644 --- a/doc/global/config.qdocconf +++ b/doc/global/config.qdocconf @@ -3,7 +3,7 @@ dita.metadata.default.author = Qt Project dita.metadata.default.permissions = all dita.metadata.default.publisher = Qt Project -dita.metadata.default.copyryear = 2017 +dita.metadata.default.copyryear = 2018 dita.metadata.default.copyrholder = The Qt Company Ltd dita.metadata.default.audience = programmer diff --git a/doc/global/html-footer-online.qdocconf b/doc/global/html-footer-online.qdocconf index d6cf5d2122..f2631555c1 100644 --- a/doc/global/html-footer-online.qdocconf +++ b/doc/global/html-footer-online.qdocconf @@ -78,7 +78,7 @@ HTML.footer += \ " <ul id=\"menu-footer-submenu\" class=\"right clearfix\"><li id=\"menu-item-1795\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1795\"><a title=\"Sign into your account.\" href=\"https://account.qt.io/login\">Sign In</a></li>\n" \ " <li id=\"menu-item-10375\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-10375\"><a href=\"mailto:feedback@theqtcompany.com?Subject=Feedback%20about%20doc.qt.io%20site\">Feedback</a></li>\n" \ " <li id=\"menu-item-1494\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1494\"><a href=\"http://qt.io/contact-us/\">Contact us</a></li>\n" \ - " <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2017 The Qt Company</a></li>\n" \ + " <li id=\"menu-item-4472\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-4472\"><a href=\"http://qt.io/about-us/\">© 2018 The Qt Company</a></li>\n" \ " </ul>\n" \ "</div>\n" \ "</div>\n" \ diff --git a/doc/global/html-footer.qdocconf b/doc/global/html-footer.qdocconf index 5a0fbd85e1..9957e71f20 100644 --- a/doc/global/html-footer.qdocconf +++ b/doc/global/html-footer.qdocconf @@ -8,7 +8,7 @@ HTML.footer = \ "</div>\n" \ "<div class=\"footer\">\n" \ " <p>\n" \ - " <acronym title=\"Copyright\">©</acronym> 2017 The Qt Company Ltd.\n" \ + " <acronym title=\"Copyright\">©</acronym> 2018 The Qt Company Ltd.\n" \ " Documentation contributions included herein are the copyrights of\n" \ " their respective owners.<br>" \ " The documentation provided herein is licensed under the terms of the" \ diff --git a/doc/global/qt-module-defaults-online.qdocconf b/doc/global/qt-module-defaults-online.qdocconf index 15c193d698..1bed0c7934 100644 --- a/doc/global/qt-module-defaults-online.qdocconf +++ b/doc/global/qt-module-defaults-online.qdocconf @@ -5,7 +5,7 @@ HTML.footer = \ " </div>\n" \ " <p class=\"copy-notice\">\n" \ - " <acronym title=\"Copyright\">©</acronym> 2017 The Qt Company Ltd.\n" \ + " <acronym title=\"Copyright\">©</acronym> 2018 The Qt Company Ltd.\n" \ " Documentation contributions included herein are the copyrights of\n" \ " their respective owners. " \ " The documentation provided herein is licensed under the terms of the" \ diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 12390928f0..caa8aaca4b 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -591,6 +591,12 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME applications. \endlist + The following parameter is available for \c {-platform cocoa} (on macOS): + + \list + \li \c {fontengine=freetype}, uses the FreeType font engine. + \endlist + For more information about the platform-specific arguments available for embedded Linux platforms, see \l{Qt for Embedded Linux}. @@ -1285,6 +1291,21 @@ void QGuiApplicationPrivate::createPlatformIntegration() #ifdef QT_QPA_DEFAULT_PLATFORM_NAME platformName = QT_QPA_DEFAULT_PLATFORM_NAME; #endif +#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) + QByteArray sessionType = qgetenv("XDG_SESSION_TYPE"); + if (!sessionType.isEmpty()) { + if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb"))) + platformName = QByteArrayLiteral("xcb"); + else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland"))) + platformName = QByteArrayLiteral("wayland"); + } +#ifdef QT_QPA_DEFAULT_PLATFORM_NAME + // Add it as fallback in case XDG_SESSION_TYPE is something wrong + if (!platformName.contains(QT_QPA_DEFAULT_PLATFORM_NAME)) + platformName += QByteArrayLiteral(";" QT_QPA_DEFAULT_PLATFORM_NAME); +#endif +#endif + QByteArray platformNameEnv = qgetenv("QT_QPA_PLATFORM"); if (!platformNameEnv.isEmpty()) { platformName = platformNameEnv; diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index a8a37492b7..44ff5b7b39 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -73,7 +73,7 @@ qtConfig(localserver) { SOURCES += socket/qlocalsocket.cpp \ socket/qlocalserver.cpp - intergrity|winrt { + integrity|winrt { SOURCES += socket/qlocalsocket_tcp.cpp \ socket/qlocalserver_tcp.cpp DEFINES += QT_LOCALSOCKET_TCP diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 02f92bbb18..f339938f86 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -254,6 +254,12 @@ void QIBusPlatformInputContext::setFocusObject(QObject *object) if (!d->busConnected) return; + // It would seem natural here to call FocusOut() on the input method if we + // transition from an IME accepted focus object to one that does not accept it. + // Mysteriously however that is not sufficient to fix bug QTBUG-63066. + if (!inputMethodAccepted()) + return; + if (debug) qDebug() << "setFocusObject" << object; if (object) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 3621e5102f..5eb45be04a 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -163,9 +163,11 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo const qreal devicePixelRatio = m_image.devicePixelRatio(); // If the flushed window is a content view, and not in unified toolbar mode, - // we can get away with copying the backingstore instead of blending. - const NSCompositingOperation compositingOperation = static_cast<QCocoaWindow *>( - window->handle())->isContentView() && !windowHasUnifiedToolbar() ? + // and is fully opaque, we can get away with copying the backingstore instead + // of blending. + QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()); + const NSCompositingOperation compositingOperation = cocoaWindow->isContentView() + && cocoaWindow->isOpaque() && !windowHasUnifiedToolbar() ? NSCompositingOperationCopy : NSCompositingOperationSourceOver; #ifdef QT_DEBUG diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index c947acd765..8e3263ad92 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -11124,7 +11124,7 @@ void QWidgetPrivate::macUpdateSizeAttribute() for (int i = 0; i < children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(children.at(i)); if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) - && !q->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent + && !w->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent && !w->testAttribute(Qt::WA_MacSmallSize) && !w->testAttribute(Qt::WA_MacNormalSize)) w->d_func()->macUpdateSizeAttribute(); diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index a6ae61545b..c624187190 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -1008,7 +1008,7 @@ void QLabel::paintEvent(QPaintEvent *) : layoutDirection(), QFlag(d->align)); #if QT_CONFIG(movie) - if (d->movie) { + if (d->movie && !d->movie->currentPixmap().isNull()) { if (d->scaledcontents) style->drawItemPixmap(&painter, cr, align, d->movie->currentPixmap().scaled(cr.size())); else diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp index 17763f31f9..810698fb4e 100644 --- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp @@ -4667,11 +4667,14 @@ void tst_QStateMachine::clonedSignals() s1->addTransition(t1); machine.setInitialState(s1); + QSignalSpy startedSpy(&machine, &QStateMachine::started); machine.start(); - QTest::qWait(1); + QVERIFY(startedSpy.wait()); + QSignalSpy transitionSpy(t1, &CloneSignalTransition::triggered); emitter.emitSignalWithDefaultArg(); - QTest::qWait(1); + QTRY_COMPARE(transitionSpy.count(), 1); + QCOMPARE(t1->eventSignalIndex, emitter.metaObject()->indexOfSignal("signalWithDefaultArg()")); TEST_ACTIVE_CHANGED(s1, 2); TEST_ACTIVE_CHANGED(s2, 1); diff --git a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp index a16e9e377c..b2ef516b4e 100644 --- a/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp +++ b/tests/auto/corelib/thread/qfuturewatcher/tst_qfuturewatcher.cpp @@ -82,11 +82,11 @@ void tst_QFutureWatcher::startFinish() QVERIFY(finishedSpy.isValid()); futureWatcher.setFuture(QtConcurrent::run(sleeper)); - QTest::qWait(10); // spin the event loop to deliver queued signals. + QVERIFY(startedSpy.wait()); QCOMPARE(startedSpy.count(), 1); QCOMPARE(finishedSpy.count(), 0); futureWatcher.future().waitForFinished(); - QTest::qWait(10); + QVERIFY(finishedSpy.wait()); QCOMPARE(startedSpy.count(), 1); QCOMPARE(finishedSpy.count(), 1); } @@ -232,13 +232,12 @@ void tst_QFutureWatcher::resultAt() void tst_QFutureWatcher::resultReadyAt() { QFutureWatcher<int> futureWatcher; - QObject::connect(&futureWatcher, SIGNAL(resultReadyAt(int)), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QSignalSpy resultSpy(&futureWatcher, &QFutureWatcher<int>::resultReadyAt); QFuture<int> future = (new IntTask())->start(); futureWatcher.setFuture(future); - QTestEventLoop::instance().enterLoop(1); - QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(resultSpy.wait()); // Setting the future again should give us another signal. // (this is to prevent the race where the task associated @@ -246,8 +245,7 @@ void tst_QFutureWatcher::resultReadyAt() futureWatcher.setFuture(QFuture<int>()); futureWatcher.setFuture(future); - QTestEventLoop::instance().enterLoop(1); - QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(resultSpy.wait()); } class SignalSlotObject : public QObject @@ -320,19 +318,17 @@ void tst_QFutureWatcher::futureSignals() const int progress = 1; a.setProgressValue(progress); - QTest::qWait(10); - QCOMPARE(progressSpy.count(), 2); + QTRY_COMPARE(progressSpy.count(), 2); QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 0); QCOMPARE(progressSpy.takeFirst().at(0).toInt(), 1); const int result = 10; a.reportResult(&result); - QTest::qWait(10); + QVERIFY(resultReadySpy.wait()); QCOMPARE(resultReadySpy.count(), 1); a.reportFinished(&result); - QTest::qWait(10); - QCOMPARE(resultReadySpy.count(), 2); + QTRY_COMPARE(resultReadySpy.count(), 2); QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 0); // check the index QCOMPARE(resultReadySpy.takeFirst().at(0).toInt(), 1); @@ -373,7 +369,7 @@ void tst_QFutureWatcher::watchFinishedFuture() QVERIFY(canceledSpy.isValid()); watcher.setFuture(f); - QTest::qWait(10); + QVERIFY(finishedSpy.wait()); QCOMPARE(startedSpy.count(), 1); QCOMPARE(finishedSpy.count(), 1); @@ -407,7 +403,7 @@ void tst_QFutureWatcher::watchCanceledFuture() QVERIFY(canceledSpy.isValid()); watcher.setFuture(f); - QTest::qWait(10); + QVERIFY(finishedSpy.wait()); QCOMPARE(startedSpy.count(), 1); QCOMPARE(finishedSpy.count(), 1); @@ -434,7 +430,7 @@ void tst_QFutureWatcher::disconnectRunningFuture() const int result = 10; a.reportResult(&result); - QTest::qWait(10); + QVERIFY(resultReadySpy.wait()); QCOMPARE(resultReadySpy.count(), 1); delete watcher; @@ -624,7 +620,7 @@ void tst_QFutureWatcher::changeFuture() QSignalSpy resultReadySpy(&watcher, &QFutureWatcher<int>::resultReadyAt); QVERIFY(resultReadySpy.isValid()); - watcher.setFuture(a); // Watch 'a' which will genere a resultReady event. + watcher.setFuture(a); // Watch 'a' which will generate a resultReady event. watcher.setFuture(b); // But oh no! we're switching to another future QTest::qWait(10); // before the event gets delivered. @@ -633,7 +629,7 @@ void tst_QFutureWatcher::changeFuture() watcher.setFuture(a); watcher.setFuture(b); watcher.setFuture(a); // setting it back gets us one event, not two. - QTest::qWait(10); + QVERIFY(resultReadySpy.wait()); QCOMPARE(resultReadySpy.count(), 1); } @@ -653,13 +649,15 @@ void tst_QFutureWatcher::cancelEvents() SignalSlotObject object; connect(&watcher, SIGNAL(resultReadyAt(int)), &object, SLOT(resultReadyAt(int))); + QSignalSpy finishedSpy(&watcher, &QFutureWatcher<int>::finished); QSignalSpy resultReadySpy(&watcher, &QFutureWatcher<int>::resultReadyAt); + QVERIFY(finishedSpy.isValid()); QVERIFY(resultReadySpy.isValid()); watcher.setFuture(a); watcher.cancel(); - QTest::qWait(10); + QVERIFY(finishedSpy.wait()); QCOMPARE(resultReadySpy.count(), 0); } @@ -730,15 +728,17 @@ void tst_QFutureWatcher::finishedState() iface.reportStarted(); QFuture<int> future = iface.future(); QFutureWatcher<int> watcher; + QSignalSpy startedSpy(&watcher, &QFutureWatcher<int>::started); + QSignalSpy finishedSpy(&watcher, &QFutureWatcher<int>::finished); watcher.setFuture(future); - QTest::qWait(10); + QVERIFY(startedSpy.wait()); iface.reportFinished(); QVERIFY(future.isFinished()); QVERIFY(!watcher.isFinished()); - QTest::qWait(10); + QVERIFY(finishedSpy.wait()); QVERIFY(watcher.isFinished()); } @@ -752,18 +752,20 @@ void tst_QFutureWatcher::throttling() iface.reportStarted(); QFuture<int> future = iface.future(); QFutureWatcher<int> watcher; + QSignalSpy resultSpy(&watcher, &QFutureWatcher<int>::resultReadyAt); watcher.setFuture(future); QVERIFY(!iface.isThrottled()); - for (int i = 0; i < 1000; ++i) { + const int resultCount = 1000; + for (int i = 0; i < resultCount; ++i) { int result = 0; iface.reportResult(result); } QVERIFY(iface.isThrottled()); - QTest::qWait(100); // process events. + QTRY_COMPARE(resultSpy.count(), resultCount); // Process the results QVERIFY(!iface.isThrottled()); diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp index 0405896ca7..aee243d880 100644 --- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp +++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp @@ -988,9 +988,7 @@ void tst_QThread::exitAndStart() connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection); connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection); QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89)); - QTest::qWait(50); - while(!thread.wait(10)) - QTest::qWait(10); + QTRY_VERIFY(thread.wait(10)); QCOMPARE(sync2.m_prop, 89); QCOMPARE(sync1.m_prop, 89); } @@ -1026,9 +1024,7 @@ void tst_QThread::exitAndExec() connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection); connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection); QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89)); - QTest::qWait(50); - while(!thread.wait(10)) - QTest::qWait(10); + QTRY_VERIFY(thread.wait(10)); QCOMPARE(sync2.m_prop, 89); QCOMPARE(sync1.m_prop, 89); } diff --git a/tests/auto/network/kernel/qdnslookup/BLACKLIST b/tests/auto/network/kernel/qdnslookup/BLACKLIST index f07a8ce9a3..edf6436384 100644 --- a/tests/auto/network/kernel/qdnslookup/BLACKLIST +++ b/tests/auto/network/kernel/qdnslookup/BLACKLIST @@ -1,2 +1,2 @@ [lookup] -* +ci diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp index 4e0cb3b835..074644393d 100644 --- a/tests/auto/other/lancelot/paintcommands.cpp +++ b/tests/auto/other/lancelot/paintcommands.cpp @@ -192,7 +192,7 @@ QList<QPair<QString,QStringList> > PaintCommands::s_enumsTable = QList<QPair<QSt QMultiHash<QString, int> PaintCommands::s_commandHash; #define DECL_PAINTCOMMAND(identifier, method, regexp, syntax, sample) \ - s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegularExpression(regexp, QRegularExpression::OptimizeOnFirstUsageOption), \ + s_commandInfoTable << PaintCommandInfos(QLatin1String(identifier), &PaintCommands::method, QRegularExpression(regexp), \ QLatin1String(syntax), QLatin1String(sample) ); #define DECL_PAINTCOMMANDSECTION(title) \ @@ -615,6 +615,8 @@ void PaintCommands::staticInit() // populate the command lookup hash for (int i=0; i<s_commandInfoTable.size(); i++) { + // and pre-optimize the regexps. + s_commandInfoTable.at(i).regExp.optimize(); if (s_commandInfoTable.at(i).isSectionHeader() || s_commandInfoTable.at(i).identifier == QLatin1String("comment") || s_commandInfoTable.at(i).identifier == QLatin1String("noop")) @@ -682,6 +684,7 @@ void PaintCommands::insertAt(int commandIndex, const QStringList &newCommands) **********************************************************************************/ void PaintCommands::runCommand(const QString &scriptLine) { + static QRegularExpression separators("\\s"); if (scriptLine.isEmpty()) { command_noop(QRegularExpressionMatch()); return; @@ -690,7 +693,7 @@ void PaintCommands::runCommand(const QString &scriptLine) command_comment(QRegularExpressionMatch()); return; } - QString firstWord = scriptLine.section(QRegularExpression("\\s"), 0, 0); + QString firstWord = scriptLine.section(separators, 0, 0); QList<int> indices = s_commandHash.values(firstWord); foreach(int idx, indices) { PaintCommandInfos command = s_commandInfoTable.at(idx); diff --git a/tests/benchmarks/gui/painting/lancebench/lancebench.pro b/tests/benchmarks/gui/painting/lancebench/lancebench.pro new file mode 100644 index 0000000000..6458c50861 --- /dev/null +++ b/tests/benchmarks/gui/painting/lancebench/lancebench.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = tst_bench_lancebench + +QT += testlib gui-private + + +SOURCES += tst_lancebench.cpp + +SOURCES += ../../../../auto/other/lancelot/paintcommands.cpp +HEADERS += ../../../../auto/other/lancelot/paintcommands.h +RESOURCES += ../../../../auto/other/lancelot/images.qrc + +TESTDATA += ../../../../auto/other/lancelot/scripts/* diff --git a/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp new file mode 100644 index 0000000000..bd0889bf4a --- /dev/null +++ b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp @@ -0,0 +1,328 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../../../../auto/other/lancelot/paintcommands.h" + +#include <qtest.h> +#include <QDir> +#include <QPainter> + +#ifndef QT_NO_OPENGL +#include <QOpenGLFramebufferObjectFormat> +#include <QOpenGLContext> +#include <QOpenGLPaintDevice> +#endif + +#include <algorithm> + +class tst_LanceBench : public QObject +{ + Q_OBJECT +public: + tst_LanceBench(); + +private: + enum GraphicsEngine { + Raster = 0, + OpenGL = 1 + }; + + void setupTestSuite(const QStringList& blacklist = QStringList()); + void runTestSuite(GraphicsEngine engine, QImage::Format format, const QSurfaceFormat &contextFormat = QSurfaceFormat()); + void paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath); + + QStringList qpsFiles; + QHash<QString, QStringList> scripts; + QString scriptsDir; + +private slots: + void initTestCase(); + void cleanupTestCase() {} + + void testRasterARGB32PM_data(); + void testRasterARGB32PM(); + void testRasterRGB32_data(); + void testRasterRGB32(); + void testRasterARGB32_data(); + void testRasterARGB32(); + void testRasterRGB16_data(); + void testRasterRGB16(); + void testRasterBGR30_data(); + void testRasterBGR30(); + void testRasterARGB8565PM_data(); + void testRasterARGB8565PM(); + void testRasterGrayscale8_data(); + void testRasterGrayscale8(); + +#ifndef QT_NO_OPENGL + void testOpenGL_data(); + void testOpenGL(); + void testCoreOpenGL_data(); + void testCoreOpenGL(); +private: + bool checkSystemGLSupport(); + bool checkSystemCoreGLSupport(); +#endif +}; + +tst_LanceBench::tst_LanceBench() +{ +} + +void tst_LanceBench::initTestCase() +{ + QString baseDir = QFINDTESTDATA("../../../../auto/other/lancelot/scripts/text.qps"); + scriptsDir = baseDir.left(baseDir.lastIndexOf('/')) + '/'; + QDir qpsDir(scriptsDir); + qpsFiles = qpsDir.entryList(QStringList() << QLatin1String("*.qps"), QDir::Files | QDir::Readable); + if (qpsFiles.isEmpty()) { + QWARN("No qps script files found in " + qpsDir.path().toLatin1()); + QSKIP("Aborted due to errors."); + } + + std::sort(qpsFiles.begin(), qpsFiles.end()); + for (const QString& fileName : qAsConst(qpsFiles)) { + QFile file(scriptsDir + fileName); + file.open(QFile::ReadOnly); + QByteArray cont = file.readAll(); + scripts.insert(fileName, QString::fromUtf8(cont).split(QLatin1Char('\n'), QString::SkipEmptyParts)); + } +} + +void tst_LanceBench::testRasterARGB32PM_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterARGB32PM() +{ + runTestSuite(Raster, QImage::Format_ARGB32_Premultiplied); +} + +void tst_LanceBench::testRasterRGB32_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterRGB32() +{ + runTestSuite(Raster, QImage::Format_RGB32); +} + +void tst_LanceBench::testRasterARGB32_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterARGB32() +{ + runTestSuite(Raster, QImage::Format_ARGB32); +} + +void tst_LanceBench::testRasterRGB16_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterRGB16() +{ + runTestSuite(Raster, QImage::Format_RGB16); +} + +void tst_LanceBench::testRasterBGR30_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterBGR30() +{ + runTestSuite(Raster, QImage::Format_BGR30); +} + +void tst_LanceBench::testRasterARGB8565PM_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterARGB8565PM() +{ + runTestSuite(Raster, QImage::Format_ARGB8565_Premultiplied); +} + +void tst_LanceBench::testRasterGrayscale8_data() +{ + setupTestSuite(); +} + +void tst_LanceBench::testRasterGrayscale8() +{ + runTestSuite(Raster, QImage::Format_Grayscale8); +} + +#ifndef QT_NO_OPENGL +bool tst_LanceBench::checkSystemGLSupport() +{ + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.create(); + QOpenGLFramebufferObjectFormat fmt; + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + QOpenGLContext ctx; + if (!ctx.create() || !ctx.makeCurrent(&win)) + return false; + QOpenGLFramebufferObject fbo(800, 800, fmt); + if (!fbo.isValid() || !fbo.bind()) + return false; + + return true; +} + +bool tst_LanceBench::checkSystemCoreGLSupport() +{ + if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) + return false; + + QSurfaceFormat coreFormat; + coreFormat.setVersion(3, 2); + coreFormat.setProfile(QSurfaceFormat::CoreProfile); + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.setFormat(coreFormat); + win.create(); + QOpenGLFramebufferObjectFormat fmt; + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + QOpenGLContext ctx; + ctx.setFormat(coreFormat); + if (!ctx.create() || !ctx.makeCurrent(&win)) + return false; + QOpenGLFramebufferObject fbo(800, 800, fmt); + if (!fbo.isValid() || !fbo.bind()) + return false; + + return true; +} + +void tst_LanceBench::testOpenGL_data() +{ + if (!checkSystemGLSupport()) + QSKIP("System under test does not meet preconditions for GL testing. Skipping."); + QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps"); + setupTestSuite(localBlacklist); +} + +void tst_LanceBench::testOpenGL() +{ + runTestSuite(OpenGL, QImage::Format_RGB32); +} + +void tst_LanceBench::testCoreOpenGL_data() +{ + if (!checkSystemCoreGLSupport()) + QSKIP("System under test does not meet preconditions for Core Profile GL testing. Skipping."); + QStringList localBlacklist = QStringList() << QLatin1String("rasterops.qps"); + setupTestSuite(localBlacklist); +} + +void tst_LanceBench::testCoreOpenGL() +{ + QSurfaceFormat coreFormat; + coreFormat.setVersion(3, 2); + coreFormat.setProfile(QSurfaceFormat::CoreProfile); + runTestSuite(OpenGL, QImage::Format_RGB32, coreFormat); +} +#endif + +void tst_LanceBench::setupTestSuite(const QStringList& blacklist) +{ + QTest::addColumn<QString>("qpsFile"); + for (const QString &fileName : qAsConst(qpsFiles)) { + if (blacklist.contains(fileName)) + continue; + QTest::newRow(fileName.toLatin1()) << fileName; + } +} + +void tst_LanceBench::runTestSuite(GraphicsEngine engine, QImage::Format format, const QSurfaceFormat &contextFormat) +{ + QFETCH(QString, qpsFile); + + QString filePath = scriptsDir + qpsFile; + QStringList script = scripts.value(qpsFile); + QImage rendered; + + if (engine == Raster) { + QImage img(800, 800, format); + paint(&img, engine, format, script, QFileInfo(filePath).absoluteFilePath()); + rendered = img; +#ifndef QT_NO_OPENGL + } else if (engine == OpenGL) { + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.setFormat(contextFormat); + win.create(); + QOpenGLFramebufferObjectFormat fmt; + fmt.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + fmt.setSamples(4); + QOpenGLContext ctx; + ctx.setFormat(contextFormat); + QVERIFY(ctx.create()); + QVERIFY(ctx.makeCurrent(&win)); + QOpenGLFramebufferObject fbo(800, 800, fmt); + fbo.bind(); + QOpenGLPaintDevice pdv(800, 800); + paint(&pdv, engine, format, script, QFileInfo(filePath).absoluteFilePath()); + rendered = fbo.toImage().convertToFormat(format); +#endif + } +} + +void tst_LanceBench::paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath) +{ + PaintCommands pcmd(script, 800, 800, format); + switch (engine) { + case OpenGL: + pcmd.setType(OpenGLBufferType); // version/profile is communicated through the context's format() + break; + case Raster: + pcmd.setType(ImageType); + break; + } + pcmd.setFilePath(filePath); + QBENCHMARK { + QPainter p(device); + pcmd.setPainter(&p); + pcmd.runCommands(); + p.end(); + } +} + +QTEST_MAIN(tst_LanceBench) + +#include "tst_lancebench.moc" diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro index 534d882578..400c2994a6 100644 --- a/tests/benchmarks/gui/painting/painting.pro +++ b/tests/benchmarks/gui/painting/painting.pro @@ -5,7 +5,8 @@ SUBDIRS = \ qpainter \ qregion \ qtransform \ - qtbench + qtbench \ + lancebench !qtHaveModule(widgets): SUBDIRS -= \ qpainter \ |