From efff8ff57a70f6de9a70e2bfda625bef86a9d6b6 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 15 Dec 2019 13:17:39 +0100 Subject: [PATCH 01/20] QFileSystemWatcher/win: watch also for attribute changes of directories The windows filesystemwatcher did not watch for attribute changes for directories (e.g. hidden flag) so it was not in sync with other backends. Fix it by adding FILE_NOTIFY_CHANGE_ATTRIBUTES to the watch flags when watching a directory. [ChangeLog][QtCore][QFileSystemWatcher] Fixed a bug that caused QFSW not to watch for attribute changes on Windows. Now it will correctly report when files and directories become hidden or unhidden, for example. Fixes: QTBUG-80545 Change-Id: I31767a0da899963e3940b4f5b36d1d581e6aa57c Reviewed-by: Thiago Macieira Reviewed-by: Friedemann Kleint --- src/corelib/io/qfilesystemwatcher_win.cpp | 1 + .../tst_qfilesystemwatcher.cpp | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 5f91ce5e3d7..3b67dd61c7e 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -403,6 +403,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath(); const uint flags = isDir ? (FILE_NOTIFY_CHANGE_DIR_NAME + | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_FILE_NAME) : (FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index cdd1f6361e5..7d88601e543 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -34,6 +34,9 @@ #include #include #include +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#include +#endif /* All tests need to run in temporary directories not used * by the application to avoid non-deterministic failures on Windows @@ -79,6 +82,9 @@ private slots: void signalsEmittedAfterFileMoved(); void watchUnicodeCharacters(); +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + void watchDirectoryAttributeChanges(); +#endif private: QString m_tempDirPattern; @@ -813,5 +819,27 @@ void tst_QFileSystemWatcher::watchUnicodeCharacters() QTRY_COMPARE(changedSpy.count(), 1); } +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +void tst_QFileSystemWatcher::watchDirectoryAttributeChanges() +{ + QTemporaryDir temporaryDirectory(m_tempDirPattern); + QVERIFY2(temporaryDirectory.isValid(), qPrintable(temporaryDirectory.errorString())); + + QDir testDir(temporaryDirectory.path()); + const QString subDir(QString::fromLatin1("attrib_test")); + QVERIFY(testDir.mkdir(subDir)); + testDir = QDir(temporaryDirectory.path() + QDir::separator() + subDir); + + QFileSystemWatcher watcher; + QVERIFY(watcher.addPath(temporaryDirectory.path())); + FileSystemWatcherSpy changedSpy(&watcher, FileSystemWatcherSpy::SpyOnDirectoryChanged); + QCOMPARE(changedSpy.count(), 0); + QVERIFY(SetFileAttributes(reinterpret_cast(testDir.absolutePath().utf16()), FILE_ATTRIBUTE_HIDDEN) != 0); + QTRY_COMPARE(changedSpy.count(), 1); + QVERIFY(SetFileAttributes(reinterpret_cast(testDir.absolutePath().utf16()), FILE_ATTRIBUTE_NORMAL) != 0); + QTRY_COMPARE(changedSpy.count(), 2); +} +#endif + QTEST_MAIN(tst_QFileSystemWatcher) #include "tst_qfilesystemwatcher.moc" From c4a9429be7e0e927289abbe7a34c061df0c07628 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Dec 2019 10:36:15 +0100 Subject: [PATCH 02/20] Fix developer build with clang-cl failing due exception spec Clang does seem to understand __declspec(nothrow) as used by the COM macros like STDMETHOD. Suppress the warning, fixing errors like: qwindowsfontenginedirectwrite.cpp(105,24): error: 'AddBeziers' is missing exception specification '__attribute__((nothrow))' [-Werror,-Wmicrosoft-exception-spec] Task-number: QTBUG-63512 Change-Id: If582cb0c12c62a7d12c4ae702747aac1f735db3c Reviewed-by: Oliver Wolff --- .../fontdatabases/windows/qwindowsfontenginedirectwrite.cpp | 3 +++ src/plugins/platforms/windows/qwindowscombase.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index e796c18e793..bc34a77e088 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -62,6 +62,9 @@ QT_BEGIN_NAMESPACE +// Clang does not consider __declspec(nothrow) as nothrow +QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec") + // Convert from design units to logical pixels #define DESIGN_TO_LOGICAL(DESIGN_UNIT_VALUE) \ QFixed::fromReal((qreal(DESIGN_UNIT_VALUE) / qreal(m_unitsPerEm)) * fontDef.pixelSize) diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h index 45cba9c68bf..bb4b2953956 100644 --- a/src/plugins/platforms/windows/qwindowscombase.h +++ b/src/plugins/platforms/windows/qwindowscombase.h @@ -107,6 +107,9 @@ private: ULONG m_ref; }; +// Clang does not consider __declspec(nothrow) as nothrow +QT_WARNING_DISABLE_CLANG("-Wmicrosoft-exception-spec") + QT_END_NAMESPACE #endif // QWINDOWSCOMBASE_H From c584380c6901b1bcd9f8100fa1087b09d3cb023d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 10 Jan 2020 13:20:42 +0100 Subject: [PATCH 03/20] Windows QPA: Update documentation on command line options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sort alphabetically and add recent relevant options with version information. Change-Id: I10c8cc82ce357775ed68cb811a0c906cd38633a5 Reviewed-by: Tor Arne Vestbรธ --- src/gui/kernel/qguiapplication.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index bdcea275c34..2b3299f745a 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -605,8 +605,13 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME The following parameters are available for \c {-platform windows}: \list + \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as + Qt::GroupSwitchModifier (since Qt 5.12). \li \c {dialogs=[xp|none]}, \c xp uses XP-style native dialogs and \c none disables them. + + \li \c {dpiawareness=[0|1|2} Sets the DPI awareness of the process + (see \l{High DPI Displays}, since Qt 5.4). \li \c {fontengine=freetype}, uses the FreeType font engine. \li \c {menus=[native|none]}, controls the use of native menus. @@ -616,10 +621,23 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME provide hover signals. They are mainly intended for Qt Quick. By default, they will be used if the application is not an instance of QApplication or for Qt Quick Controls 2 - applications. + applications (since Qt 5.10). - \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as - Qt::GroupSwitchModifier. + \li \c {nocolorfonts} Turn off DirectWrite Color fonts + (since Qt 5.8). + + \li \c {nodirectwrite} Turn off DirectWrite fonts (since Qt 5.8). + + \li \c {nomousefromtouch} Ignores mouse events synthesized + from touch events by the operating system. + + \li \c {nowmpointer} Switches from Pointer Input Messages handling + to legacy mouse handling (since Qt 5.12). + \li \c {reverse} Activates Right-to-left mode (experimental). + Windows title bars will be shown accordingly in Right-to-left locales + (since Qt 5.13). + \li \c {tabletabsoluterange=} Sets a value for mouse mode detection + of WinTab tablets (Legacy, since Qt 5.3). \endlist The following parameter is available for \c {-platform cocoa} (on macOS): From 577d698b8e72bc0969ae7545a1a56d3a3d08bdda Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 16 Dec 2019 20:09:25 +0100 Subject: [PATCH 04/20] QString::isLower/isUpper: redo the implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use QStringIterator rather than indexed loops. This fixes handling of non-BMP code points (which may be lower or uppercase, see the test). Change also the semantics of the functions, adopting Unicode ยง3.13 definitions: a string is lowercase/uppercase if it's equal to its own toLower/toUpper folding. As a side effect, empty strings are now correctly reported to be lowercase AND uppercase. [ChangeLog][Important Behavior Changes] The semantics of QString::isLower() and QString::isUpper() have been changed to match the Unicode specification. Now lowercase (resp. uppercase) strings are allowed to contain any character; a string is considered lowercase (resp. uppercase) if it's equal to its own toLower() (resp. toUpper()) folding. Previously, a non-letter character would make the string not lowercase nor uppercase, and the mere presence of an uppercase (resp. lowercase) letter would make isLower() (resp. isUpper()) return false, even if the letter wouldn't change under case folding. As a consequence, now empty strings are lowercase and uppercase. [ChangeLog][QtCore][QString] Fixed a number of bugs of QString::isLower() and QString::isUpper(). Empty strings are now correctly reported to be lowercase (resp. uppercase), and strings containing code points outside the BMP are now correctly handled. Note that the behavior of these functions has also been changed. Change-Id: Iba1398279a072399a9f21295fe75f6e414f3f813 Reviewed-by: Thiago Macieira --- src/corelib/text/qstring.cpp | 44 ++++--- .../auto/corelib/text/qstring/tst_qstring.cpp | 111 ++++++++++++------ 2 files changed, 101 insertions(+), 54 deletions(-) diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index b929786255e..fa8b5cf3f81 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -5109,21 +5109,25 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const } /*! - Returns \c true if the string only contains uppercase letters, - otherwise returns \c false. + Returns \c true if the string is uppercase, that is, it's identical + to its toUpper() folding. + + Note that this does \e not mean that the string does not contain + lowercase letters (some lowercase letters do not have a uppercase + folding; they are left unchanged by toUpper()). + For more information, refer to the Unicode standard, section 3.13. + \since 5.12 - \sa QChar::isUpper(), isLower() + \sa QChar::toUpper(), isLower() */ bool QString::isUpper() const { - if (isEmpty()) - return false; + QStringIterator it(*this); - const QChar *d = data(); - - for (int i = 0, max = size(); i < max; ++i) { - if (!d[i].isUpper()) + while (it.hasNext()) { + uint uc = it.nextUnchecked(); + if (qGetProp(uc)->cases[QUnicodeTables::UpperCase].diff) return false; } @@ -5131,21 +5135,25 @@ bool QString::isUpper() const } /*! - Returns \c true if the string only contains lowercase letters, - otherwise returns \c false. + Returns \c true if the string is lowercase, that is, it's identical + to its toLower() folding. + + Note that this does \e not mean that the string does not contain + uppercase letters (some uppercase letters do not have a lowercase + folding; they are left unchanged by toLower()). + For more information, refer to the Unicode standard, section 3.13. + \since 5.12 - \sa QChar::isLower(), isUpper() + \sa QChar::toLower(), isUpper() */ bool QString::isLower() const { - if (isEmpty()) - return false; + QStringIterator it(*this); - const QChar *d = data(); - - for (int i = 0, max = size(); i < max; ++i) { - if (!d[i].isLower()) + while (it.hasNext()) { + uint uc = it.nextUnchecked(); + if (qGetProp(uc)->cases[QUnicodeTables::LowerCase].diff) return false; } diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 2108e99f207..7ea93a87d61 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -459,8 +459,8 @@ private slots: void trimmed(); void toUpper(); void toLower(); - void isUpper(); - void isLower(); + void isLower_isUpper_data(); + void isLower_isUpper(); void toCaseFolded(); void rightJustified(); void leftJustified(); @@ -2311,44 +2311,83 @@ void tst_QString::toLower() #endif // icu } -void tst_QString::isUpper() +void tst_QString::isLower_isUpper_data() { - QVERIFY(!QString().isUpper()); - QVERIFY(!QString("").isUpper()); - QVERIFY(QString("TEXT").isUpper()); - QVERIFY(!QString("text").isUpper()); - QVERIFY(!QString("Text").isUpper()); - QVERIFY(!QString("tExt").isUpper()); - QVERIFY(!QString("teXt").isUpper()); - QVERIFY(!QString("texT").isUpper()); - QVERIFY(!QString("TExt").isUpper()); - QVERIFY(!QString("teXT").isUpper()); - QVERIFY(!QString("tEXt").isUpper()); - QVERIFY(!QString("tExT").isUpper()); - QVERIFY(!QString("@ABYZ[").isUpper()); - QVERIFY(!QString("@abyz[").isUpper()); - QVERIFY(!QString("`ABYZ{").isUpper()); - QVERIFY(!QString("`abyz{").isUpper()); + QTest::addColumn("string"); + QTest::addColumn("isLower"); + QTest::addColumn("isUpper"); + + int row = 0; + QTest::addRow("lower-and-upper-%02d", row++) << QString() << true << true; + QTest::addRow("lower-and-upper-%02d", row++) << QString("") << true << true; + QTest::addRow("lower-and-upper-%02d", row++) << QString(" ") << true << true; + QTest::addRow("lower-and-upper-%02d", row++) << QString("123") << true << true; + QTest::addRow("lower-and-upper-%02d", row++) << QString("@123$#") << true << true; + QTest::addRow("lower-and-upper-%02d", row++) << QString("๐„ž๐„ด๐†โ™ซ") << true << true; // Unicode Block 'Musical Symbols' + // not foldable + QTest::addRow("lower-and-upper-%02d", row++) << QString("๐šŠ๐š‹๐šŒ๐š๐šŽ") << true << true; // MATHEMATICAL MONOSPACE SMALL A, ... E + QTest::addRow("lower-and-upper-%02d", row++) << QString("๐™–,๐™—,๐™˜,๐™™,๐™š") << true << true; // MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A, ... E + QTest::addRow("lower-and-upper-%02d", row++) << QString("๐—”๐—•๐—–๐——๐—˜") << true << true; // MATHEMATICAL SANS-SERIF BOLD CAPITAL A, ... E + QTest::addRow("lower-and-upper-%02d", row++) << QString("๐€,๐,๐‚,๐ƒ,๐„") << true << true; // MATHEMATICAL BOLD CAPITAL A, ... E + + row = 0; + QTest::addRow("only-lower-%02d", row++) << QString("text") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("ร aa") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("รธรฆรŸ") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("text ") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString(" text") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("hello, world!") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("123@abyz[") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("`abyz{") << true << false; + QTest::addRow("only-lower-%02d", row++) << QString("a๐™–a|b๐™—b|c๐™˜c|d๐™™d|e๐™še") << true << false; // MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A, ... E + QTest::addRow("only-lower-%02d", row++) << QString("๐จ") << true << false; // DESERET SMALL LETTER LONG I + // uppercase letters, not foldable + QTest::addRow("only-lower-%02d", row++) << QString("text๐—”text") << true << false; // MATHEMATICAL SANS-SERIF BOLD CAPITAL A + + row = 0; + QTest::addRow("only-upper-%02d", row++) << QString("TEXT") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("ร€AA") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("ร˜ร†แบž") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("TEXT ") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString(" TEXT") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("HELLO, WORLD!") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("123@ABYZ[") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("`ABYZ{") << false << true; + QTest::addRow("only-upper-%02d", row++) << QString("A๐€A|B๐B|C๐‚C|D๐ƒD|E๐„E") << false << true; // MATHEMATICAL BOLD CAPITAL A, ... E + QTest::addRow("only-upper-%02d", row++) << QString("๐€") << false << true; // DESERET CAPITAL LETTER LONG I + // lowercase letters, not foldable + QTest::addRow("only-upper-%02d", row++) << QString("TEXT๐šŠTEXT") << false << true; // MATHEMATICAL MONOSPACE SMALL A + + row = 0; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("Text") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("tExt") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("teXt") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("texT") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("TExt") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("teXT") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("tEXt") << false << false; + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("tExT") << false << false; + // not foldable + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("TEXT๐šŠtext") << false << false; // MATHEMATICAL MONOSPACE SMALL A + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("text๐—”TEXT") << false << false; // MATHEMATICAL SANS-SERIF BOLD CAPITAL A + // titlecase, foldable + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("abcวˆdef") << false << false; // LATIN CAPITAL LETTER L WITH SMALL LETTER J + QTest::addRow("not-lower-nor-upper-%02d", row++) << QString("ABCวˆDEF") << false << false; // LATIN CAPITAL LETTER L WITH SMALL LETTER J } -void tst_QString::isLower() +void tst_QString::isLower_isUpper() { - QVERIFY(!QString().isLower()); - QVERIFY(!QString("").isLower()); - QVERIFY(QString("text").isLower()); - QVERIFY(!QString("Text").isLower()); - QVERIFY(!QString("tExt").isLower()); - QVERIFY(!QString("teXt").isLower()); - QVERIFY(!QString("texT").isLower()); - QVERIFY(!QString("TExt").isLower()); - QVERIFY(!QString("teXT").isLower()); - QVERIFY(!QString("tEXt").isLower()); - QVERIFY(!QString("tExT").isLower()); - QVERIFY(!QString("TEXT").isLower()); - QVERIFY(!QString("@ABYZ[").isLower()); - QVERIFY(!QString("@abyz[").isLower()); - QVERIFY(!QString("`ABYZ{").isLower()); - QVERIFY(!QString("`abyz{").isLower()); + QFETCH(QString, string); + QFETCH(bool, isLower); + QFETCH(bool, isUpper); + + QCOMPARE(string.isLower(), isLower); + QCOMPARE(string.toLower() == string, isLower); + QVERIFY(string.toLower().isLower()); + + QCOMPARE(string.isUpper(), isUpper); + QCOMPARE(string.toUpper() == string, isUpper); + QVERIFY(string.toUpper().isUpper()); } void tst_QString::toCaseFolded() From 2f536411d8d6918a8fed53198190d60fe188b0a4 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 6 Jan 2020 11:51:07 +0100 Subject: [PATCH 05/20] QRegularExpression: minor doc fixes Amends d24a1d4323e73400ef4ecca99e03ff0f41c60389 Change-Id: I108f85b174e21ef71bf269fb9f6725972e76f107 Reviewed-by: David Faure --- src/corelib/text/qregularexpression.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/text/qregularexpression.cpp b/src/corelib/text/qregularexpression.cpp index 8627cbba4fe..67be67c243f 100644 --- a/src/corelib/text/qregularexpression.cpp +++ b/src/corelib/text/qregularexpression.cpp @@ -463,10 +463,10 @@ QT_BEGIN_NAMESPACE \c{\xHHHH} with more than 2 digits. A pattern like \c{\x2022} neeeds to be ported to \c{\x{2022}}, or it will match a space (\c{0x20}) followed by the string \c{"22"}. In general, it is highly recommended to always use - curly braces with the \c{\\x} escape, no matter the amount of digits + curly braces with the \c{\x} escape, no matter the amount of digits specified. - \li A 0-to-n quantification like \c{{,n}} needs to be ported to c{{0,n}} to + \li A 0-to-n quantification like \c{{,n}} needs to be ported to \c{{0,n}} to preserve semantics. Otherwise, a pattern such as \c{\d{,3}} would actually match a digit followed by the exact string \c{"{,3}"}. From 3d1e257770e8c79c7cd9a08f9caf1bd8395cb10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 31 Oct 2019 09:33:40 +0100 Subject: [PATCH 06/20] Wasm: Support event loop wakeup from secondary threads Minimal fix for the missing wakeup issue, in leu of a new event loop implementation. So far, emscripten_async_run_in_main_runtime_thread_ looks to be our option for scheduling calls on the main thread. This function is available on emsdk 1.38.22 and higher. Requires making from QEventDispatcherUNIX::wakeUp() non-final. The future event dispatcher implementation will not inherit QEventDispatcherUNIX, so this is a temporary change. Fixes: QTBUG-75793 Task-number: QTBUG-76007 Change-Id: Ie6f6ee6f7674206fc0673a4fe866ac614432ab65 Reviewed-by: Lorn Potter --- src/corelib/kernel/qeventdispatcher_unix_p.h | 2 +- .../platforms/wasm/qwasmeventdispatcher.cpp | 23 +++++++++++++++++++ .../platforms/wasm/qwasmeventdispatcher.h | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index f37edfc9671..581df9242cb 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -118,7 +118,7 @@ public: int remainingTime(int timerId) final; - void wakeUp() final; + void wakeUp() override; void interrupt() final; void flush() override; diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp index 41355d72aef..d89cd78b285 100644 --- a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp @@ -33,6 +33,14 @@ #include +#if (__EMSCRIPTEN_major__ > 1 || __EMSCRIPTEN_minor__ > 38 || __EMSCRIPTEN_minor__ == 38 && __EMSCRIPTEN_tiny__ >= 22) +# define EMSCRIPTEN_HAS_ASYNC_RUN_IN_MAIN_RUNTIME_THREAD +#endif + +#ifdef EMSCRIPTEN_HAS_ASYNC_RUN_IN_MAIN_RUNTIME_THREAD +#include +#endif + class QWasmEventDispatcherPrivate : public QEventDispatcherUNIXPrivate { @@ -179,3 +187,18 @@ void QWasmEventDispatcher::doMaintainTimers() emscripten_async_call(callback, this, toWaitDuration); m_currentTargetTime = newTargetTime; } + +void QWasmEventDispatcher::wakeUp() +{ +#ifdef EMSCRIPTEN_HAS_ASYNC_RUN_IN_MAIN_RUNTIME_THREAD + if (!emscripten_is_main_runtime_thread()) + emscripten_async_run_in_main_runtime_thread_(EM_FUNC_SIG_VI, (void*)(&QWasmEventDispatcher::mainThreadWakeUp), this); +#endif + QEventDispatcherUNIX::wakeUp(); +} + +void QWasmEventDispatcher::mainThreadWakeUp(void *eventDispatcher) +{ + emscripten_resume_main_loop(); // Service possible requestUpdate Calls + static_cast(eventDispatcher)->processEvents(QEventLoop::AllEvents); +} diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.h b/src/plugins/platforms/wasm/qwasmeventdispatcher.h index 5300b3de73a..f72d92ce079 100644 --- a/src/plugins/platforms/wasm/qwasmeventdispatcher.h +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.h @@ -51,6 +51,8 @@ public: protected: bool processEvents(QEventLoop::ProcessEventsFlags flags) override; void doMaintainTimers(); + void wakeUp() override; + static void mainThreadWakeUp(void *eventDispatcher); private: bool m_hasMainLoop = false; From a16c37b78fff5c4b24328d52bf9b2c7f57db0d12 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 11 Jan 2020 12:36:01 +0100 Subject: [PATCH 07/20] Enforce that char16_t / char32_t are 16/32 bits The standard makes them as big as int_least16_t / 32_t, i.e. big enough to hold UTF-16 / UTF-32 code units. We're relying on them to be *exactly* 16/32 bit instead. Drive by: move the check that a char is 8 bits before saying that some other type is not its expected sizeof() * 8. Change-Id: Idbf3d33331667d417702d9dde221905bcfc4d021 Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 20046e3fcf8..da69628d2b7 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -139,10 +139,12 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); // in. The idea here is to error or warn if otherwise implicit Qt // assumptions are not fulfilled on new hardware or compilers // (if this list becomes too long, consider factoring into a separate file) -Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits"); Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); +Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits"); Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined incorrectly"); Q_STATIC_ASSERT_X(sizeof(float) == 4, "Qt assumes that float is 32 bits"); +Q_STATIC_ASSERT_X(sizeof(char16_t) == 2, "Qt assumes that char16_t is 16 bits"); +Q_STATIC_ASSERT_X(sizeof(char32_t) == 4, "Qt assumes that char32_t is 32 bits"); // While we'd like to check for __STDC_IEC_559__, as per ISO/IEC 9899:2011 // Annex F (C11, normative for C++11), there are a few corner cases regarding From ccb2cb84f535b0bfce19a95d7f3a36803480cae8 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 10 Jan 2020 14:15:35 +0100 Subject: [PATCH 08/20] QNetworkReply: deprecate the 'error' getter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To disambiguate &QNetworkReply::error expression. [ChangeLog][Deprecation Notice] QNetworkReply::error() (the getter) was deprecated; superseded by networkError(). Task-number: QTBUG-80369 Change-Id: I545f963788bce0800c9e0f0c94d5f1029946effe Reviewed-by: Mรฅrten Nordheim --- examples/embedded/flightinfo/flightinfo.cpp | 2 +- examples/embedded/lightmaps/slippymap.cpp | 2 +- examples/network/download/main.cpp | 2 +- .../downloadmanager/downloadmanager.cpp | 2 +- .../network/googlesuggest/googlesuggest.cpp | 2 +- examples/network/http/httpwindow.cpp | 2 +- examples/network/torrent/trackerclient.cpp | 4 +- src/network/access/qnetworkreply.cpp | 25 +- src/network/access/qnetworkreply.h | 7 +- tests/auto/network/access/http2/tst_http2.cpp | 20 +- .../tst_qabstractnetworkcache.cpp | 10 +- .../qnetworkreply/tst_qnetworkreply.cpp | 327 +++++++++--------- tests/auto/network/access/spdy/tst_spdy.cpp | 8 +- .../qxmlinputsource/tst_qxmlinputsource.cpp | 2 +- .../qnetworkreply/tst_qnetworkreply.cpp | 22 +- 15 files changed, 229 insertions(+), 208 deletions(-) diff --git a/examples/embedded/flightinfo/flightinfo.cpp b/examples/embedded/flightinfo/flightinfo.cpp index f46fc9693fa..732e07583a7 100644 --- a/examples/embedded/flightinfo/flightinfo.cpp +++ b/examples/embedded/flightinfo/flightinfo.cpp @@ -144,7 +144,7 @@ public: private slots: void handleNetworkData(QNetworkReply *networkReply) { - if (!networkReply->error()) { + if (!networkReply->networkError()) { if (!mapReplies.contains(networkReply)) { // Assume UTF-8 encoded QByteArray data = networkReply->readAll(); diff --git a/examples/embedded/lightmaps/slippymap.cpp b/examples/embedded/lightmaps/slippymap.cpp index da003981ff8..dfc21862fb5 100644 --- a/examples/embedded/lightmaps/slippymap.cpp +++ b/examples/embedded/lightmaps/slippymap.cpp @@ -162,7 +162,7 @@ void SlippyMap::handleNetworkData(QNetworkReply *reply) { QImage img; QPoint tp = reply->request().attribute(QNetworkRequest::User).toPoint(); - if (!reply->error()) + if (!reply->networkError()) if (!img.load(reply, 0)) img = QImage(); reply->deleteLater(); diff --git a/examples/network/download/main.cpp b/examples/network/download/main.cpp index 076dfdfd0b2..f496c1723e8 100644 --- a/examples/network/download/main.cpp +++ b/examples/network/download/main.cpp @@ -175,7 +175,7 @@ void DownloadManager::sslErrors(const QList &sslErrors) void DownloadManager::downloadFinished(QNetworkReply *reply) { QUrl url = reply->url(); - if (reply->error()) { + if (reply->networkError()) { fprintf(stderr, "Download of %s failed: %s\n", url.toEncoded().constData(), qPrintable(reply->errorString())); diff --git a/examples/network/downloadmanager/downloadmanager.cpp b/examples/network/downloadmanager/downloadmanager.cpp index cbad29541a8..eceb48977bd 100644 --- a/examples/network/downloadmanager/downloadmanager.cpp +++ b/examples/network/downloadmanager/downloadmanager.cpp @@ -162,7 +162,7 @@ void DownloadManager::downloadFinished() progressBar.clear(); output.close(); - if (currentDownload->error()) { + if (currentDownload->networkError()) { // download failed fprintf(stderr, "Failed: %s\n", qPrintable(currentDownload->errorString())); output.remove(); diff --git a/examples/network/googlesuggest/googlesuggest.cpp b/examples/network/googlesuggest/googlesuggest.cpp index 2cba43178ea..1ae515f5305 100644 --- a/examples/network/googlesuggest/googlesuggest.cpp +++ b/examples/network/googlesuggest/googlesuggest.cpp @@ -209,7 +209,7 @@ void GSuggestCompletion::preventSuggest() void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply) { QUrl url = networkReply->url(); - if (networkReply->error() == QNetworkReply::NoError) { + if (networkReply->networkError() == QNetworkReply::NoError) { QVector choices; QByteArray response(networkReply->readAll()); diff --git a/examples/network/http/httpwindow.cpp b/examples/network/http/httpwindow.cpp index c7bf0c0dff9..d0eb2529cde 100644 --- a/examples/network/http/httpwindow.cpp +++ b/examples/network/http/httpwindow.cpp @@ -249,7 +249,7 @@ void HttpWindow::httpFinished() return; } - if (reply->error()) { + if (reply->networkError()) { QFile::remove(fi.absoluteFilePath()); statusLabel->setText(tr("Download failed:\n%1.").arg(reply->errorString())); downloadButton->setEnabled(true); diff --git a/examples/network/torrent/trackerclient.cpp b/examples/network/torrent/trackerclient.cpp index 00810a98afe..540ab315577 100644 --- a/examples/network/torrent/trackerclient.cpp +++ b/examples/network/torrent/trackerclient.cpp @@ -165,8 +165,8 @@ void TrackerClient::httpRequestDone(QNetworkReply *reply) return; } - if (reply->error() != QNetworkReply::NoError) { - emit connectionError(reply->error()); + if (reply->networkError() != QNetworkReply::NoError) { + emit connectionError(reply->networkError()); return; } diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index fb30bfd4f18..0a5a17a3b84 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -554,13 +554,34 @@ QNetworkAccessManager::Operation QNetworkReply::operation() const return d_func()->operation; } +#if QT_DEPRECATED_SINCE(5, 15) /*! + \deprecated + + Use networkError() instead. + + Returns the error that was found during the processing of this + request. If no error was found, returns NoError. + + \sa setError(), networkError() +*/ +/* +QNetworkReply::NetworkError QNetworkReply::error() const +{ + return networkError(); +} +*/ +#endif // QT_DEPRECATED_SINCE(5, 15) + +/*! + \since 5.15 + Returns the error that was found during the processing of this request. If no error was found, returns NoError. \sa setError() */ -QNetworkReply::NetworkError QNetworkReply::error() const +QNetworkReply::NetworkError QNetworkReply::networkError() const { return d_func()->errorCode; } @@ -858,7 +879,7 @@ void QNetworkReply::setRequest(const QNetworkRequest &request) Calling setError() does not emit the error(QNetworkReply::NetworkError) signal. - \sa error(), errorString() + \sa error(), errorString(), networkError() */ void QNetworkReply::setError(NetworkError errorCode, const QString &errorString) { diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 4a402daa91a..1bcb6d9680f 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -124,7 +124,12 @@ public: QNetworkAccessManager *manager() const; QNetworkAccessManager::Operation operation() const; QNetworkRequest request() const; - NetworkError error() const; + +#if QT_DEPRECATED_SINCE(5, 15) + // QT_DEPRECATED_X("Use networkError()") NetworkError error() const; +#endif // QT_DEPRECATED_SINCE(5, 15) + NetworkError networkError() const; + bool isFinished() const; bool isRunning() const; QUrl url() const; diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 6f94692cb19..d4e967d2cb8 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -279,7 +279,7 @@ void tst_Http2::singleRequest() QVERIFY(prefaceOK); QVERIFY(serverGotSettingsACK); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); } @@ -444,7 +444,7 @@ void tst_Http2::pushPromise() QVERIFY(prefaceOK); QVERIFY(serverGotSettingsACK); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); // Now, the most interesting part! @@ -466,7 +466,7 @@ void tst_Http2::pushPromise() QCOMPARE(nSentRequests, 0); // Decreased by replyFinished(): QCOMPARE(nRequests, 0); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); } @@ -511,7 +511,7 @@ void tst_Http2::goaway() QNetworkRequest request(url); request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true)); replies[i] = manager->get(request); - QCOMPARE(replies[i]->error(), QNetworkReply::NoError); + QCOMPARE(replies[i]->networkError(), QNetworkReply::NoError); void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error; connect(replies[i], errorSignal, this, &tst_Http2::replyFinishedWithError); @@ -671,7 +671,7 @@ void tst_Http2::connectToHost() connect(reply, &QNetworkReply::finished, [this, reply]() { --nRequests; eventLoop.exitLoop(); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); // Nothing received back: QVERIFY(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).isNull()); @@ -698,7 +698,7 @@ void tst_Http2::connectToHost() QVERIFY(prefaceOK); QVERIFY(serverGotSettingsACK); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); } @@ -927,10 +927,10 @@ void tst_Http2::replyFinished() QVERIFY(nRequests); if (const auto reply = qobject_cast(sender())) { - if (reply->error() != QNetworkReply::NoError) + if (reply->networkError() != QNetworkReply::NoError) stopEventLoop(); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); const QVariant http2Used(reply->attribute(QNetworkRequest::Http2WasUsedAttribute)); if (!http2Used.isValid() || !http2Used.toBool()) @@ -967,9 +967,9 @@ void tst_Http2::replyFinishedWithError() if (const auto reply = qobject_cast(sender())) { // For now this is a 'generic' code, it just verifies some error was // reported without testing its type. - if (reply->error() == QNetworkReply::NoError) + if (reply->networkError() == QNetworkReply::NoError) stopEventLoop(); - QVERIFY(reply->error() != QNetworkReply::NoError); + QVERIFY(reply->networkError() != QNetworkReply::NoError); } --nRequests; diff --git a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp index 182e3e95476..4b6e04f4677 100644 --- a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp +++ b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp @@ -322,10 +322,10 @@ void tst_QAbstractNetworkCache::runTest() QByteArray secondData = reply2->readAll(); if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) { - QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError); + QCOMPARE(reply2->networkError(), QNetworkReply::ContentNotFoundError); QCOMPARE(secondData, QByteArray()); } else { - QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(reply2->networkError(), QNetworkReply::NoError); QCOMPARE(QString(secondData), QString(goodData)); QCOMPARE(secondData, goodData); QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -375,12 +375,12 @@ void tst_QAbstractNetworkCache::checkSynchronous() QByteArray secondData = reply2->readAll(); if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) { - QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError); + QCOMPARE(reply2->networkError(), QNetworkReply::ContentNotFoundError); QCOMPARE(secondData, QByteArray()); } else { - if (reply2->error() != QNetworkReply::NoError) + if (reply2->networkError() != QNetworkReply::NoError) qDebug() << reply2->errorString(); - QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(reply2->networkError(), QNetworkReply::NoError); QCOMPARE(QString(secondData), QString(goodData)); QCOMPARE(secondData, goodData); QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 36f19c1582b..c5c1b8efb60 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -1426,7 +1426,7 @@ QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op, if (request.attribute(QNetworkRequest::SynchronousRequestAttribute).toBool()) { if (reply->isFinished()) - code = reply->error() != QNetworkReply::NoError ? Failure : Success; + code = reply->networkError() != QNetworkReply::NoError ? Failure : Success; else code = Failure; } else { @@ -1491,10 +1491,10 @@ static QByteArray msgWaitForFinished(QNetworkReplyPtr &reply) debug << reply->url(); if (!reply->isFinished()) debug << "timed out."; - else if (reply->error() == QNetworkReply::NoError) + else if (reply->networkError() == QNetworkReply::NoError) debug << "finished."; else - debug << "failed: #" << reply->error() << reply->errorString(); + debug << "failed: #" << reply->networkError() << reply->errorString(); return result.toLocal8Bit(); } @@ -1642,7 +1642,7 @@ void tst_QNetworkReply::stateChecking() QCOMPARE(int(reply->operation()), int(QNetworkAccessManager::GetOperation)); // error and not error are OK since we might change underlying behaviour again if (!reply->isFinished()) - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->url(), url); reply->abort(); @@ -1659,7 +1659,7 @@ void tst_QNetworkReply::invalidProtocol() QCOMPARE(result, errorMsg); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::ProtocolUnknownError); + QCOMPARE(reply->networkError(), QNetworkReply::ProtocolUnknownError); } void tst_QNetworkReply::getFromData_data() @@ -1751,7 +1751,7 @@ void tst_QNetworkReply::getFromData() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, req, reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader).toString(), mimeType); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(expected.size())); @@ -1790,7 +1790,7 @@ void tst_QNetworkReply::getFromFile() QVERIFY(waitForFinish(reply) != Timeout); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), file.size()); QCOMPARE(reply->readAll(), data); @@ -1807,7 +1807,7 @@ void tst_QNetworkReply::getFromFile() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), file.size()); QCOMPARE(qint64(reply->readAll().size()), file.size()); @@ -1846,7 +1846,7 @@ void tst_QNetworkReply::getFromFileSpecial() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), resource.size()); QCOMPARE(reply->readAll(), resource.readAll()); @@ -1879,7 +1879,7 @@ void tst_QNetworkReply::getFromFtp() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size()); QCOMPARE(reply->readAll(), reference.readAll()); @@ -1892,7 +1892,7 @@ void tst_QNetworkReply::getFromFtpAfterError() invalidReply.reset(manager.get(invalidRequest)); QSignalSpy spy(invalidReply.data(), SIGNAL(error(QNetworkReply::NetworkError))); QVERIFY(spy.wait()); - QCOMPARE(invalidReply->error(), QNetworkReply::ContentNotFoundError); + QCOMPARE(invalidReply->networkError(), QNetworkReply::ContentNotFoundError); QFile reference(testDataDir + "/rfc3252.txt"); QVERIFY(reference.open(QIODevice::ReadOnly)); @@ -1900,7 +1900,7 @@ void tst_QNetworkReply::getFromFtpAfterError() QNetworkReplyPtr validReply; RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, validRequest, validReply)); QCOMPARE(validReply->url(), validRequest.url()); - QCOMPARE(validReply->error(), QNetworkReply::NoError); + QCOMPARE(validReply->networkError(), QNetworkReply::NoError); QCOMPARE(validReply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size()); QCOMPARE(validReply->readAll(), reference.readAll()); } @@ -1936,7 +1936,7 @@ void tst_QNetworkReply::getFromHttp() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply->size(), reference.size()); // only compare when the header is set. @@ -2031,7 +2031,7 @@ void tst_QNetworkReply::headFromHttp() QVERIFY(time.elapsed() < 8000); //check authentication didn't wait for the server to timeout the http connection (15s on qt test server) QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // only compare when the header is set. if (reply->header(QNetworkRequest::ContentLengthHeader).isValid() && referenceSize >= 0) @@ -2105,8 +2105,8 @@ static QByteArray msgGetErrors(int waitResult, const QNetworkReplyPtr &reply) QByteArray result ="waitResult=" + QByteArray::number(waitResult); if (reply->isFinished()) result += ", finished"; - if (reply->error() != QNetworkReply::NoError) - result += ", error: " + QByteArray::number(int(reply->error())); + if (reply->networkError() != QNetworkReply::NoError) + result += ", error: " + QByteArray::number(int(reply->networkError())); return result; } @@ -2136,7 +2136,7 @@ void tst_QNetworkReply::getErrors() reply->setParent(this); // we have expect-fails if (!reply->isFinished()) - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); // now run the request: const int waitResult = waitForFinish(reply); @@ -2146,7 +2146,7 @@ void tst_QNetworkReply::getErrors() QEXPECT_FAIL("ftp-is-dir", "QFtp cannot provide enough detail", Abort); // the line below is not necessary QEXPECT_FAIL("ftp-dir-not-readable", "QFtp cannot provide enough detail", Abort); - QCOMPARE(reply->error(), QNetworkReply::NetworkError(error)); + QCOMPARE(reply->networkError(), QNetworkReply::NetworkError(error)); QTEST(reply->readAll().isEmpty(), "dataIsEmpty"); @@ -2205,7 +2205,7 @@ void tst_QNetworkReply::putToFile() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -2235,7 +2235,7 @@ void tst_QNetworkReply::putToFtp() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -2283,7 +2283,7 @@ void tst_QNetworkReply::putToFtpWithInvalidCredentials() QVERIFY(r->isFinished()); QCOMPARE(r->url(), url); - QCOMPARE(r->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(r->networkError(), QNetworkReply::AuthenticationRequiredError); r->close(); } } @@ -2308,7 +2308,7 @@ void tst_QNetworkReply::putToHttp() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 201); // 201 Created @@ -2349,7 +2349,7 @@ void tst_QNetworkReply::putToHttpSynchronous() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 201); // 201 Created @@ -2383,7 +2383,7 @@ void tst_QNetworkReply::postToHttp() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -2415,7 +2415,7 @@ void tst_QNetworkReply::postToHttpSynchronous() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -2678,7 +2678,7 @@ void tst_QNetworkReply::postToHttpMultipart() multiPart->deleteLater(); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -2720,7 +2720,7 @@ void tst_QNetworkReply::multipartSkipIndices() // QTBUG-32534 QNetworkReplyPtr reply; RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "POST")); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok QByteArray line; @@ -2766,7 +2766,7 @@ void tst_QNetworkReply::putToHttpMultipart() multiPart->deleteLater(); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -2805,7 +2805,7 @@ void tst_QNetworkReply::putToHttps() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 201); // 201 Created @@ -2850,7 +2850,7 @@ void tst_QNetworkReply::putToHttpsSynchronous() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 201); // 201 Created @@ -2888,7 +2888,7 @@ void tst_QNetworkReply::postToHttps() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -2924,7 +2924,7 @@ void tst_QNetworkReply::postToHttpsSynchronous() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -2969,7 +2969,7 @@ void tst_QNetworkReply::postToHttpsMultipart() multiPart->deleteLater(); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -3022,7 +3022,7 @@ void tst_QNetworkReply::deleteFromHttp() QNetworkReplyPtr reply; runSimpleRequest(QNetworkAccessManager::DeleteOperation, request, reply, 0); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), error); + QCOMPARE(reply->networkError(), error); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), resultCode); } @@ -3072,19 +3072,19 @@ void tst_QNetworkReply::putGetDeleteGetFromHttp() QNetworkReplyPtr reply; RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, putRequest, reply, 0)); - QCOMPARE(reply->error(), putError); + QCOMPARE(reply->networkError(), putError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), putResultCode); runSimpleRequest(QNetworkAccessManager::GetOperation, putRequest, reply, 0); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); runSimpleRequest(QNetworkAccessManager::DeleteOperation, deleteRequest, reply, 0); - QCOMPARE(reply->error(), deleteError); + QCOMPARE(reply->networkError(), deleteError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), deleteResultCode); runSimpleRequest(QNetworkAccessManager::GetOperation, get2Request, reply, 0); - QCOMPARE(reply->error(), get2Error); + QCOMPARE(reply->networkError(), get2Error); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), get2ResultCode); } @@ -3129,7 +3129,7 @@ void tst_QNetworkReply::connectToIPv6Address() QVERIFY(server.receivedData.contains(hostinfo)); QCOMPARE(content, dataToSend); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), error); + QCOMPARE(reply->networkError(), error); } void tst_QNetworkReply::sendCustomRequestToHttp_data() @@ -3175,7 +3175,7 @@ void tst_QNetworkReply::sendCustomRequestToHttp() runCustomRequest(request, reply, verb, device); QCOMPARE(reply->url(), url); QFETCH(QNetworkReply::NetworkError, error); - QCOMPARE(reply->error(), error); + QCOMPARE(reply->networkError(), error); QFETCH(int, resultCode); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), resultCode); QFETCH(QByteArray, expectedContent); @@ -3211,7 +3211,7 @@ void tst_QNetworkReply::ioGetFromData() QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QFETCH(QByteArray, data); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toInt(), data.size()); @@ -3247,7 +3247,7 @@ void tst_QNetworkReply::ioGetFromFileSpecial() QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), resource.size()); QCOMPARE(qint64(reader.data.size()), resource.size()); @@ -3280,7 +3280,7 @@ void tst_QNetworkReply::ioGetFromFile() QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), file.size()); QCOMPARE(qint64(reader.data.size()), file.size()); @@ -3311,7 +3311,7 @@ void tst_QNetworkReply::ioGetFromFtp() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QFETCH(qint64, expectedSize); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), expectedSize); @@ -3341,8 +3341,8 @@ void tst_QNetworkReply::ioGetFromFtpWithReuse() QCOMPARE(reply1->url(), request.url()); QCOMPARE(reply2->url(), request.url()); - QCOMPARE(reply1->error(), QNetworkReply::NoError); - QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(reply1->networkError(), QNetworkReply::NoError); + QCOMPARE(reply2->networkError(), QNetworkReply::NoError); QCOMPARE(qint64(reader1.data.size()), reference.size()); QCOMPARE(qint64(reader2.data.size()), reference.size()); @@ -3366,7 +3366,7 @@ void tst_QNetworkReply::ioGetFromHttp() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size()); @@ -3392,8 +3392,8 @@ void tst_QNetworkReply::ioGetFromHttpWithReuseParallel() QCOMPARE(reply1->url(), request.url()); QCOMPARE(reply2->url(), request.url()); - QCOMPARE(reply1->error(), QNetworkReply::NoError); - QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(reply1->networkError(), QNetworkReply::NoError); + QCOMPARE(reply2->networkError(), QNetworkReply::NoError); QCOMPARE(reply1->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -3420,7 +3420,7 @@ void tst_QNetworkReply::ioGetFromHttpWithReuseSequential() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size()); @@ -3438,7 +3438,7 @@ void tst_QNetworkReply::ioGetFromHttpWithReuseSequential() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size()); @@ -3561,7 +3561,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth() QVERIFY(replySync->isFinished()); // synchronous if (expectedAuth) { // bad credentials in a synchronous request should just fail - QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(replySync->networkError(), QNetworkReply::AuthenticationRequiredError); } else { QCOMPARE(authspy.count(), 0); @@ -3587,7 +3587,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth() QVERIFY(replySync->isFinished()); // synchronous if (expectedAuth) { // bad credentials in a synchronous request should just fail - QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(replySync->networkError(), QNetworkReply::AuthenticationRequiredError); } else { QCOMPARE(authspy.count(), 0); @@ -3614,7 +3614,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuthSynchronous() QSignalSpy authspy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); QNetworkReplyPtr replySync(manager.get(request)); QVERIFY(replySync->isFinished()); // synchronous - QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(replySync->networkError(), QNetworkReply::AuthenticationRequiredError); QCOMPARE(authspy.count(), 0); QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 401); } @@ -3719,7 +3719,7 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuthSynchronous() QNetworkReplyPtr replySync(manager.get(request)); manager.setProxy(QNetworkProxy()); // reset QVERIFY(replySync->isFinished()); // synchronous - QCOMPARE(replySync->error(), QNetworkReply::ProxyAuthenticationRequiredError); + QCOMPARE(replySync->networkError(), QNetworkReply::ProxyAuthenticationRequiredError); QCOMPARE(authspy.count(), 0); QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 407); } @@ -3775,9 +3775,9 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy() QVERIFY(!reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).isValid()); QVERIFY(reader.data.isEmpty()); - QVERIFY(int(reply->error()) > 0); + QVERIFY(int(reply->networkError()) > 0); QEXPECT_FAIL("", "QTcpSocket doesn't return enough information yet", Continue); - QCOMPARE(int(reply->error()), int(QNetworkReply::ProxyConnectionRefusedError)); + QCOMPARE(int(reply->networkError()), int(QNetworkReply::ProxyConnectionRefusedError)); QCOMPARE(authspy.count(), 0); } @@ -3857,7 +3857,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithSslHandshakeError() QCOMPARE(waitForFinish(reply), int(Failure)); - QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError); + QCOMPARE(reply->networkError(), QNetworkReply::SslHandshakeFailedError); QCOMPARE(sslspy.count(), 0); } #endif @@ -3917,7 +3917,7 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer() QCOMPARE(reply->url(), request.url()); QCOMPARE(spy.count(), 1); - QVERIFY(reply->error() != QNetworkReply::NoError); + QVERIFY(reply->networkError() != QNetworkReply::NoError); } void tst_QNetworkReply::ioGetFromHttpStatus100_data() @@ -3946,7 +3946,7 @@ void tst_QNetworkReply::ioGetFromHttpStatus100() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode); QVERIFY(reply->rawHeader("bla").isNull()); } @@ -3969,7 +3969,7 @@ void tst_QNetworkReply::ioGetFromHttpNoHeaders() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); } @@ -4408,7 +4408,7 @@ void tst_QNetworkReply::ioGetWithManyProxies() QFETCH(QNetworkReply::NetworkError, expectedError); QEXPECT_FAIL("ftp-on-socks", "QFtp is too limited and won't accept non-FTP proxies", Abort); - QCOMPARE(reply->error(), expectedError); + QCOMPARE(reply->networkError(), expectedError); // Verify that the factory was called properly QCOMPARE(proxyFactory->callCount, 1); @@ -4460,7 +4460,7 @@ void tst_QNetworkReply::ioPutToFileFromFile() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -4493,10 +4493,10 @@ void tst_QNetworkReply::ioPutToFileFromSocket() socketpair.endPoints[0]->close(); QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -4541,10 +4541,10 @@ void tst_QNetworkReply::ioPutToFileFromLocalSocket() QEXPECT_FAIL("", "QTBUG-18385", Abort); #endif QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -4593,7 +4593,7 @@ void tst_QNetworkReply::ioPutToFileFromProcess() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -4627,7 +4627,7 @@ void tst_QNetworkReply::ioPutToFtpFromFile() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(reply->readAll().isEmpty()); @@ -4676,7 +4676,7 @@ void tst_QNetworkReply::ioPutToHttpFromFile() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); // verify that the HTTP status code is 201 Created QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 201); @@ -4691,7 +4691,7 @@ void tst_QNetworkReply::ioPutToHttpFromFile() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok QCOMPARE(reply->readAll(), sourceFile.readAll()); @@ -4717,7 +4717,7 @@ void tst_QNetworkReply::ioPostToHttpFromFile() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); // verify that the HTTP status code is 200 Ok QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -4807,10 +4807,10 @@ void tst_QNetworkReply::ioPostToHttpFromSocket() this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); // verify that the HTTP status code is 200 Ok QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -4870,10 +4870,10 @@ void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous() QVERIFY(reply->isFinished()); socketpair.endPoints[0]->close(); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); // verify that the HTTP status code is 200 Ok QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -4993,7 +4993,7 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag() this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); // verify: error code is QNetworkReply::ContentReSendError - QCOMPARE(reply->error(), QNetworkReply::ContentReSendError); + QCOMPARE(reply->networkError(), QNetworkReply::ContentReSendError); } #ifndef QT_NO_SSL @@ -5175,7 +5175,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() << "(it received" << reader.totalBytesRead << "bytes in" << elapsedTime << "ms)"; QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), (qint64)testData.size()); @@ -5411,7 +5411,7 @@ void tst_QNetworkReply::httpCanReadLine() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->canReadLine()); QVERIFY(!reply->readAll().isEmpty()); @@ -5470,7 +5470,7 @@ void tst_QNetworkReply::rateControl() sender.wait(); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(sender.transferRate != -1); int minRate = rate * 1024 * 9 / 10; @@ -5620,11 +5620,11 @@ void tst_QNetworkReply::chaining() QCOMPARE(waitForFinish(putReply), int(Success)); QCOMPARE(getReply->url(), QUrl::fromLocalFile(sourceFile.fileName())); - QCOMPARE(getReply->error(), QNetworkReply::NoError); + QCOMPARE(getReply->networkError(), QNetworkReply::NoError); QCOMPARE(getReply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), sourceFile.size()); QCOMPARE(putReply->url(), url); - QCOMPARE(putReply->error(), QNetworkReply::NoError); + QCOMPARE(putReply->networkError(), QNetworkReply::NoError); QCOMPARE(putReply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), Q_INT64_C(0)); QVERIFY(putReply->readAll().isEmpty()); @@ -5695,7 +5695,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -5727,7 +5727,7 @@ void tst_QNetworkReply::receiveCookiesFromHttpSynchronous() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -5790,7 +5790,7 @@ void tst_QNetworkReply::sendCookies() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -5819,7 +5819,7 @@ void tst_QNetworkReply::sendCookiesSynchronous() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok @@ -5912,9 +5912,6 @@ void tst_QNetworkReply::httpProxyCommands() // wait for the finished signal QVERIFY(waitForFinish(reply) != Timeout); - //qDebug() << reply->error() << reply->errorString(); - //qDebug() << proxyServer.receivedData; - // we don't really care if the request succeeded // especially since it won't succeed in the HTTPS case // so just check that the command was correct @@ -5997,8 +5994,6 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() QVERIFY(reply->isFinished()); // synchronous manager.setProxy(QNetworkProxy()); - //qDebug() << reply->error() << reply->errorString(); - // we don't really care if the request succeeded // especially since it won't succeed in the HTTPS case // so just check that the command was correct @@ -6038,11 +6033,11 @@ void tst_QNetworkReply::proxyChange() QVERIFY(!QTestEventLoop::instance().timeout()); // verify that the replies succeeded - QCOMPARE(reply1->error(), QNetworkReply::NoError); + QCOMPARE(reply1->networkError(), QNetworkReply::NoError); QCOMPARE(reply1->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QCOMPARE(reply1->size(), 1); - QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(reply2->networkError(), QNetworkReply::NoError); QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QVERIFY(reply2->size() > 1); @@ -6059,7 +6054,7 @@ void tst_QNetworkReply::proxyChange() QCOMPARE(waitForFinish(reply3), int(Failure)); - QVERIFY(int(reply3->error()) > 0); + QVERIFY(int(reply3->networkError()) > 0); } #endif // !QT_NO_NETWORKPROXY @@ -6092,7 +6087,7 @@ void tst_QNetworkReply::authorizationError() QNetworkRequest request(url); QNetworkReplyPtr reply(manager.get(request)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QSignalSpy errorSpy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); QSignalSpy finishedSpy(reply.data(), SIGNAL(finished())); @@ -6104,7 +6099,7 @@ void tst_QNetworkReply::authorizationError() QFETCH(int, finishedSignalCount); QCOMPARE(finishedSpy.count(), finishedSignalCount); QFETCH(int, error); - QCOMPARE(reply->error(), QNetworkReply::NetworkError(error)); + QCOMPARE(reply->networkError(), QNetworkReply::NetworkError(error)); QFETCH(int, httpStatusCode); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), httpStatusCode); @@ -6172,7 +6167,7 @@ void tst_QNetworkReply::httpReUsingConnectionSequential() connect(reply1, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(2); QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(!reply1->error()); + QVERIFY(!reply1->networkError()); int reply1port = server.client->peerPort(); if (doDeleteLater) @@ -6183,7 +6178,7 @@ void tst_QNetworkReply::httpReUsingConnectionSequential() connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(2); QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(!reply2->error()); + QVERIFY(!reply2->networkError()); int reply2port = server.client->peerPort(); // should still be the same object QVERIFY(reply1port > 0); @@ -6206,7 +6201,7 @@ public: public slots: void finishedSlot() { - QVERIFY(!reply1->error()); + QVERIFY(!reply1->networkError()); QFETCH(bool, doDeleteLater); if (doDeleteLater) { @@ -6248,7 +6243,7 @@ void tst_QNetworkReply::httpReUsingConnectionFromFinishedSlot() QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(helper.reply2); - QVERIFY(!helper.reply2->error()); + QVERIFY(!helper.reply2->networkError()); QCOMPARE(server.totalConnections, 1); } @@ -6275,7 +6270,7 @@ public slots: requestsFinishedCount++; QNetworkReply *reply = qobject_cast(sender()); - QVERIFY(!reply->error()); + QVERIFY(!reply->networkError()); QCOMPARE(reply->bytesAvailable(), 27906); if (requestsFinishedCount == 60) { @@ -6293,7 +6288,7 @@ public slots: void readyReadSlot() { QNetworkReply *reply = qobject_cast(sender()); - QVERIFY(!reply->error()); + QVERIFY(!reply->networkError()); if (requestsStartedCount_readyRead < 30 && reply->bytesAvailable() > 27906/2) { startOne(); @@ -6355,7 +6350,7 @@ void tst_QNetworkReply::ignoreSslErrorsList() QVERIFY(waitForFinish(reply) != Timeout); QFETCH(QNetworkReply::NetworkError, expectedNetworkError); - QCOMPARE(reply->error(), expectedNetworkError); + QCOMPARE(reply->networkError(), expectedNetworkError); } void tst_QNetworkReply::ignoreSslErrorsListWithSlot_data() @@ -6386,7 +6381,7 @@ void tst_QNetworkReply::ignoreSslErrorsListWithSlot() QVERIFY(waitForFinish(reply) != Timeout); QFETCH(QNetworkReply::NetworkError, expectedNetworkError); - QCOMPARE(reply->error(), expectedNetworkError); + QCOMPARE(reply->networkError(), expectedNetworkError); } void tst_QNetworkReply::sslConfiguration_data() @@ -6465,7 +6460,7 @@ void tst_QNetworkReply::sslConfiguration() QFETCH(bool, works); QNetworkReply::NetworkError expectedError = works ? QNetworkReply::NoError : QNetworkReply::SslHandshakeFailedError; - QCOMPARE(reply->error(), expectedError); + QCOMPARE(reply->networkError(), expectedError); } #ifdef QT_BUILD_INTERNAL @@ -6500,7 +6495,7 @@ void tst_QNetworkReply::sslSessionSharing() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(20); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); reply->deleteLater(); // now send several requests at the same time, so we open more sockets and reuse the SSL session @@ -6525,7 +6520,7 @@ void tst_QNetworkReply::sslSessionSharingHelperSlot() sslSessionSharingWasUsed = true; QString urlQueryString = reply->url().query(); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); count++; @@ -6566,7 +6561,7 @@ void tst_QNetworkReply::sslSessionSharingFromPersistentSession() connect(warmupReply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(20); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(warmupReply->error(), QNetworkReply::NoError); + QCOMPARE(warmupReply->networkError(), QNetworkReply::NoError); QByteArray sslSession = warmupReply->sslConfiguration().sessionTicket(); QCOMPARE(!sslSession.isEmpty(), sessionPersistenceEnabled); @@ -6594,7 +6589,7 @@ void tst_QNetworkReply::sslSessionSharingFromPersistentSession() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(20); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); bool sslSessionSharingWasUsedInReply = QSslConfigurationPrivate::peerSessionWasShared( reply->sslConfiguration()); @@ -6648,7 +6643,7 @@ void tst_QNetworkReply::symbianOpenCDataUrlCrash() RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, req, reply)); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(598)); } @@ -6868,7 +6863,7 @@ void tst_QNetworkReply::getFromHttpIntoBuffer2() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QTestEventLoop::instance().enterLoop(40); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(!QTestEventLoop::instance().timeout()); } @@ -6886,7 +6881,7 @@ void tst_QNetworkReply::getFromHttpIntoBufferCanReadLine() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->canReadLine()); QCOMPARE(reply->read(1), QByteArray("x")); QVERIFY(reply->canReadLine()); @@ -6912,7 +6907,7 @@ void tst_QNetworkReply::ioGetFromHttpWithoutContentLength() QCOMPARE(reply->url(), request.url()); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); } // Is handled somewhere else too, introduced this special test to have it more accessible @@ -6934,7 +6929,7 @@ void tst_QNetworkReply::ioGetFromHttpBrokenChunkedEncoding() QVERIFY(!QTestEventLoop::instance().timeout()); QEXPECT_FAIL(0, "We should close the socket and not just do nothing", Continue); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); } // TODO: @@ -6958,7 +6953,7 @@ void tst_QNetworkReply::qtbug12908compressedHttpReply() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->size(), qint64(16384)); QCOMPARE(reply->readAll(), QByteArray(16384, '\0')); } @@ -6981,7 +6976,7 @@ void tst_QNetworkReply::compressedHttpReplyBrokenGzip() QCOMPARE(waitForFinish(reply), int(Failure)); - QCOMPARE(reply->error(), QNetworkReply::ProtocolFailure); + QCOMPARE(reply->networkError(), QNetworkReply::ProtocolFailure); } // TODO add similar test for FTP @@ -7036,7 +7031,7 @@ void tst_QNetworkReply::getFromUnreachableIp() QCOMPARE(waitForFinish(reply), int(Failure)); - QVERIFY(reply->error() != QNetworkReply::NoError); + QVERIFY(reply->networkError() != QNetworkReply::NoError); } void tst_QNetworkReply::qtbug4121unknownAuthentication() @@ -7060,7 +7055,7 @@ void tst_QNetworkReply::qtbug4121unknownAuthentication() QCOMPARE(finishedSpy.count(), 1); QCOMPARE(errorSpy.count(), 1); - QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(reply->networkError(), QNetworkReply::AuthenticationRequiredError); } #ifndef QT_NO_NETWORKPROXY @@ -7151,7 +7146,7 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); + QCOMPARE(reply->networkError(), QNetworkReply::ProxyAuthenticationRequiredError); QCOMPARE(authSpy.count(), 0); QCOMPARE(proxyAuthSpy.count(), 1); proxyAuthSpy.clear(); @@ -7165,8 +7160,8 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QVERIFY(!QTestEventLoop::instance().timeout()); // Work round known quirk in the old test server (danted -v < v1.1.19): - if (reply->error() != QNetworkReply::HostNotFoundError) - QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); + if (reply->networkError() != QNetworkReply::HostNotFoundError) + QCOMPARE(reply->networkError(), QNetworkReply::ProxyAuthenticationRequiredError); QCOMPARE(authSpy.count(), 0); QVERIFY(proxyAuthSpy.count() > 0); proxyAuthSpy.clear(); @@ -7192,7 +7187,7 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(reply->networkError(), QNetworkReply::AuthenticationRequiredError); QVERIFY(authSpy.count() > 0); authSpy.clear(); if (proxyAuth) { @@ -7208,7 +7203,7 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(reply->networkError(), QNetworkReply::AuthenticationRequiredError); QVERIFY(authSpy.count() > 0); authSpy.clear(); if (proxyAuth) { @@ -7226,7 +7221,7 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(authSpy.count() > 0); authSpy.clear(); if (proxyAuth) { @@ -7241,7 +7236,7 @@ void tst_QNetworkReply::authenticationCacheAfterCancel() QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); //should be supplied from cache QCOMPARE(authSpy.count(), 0); authSpy.clear(); @@ -7272,7 +7267,7 @@ void tst_QNetworkReply::authenticationWithDifferentRealm() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); helper.httpUserName = "httptest"; helper.httpPassword = "httptest"; @@ -7282,7 +7277,7 @@ void tst_QNetworkReply::authenticationWithDifferentRealm() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); } #endif // !QT_NO_NETWORKPROXY @@ -7333,7 +7328,7 @@ void tst_QNetworkReply::qtbug13431replyThrottling() QTestEventLoop::instance().enterLoop(30); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(helper.m_reply->isFinished()); - QCOMPARE(helper.m_reply->error(), QNetworkReply::NoError); + QCOMPARE(helper.m_reply->networkError(), QNetworkReply::NoError); } void tst_QNetworkReply::httpWithNoCredentialUsage() @@ -7382,7 +7377,7 @@ void tst_QNetworkReply::httpWithNoCredentialUsage() QCOMPARE(finishedSpy.count(), 1); QCOMPARE(errorSpy.count(), 1); - QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(reply->networkError(), QNetworkReply::AuthenticationRequiredError); } } @@ -7398,7 +7393,7 @@ void tst_QNetworkReply::qtbug15311doubleContentLength() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->size(), qint64(3)); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(3)); QCOMPARE(reply->rawHeader("Content-length"), QByteArray("3, 3")); @@ -7417,7 +7412,7 @@ void tst_QNetworkReply::qtbug18232gzipContentLengthZero() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->size(), qint64(0)); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(0)); QCOMPARE(reply->readAll(), QByteArray()); @@ -7438,7 +7433,7 @@ void tst_QNetworkReply::qtbug22660gzipNoContentLengthEmptyContent() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->size(), qint64(0)); QVERIFY(!reply->header(QNetworkRequest::ContentLengthHeader).isValid()); QCOMPARE(reply->readAll(), QByteArray()); @@ -7511,7 +7506,7 @@ void tst_QNetworkReply::qtbug27161httpHeaderMayBeDamaged(){ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->size(), qint64(3)); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(3)); QCOMPARE(reply->rawHeader("Content-length"), QByteArray("3")); @@ -7562,7 +7557,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll(), QByteArray("GET")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false); @@ -7572,7 +7567,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll(), QByteArray("GET")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), true); @@ -7584,7 +7579,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->rawHeader("Content-length"), QByteArray("4")); QCOMPARE(reply->readAll(), QByteArray("POST")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false); @@ -7596,7 +7591,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll(), QByteArray("GET")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false); @@ -7607,7 +7602,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll(), QByteArray("GET")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), true); @@ -7618,7 +7613,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false); server.clearHeaderParserState(); @@ -7628,7 +7623,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll(), QByteArray("GET")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false); @@ -7639,7 +7634,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() { QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll(), QByteArray("GET")); QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), true); } @@ -7790,7 +7785,7 @@ void tst_QNetworkReply::synchronousRequestSslFailure() QSignalSpy sslErrorsSpy(&manager, SIGNAL(sslErrors(QNetworkReply*,QList))); runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply, 0); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError); + QCOMPARE(reply->networkError(), QNetworkReply::SslHandshakeFailedError); QCOMPARE(sslErrorsSpy.count(), 0); } #endif @@ -7832,14 +7827,14 @@ void tst_QNetworkReply::httpAbort() HttpAbortHelper replyHolder(reply.data()); QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError); + QCOMPARE(reply->networkError(), QNetworkReply::OperationCanceledError); QVERIFY(reply->isFinished()); // Abort immediately after the get() QNetworkReplyPtr reply2(manager.get(request)); connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); reply2->abort(); - QCOMPARE(reply2->error(), QNetworkReply::OperationCanceledError); + QCOMPARE(reply2->networkError(), QNetworkReply::OperationCanceledError); QVERIFY(reply2->isFinished()); // Abort after the finished() @@ -7850,7 +7845,7 @@ void tst_QNetworkReply::httpAbort() QVERIFY(reply3->isFinished()); reply3->abort(); - QCOMPARE(reply3->error(), QNetworkReply::NoError); + QCOMPARE(reply3->networkError(), QNetworkReply::NoError); } void tst_QNetworkReply::dontInsertPartialContentIntoTheCache() @@ -7897,7 +7892,7 @@ void tst_QNetworkReply::httpUserAgent() QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(server.receivedData.contains("\r\nUser-Agent: abcDEFghi\r\n")); } @@ -7950,7 +7945,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache() QNetworkReplyPtr reply(manager.get(request)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(reply->networkError(), QNetworkReply::AuthenticationRequiredError); } //2) URL with credentials, we are authenticated @@ -7961,7 +7956,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache() QNetworkReplyPtr reply(manager.get(request)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll().constData(), "OK"); } @@ -7973,7 +7968,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache() QNetworkReplyPtr reply(manager.get(request)); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->readAll().constData(), "OK"); } } @@ -8067,7 +8062,7 @@ void tst_QNetworkReply::ftpAuthentication() runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply); QCOMPARE(reply->url(), request.url()); - QCOMPARE(reply->error(), QNetworkReply::NetworkError(error)); + QCOMPARE(reply->networkError(), QNetworkReply::NetworkError(error)); } void tst_QNetworkReply::emitErrorForAllReplies() // QTBUG-36890 @@ -8170,7 +8165,7 @@ void tst_QNetworkReply::backgroundRequest() QNetworkSessionPrivate::setUsagePolicies(*session, original); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), error); + QCOMPARE(reply->networkError(), error); #endif } #endif @@ -8248,7 +8243,7 @@ void tst_QNetworkReply::backgroundRequestInterruption() QNetworkSessionPrivate::setUsagePolicies(*session, original); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), error); + QCOMPARE(reply->networkError(), error); #endif } #endif @@ -8395,7 +8390,7 @@ void tst_QNetworkReply::putWithRateLimiting() rateLimitedUploadDevice.open(QIODevice::ReadOnly); RUN_REQUEST(runCustomRequest(request, reply,QByteArray("POST"), &rateLimitedUploadDevice)); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); QByteArray uploadedData = reply->readAll(); @@ -8443,7 +8438,7 @@ void tst_QNetworkReply::ioHttpSingleRedirect() // Reply url is set to the redirect url QCOMPARE(reply->url(), redirectUrl); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(validateRedirectedResponseHeaders(reply)); } @@ -8480,7 +8475,7 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects() QCOMPARE(redSpy.count(), request.maximumRedirectsAllowed()); QCOMPARE(spy.count(), 1); - QCOMPARE(reply->error(), QNetworkReply::TooManyRedirectsError); + QCOMPARE(reply->networkError(), QNetworkReply::TooManyRedirectsError); // Increase max redirects to allow successful completion request.setMaximumRedirectsAllowed(3); @@ -8492,7 +8487,7 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects() QCOMPARE(redSpy2.count(), 2); QCOMPARE(reply2->url(), server3Url); - QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(reply2->networkError(), QNetworkReply::NoError); QVERIFY(validateRedirectedResponseHeaders(reply2)); } @@ -8550,7 +8545,7 @@ void tst_QNetworkReply::ioHttpRedirectErrors() watchDog.start(5000); QCOMPARE(eventLoop.exec(), int(Failure)); - QCOMPARE(reply->error(), error); + QCOMPARE(reply->networkError(), error); } struct SameOriginRedirector : MiniHttpServer @@ -8708,7 +8703,7 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors() QCOMPARE(waitForFinish(reply), int(Failure)); QCOMPARE(spy.count(), 1); - QCOMPARE(reply->error(), expectedError); + QCOMPARE(reply->networkError(), expectedError); } void tst_QNetworkReply::ioHttpUserVerifiedRedirect_data() @@ -8851,7 +8846,7 @@ void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote() QCOMPARE(waitForFinish(reply), int(Success)); QCOMPARE(reply->url(), targetUrl); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), reference.size()); QCOMPARE(reply->readAll(), reference.readAll()); } @@ -8970,7 +8965,7 @@ void tst_QNetworkReply::ioHttpRedirectMultipartPost() multiPart->deleteLater(); QCOMPARE(reply->url(), url); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 OK @@ -9357,7 +9352,7 @@ void tst_QNetworkReply::getWithTimeout() QCOMPARE(waitForFinish(reply), int(Success)); QCOMPARE(spy.count(), 0); - QVERIFY(reply->error() == QNetworkReply::NoError); + QVERIFY(reply->networkError() == QNetworkReply::NoError); request.setTransferTimeout(1000); server.stopTransfer = true; @@ -9368,7 +9363,7 @@ void tst_QNetworkReply::getWithTimeout() QCOMPARE(waitForFinish(reply2), int(Failure)); QCOMPARE(spy2.count(), 1); - QVERIFY(reply2->error() == QNetworkReply::OperationCanceledError); + QVERIFY(reply2->networkError() == QNetworkReply::OperationCanceledError); request.setTransferTimeout(0); manager.setTransferTimeout(1000); @@ -9379,7 +9374,7 @@ void tst_QNetworkReply::getWithTimeout() QCOMPARE(waitForFinish(reply3), int(Failure)); QCOMPARE(spy3.count(), 1); - QVERIFY(reply3->error() == QNetworkReply::OperationCanceledError); + QVERIFY(reply3->networkError() == QNetworkReply::OperationCanceledError); manager.setTransferTimeout(0); } @@ -9397,7 +9392,7 @@ void tst_QNetworkReply::postWithTimeout() QCOMPARE(waitForFinish(reply), int(Success)); QCOMPARE(spy.count(), 0); - QVERIFY(reply->error() == QNetworkReply::NoError); + QVERIFY(reply->networkError() == QNetworkReply::NoError); request.setTransferTimeout(1000); server.stopTransfer = true; @@ -9408,7 +9403,7 @@ void tst_QNetworkReply::postWithTimeout() QCOMPARE(waitForFinish(reply2), int(Failure)); QCOMPARE(spy2.count(), 1); - QVERIFY(reply2->error() == QNetworkReply::OperationCanceledError); + QVERIFY(reply2->networkError() == QNetworkReply::OperationCanceledError); request.setTransferTimeout(0); manager.setTransferTimeout(1000); @@ -9419,7 +9414,7 @@ void tst_QNetworkReply::postWithTimeout() QCOMPARE(waitForFinish(reply3), int(Failure)); QCOMPARE(spy3.count(), 1); - QVERIFY(reply3->error() == QNetworkReply::OperationCanceledError); + QVERIFY(reply3->networkError() == QNetworkReply::OperationCanceledError); manager.setTransferTimeout(0); } diff --git a/tests/auto/network/access/spdy/tst_spdy.cpp b/tests/auto/network/access/spdy/tst_spdy.cpp index f4a59765583..671067c44f2 100644 --- a/tests/auto/network/access/spdy/tst_spdy.cpp +++ b/tests/auto/network/access/spdy/tst_spdy.cpp @@ -274,7 +274,7 @@ void tst_Spdy::download() QVERIFY(proxyAuthRequiredSpy.count() <= 1); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); QCOMPARE(reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -507,7 +507,7 @@ void tst_Spdy::upload() QVERIFY(uploadProgressSpy.count() > 0); QVERIFY(readyReadSpy.count() > 0); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); QCOMPARE(reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); @@ -590,7 +590,7 @@ void tst_Spdy::errors() QCOMPARE(finishedSpy.count(), 1); QCOMPARE(errorSpy.count(), 1); - QCOMPARE(reply->error(), static_cast(expectedReplyError)); + QCOMPARE(reply->networkError(), static_cast(expectedReplyError)); m_manager.setProxy(QNetworkProxy()); // reset m_manager.clearAccessCache(); // e.g. to get an SSL error we need a new connection @@ -665,7 +665,7 @@ void tst_Spdy::multipleRequests() QByteArray(QSslConfiguration::NextProtocolSpdy3_0)); #endif // QT_NO_OPENSSL - QCOMPARE(replies.at(a)->error(), QNetworkReply::NoError); + QCOMPARE(replies.at(a)->networkError(), QNetworkReply::NoError); QCOMPARE(replies.at(a)->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); QCOMPARE(replies.at(a)->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); QCOMPARE(replies.at(a)->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); diff --git a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp index afdcc825d80..5dce69bd8c8 100644 --- a/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp +++ b/tests/auto/xml/sax/qxmlinputsource/tst_qxmlinputsource.cpp @@ -149,7 +149,7 @@ public slots: void requestFinished(QNetworkReply *reply) { - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); reply->deleteLater(); } diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp index c182ef7ebf6..8f00155b223 100644 --- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -536,7 +536,7 @@ void tst_qnetworkreply::echoPerformance() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(reply->error() == QNetworkReply::NoError); + QVERIFY(reply->networkError() == QNetworkReply::NoError); delete reply; } } @@ -566,7 +566,7 @@ void tst_qnetworkreply::preConnectEncrypted() QPair normalResult = runGetRequest(&manager, request); QNetworkReply *normalReply = normalResult.first; QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(normalReply->error() == QNetworkReply::NoError); + QVERIFY(normalReply->networkError() == QNetworkReply::NoError); qint64 normalElapsed = normalResult.second; // clear all caches again @@ -590,7 +590,7 @@ void tst_qnetworkreply::preConnectEncrypted() QPair preConnectResult = runGetRequest(&manager, request); QNetworkReply *preConnectReply = normalResult.first; QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(preConnectReply->error() == QNetworkReply::NoError); + QVERIFY(preConnectReply->networkError() == QNetworkReply::NoError); bool spdyWasUsed = preConnectReply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(); QCOMPARE(spdyEnabled, spdyWasUsed); qint64 preConnectElapsed = preConnectResult.second; @@ -663,7 +663,7 @@ void tst_qnetworkreply::uploadPerformance() QTimer::singleShot(5000, &generator, SLOT(stop())); QTestEventLoop::instance().enterLoop(30); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(!QTestEventLoop::instance().timeout()); } @@ -689,7 +689,7 @@ void tst_qnetworkreply::httpUploadPerformance() reader.exit(); reader.wait(); QVERIFY(reply->isFinished()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(!QTestEventLoop::instance().timeout()); qDebug() << "tst_QNetworkReply::httpUploadPerformance" << elapsed << "msec, " @@ -750,7 +750,7 @@ void tst_qnetworkreply::httpDownloadPerformance() QTime time; time.start(); QTestEventLoop::instance().enterLoop(40); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(!QTestEventLoop::instance().timeout()); qint64 elapsed = time.elapsed(); @@ -832,7 +832,7 @@ void tst_qnetworkreply::httpDownloadPerformanceDownloadBuffer() QBENCHMARK_ONCE { QTestEventLoop::instance().enterLoop(40); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); QVERIFY(!QTestEventLoop::instance().timeout()); } @@ -867,7 +867,7 @@ public slots: } QNetworkReply *reply = qobject_cast(sender()); if (reply) { - QVERIFY(reply->error() == QNetworkReply::NoError); + QVERIFY(reply->networkError() == QNetworkReply::NoError); qDebug() << "time =" << timeOneRequest.elapsed() << "ms"; timeList.append(timeOneRequest.elapsed()); } @@ -922,7 +922,7 @@ void tst_qnetworkreply::runHttpsUploadRequest(const QByteArray &data, const QNet connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(15); QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->networkError(), QNetworkReply::NoError); reply->deleteLater(); } @@ -962,7 +962,7 @@ void tst_qnetworkreply::preConnect() QPair normalResult = runGetRequest(&manager, request); QNetworkReply *normalReply = normalResult.first; QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(normalReply->error() == QNetworkReply::NoError); + QVERIFY(normalReply->networkError() == QNetworkReply::NoError); qint64 normalElapsed = normalResult.second; // clear all caches again @@ -982,7 +982,7 @@ void tst_qnetworkreply::preConnect() QPair preConnectResult = runGetRequest(&manager, request); QNetworkReply *preConnectReply = normalResult.first; QVERIFY(!QTestEventLoop::instance().timeout()); - QVERIFY(preConnectReply->error() == QNetworkReply::NoError); + QVERIFY(preConnectReply->networkError() == QNetworkReply::NoError); qint64 preConnectElapsed = preConnectResult.second; qDebug() << request.url().toString() << "full request:" << normalElapsed << "ms, pre-connect request:" << preConnectElapsed << "ms, difference:" From fe97af0c9ad58f0f823f3b1942cd9ad383ba85d3 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 7 Jan 2020 15:15:09 +0100 Subject: [PATCH 09/20] rhi: Add manual test for RGBA16F and compute Uses the two compute shaders from Qt Quick 3D. Demonstrates and tests both RGBA16F textures and using them (and doing load/store with mip levels individually) in combination with compute. Task-number: QTBUG-81213 Change-Id: I3f0f250d5997a26c857b7c45517684c63b44e58e Reviewed-by: Johan Helsing --- .../buildshaders.sh | 3 + .../float16texture_with_compute.cpp | 312 ++++++++++++++++++ .../float16texture_with_compute.pro | 8 + .../float16texture_with_compute.qrc | 9 + .../rhi/float16texture_with_compute/load.comp | 19 ++ .../float16texture_with_compute/load.comp.qsb | Bin 0 -> 1596 bytes .../prefilter.comp | 50 +++ .../prefilter.comp.qsb | Bin 0 -> 3659 bytes tests/manual/rhi/rhi.pro | 1 + 9 files changed, 402 insertions(+) create mode 100755 tests/manual/rhi/float16texture_with_compute/buildshaders.sh create mode 100644 tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.cpp create mode 100644 tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.pro create mode 100644 tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.qrc create mode 100644 tests/manual/rhi/float16texture_with_compute/load.comp create mode 100644 tests/manual/rhi/float16texture_with_compute/load.comp.qsb create mode 100644 tests/manual/rhi/float16texture_with_compute/prefilter.comp create mode 100644 tests/manual/rhi/float16texture_with_compute/prefilter.comp.qsb diff --git a/tests/manual/rhi/float16texture_with_compute/buildshaders.sh b/tests/manual/rhi/float16texture_with_compute/buildshaders.sh new file mode 100755 index 00000000000..7d4d27741d2 --- /dev/null +++ b/tests/manual/rhi/float16texture_with_compute/buildshaders.sh @@ -0,0 +1,3 @@ +#!/bin/sh +qsb --glsl "430,310 es" --hlsl 50 --msl 12 load.comp -o load.comp.qsb +qsb --glsl "430,310 es" --hlsl 50 --msl 12 prefilter.comp -o prefilter.comp.qsb diff --git a/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.cpp b/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.cpp new file mode 100644 index 00000000000..9d74fe797b8 --- /dev/null +++ b/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.cpp @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// An advanced version of floattexture. Instead of RGBA32F, we use RGBA16F, and +// also generate the floating point data from rgba with compute. Then there's a +// compute pass using the BSDF prefiltering taken from Qt Quick 3D, which +// generates all the mip levels. + +// Why do we animate the scale of the quad rendered to the window? To have +// different mip levels used, to prove that all of them are generated +// correctly, without artifacts (which would occur if memory barriers were not +// correctly generated by QRhi). For full verification use RenderDoc or similar. + +#include "../shared/examplefw.h" +#include + +static float vertexData[] = +{ // Y up, CCW + -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 1.0f, 0.0f +}; + +static quint16 indexData[] = +{ + 0, 1, 2, 0, 2, 3 +}; + +static const int MAX_MIP_LEVELS = 20; + +struct { + QVector releasePool; + + QRhiBuffer *vbuf = nullptr; + QRhiBuffer *ibuf = nullptr; + QRhiBuffer *ubuf = nullptr; + QRhiTexture *texRgba = nullptr; + QRhiTexture *texFloat16 = nullptr; + QRhiSampler *sampler = nullptr; + QRhiShaderResourceBindings *srb = nullptr; + QRhiGraphicsPipeline *ps = nullptr; + + QRhiBuffer *computeUBuf_load = nullptr; + QRhiShaderResourceBindings *computeBindings_load = nullptr; + QRhiComputePipeline *computePipeline_load = nullptr; + QRhiBuffer *computeUBuf_prefilter = nullptr; + QRhiShaderResourceBindings *computeBindings_prefilter[MAX_MIP_LEVELS]; + QRhiComputePipeline *computePipeline_prefilter = nullptr; + + QRhiResourceUpdateBatch *initialUpdates = nullptr; + bool computeDone = false; + int mipCount; + int prefilterUBufElemSize; + quint32 prefilterNumWorkGroups[MAX_MIP_LEVELS][3]; + float scale = 2.5f; + int scale_dir = -1; +} d; + +void recordUploadThenFilterFloat16TextureWithCompute(QRhiCommandBuffer *cb) +{ + const int w = d.texRgba->pixelSize().width() / 16; + const int h = d.texRgba->pixelSize().height() / 16; + + cb->beginComputePass(); + + cb->setComputePipeline(d.computePipeline_load); + cb->setShaderResources(); + cb->dispatch(w, h, 1); + + cb->setComputePipeline(d.computePipeline_prefilter); + for (int level = 1; level < d.mipCount; ++level) { + const int i = level - 1; + const int mipW = d.prefilterNumWorkGroups[i][0]; + const int mipH = d.prefilterNumWorkGroups[i][1]; + QPair dynamicOffset = { 0, quint32(d.prefilterUBufElemSize * i) }; + cb->setShaderResources(d.computeBindings_prefilter[i], 1, &dynamicOffset); + cb->dispatch(mipW, mipH, 1); + } + + cb->endComputePass(); +} + +void Window::customInit() +{ + if (!m_r->isFeatureSupported(QRhi::Compute)) + qFatal("Compute is not supported"); + + if (!m_r->isTextureFormatSupported(QRhiTexture::RGBA16F)) + qFatal("RGBA16F texture format is not supported"); + + d.initialUpdates = m_r->nextResourceUpdateBatch(); + + // load rgba8 image data + + QImage image; + image.load(QLatin1String(":/qt256.png")); + image = image.convertToFormat(QImage::Format_RGBA8888); + Q_ASSERT(!image.isNull()); + d.texRgba = m_r->newTexture(QRhiTexture::RGBA8, image.size(), 1, QRhiTexture::UsedWithLoadStore); + d.texRgba->build(); + d.releasePool << d.texRgba; + + d.initialUpdates->uploadTexture(d.texRgba, image); + + d.mipCount = m_r->mipLevelsForSize(image.size()); + Q_ASSERT(d.mipCount <= MAX_MIP_LEVELS); + + d.texFloat16 = m_r->newTexture(QRhiTexture::RGBA16F, image.size(), 1, QRhiTexture::UsedWithLoadStore | QRhiTexture::MipMapped); + d.releasePool << d.texFloat16; + d.texFloat16->build(); + + // compute + + d.computeUBuf_load = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 12); + d.computeUBuf_load->build(); + d.releasePool << d.computeUBuf_load; + + quint32 numWorkGroups[3] = { quint32(image.width()), quint32(image.height()), 0 }; + d.initialUpdates->updateDynamicBuffer(d.computeUBuf_load, 0, 12, numWorkGroups); + + d.computeBindings_load = m_r->newShaderResourceBindings(); + d.computeBindings_load->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::ComputeStage, d.computeUBuf_load), + QRhiShaderResourceBinding::imageLoad(1, QRhiShaderResourceBinding::ComputeStage, d.texRgba, 0), + QRhiShaderResourceBinding::imageStore(2, QRhiShaderResourceBinding::ComputeStage, d.texFloat16, 0) + }); + d.computeBindings_load->build(); + d.releasePool << d.computeBindings_load; + + d.computePipeline_load = m_r->newComputePipeline(); + d.computePipeline_load->setShaderResourceBindings(d.computeBindings_load); + d.computePipeline_load->setShaderStage({ QRhiShaderStage::Compute, getShader(QLatin1String(":/load.comp.qsb")) }); + d.computePipeline_load->build(); + d.releasePool << d.computePipeline_load; + + d.prefilterUBufElemSize = m_r->ubufAligned(12); + d.computeUBuf_prefilter = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, d.prefilterUBufElemSize * d.mipCount); + d.computeUBuf_prefilter->build(); + d.releasePool << d.computeUBuf_prefilter; + + int mipW = image.width() >> 1; + int mipH = image.height() >> 1; + for (int level = 1; level < d.mipCount; ++level) { + const int i = level - 1; + d.prefilterNumWorkGroups[i][0] = quint32(mipW); + d.prefilterNumWorkGroups[i][1] = quint32(mipH); + d.prefilterNumWorkGroups[i][2] = 0; + d.initialUpdates->updateDynamicBuffer(d.computeUBuf_prefilter, d.prefilterUBufElemSize * i, 12, d.prefilterNumWorkGroups[i]); + mipW = mipW > 2 ? mipW >> 1 : 1; + mipH = mipH > 2 ? mipH >> 1 : 1; + + d.computeBindings_prefilter[i] = m_r->newShaderResourceBindings(); + d.computeBindings_prefilter[i]->setBindings({ + QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, QRhiShaderResourceBinding::ComputeStage, d.computeUBuf_prefilter, 12), + QRhiShaderResourceBinding::imageLoad(1, QRhiShaderResourceBinding::ComputeStage, d.texFloat16, level - 1), + QRhiShaderResourceBinding::imageStore(2, QRhiShaderResourceBinding::ComputeStage, d.texFloat16, level) + }); + d.computeBindings_prefilter[i]->build(); + d.releasePool << d.computeBindings_prefilter[i]; + } + + d.computePipeline_prefilter = m_r->newComputePipeline(); + d.computePipeline_prefilter->setShaderResourceBindings(d.computeBindings_prefilter[0]); // just need a layout compatible one + d.computePipeline_prefilter->setShaderStage({ QRhiShaderStage::Compute, getShader(QLatin1String(":/prefilter.comp.qsb")) }); + d.computePipeline_prefilter->build(); + d.releasePool << d.computePipeline_prefilter; + + // graphics + + d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)); + d.vbuf->build(); + d.releasePool << d.vbuf; + + d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indexData)); + d.ibuf->build(); + d.releasePool << d.ibuf; + + d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68); + d.ubuf->build(); + d.releasePool << d.ubuf; + + // enable mipmaps + d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::Linear, + QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge); + d.releasePool << d.sampler; + d.sampler->build(); + + d.srb = m_r->newShaderResourceBindings(); + d.releasePool << d.srb; + d.srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf), + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.texFloat16, d.sampler) + }); + d.srb->build(); + + d.ps = m_r->newGraphicsPipeline(); + d.releasePool << d.ps; + d.ps->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 4 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) } + }); + d.ps->setVertexInputLayout(inputLayout); + d.ps->setShaderResourceBindings(d.srb); + d.ps->setRenderPassDescriptor(m_rp); + d.ps->build(); + + d.initialUpdates->uploadStaticBuffer(d.vbuf, vertexData); + d.initialUpdates->uploadStaticBuffer(d.ibuf, indexData); + + qint32 flip = 0; + d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip); +} + +void Window::customRelease() +{ + qDeleteAll(d.releasePool); + d.releasePool.clear(); +} + +void Window::customRender() +{ + QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer(); + QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch(); + if (d.initialUpdates) { + u->merge(d.initialUpdates); + d.initialUpdates->release(); + d.initialUpdates = nullptr; + } + + QMatrix4x4 mvp = m_proj; + mvp.scale(d.scale); + d.scale += d.scale_dir * 0.01f; + if (qFuzzyIsNull(d.scale) || d.scale >= 2.5f) + d.scale_dir *= -1; + u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData()); + + cb->resourceUpdate(u); + + // If not yet done, then do a compute pass that uploads level 0, doing an + // rgba8 -> float16 conversion. Follow that with another compute pass to do + // the filtering and generate all the mip levels. + if (!d.computeDone) { + recordUploadThenFilterFloat16TextureWithCompute(cb); + d.computeDone = true; + } + + const QSize outputSizeInPixels = m_sc->currentPixelSize(); + cb->beginPass(m_sc->currentFrameRenderTarget(), m_clearColor, { 1.0f, 0 }); + cb->setGraphicsPipeline(d.ps); + cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) }); + cb->setShaderResources(); + const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0); + cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16); + cb->drawIndexed(6); + cb->endPass(); +} diff --git a/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.pro b/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.pro new file mode 100644 index 00000000000..7708e845d0e --- /dev/null +++ b/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.pro @@ -0,0 +1,8 @@ +TEMPLATE = app + +QT += gui-private + +SOURCES = \ + float16texture_with_compute.cpp + +RESOURCES = float16texture_with_compute.qrc diff --git a/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.qrc b/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.qrc new file mode 100644 index 00000000000..ce3c52aac50 --- /dev/null +++ b/tests/manual/rhi/float16texture_with_compute/float16texture_with_compute.qrc @@ -0,0 +1,9 @@ + + + load.comp.qsb + prefilter.comp.qsb + ../shared/texture.vert.qsb + ../shared/texture.frag.qsb + ../shared/qt256.png + + diff --git a/tests/manual/rhi/float16texture_with_compute/load.comp b/tests/manual/rhi/float16texture_with_compute/load.comp new file mode 100644 index 00000000000..eb7bc1ece41 --- /dev/null +++ b/tests/manual/rhi/float16texture_with_compute/load.comp @@ -0,0 +1,19 @@ +#version 440 + +layout(local_size_x = 16, local_size_y = 16) in; +layout(rgba8, binding = 1) readonly uniform image2D inputImage; +layout(rgba16f, binding = 2) writeonly uniform image2D outputImage; + +// There is no equivalent of gl_NumWorkGroups in HLSL. So instead pass the +// values in in a uniform buffer. +layout(std140, binding = 0) uniform numWorkGroupsBuf { + uvec3 numWorkGroups; +}; + +void main() +{ + if (gl_GlobalInvocationID.x >= numWorkGroups.x || gl_GlobalInvocationID.y >= numWorkGroups.y) + return; + vec4 value = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.xy)); + imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), value); +} diff --git a/tests/manual/rhi/float16texture_with_compute/load.comp.qsb b/tests/manual/rhi/float16texture_with_compute/load.comp.qsb new file mode 100644 index 0000000000000000000000000000000000000000..bfdd7f54468a6c80581a542767636f0454118a75 GIT binary patch literal 1596 zcmV-C2E+LP02FU{ob6ayZyQwo8&*UmJvShIw{r#|z_Kj6F{9%~*ziZacnZI@|VR@#)-L#tkDsFxz6wg;TD-;oHM%|8ROWDdsPdl5|ZlQL0MXK-naWq-qjXk>sI(Hz%{qV_G zi8*FBkn$cF=ydWW;gc_<19yPm@>?zGC4_WON?#&A5LVUd zQy+y<5L*!%w~X>lRVR5hS?`+RQ`v=Cs2`hU$5@@HFS0C97(2mc1=ri(A3EGy{!$&p9O!64cAI$LOeFimwHn&4&@`qG?n z{t41Y`IE#$`c~AM>~d zPh96n_YKm!ChKyX>BP^l!7H26xlS~l;=L~Y_G|Sf+04=!hvN*b(MRN5V0$5DqX4JbMfig`tF?Wq(y$w|C(F=_A@LVT9r-*(V z{G5|LQT;hPBzK;8Pr=rV%w6ds{cDgx+6AKj0MT5cxPAuS1*UL$iDJB%is=f)bUEeg z6{06GT}{Q5mV1?WNlct{k^U3-N&MmSd(c3cd5UqGGOp3v?9U z7s$UZd!w*Xrx_|zF7Jac#K{e!70EVY;$y;0nfMKe1o2rRdq`i0cr>D+?W*jz!bsxl z=8&&jM7uf0*IUG|(~PVVHY`}L5Py|&yrqzvqx~5cnWwCGWxriGfCCCPXTDS|Rd8NQpr0yu`F_Ls{d$oLC9a(&Mf6srE=WxjrZjf2aAAuSjuOoUK z&OKmLWOV4Fy8@Rdzs?iQK$uP6bGn>PY~DW(YNPrUrC(lY^(}lD*pV18kvcsfhy&kl zaxA2#Q#uXbceqihg2Ax|Uh$Bx*D;0SKwibeT1vfIRV%y2wRte6%aw9~7YIzW-yLti zt1KSLyKq7=)+G2!%b|Z@47(3R6bD{f5PG=8<>3oPWU21@W>f3eyTEObsb~{w($#g! z7=^dtD^F;tN6TL(af2oe0dBWlfEesi9 u(zEfsuct+e6R?HqDG*>(gI{{XC!qX`S$_Hb3Rgm;cO32vzW)aD+{>ZXhA7Se literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/float16texture_with_compute/prefilter.comp b/tests/manual/rhi/float16texture_with_compute/prefilter.comp new file mode 100644 index 00000000000..ba09ecb1296 --- /dev/null +++ b/tests/manual/rhi/float16texture_with_compute/prefilter.comp @@ -0,0 +1,50 @@ +#version 440 + +layout(local_size_x = 16, local_size_y = 16) in; +layout(rgba16f, binding = 1) readonly uniform image2D inputImage; +layout(rgba16f, binding = 2) writeonly uniform image2D outputImage; + +// There is no equivalent of gl_NumWorkGroups in HLSL. So instead pass the +// values in in a uniform buffer. +layout(std140, binding = 0) uniform numWorkGroupsBuf { + uvec3 numWorkGroups; +}; + +int wrapMod( in int a, in int base ) +{ + return ( a >= 0 ) ? a % base : -(a % base) + base; +} + +void getWrappedCoords( inout int sX, inout int sY, in int width, in int height ) +{ + if (sY < 0) { sX -= width >> 1; sY = -sY; } + if (sY >= height) { sX += width >> 1; sY = height - sY; } + sX = wrapMod( sX, width ); +} + +void main() +{ + int prevWidth = int(numWorkGroups.x) << 1; + int prevHeight = int(numWorkGroups.y) << 1; + if (gl_GlobalInvocationID.x >= numWorkGroups.x || gl_GlobalInvocationID.y >= numWorkGroups.y) + return; + vec4 accumVal = vec4(0.0); + for (int sy = -2; sy <= 2; ++sy) { + for (int sx = -2; sx <= 2; ++sx) { + int sampleX = sx + (int(gl_GlobalInvocationID.x) << 1); + int sampleY = sy + (int(gl_GlobalInvocationID.y) << 1); + getWrappedCoords(sampleX, sampleY, prevWidth, prevHeight); + if ((sampleY * prevWidth + sampleX) < 0 ) + sampleY = prevHeight + sampleY; + ivec2 pos = ivec2(sampleX, sampleY); + vec4 value = imageLoad(inputImage, pos); + float filterPdf = 1.0 / ( 1.0 + float(sx*sx + sy*sy)*2.0 ); + filterPdf /= 4.71238898; + accumVal[0] += filterPdf * value.r; + accumVal[1] += filterPdf * value.g; + accumVal[2] += filterPdf * value.b; + accumVal[3] += filterPdf * value.a; + } + } + imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), accumVal); +} diff --git a/tests/manual/rhi/float16texture_with_compute/prefilter.comp.qsb b/tests/manual/rhi/float16texture_with_compute/prefilter.comp.qsb new file mode 100644 index 0000000000000000000000000000000000000000..77618a12b970c24341efb3879b04bfbd4abb7739 GIT binary patch literal 3659 zcmV-R4z%$A06vX)ob6i)bX-*#zDYM4pp<rsMU$4~(x0f-;lY(5fkm>gF1IzMWA?F`eNcCl$Os|vo zH(x6aWXk9%FO`y3e2RAuY0D`LI*HcA2zG-XTIF^*^sH;3E5Qi@;j9E@Kyaop>Qz@SWuP^;W0ijI_)tG+63SAu8?LGTdz1 z%{o>*ZU;f$?JWdOJRXVI>5X>Lk1Jv{T1OhJjd?qFoR^FQ{dvbuTG9~`5013#25U63 z*Y=$#qG9oPtgS-;y~dyiJvV9fIYBoCo^z5%dtN^2>+ofa{@POH3ht?tiH&YD=&wZRcig`I zpp+!ai{E1{7@Ze?t<^}ON#O7@_r078?B?GiYd{6l)8k^wsZFpAxegt&m=t z#+;qEGsNPr?I_2^TL>#vDgqhlEY*zUXwZyNITr&?KI^0{ndOY_W}73W+72&@BQ09V zRNB3TRLaRmnxpI2Q$C#`np-E9T#!n8cF<*wY-Pj>YGvLA%T6R5-=9B!W8Mv%F3Z@) z4A~YbTUuz#(q6BfUXdN79XD{j?20AKD`z#H^L&?aR6X&&yh{tuto>Zx8SIwX?qoPZ z(KMCC*fbQi7A&w@I?6 zEwK(BEaL@K!4GCg^uE-@`%I)Db&$GfB{?hQrUNIxDw!hDmZoNFmKEU}6_KP zkLobb>6)8_E>9k`|P>Rtu3+H<@|a9(oVyt%ZT_)6%AE< z6@g+Efnqg*;VJ^d)dV(H5!h%5Y%=x~<2-1RM?^%cQs+S|BL7rb*_2Xs#BuW}k2V_A z(iI!&KqtR|UPSc+Rl2!q&09j9grg2hYd&p|eXdVoMtYm0Wz8h*%<(dQVy2FCK=ss- z1aFqyVV=}|GEU1S>a=VtJ6a731>Siov75)K$saQs&z&5r9lAMQy=uitYvM=eJ>QS7 zU>C{)s(d8Rw^px-FL9~a4ifz*%hQ=Pa%5%~%VX+W`SzylR4X^1ZkAH34vDqwd**6OHAngP+^zKC-PT-0g%bty1u9r@OHp#d5;w{LR39 z8QEHf?>WoJ7Uyt!iKgIb2HY)cTZlseZwv8n1Ah&4Gkg$e+e5tD!CMPnh7ShqCD>tj zU*f2hyyN8R;qm^&Gm-8VY*_@;VwBfJ$;&gY#u`73{_Y9+NujGA`u2x^`w`ax2EGw? z*zPf~%bx=YUP^byv2TYVpG)D>@=|<4bO2rfTs?Fh3ti0rZqSY~=qDO6uEBUI^fBCR z(AQ$jatDwv8{jMZIY4)Y$AdSG*au*XX?mk;APVC>;LJze{WkU2^2p$f>TSD-KA^4IId}#>2ECg>gV4lYtLjK)kz&t0n171uy;d)*v zRL%3+;#%)S?v4ZP4Ajr@z}+WLGa*g@j@MonWo`*@TJK4Q-V+VIt3lIxPXxSC8-=R<+Ym<)xFPt% zF!urhWPR8jHte1b+Uc;niSB0_cFzL+EW_^ELai}vcQbI>?q*qQLh54KGYr{tAgkx` z+zPdI9`L$e-w&Lw*YkmEly(*F0_Z*;F>V1)+x-A?rR`o+p?*FHytexx;I!R~fivxX z7`iWp-3x)!c0VH2{=>9O0BhPuh1!dlb}3*@`19ay7RvJ z3A(t4Wm~M1Ww#o#mxHErbh$yh0x~*|D-7Bv;j4zPgn#EE51#_hl?KnJ5xdUSXTZn! zTTwfo1)kR^ucxa~dt66MyNa%>QAbx9y01YFG<+@m)3&Yy&$UK8jN_Wt`mQ$QKM!9u zd?WO&B7J;De*ru1$BUxobpHT-+Z;CUK&?cXzyd)kou4eXe5&jPRg`z>(K7;?`Ua_rx8;Nv}k z&%Bp$*X!wbLajl)c76|>?vsXrGtbdYfD3>NhQ2=twLZ1JKLV%q<$yE$fk2GxG0zLt ze|O?L)}Mts!%m_>kAy%XPi{)${A2!0-P#&N$gkFGiJad+tA z?~ZfHNA6=M8{<0o$#13U{+PetPBP-&4>H@Z=N|~1-t!NE4c_ya#@}%dgWiJ;J@0@X z4Ic{o7s1zeg6B}=^B~|jpNBx-VTSy>Li((bzG>iL{F&gH4!o9`0U14~hl6K^;ltq} z9}Y3(k3ha&Av}+D?)fa=2YK1k$oCXuyq7VaYK-@WoqdftSt!cC!z>QXQ3U$*xf}&f z&r!WGM@*Y3gv7C(nTDPQ_;N4u(F9zh!7~eSYynR*a81bB6yP*}3w+aa5Cg6YzrDqf zU+qu5A=?UB4Ywgbx)x`Hrwwt=HR5F29GO?8caEWFUMS9X;LJGZBTii#9l*64adsH| z3*eiEJK?*|Qx|wTjo7;oyY_LeA-@RrnRg*zO*;zyGi@>8cA_xtXrb2qLez=&mGOFi z5F@_>6HudnnxN0*=`#kMyzhEhtF5)UE^QaRLJ*Pf_s03v);K=`SJoOH{};n?rVrL4K<)ql literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/rhi.pro b/tests/manual/rhi/rhi.pro index 4768ee1c6da..5208e5dea57 100644 --- a/tests/manual/rhi/rhi.pro +++ b/tests/manual/rhi/rhi.pro @@ -14,6 +14,7 @@ SUBDIRS += \ triquadcube \ offscreen \ floattexture \ + float16texture_with_compute \ mrt \ shadowmap \ computebuffer \ From 1f267b7e6def96f8041f29a9b4c7da753c736458 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 9 Jan 2020 12:38:27 +0100 Subject: [PATCH 10/20] rhi: Add render-to-cubemap manual test What's more, demonstrate two types of rendering to a cubemap: one by one to each face, and by attaching all faces as color attachments in one go. Both are used by Qt Quick 3D in connection with shadows, so this proves that the same is possible to implement with QRhi. Task-number: QTBUG-81261 Change-Id: I5c7077224d7cae0dd6ea02ac30a9e6f9f1f0c229 Reviewed-by: Eirik Aavitsland --- .../manual/rhi/cubemap_render/buildshader.bat | 6 + .../rhi/cubemap_render/cubemap_mrt.frag | 28 ++ .../rhi/cubemap_render/cubemap_mrt.frag.qsb | Bin 0 -> 1688 bytes .../rhi/cubemap_render/cubemap_mrt.vert | 20 + .../rhi/cubemap_render/cubemap_mrt.vert.qsb | Bin 0 -> 1223 bytes .../rhi/cubemap_render/cubemap_oneface.frag | 13 + .../cubemap_render/cubemap_oneface.frag.qsb | Bin 0 -> 993 bytes .../rhi/cubemap_render/cubemap_oneface.vert | 15 + .../cubemap_render/cubemap_oneface.vert.qsb | Bin 0 -> 1073 bytes .../rhi/cubemap_render/cubemap_render.cpp | 466 ++++++++++++++++++ .../rhi/cubemap_render/cubemap_render.pro | 8 + .../rhi/cubemap_render/cubemap_render.qrc | 10 + .../rhi/cubemap_render/cubemap_sample.frag | 10 + .../cubemap_render/cubemap_sample.frag.qsb | Bin 0 -> 1028 bytes .../rhi/cubemap_render/cubemap_sample.vert | 16 + .../cubemap_render/cubemap_sample.vert.qsb | Bin 0 -> 1145 bytes tests/manual/rhi/rhi.pro | 1 + tests/manual/rhi/shared/examplefw.h | 3 + 18 files changed, 596 insertions(+) create mode 100755 tests/manual/rhi/cubemap_render/buildshader.bat create mode 100644 tests/manual/rhi/cubemap_render/cubemap_mrt.frag create mode 100644 tests/manual/rhi/cubemap_render/cubemap_mrt.frag.qsb create mode 100644 tests/manual/rhi/cubemap_render/cubemap_mrt.vert create mode 100644 tests/manual/rhi/cubemap_render/cubemap_mrt.vert.qsb create mode 100644 tests/manual/rhi/cubemap_render/cubemap_oneface.frag create mode 100644 tests/manual/rhi/cubemap_render/cubemap_oneface.frag.qsb create mode 100644 tests/manual/rhi/cubemap_render/cubemap_oneface.vert create mode 100644 tests/manual/rhi/cubemap_render/cubemap_oneface.vert.qsb create mode 100644 tests/manual/rhi/cubemap_render/cubemap_render.cpp create mode 100644 tests/manual/rhi/cubemap_render/cubemap_render.pro create mode 100644 tests/manual/rhi/cubemap_render/cubemap_render.qrc create mode 100644 tests/manual/rhi/cubemap_render/cubemap_sample.frag create mode 100644 tests/manual/rhi/cubemap_render/cubemap_sample.frag.qsb create mode 100644 tests/manual/rhi/cubemap_render/cubemap_sample.vert create mode 100644 tests/manual/rhi/cubemap_render/cubemap_sample.vert.qsb diff --git a/tests/manual/rhi/cubemap_render/buildshader.bat b/tests/manual/rhi/cubemap_render/buildshader.bat new file mode 100755 index 00000000000..3886c138d8a --- /dev/null +++ b/tests/manual/rhi/cubemap_render/buildshader.bat @@ -0,0 +1,6 @@ +qsb --glsl "300 es,120" --hlsl 50 --msl 12 cubemap_oneface.vert -o cubemap_oneface.vert.qsb +qsb --glsl "300 es,120" --hlsl 50 --msl 12 cubemap_oneface.frag -o cubemap_oneface.frag.qsb +qsb --glsl "300 es,120" --hlsl 50 --msl 12 cubemap_mrt.vert -o cubemap_mrt.vert.qsb +qsb --glsl "300 es,120" --hlsl 50 --msl 12 cubemap_mrt.frag -o cubemap_mrt.frag.qsb +qsb --glsl "300 es,120" --hlsl 50 --msl 12 cubemap_sample.vert -o cubemap_sample.vert.qsb +qsb --glsl "300 es,120" --hlsl 50 --msl 12 cubemap_sample.frag -o cubemap_sample.frag.qsb diff --git a/tests/manual/rhi/cubemap_render/cubemap_mrt.frag b/tests/manual/rhi/cubemap_render/cubemap_mrt.frag new file mode 100644 index 00000000000..06a08f6cd63 --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_mrt.frag @@ -0,0 +1,28 @@ +#version 440 + +layout(location = 0) out vec4 c0; +layout(location = 1) out vec4 c1; +layout(location = 2) out vec4 c2; +layout(location = 3) out vec4 c3; +layout(location = 4) out vec4 c4; +layout(location = 5) out vec4 c5; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + vec3 color0; + vec3 color1; + vec3 color2; + vec3 color3; + vec3 color4; + vec3 color5; +} ubuf; + +void main() +{ + c0 = vec4(ubuf.color0, 1.0); + c1 = vec4(ubuf.color1, 1.0); + c2 = vec4(ubuf.color2, 1.0); + c3 = vec4(ubuf.color3, 1.0); + c4 = vec4(ubuf.color4, 1.0); + c5 = vec4(ubuf.color5, 1.0); +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_mrt.frag.qsb b/tests/manual/rhi/cubemap_render/cubemap_mrt.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..7a0be83a813241d13aa227ea7ddc34171bee73a8 GIT binary patch literal 1688 zcmV;J250#I02VHIoXuEUZyQAv9^Vq`gkC7LO@Xp$ptalL?lo=VCT#&xkPrld`chS{ zvtB#f`X=u>v{aRfkl?jHfVUQY1AlpajiaAl?js(Dqao`I+k;@wH#_l@anLykd^aTv zL|S=dkw`m_ED`DCk!2#?JhDQhmy(0&Fzk*dgO5P-DEi^I-d;HDgu@;S_YnCK^#0zo z+ZzOfyUN_bW}OJ~apsm70Hp3KF6sKC{%B&7 z3V4()CpH{aWl7b}VJcgy9vr4}q-uPa%9X0;hp9ZNdZDZQbmqT2jN-}Ek1=tbDP#^x zqr$|e!;;V9t5R`ok+A|>WUsN?gq~nUKp0zM3;h3`FLu9ZL~*C#dM5HmdG#^Q9RpQa z)FK9Xzy@1BbGw~JRun*r9_sejPQ&<4i zGI@lxhIWOw(T7-AmS9DRSt(YMn4Mx}i8(1&k(ire3lj5$-=ol`ymF5?U*8hon*W$#0osWvFt|H{wldA0g}vw5!CGDSnCKOMKiTe6FZj znseb8ualQ$8Ux!$3406L$H*V%;4-z3Qyb$?kamf99RE$8!RI%n=N0lKqF8hC%FxAI7!c-sc z5vKYuDE=Jr(#HyM(#IP4IIsA4pK#g#2ZX6UE)b^rxJa1lqek%;h?hQAiIYAqlaEV^ zk1K@B{y!v4_0b?q^>LLj)rU#(4dSJbI&sp6Lq2T9hfBEZ-y=-*u}+xk;~HVAkLwh_ zPQ3JC5hr~#$;YPR;|Aff|1H8)AKQefK5i1G`nW~$+r&#B8^rw$JzVF#uri&ExUJ-) zAA9?AEgbs&X(upl41&1bZ^1F$5BIjKDISG`&Q<)=*x#;JrxCnW8Td94joW@;@Tg|B zDqa^1IMJ$4s|I|!{Smx2J$4N^X`3nH7~-VOLRJ>CvyhX8+$`iZtItwXICrxJFSaw* z4Bs^F-Q)6_S-*e3Im1~AXJt4$;p`0OB%G7s+=O#8oR@GO=g@w4(uNn-p)vt+SMx{1 zC~gmVx-S^`8UfMpw;PD5)M=t=99~<-(`RB(XfJq=`mQx-KO9Zc;>KZHP~i{&+u@OTv#$Aac&bUR68Y7H?mVHT3B7qjTNAF& z6FQpk+B~7F39ru+dYW*fF6tKc9ehvo(|y*|5i5h(8N|sTZU*tvO}@MH`8Ri4A5TV6 z)cT5lht2HvO=I_N>)ZCE7sRH%+ZE2zce}#b`fgV^N8jxV=jyv%;pky?FbX>cZuu5g zXiXNKzE4}qKJC)V=$o{qY|=zy=V|O&jgzNwW;Je}#+}u8c^WU#z)s9AmoYPKB@v>} zoB$|>UeFRhSO}4dh$ozH<}sKr-^yb!OTL}QU~YUTkHL)iZXSbqz#>&1MYE=#Rh7dT zPU?bu55fo3leL3j5{09o;h3foMAh*m@IwylhrRu=NO3a*hr>AUM8=;n($g5f@XwsZ zDPZY>ZO+U-hX;n0-zDm;)Iy>->De-*NbQWfhjHu<{hPs<87E zj;e6-6t1dp^Aw({@Z_e=?pGAdJ5_n{X@Z&al-Hmpm^n##DQbe5Gn7}PCYU)rd0}dT zTm|34N<6^` iPL9}_Cw6nh?mV%VBR*t-wXX&83B=ex@c9>aDZKGiE?p}C literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/cubemap_render/cubemap_mrt.vert b/tests/manual/rhi/cubemap_render/cubemap_mrt.vert new file mode 100644 index 00000000000..6d82feccc80 --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_mrt.vert @@ -0,0 +1,20 @@ +#version 440 + +layout(location = 0) in vec4 position; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + vec3 color0; + vec3 color1; + vec3 color2; + vec3 color3; + vec3 color4; + vec3 color5; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + gl_Position = ubuf.mvp * position; +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_mrt.vert.qsb b/tests/manual/rhi/cubemap_render/cubemap_mrt.vert.qsb new file mode 100644 index 0000000000000000000000000000000000000000..9358ac27920e529999b18e5bf1cafe96e9110037 GIT binary patch literal 1223 zcmV;&1UUNu01c#goXu8SZyQAvo_Osz*|fP7LQ0X)&>&<(WPB|pAyJ{Av{FT)8bwG| z}mMQX(ZujLuu3j79sT3-;HGjql}UdMSu!pVAlzWL5|&YoGun8Czn z?$_6S*B>Qu^z!w|FtEC@8~DujyPk703L+OpJAO8D>{G{Ty2u!|-5;HwK-Wurw;zPw zSAaf^Uj8}gxxVfC1LpP+`4((gy`(?z9Ixku(a(Pjy>1-3XKnbhomJt)@=iznpx=+2 znAs5+zJ5o#18VbkLFrq;FbJ!}f_0=_83)zSSvAEvyo^;>tjCwJ8j3Z#jMY@E7niYG ziuEeXveL|ddlJQAV#QcEJAukUjSFz);kv@cpPaGj`qnV99sY&q#NA;hitVA>+cQ%< zay|P~{HmPnnPw8fu5gSd8g(s)3#}c~lhp((@1LG*h^xk zR4psrQzwj_v(&HrRZ_ONi;7X)9XKEzA8$d>K8U`k-$xwx3kdMtcS2#dOzu;Qc)-uG_EMh%Fyfus1 z$Pho9MQmn>w`UPs8RF+<*%Q!EFc7T^nr|nwlx~)4!uH|)hew^eVGu=~`#51|bmKPv z?wjxL9vnRUx;oLsy8b~DPZ`i#XPdW=w9rI52d>Srr#sjtCAIUD4d*4pk_u#N+yZ6M zVblIaCzq!3;_9J*-^$G>^`Wh1T3U-v0vEWH+JO)xNk=lz&&2*{56z^Jb9{L6=oimF z_}`LuaU3pgLR1l&YgDV;i7ptDcrv8}5@-0tcuav>7N}=|Miyvh0UC;Q(uyYks0n`T zv?TctjofAtOI2hG>^(x)U^Zj%me{}fisK9AmX|`~1vt@b>!?hLAWOUjqAL#HM z9O>|fQ~s|xd?UzDa0+010q&TA6CR0E4Dorw8Ld$sz&C_lscV2=#_(NZ9;~hq4yl7& z5HiLlcaM#+oWg1;W+<$lVtIu%Qmmk`W{S-#tR?eX1DRfcKrVDnzEzrt|bwk9H6Fp-H`y8$f;1|hXUg*g>6~%g;@)}{devN)#C3&6VDH4C3 z$>(H_*54)nxPA-joul{|;co!JJ^2#8uZbE;f0)-U<@7e;yHvjo^6?Ak6h-cmvq5&y l=MAbI+Svn7H;DH)M0Q)AG5So+yx6Nlh_Qd*^DpoFIluA|V;=wj literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/cubemap_render/cubemap_oneface.frag b/tests/manual/rhi/cubemap_render/cubemap_oneface.frag new file mode 100644 index 00000000000..8bafe689bea --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_oneface.frag @@ -0,0 +1,13 @@ +#version 440 + +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + vec3 color; +} ubuf; + +void main() +{ + fragColor = vec4(ubuf.color, 1.0); +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_oneface.frag.qsb b/tests/manual/rhi/cubemap_render/cubemap_oneface.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..a6187939a097c3aea72d82432edbb55cfa323238 GIT binary patch literal 993 zcmV<710MVU00{4RoUK(`Z`@Q6KG{psI4Mmjq~!%28mZbWs$#ld5CzS(?s}*8!H`TZg@A1(#$WOO_hJ7ykT4> zI!LqlGf;h+zxXwr=)~7aDD(u8uffclltCD)c%riWhhL)DEi!#PhKH{<$gdY4O@lND za#aXF2NqZEm;j(U{FzjghhbR>mQicHVzKSjrh8BFA}hTDBl{(UhK#zL>AI+{rM)ek zcv0yq`EjfYH*)gAkMv~Ms_|UM{`>eC9PV0HnL}C<$>dYlQ>jlUbqP{ zxh64lu!d)#jCr49)OL99$mb`9BuIlg@D6k7p`!tjxFK&2?7mUXR8eLL+5jud!Wxrb zcxl0Xt5N9RJVOF`$=hHV>bw9>6MM!eOTTqu_X$L;N{3M$s2>_^bp!zBM+U(;-^5VGO#^R?c`J1=w|0A14j$!0{0W?2% z3wPf>cwM4+`8ChhU+vb`3i4kO=fpdVUW8+b8Lf$B`n|U|-W$Ng8w@|dGb`SpuYt+> z0_b#jV$Nc$!o2}Hh=Fr>YtupheF>*)XHK^Zf2d!ToUk@cU!2G2eKv`qU?6u%#@Jq^ z-vLfS@BkP0Kt`YMvfY;rA6=5WmAqBy)YuB~udyZ8yFCD3Y- z+@^}*`zE|C!>@$cUS;eG$QG}4*nW-e+mx@#)1uxPf9E;w zI{Q0M{WI9xAYWiEnB#SpH&{mdi>$lG>lo`T%I^D5K7{(Tn2TTze*=Ow{uG{Q`zFUj zpF7O=65|g+XPI~yOf;}f#+Dk`WyUb(1E|6Z)x_9u@;Y+c1tzP!_78aY$PA_CVSVKT PUrjCXFI@it`X}_3+4lPk literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/cubemap_render/cubemap_oneface.vert b/tests/manual/rhi/cubemap_render/cubemap_oneface.vert new file mode 100644 index 00000000000..2db9076a74d --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_oneface.vert @@ -0,0 +1,15 @@ +#version 440 + +layout(location = 0) in vec4 position; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + vec3 color; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + gl_Position = ubuf.mvp * position; +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_oneface.vert.qsb b/tests/manual/rhi/cubemap_render/cubemap_oneface.vert.qsb new file mode 100644 index 0000000000000000000000000000000000000000..58772179e5c785ce6ec51e8b333d6548ddfac450 GIT binary patch literal 1073 zcmV-11kU>a017X7oV8ZnZroH5KKqv~PMe>WG^I$@fk@RZM2p*Q5z3ONP*7SaYN~7% zAyv`JYoFbm);}xzcuA@DqVNQ~0s&rt8yt%=gWVJ;#i( z8Z*Zqrz06oQkA?pJ@zBlQ8Egd7dnABoP zC1_tJZ+;yQW$4Lp%;XR?PauXnOh@BD1Va%g-~ZwVj*8_;A1^uTO1C==0L2cB?RG`L(iJ^EQ_*6dyXKWaulRAOqD?6F3$=FE7M4N z5Ko4!HU%I1gQv94w{?IHK=F?XUNg%AmUVO^#$Hao_NZ3fXkt=Lc8R@D+ErH7X)dw_ zec#>d?{yO8b-MR$TwkJw&y)HD%`1yAU8C>tVpPP1iB1& zk?y;IgSx6-&v6=LpUE3^FY2%=D+OJJ>>g0uWs18?+&-LR8u^2Qj9hP#d=0#+dcCH* zP}Q}rLEemUIM>0xsq1KZa*J|k>h(H%hnd$Ebv=?T(yf8KNO6$w$0T1S>>D6op;&do zS|Y5P#xgZRn`vaQ!O%ze4gFVK>QsjhSbuLhJ7l7OsB^wXG5tM*2TN zgZ=peu2*%v3?AmNP5j>_{WjHVoiKg`pQg^!*sN0=#Jov$!Z!+UJp9exY{s3MjUk-PyT%X9m`vfnY;~f|Z2@F1t<0_druHf3Mcfo8K z`4LQ)lfrz_n$mI*!Fy&W)bn+=C5Zab&xu5orf~);YnLap>Vo zv*EN{yIty&w$jZyW7ln)Dnbij7j-XaSMSVHVV|J3^`AaII2=5Tqa+zT#%=j6{oCTt zzW(On{{F#NcB$<}|NT^*3s5Zf7VjSxsLit73ZH_(zie4S>bEi?oAaWzbx+RYo6YZB zUOan@;C}`)$uSD6XC8tAJEOP&(s)N&Fh)hqnJ2E)pTc8S4l*n5$S^u8n>66?_-+0@ ranH87NdAjY3g3AJ*sbi742arod;$N54~)wB0XR>M{SC)IVQo?VqGJ$} literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/cubemap_render/cubemap_render.cpp b/tests/manual/rhi/cubemap_render/cubemap_render.cpp new file mode 100644 index 00000000000..a08e96f0c6c --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_render.cpp @@ -0,0 +1,466 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// Demonstrates rendering to two cubemaps in two different ways: +// - one by one, to each face, +// - if the supported max number of color attachments is greater than 4: in +// one go with all 6 faces attached as render targets. +// +// Finally, show what we got in a skybox-ish thing. Press the arrow keys to +// switch between the two cubemaps. (the only difference should be their +// background clear color) + +#define EXAMPLEFW_KEYPRESS_EVENTS +#include "../shared/examplefw.h" +#include "../shared/cube.h" + +// each face is 512x512 +static const QSize cubemapSize(512, 512); + +// each cubemap face gets a 256x256 quad in the center +static float halfQuadVertexData[] = +{ // Y up, CCW + -0.5f, 0.5f, + -0.5f, -0.5f, + 0.5f, -0.5f, + 0.5f, 0.5f, +}; + +static quint16 halfQuadIndexData[] = +{ + 0, 1, 2, 0, 2, 3 +}; + +struct { + QVector releasePool; + + QRhiTexture *cubemap1 = nullptr; + QRhiTexture *cubemap2 = nullptr; + bool canDoMrt = false; + + QRhiBuffer *half_quad_vbuf = nullptr; + QRhiBuffer *half_quad_ibuf = nullptr; + + QRhiBuffer *oneface_ubuf = nullptr; + int ubufSizePerFace; + QRhiTextureRenderTarget *oneface_rt[6]; + QRhiRenderPassDescriptor *oneface_rp = nullptr; + QRhiShaderResourceBindings *oneface_srb = nullptr; + QRhiGraphicsPipeline *oneface_ps = nullptr; + + QRhiBuffer *mrt_ubuf = nullptr; + QRhiTextureRenderTarget *mrt_rt = nullptr; + QRhiRenderPassDescriptor *mrt_rp = nullptr; + QRhiShaderResourceBindings *mrt_srb = nullptr; + QRhiGraphicsPipeline *mrt_ps = nullptr; + + QRhiBuffer *vbuf = nullptr; + QRhiBuffer *ubuf = nullptr; + QRhiSampler *sampler = nullptr; + QRhiShaderResourceBindings *srb = nullptr; + QRhiGraphicsPipeline *ps = nullptr; + + QRhiResourceUpdateBatch *initialUpdates = nullptr; + QMatrix4x4 winProj; + float rx = 0; +} d; + +void initializePerFaceRendering(QRhi *rhi) +{ + d.cubemap1 = rhi->newTexture(QRhiTexture::RGBA8, cubemapSize, 1, QRhiTexture::CubeMap | QRhiTexture::RenderTarget); + d.cubemap1->build(); + d.releasePool << d.cubemap1; + + d.ubufSizePerFace = rhi->ubufAligned(64 + 12); + d.oneface_ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, d.ubufSizePerFace * 6); + d.oneface_ubuf->build(); + d.releasePool << d.oneface_ubuf; + + for (int face = 0; face < 6; ++face) { + QRhiColorAttachment att(d.cubemap1); + att.setLayer(face); + QRhiTextureRenderTargetDescription rtDesc(att); + d.oneface_rt[face] = rhi->newTextureRenderTarget(rtDesc); + if (face == 0) { + d.oneface_rp = d.oneface_rt[0]->newCompatibleRenderPassDescriptor(); + d.releasePool << d.oneface_rp; + } + d.oneface_rt[face]->setRenderPassDescriptor(d.oneface_rp); + d.oneface_rt[face]->build(); + d.releasePool << d.oneface_rt[face]; + } + + d.oneface_srb = rhi->newShaderResourceBindings(); + const QRhiShaderResourceBinding::StageFlags visibility = + QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage; + d.oneface_srb->setBindings({ + QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(0, visibility, d.oneface_ubuf, 64 + 12) + }); + d.oneface_srb->build(); + d.releasePool << d.oneface_srb; + + d.oneface_ps = rhi->newGraphicsPipeline(); + d.oneface_ps->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String(":/cubemap_oneface.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String(":/cubemap_oneface.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 2 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + }); + d.oneface_ps->setVertexInputLayout(inputLayout); + d.oneface_ps->setShaderResourceBindings(d.oneface_srb); + d.oneface_ps->setRenderPassDescriptor(d.oneface_rp); + d.oneface_ps->build(); + d.releasePool << d.oneface_ps; + + // wasteful to duplicate the mvp as well but will do for now + for (int face = 0; face < 6; ++face) { + const int offset = d.ubufSizePerFace * face; + QMatrix4x4 identity; + d.initialUpdates->updateDynamicBuffer(d.oneface_ubuf, offset, 64, identity.constData()); + // will use a different color for each face + QColor c; + switch (face) { + case 0: + c = Qt::red; + break; + case 1: + c = Qt::green; + break; + case 2: + c = Qt::blue; + break; + case 3: + c = Qt::yellow; + break; + case 4: + c = Qt::lightGray; + break; + case 5: + c = Qt::cyan; + break; + } + float color[] = { float(c.redF()), float(c.greenF()), float(c.blueF()) }; + d.initialUpdates->updateDynamicBuffer(d.oneface_ubuf, offset + 64, 12, color); + } +} + +// 6 render passes, 1 draw call each, targeting one cubemap face at a time +void renderPerFace(QRhiCommandBuffer *cb) +{ + for (int face = 0; face < 6; ++face) { + cb->beginPass(d.oneface_rt[face], Qt::black, { 1.0f, 0 }); + cb->setGraphicsPipeline(d.oneface_ps); + cb->setViewport({ 0, 0, + float(d.oneface_rt[face]->pixelSize().width()), + float(d.oneface_rt[face]->pixelSize().height()) }); + const QRhiCommandBuffer::DynamicOffset dynamicOffset(0, face * d.ubufSizePerFace); + cb->setShaderResources(nullptr, 1, &dynamicOffset); + QRhiCommandBuffer::VertexInput vbufBinding(d.half_quad_vbuf, 0); + cb->setVertexInput(0, 1, &vbufBinding, d.half_quad_ibuf, 0, QRhiCommandBuffer::IndexUInt16); + cb->drawIndexed(6); + cb->endPass(); + } +} + +void initializeMrtRendering(QRhi *rhi) +{ + d.cubemap2 = rhi->newTexture(QRhiTexture::RGBA8, cubemapSize, 1, QRhiTexture::CubeMap | QRhiTexture::RenderTarget); + d.cubemap2->build(); + d.releasePool << d.cubemap2; + + d.mrt_ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 6 * 16); // note that vec3 is aligned to 16 bytes + d.mrt_ubuf->build(); + d.releasePool << d.mrt_ubuf; + + QVarLengthArray attachments; + for (int face = 0; face < 6; ++face) { + QRhiColorAttachment att(d.cubemap2); + att.setLayer(face); + attachments.append(att); + } + QRhiTextureRenderTargetDescription rtDesc; + rtDesc.setColorAttachments(attachments.cbegin(), attachments.cend()); + d.mrt_rt = rhi->newTextureRenderTarget(rtDesc); + d.mrt_rp = d.mrt_rt->newCompatibleRenderPassDescriptor(); + d.releasePool << d.mrt_rp; + d.mrt_rt->setRenderPassDescriptor(d.mrt_rp); + d.mrt_rt->build(); + d.releasePool << d.mrt_rt; + + d.mrt_srb = rhi->newShaderResourceBindings(); + const QRhiShaderResourceBinding::StageFlags visibility = + QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage; + d.mrt_srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, visibility, d.mrt_ubuf) + }); + d.mrt_srb->build(); + d.releasePool << d.mrt_srb; + + d.mrt_ps = rhi->newGraphicsPipeline(); + d.mrt_ps->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String(":/cubemap_mrt.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String(":/cubemap_mrt.frag.qsb")) } + }); + QVarLengthArray targetBlends; + for (int face = 0; face < 6; ++face) + targetBlends.append({}); // default to blend = false, color write = all, which is good + d.mrt_ps->setTargetBlends(targetBlends.cbegin(), targetBlends.cend()); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 2 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + }); + d.mrt_ps->setVertexInputLayout(inputLayout); + d.mrt_ps->setShaderResourceBindings(d.mrt_srb); + d.mrt_ps->setRenderPassDescriptor(d.mrt_rp); + d.mrt_ps->build(); + d.releasePool << d.mrt_ps; + + QMatrix4x4 identity; + d.initialUpdates->updateDynamicBuffer(d.mrt_ubuf, 0, 64, identity.constData()); + for (int face = 0; face < 6; ++face) { + const int offset = 64 + face * 16; + // will use a different color for each face + QColor c; + switch (face) { + case 0: + c = Qt::red; + break; + case 1: + c = Qt::green; + break; + case 2: + c = Qt::blue; + break; + case 3: + c = Qt::yellow; + break; + case 4: + c = Qt::lightGray; + break; + case 5: + c = Qt::cyan; + break; + } + float color[] = { float(c.redF()), float(c.greenF()), float(c.blueF()) }; + d.initialUpdates->updateDynamicBuffer(d.mrt_ubuf, offset, 12, color); + } +} + +// 1 render pass, 1 draw call, with all 6 faces attached and written to +void renderWithMrt(QRhiCommandBuffer *cb) +{ + // use a different clear color to differentiate from cubemap1 (because the + // results are expected to be identical otherwise) + cb->beginPass(d.mrt_rt, Qt::magenta, { 1.0f, 0 }); + cb->setGraphicsPipeline(d.mrt_ps); + cb->setViewport({ 0, 0, + float(d.mrt_rt->pixelSize().width()), + float(d.mrt_rt->pixelSize().height()) }); + cb->setShaderResources(); + QRhiCommandBuffer::VertexInput vbufBinding(d.half_quad_vbuf, 0); + cb->setVertexInput(0, 1, &vbufBinding, d.half_quad_ibuf, 0, QRhiCommandBuffer::IndexUInt16); + cb->drawIndexed(6); + cb->endPass(); +} + +void Window::customInit() +{ + d.half_quad_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(halfQuadVertexData)); + d.half_quad_vbuf->build(); + d.releasePool << d.half_quad_vbuf; + + d.half_quad_ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(halfQuadIndexData)); + d.half_quad_ibuf->build(); + d.releasePool << d.half_quad_ibuf; + + d.initialUpdates = m_r->nextResourceUpdateBatch(); + d.initialUpdates->uploadStaticBuffer(d.half_quad_vbuf, 0, sizeof(halfQuadVertexData), halfQuadVertexData); + d.initialUpdates->uploadStaticBuffer(d.half_quad_ibuf, halfQuadIndexData); + + initializePerFaceRendering(m_r); + + d.canDoMrt = m_r->resourceLimit(QRhi::MaxColorAttachments) >= 6; + if (d.canDoMrt) + initializeMrtRendering(m_r); + else + qWarning("Not enough color attachments (need 6, supports %d)", m_r->resourceLimit(QRhi::MaxColorAttachments)); + + + // onscreen stuff + d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube)); + d.vbuf->build(); + d.releasePool << d.vbuf; + d.initialUpdates->uploadStaticBuffer(d.vbuf, cube); + + d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64); + d.ubuf->build(); + d.releasePool << d.ubuf; + + d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, + QRhiSampler::Repeat, QRhiSampler::Repeat); + d.sampler->build(); + d.releasePool << d.sampler; + + d.srb = m_r->newShaderResourceBindings(); + d.srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf), + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.cubemap1, d.sampler) + }); + d.srb->build(); + d.releasePool << d.srb; + + d.ps = m_r->newGraphicsPipeline(); + d.ps->setDepthTest(true); + d.ps->setDepthWrite(true); + d.ps->setDepthOp(QRhiGraphicsPipeline::LessOrEqual); + d.ps->setCullMode(QRhiGraphicsPipeline::Front); // we are inside the cube so cull front, not back + d.ps->setFrontFace(QRhiGraphicsPipeline::CCW); // front is ccw in the cube data + QShader vs = getShader(QLatin1String(":/cubemap_sample.vert.qsb")); + Q_ASSERT(vs.isValid()); + QShader fs = getShader(QLatin1String(":/cubemap_sample.frag.qsb")); + Q_ASSERT(fs.isValid()); + d.ps->setShaderStages({ + { QRhiShaderStage::Vertex, vs }, + { QRhiShaderStage::Fragment, fs } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 3 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float3, 0 } + }); + d.ps->setVertexInputLayout(inputLayout); + d.ps->setShaderResourceBindings(d.srb); + d.ps->setRenderPassDescriptor(m_rp); + d.ps->build(); + d.releasePool << d.ps; + + if (d.canDoMrt) + qDebug("Use the arrow keys to switch between the two generated cubemaps"); +} + +void Window::customRelease() +{ + qDeleteAll(d.releasePool); + d.releasePool.clear(); +} + +void Window::customRender() +{ + const QSize outputSizeInPixels = m_sc->currentPixelSize(); + QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer(); + QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch(); + if (d.initialUpdates) { + u->merge(d.initialUpdates); + d.initialUpdates->release(); + d.initialUpdates = nullptr; + } + + QMatrix4x4 mvp = m_r->clipSpaceCorrMatrix(); + mvp.perspective(90.0f, outputSizeInPixels.width() / (float) outputSizeInPixels.height(), 0.01f, 1000.0f); + mvp.scale(10); + mvp.rotate(d.rx, 1, 0, 0); + d.rx += 0.5f; + u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData()); + + cb->resourceUpdate(u); + + renderPerFace(cb); + + if (d.canDoMrt) + renderWithMrt(cb); + + cb->beginPass(m_sc->currentFrameRenderTarget(), m_clearColor, { 1.0f, 0 }); + cb->setGraphicsPipeline(d.ps); + cb->setViewport(QRhiViewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height())); + cb->setShaderResources(); + const QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(36); + cb->endPass(); +} + +void Window::keyPressEvent(QKeyEvent *e) +{ + switch (e->key()) { + case Qt::Key_Left: + case Qt::Key_Up: + qDebug("Showing first cubemap (generated by rendering to the faces one by one; black background)"); + d.srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf), + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.cubemap1, d.sampler) + }); + d.srb->build(); + break; + case Qt::Key_Right: + case Qt::Key_Down: + if (d.canDoMrt) { + qDebug("Showing second cubemap (generated with multiple render targets; magenta background)"); + d.srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf), + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.cubemap2, d.sampler) + }); + d.srb->build(); + } + break; + default: + e->ignore(); + break; + } +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_render.pro b/tests/manual/rhi/cubemap_render/cubemap_render.pro new file mode 100644 index 00000000000..71208cc01f2 --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_render.pro @@ -0,0 +1,8 @@ +TEMPLATE = app + +QT += gui-private + +SOURCES = \ + cubemap_render.cpp + +RESOURCES = cubemap_render.qrc diff --git a/tests/manual/rhi/cubemap_render/cubemap_render.qrc b/tests/manual/rhi/cubemap_render/cubemap_render.qrc new file mode 100644 index 00000000000..f6029d3f3ad --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_render.qrc @@ -0,0 +1,10 @@ + + + cubemap_oneface.vert.qsb + cubemap_oneface.frag.qsb + cubemap_mrt.vert.qsb + cubemap_mrt.frag.qsb + cubemap_sample.vert.qsb + cubemap_sample.frag.qsb + + diff --git a/tests/manual/rhi/cubemap_render/cubemap_sample.frag b/tests/manual/rhi/cubemap_render/cubemap_sample.frag new file mode 100644 index 00000000000..13a365ed0cb --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_sample.frag @@ -0,0 +1,10 @@ +#version 440 + +layout(location = 0) in vec3 v_coord; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform samplerCube tex; + +void main() +{ + fragColor = vec4(texture(tex, v_coord).rgb, 1.0); +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_sample.frag.qsb b/tests/manual/rhi/cubemap_render/cubemap_sample.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..f26e3985b6a3c7b9e6d587f6c5b30a9aebfce24b GIT binary patch literal 1028 zcmV+f1pE5{010MzoQ+mnZ`?!_p6uq*IFtqogo}iR=4Dr`jMIb)WxL@ag(y;`lx|dz zqLt;?v(5;wy|TTlq*Wy$s@35N6X^X9^_T+K*v0Idpd+?=4<8P}i zs`I`B%T=>sZH!IjgRyP!2uA>X)!~(~KUZkGtj_S)@Iy9}bx>HH-A0SN6rcQ=^w~Z)6BU@-43K5^ey)<1py z05euI+L`h3HxN3e9iUrk4RySZiS@4W_dQq}YK}CA@H1pfoc9cVw~`yh`3^SgY7RAr zRj?g{tyHiN4Mw(45N$)vp|;;K2OD zD1*eumQCd4ku${$If%ZXKkn5L4rW1zkLp@63_`(`70zE#=A*DwC(!dzRBV}`f>kLl z{Nf^{w&681(%a!Lpo(zx+-iZ;vq1I6)ovQraSIaN zWhIE*zYpNKxcLcFR?62C@=Tm*IbC*GAIT2!SHRa z6=p$9EDY|6aA67CGXvEcY*w=SJ}h^|HjLzvKD$S8r4}?av${dg|H|~UpEWca=YK~Z3Wnz yJJmsVGILg=QLTX`0kyIIM?;gU$n2JzE>~qM%{q8Fe<9CR2Zh;U%>D)Zbu>pe90>gY literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/cubemap_render/cubemap_sample.vert b/tests/manual/rhi/cubemap_render/cubemap_sample.vert new file mode 100644 index 00000000000..f1caf1a74f0 --- /dev/null +++ b/tests/manual/rhi/cubemap_render/cubemap_sample.vert @@ -0,0 +1,16 @@ +#version 440 + +layout(location = 0) in vec4 position; +layout(location = 0) out vec3 v_coord; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + v_coord = position.xyz; + gl_Position = ubuf.mvp * position; +} diff --git a/tests/manual/rhi/cubemap_render/cubemap_sample.vert.qsb b/tests/manual/rhi/cubemap_render/cubemap_sample.vert.qsb new file mode 100644 index 0000000000000000000000000000000000000000..0cbc1440119b1893a8b2a0dad4720b6f66f18bf8 GIT binary patch literal 1145 zcmV-<1cv(n01HicoV`|CZyQAvp4g7lY6Q zZ_l(`A`uf!mzY#h*OM5)ro`Bca(oKJJ#3@u6=$qIv*Mmj*#o z`n|B?2Okx3b_xmYXQ^l@11LKdaVjQ-Z)(-jy10jeNoo%TP{+qx+=)UULmBbg95W06 zcn-jKRNE%=g+{#h_=__Y5l|f+@*b$~Xa_r!)8_@G9Pyqs(}8^Qcghk99g8%JLllCD z3#E1MmY3@qG=IFSoqeESrbEj_})O|y-g z9tVE8HD%FXvEHTKTWC~UwG=Fy6g!puo(KE>J@Zu}9oz9K4(w{Q`2_sG!mIyK zuWc@1*bD3udyBX$Ft9KYOROp12M>D>J8&*_c0Ryq#;(%2jo+?;9HVnh+gPMCZUrsC zACAA@=J5P$RB%WmmLddtUdn0b6{ZO`;FyO!ZE%|`-9imqORg-jGRsh%Quxi4a!+itr3o5 z)gb&5)pAbeLd9zkcA4~CBkXcsa|SUr*lXk$%DzkVD#fw^^mWqJAl;aU>!f>~;#(u# z>(XDv!|xlk*7#dw7xjGzd9IOOM*P2lgLT=Xn6FS=hmaA>%~j%EA(=VSzYo%j^!-!N zfOcOeUsg#U`tSzvwf>u=|9g-@`c1;zBt5s7>a7*hgLZBc?jNxJk(#&Vxpd*DV?L1C Lzi|Br`Tw0^VM9b+ literal 0 HcmV?d00001 diff --git a/tests/manual/rhi/rhi.pro b/tests/manual/rhi/rhi.pro index 5208e5dea57..4bee1649696 100644 --- a/tests/manual/rhi/rhi.pro +++ b/tests/manual/rhi/rhi.pro @@ -9,6 +9,7 @@ SUBDIRS += \ msaarenderbuffer \ cubemap \ cubemap_scissor \ + cubemap_render \ multiwindow \ multiwindow_threaded \ triquadcube \ diff --git a/tests/manual/rhi/shared/examplefw.h b/tests/manual/rhi/shared/examplefw.h index dc388274d7f..84895cf5305 100644 --- a/tests/manual/rhi/shared/examplefw.h +++ b/tests/manual/rhi/shared/examplefw.h @@ -148,6 +148,9 @@ protected: void exposeEvent(QExposeEvent *) override; bool event(QEvent *) override; +#ifdef EXAMPLEFW_KEYPRESS_EVENTS + void keyPressEvent(QKeyEvent *e) override; +#endif bool m_running = false; bool m_notExposed = false; From 62e98af40f97b865aeed897e90231e76b329d614 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 9 Jan 2020 15:08:11 +0100 Subject: [PATCH 11/20] rhi: gl: Do not issue glMemoryBarrier when compute is not supported Avoid crashing in a < GLES 3.1 and < GL 4.3 contexts. Change-Id: I0f713a527890ec209c967ebb6c5bb3baa77d9a31 Reviewed-by: Eirik Aavitsland --- src/gui/rhi/qrhigles2.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index afa3a397e60..81a1daa16bb 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -2287,12 +2287,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) barriers |= GL_ALL_BARRIER_BITS; } } - if (barriers) + if (barriers && caps.compute) f->glMemoryBarrier(barriers); } break; case QGles2CommandBuffer::Command::Barrier: - f->glMemoryBarrier(cmd.args.barrier.barriers); + if (caps.compute) + f->glMemoryBarrier(cmd.args.barrier.barriers); break; default: break; From 9a0ab41f28042c7f27208337e419435d16f00006 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 8 Jan 2020 12:55:57 +0100 Subject: [PATCH 12/20] rhi: gl: vulkan: Generate barriers between dispatches in a compute pass The new float16texture_with_compute manual test demonstrates a case that was not handled correctly before: multiple dispatch() calls in a row storing to and then loading from the same subresource(s). Without the appropriate barriers subtle data corruption issues appear. For Vulkan this also adds better batching for image/buffer barriers when using deferred recording. Also, for OpenGL this fixes the case of updating a buffer or rendering into a texture and then using it for load/store in a compute pass (previously this also lacked an appropriate glMemoryBarrier). Task-number: QTBUG-81217 Change-Id: I7970c445564473f9452662f4b1a20618cb8627a3 Reviewed-by: Paul Olav Tvete Reviewed-by: Johan Helsing --- src/gui/rhi/qrhigles2.cpp | 124 ++++++++++++++++++++++++--- src/gui/rhi/qrhigles2_p_p.h | 11 +++ src/gui/rhi/qrhivulkan.cpp | 157 +++++++++++++++++++++++++++++++++-- src/gui/rhi/qrhivulkan_p_p.h | 17 +++- 4 files changed, 291 insertions(+), 18 deletions(-) diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 81a1daa16bb..ec5e531e14c 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -269,6 +269,14 @@ QT_BEGIN_NAMESPACE #define GL_ALL_BARRIER_BITS 0xFFFFFFFF #endif +#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#endif + +#ifndef GL_SHADER_STORAGE_BARRIER_BIT +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#endif + #ifndef GL_VERTEX_PROGRAM_POINT_SIZE #define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 #endif @@ -1307,6 +1315,21 @@ QRhi::FrameOpResult QRhiGles2::finish() return QRhi::FrameOpSuccess; } +static bool bufferAccessIsWrite(QGles2Buffer::Access access) +{ + return access == QGles2Buffer::AccessStorageWrite + || access == QGles2Buffer::AccessStorageReadWrite + || access == QGles2Buffer::AccessUpdate; +} + +static bool textureAccessIsWrite(QGles2Texture::Access access) +{ + return access == QGles2Texture::AccessStorageWrite + || access == QGles2Texture::AccessStorageReadWrite + || access == QGles2Texture::AccessUpdate + || access == QGles2Texture::AccessFramebuffer; +} + void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access) { Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); // this is for resource updates only @@ -1314,7 +1337,7 @@ void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *buf if (access == prevAccess) return; - if (prevAccess == QGles2Buffer::AccessStorageWrite || prevAccess == QGles2Buffer::AccessStorageReadWrite) { + if (bufferAccessIsWrite(prevAccess)) { // Generating the minimal barrier set is way too complicated to do // correctly (prevAccess is overwritten so we won't have proper // tracking across multiple passes) so setting all barrier bits will do @@ -1335,7 +1358,7 @@ void QRhiGles2::trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *tex if (access == prevAccess) return; - if (prevAccess == QGles2Texture::AccessStorageWrite || prevAccess == QGles2Texture::AccessStorageReadWrite) { + if (textureAccessIsWrite(prevAccess)) { QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::Barrier; cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; @@ -2273,19 +2296,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) // subsequent pass. for (auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers(); it != itEnd; ++it) { QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(it->stateAtPassBegin.access); - if (accessBeforePass == QGles2Buffer::AccessStorageWrite - || accessBeforePass == QGles2Buffer::AccessStorageReadWrite) - { + if (bufferAccessIsWrite(accessBeforePass)) barriers |= GL_ALL_BARRIER_BITS; - } } for (auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures(); it != itEnd; ++it) { QGles2Texture::Access accessBeforePass = QGles2Texture::Access(it->stateAtPassBegin.access); - if (accessBeforePass == QGles2Texture::AccessStorageWrite - || accessBeforePass == QGles2Texture::AccessStorageReadWrite) - { + if (textureAccessIsWrite(accessBeforePass)) barriers |= GL_ALL_BARRIER_BITS; - } } if (barriers && caps.compute) f->glMemoryBarrier(barriers); @@ -2792,6 +2809,8 @@ void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch cbD->recordingPass = QGles2CommandBuffer::ComputePass; cbD->resetCachedState(); + + cbD->computePassState.reset(); } void QRhiGles2::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) @@ -2824,11 +2843,96 @@ void QRhiGles2::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *p } } +template +inline void qrhigl_accumulateComputeResource(T *writtenResources, QRhiResource *resource, + QRhiShaderResourceBinding::Type bindingType, + int loadTypeVal, int storeTypeVal, int loadStoreTypeVal) +{ + int access = 0; + if (bindingType == loadTypeVal) { + access = QGles2CommandBuffer::ComputePassState::Read; + } else { + access = QGles2CommandBuffer::ComputePassState::Write; + if (bindingType == loadStoreTypeVal) + access |= QGles2CommandBuffer::ComputePassState::Read; + } + auto it = writtenResources->find(resource); + if (it != writtenResources->end()) + it->first |= access; + else if (bindingType == storeTypeVal || bindingType == loadStoreTypeVal) + writtenResources->insert(resource, { access, true }); +} + void QRhiGles2::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::ComputePass); + if (cbD->currentComputeSrb) { + GLbitfield barriers = 0; + + // The key in the writtenResources map indicates that the resource was + // written in a previous dispatch, whereas the value accumulates the + // access mask in the current one. + for (auto &accessAndIsNewFlag : cbD->computePassState.writtenResources) + accessAndIsNewFlag = { 0, false }; + + QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, cbD->currentComputeSrb); + const int bindingCount = srbD->m_bindings.count(); + for (int i = 0; i < bindingCount; ++i) { + const QRhiShaderResourceBinding::Data *b = srbD->m_bindings.at(i).data(); + switch (b->type) { + case QRhiShaderResourceBinding::ImageLoad: + case QRhiShaderResourceBinding::ImageStore: + case QRhiShaderResourceBinding::ImageLoadStore: + qrhigl_accumulateComputeResource(&cbD->computePassState.writtenResources, + b->u.simage.tex, + b->type, + QRhiShaderResourceBinding::ImageLoad, + QRhiShaderResourceBinding::ImageStore, + QRhiShaderResourceBinding::ImageLoadStore); + break; + case QRhiShaderResourceBinding::BufferLoad: + case QRhiShaderResourceBinding::BufferStore: + case QRhiShaderResourceBinding::BufferLoadStore: + qrhigl_accumulateComputeResource(&cbD->computePassState.writtenResources, + b->u.sbuf.buf, + b->type, + QRhiShaderResourceBinding::BufferLoad, + QRhiShaderResourceBinding::BufferStore, + QRhiShaderResourceBinding::BufferLoadStore); + break; + default: + break; + } + } + + for (auto it = cbD->computePassState.writtenResources.begin(); it != cbD->computePassState.writtenResources.end(); ) { + const int accessInThisDispatch = it->first; + const bool isNewInThisDispatch = it->second; + if (accessInThisDispatch && !isNewInThisDispatch) { + if (it.key()->resourceType() == QRhiResource::Texture) + barriers |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; + else + barriers |= GL_SHADER_STORAGE_BARRIER_BIT; + } + // Anything that was previously written, but is only read now, can be + // removed from the written list (because that previous write got a + // corresponding barrier now). + if (accessInThisDispatch == QGles2CommandBuffer::ComputePassState::Read) + it = cbD->computePassState.writtenResources.erase(it); + else + ++it; + } + + if (barriers) { + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::Barrier; + cmd.args.barrier.barriers = barriers; + cbD->commands.append(cmd); + } + } + QGles2CommandBuffer::Command cmd; cmd.cmd = QGles2CommandBuffer::Command::Dispatch; cmd.args.dispatch.x = GLuint(x); diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index a9b30226125..679f8060040 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -521,6 +521,17 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer QRhiShaderResourceBindings *currentComputeSrb; uint currentSrbGeneration; + struct ComputePassState { + enum Access { + Read = 0x01, + Write = 0x02 + }; + QHash > writtenResources; + void reset() { + writtenResources.clear(); + } + } computePassState; + QVector dataRetainPool; QVector imageRetainPool; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index c4f56f2dd26..f4c72d2ccac 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -2219,6 +2219,8 @@ void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch cbD->recordingPass = QVkCommandBuffer::ComputePass; + cbD->computePassState.reset(); + if (cbD->useSecondaryCb) cbD->secondaryCbs.append(startSecondaryCommandBuffer()); } @@ -2267,15 +2269,152 @@ void QRhiVulkan::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline * psD->lastActiveFrameSlot = currentFrameSlot; } +template +inline void qrhivk_accumulateComputeResource(T *writtenResources, QRhiResource *resource, + QRhiShaderResourceBinding::Type bindingType, + int loadTypeVal, int storeTypeVal, int loadStoreTypeVal) +{ + VkAccessFlags access = 0; + if (bindingType == loadTypeVal) { + access = VK_ACCESS_SHADER_READ_BIT; + } else { + access = VK_ACCESS_SHADER_WRITE_BIT; + if (bindingType == loadStoreTypeVal) + access |= VK_ACCESS_SHADER_READ_BIT; + } + auto it = writtenResources->find(resource); + if (it != writtenResources->end()) + it->first |= access; + else if (bindingType == storeTypeVal || bindingType == loadStoreTypeVal) + writtenResources->insert(resource, { access, true }); +} + void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) { QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass); + // When there are multiple dispatches, read-after-write and + // write-after-write need a barrier. + QVarLengthArray imageBarriers; + QVarLengthArray bufferBarriers; + if (cbD->currentComputeSrb) { + // The key in the writtenResources map indicates that the resource was + // written in a previous dispatch, whereas the value accumulates the + // access mask in the current one. + for (auto &accessAndIsNewFlag : cbD->computePassState.writtenResources) + accessAndIsNewFlag = { 0, false }; + + QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, cbD->currentComputeSrb); + const int bindingCount = srbD->m_bindings.count(); + for (int i = 0; i < bindingCount; ++i) { + const QRhiShaderResourceBinding::Data *b = srbD->m_bindings.at(i).data(); + switch (b->type) { + case QRhiShaderResourceBinding::ImageLoad: + case QRhiShaderResourceBinding::ImageStore: + case QRhiShaderResourceBinding::ImageLoadStore: + qrhivk_accumulateComputeResource(&cbD->computePassState.writtenResources, + b->u.simage.tex, + b->type, + QRhiShaderResourceBinding::ImageLoad, + QRhiShaderResourceBinding::ImageStore, + QRhiShaderResourceBinding::ImageLoadStore); + break; + case QRhiShaderResourceBinding::BufferLoad: + case QRhiShaderResourceBinding::BufferStore: + case QRhiShaderResourceBinding::BufferLoadStore: + qrhivk_accumulateComputeResource(&cbD->computePassState.writtenResources, + b->u.sbuf.buf, + b->type, + QRhiShaderResourceBinding::BufferLoad, + QRhiShaderResourceBinding::BufferStore, + QRhiShaderResourceBinding::BufferLoadStore); + break; + default: + break; + } + } + + for (auto it = cbD->computePassState.writtenResources.begin(); it != cbD->computePassState.writtenResources.end(); ) { + const int accessInThisDispatch = it->first; + const bool isNewInThisDispatch = it->second; + if (accessInThisDispatch && !isNewInThisDispatch) { + if (it.key()->resourceType() == QRhiResource::Texture) { + QVkTexture *texD = QRHI_RES(QVkTexture, it.key()); + VkImageMemoryBarrier barrier; + memset(&barrier, 0, sizeof(barrier)); + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + // won't care about subresources, pretend the whole resource was written + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barrier.oldLayout = texD->usageState.layout; + barrier.newLayout = texD->usageState.layout; + barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + barrier.dstAccessMask = accessInThisDispatch; + barrier.image = texD->image; + imageBarriers.append(barrier); + } else { + QVkBuffer *bufD = QRHI_RES(QVkBuffer, it.key()); + VkBufferMemoryBarrier barrier; + memset(&barrier, 0, sizeof(barrier)); + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + barrier.dstAccessMask = accessInThisDispatch; + barrier.buffer = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0]; + barrier.size = VK_WHOLE_SIZE; + bufferBarriers.append(barrier); + } + } + // Anything that was previously written, but is only read now, can be + // removed from the written list (because that previous write got a + // corresponding barrier now). + if (accessInThisDispatch == VK_ACCESS_SHADER_READ_BIT) + it = cbD->computePassState.writtenResources.erase(it); + else + ++it; + } + } + if (cbD->useSecondaryCb) { - df->vkCmdDispatch(cbD->secondaryCbs.last(), uint32_t(x), uint32_t(y), uint32_t(z)); + VkCommandBuffer secondaryCb = cbD->secondaryCbs.last(); + if (!imageBarriers.isEmpty()) { + df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, 0, nullptr, + 0, nullptr, + imageBarriers.count(), imageBarriers.constData()); + } + if (!bufferBarriers.isEmpty()) { + df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, 0, nullptr, + bufferBarriers.count(), bufferBarriers.constData(), + 0, nullptr); + } + df->vkCmdDispatch(secondaryCb, uint32_t(x), uint32_t(y), uint32_t(z)); } else { QVkCommandBuffer::Command cmd; + if (!imageBarriers.isEmpty()) { + cmd.cmd = QVkCommandBuffer::Command::ImageBarrier; + cmd.args.imageBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + cmd.args.imageBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + cmd.args.imageBarrier.count = imageBarriers.count(); + cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count(); + cbD->pools.imageBarrier.append(imageBarriers.constData(), imageBarriers.count()); + cbD->commands.append(cmd); + } + if (!bufferBarriers.isEmpty()) { + cmd.cmd = QVkCommandBuffer::Command::BufferBarrier; + cmd.args.bufferBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + cmd.args.bufferBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + cmd.args.bufferBarrier.count = bufferBarriers.count(); + cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.count(); + cbD->pools.bufferBarrier.append(bufferBarriers.constData(), bufferBarriers.count()); + cbD->commands.append(cmd); + } cmd.cmd = QVkCommandBuffer::Command::Dispatch; cmd.args.dispatch.x = x; cmd.args.dispatch.y = y; @@ -2465,7 +2604,9 @@ void QRhiVulkan::trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, in cmd.cmd = QVkCommandBuffer::Command::BufferBarrier; cmd.args.bufferBarrier.srcStageMask = s.stage; cmd.args.bufferBarrier.dstStageMask = stage; - cmd.args.bufferBarrier.desc = bufMemBarrier; + cmd.args.bufferBarrier.count = 1; + cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.count(); + cbD->pools.bufferBarrier.append(bufMemBarrier); cbD->commands.append(cmd); s.access = access; @@ -2507,7 +2648,9 @@ void QRhiVulkan::trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD, cmd.cmd = QVkCommandBuffer::Command::ImageBarrier; cmd.args.imageBarrier.srcStageMask = srcStage; cmd.args.imageBarrier.dstStageMask = stage; - cmd.args.imageBarrier.desc = barrier; + cmd.args.imageBarrier.count = 1; + cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count(); + cbD->pools.imageBarrier.append(barrier); cbD->commands.append(cmd); s.layout = layout; @@ -2541,7 +2684,9 @@ void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image, cmd.cmd = QVkCommandBuffer::Command::ImageBarrier; cmd.args.imageBarrier.srcStageMask = srcStage; cmd.args.imageBarrier.dstStageMask = dstStage; - cmd.args.imageBarrier.desc = barrier; + cmd.args.imageBarrier.count = 1; + cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count(); + cbD->pools.imageBarrier.append(barrier); cbD->commands.append(cmd); } @@ -3409,12 +3554,12 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD) case QVkCommandBuffer::Command::ImageBarrier: df->vkCmdPipelineBarrier(cbD->cb, cmd.args.imageBarrier.srcStageMask, cmd.args.imageBarrier.dstStageMask, 0, 0, nullptr, 0, nullptr, - 1, &cmd.args.imageBarrier.desc); + cmd.args.imageBarrier.count, cbD->pools.imageBarrier.constData() + cmd.args.imageBarrier.index); break; case QVkCommandBuffer::Command::BufferBarrier: df->vkCmdPipelineBarrier(cbD->cb, cmd.args.bufferBarrier.srcStageMask, cmd.args.bufferBarrier.dstStageMask, 0, 0, nullptr, - 1, &cmd.args.bufferBarrier.desc, + cmd.args.bufferBarrier.count, cbD->pools.bufferBarrier.constData() + cmd.args.bufferBarrier.index, 0, nullptr); break; case QVkCommandBuffer::Command::BlitImage: diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index 9f18d0bf5e0..b0e90dae560 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -370,6 +370,13 @@ struct QVkCommandBuffer : public QRhiCommandBuffer QVarLengthArray secondaryCbs; bool inExternal; + struct { + QHash > writtenResources; + void reset() { + writtenResources.clear(); + } + } computePassState; + struct Command { enum Cmd { CopyBuffer, @@ -429,12 +436,14 @@ struct QVkCommandBuffer : public QRhiCommandBuffer struct { VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; - VkImageMemoryBarrier desc; + int count; + int index; } imageBarrier; struct { VkPipelineStageFlags srcStageMask; VkPipelineStageFlags dstStageMask; - VkBufferMemoryBarrier desc; + int count; + int index; } bufferBarrier; struct { VkImage src; @@ -537,6 +546,8 @@ struct QVkCommandBuffer : public QRhiCommandBuffer pools.vertexBuffer.clear(); pools.vertexBufferOffset.clear(); pools.debugMarkerData.clear(); + pools.imageBarrier.clear(); + pools.bufferBarrier.clear(); } struct { @@ -546,6 +557,8 @@ struct QVkCommandBuffer : public QRhiCommandBuffer QVarLengthArray vertexBuffer; QVarLengthArray vertexBufferOffset; QVarLengthArray debugMarkerData; + QVarLengthArray imageBarrier; + QVarLengthArray bufferBarrier; } pools; friend class QRhiVulkan; From 7e2cef0f15b133c07bd11aa5e5065b0b9959fb0d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sun, 12 Jan 2020 17:33:31 +0100 Subject: [PATCH 13/20] Move away from CBOR in QShaderDescription serialization ...but keep support for deserializing for all older versions in order to play nice with existing .qsb files. The usage of binary JSON and then CBOR is a historical artifact: relying on the QJsonDocument (which we generate for purposes unrelated to binary serialization) was a convenient shortcut. However, writing to and reading from a QDataStream instead (which QShader already does) is trivial. In order not to be limited by potential CBOR requirements in the future, take it all into our own hands. Extend the qshader autotest accordingly. Task-number: QTBUG-81298 Change-Id: If0047b659bd6601ca47b5bbbce1b719630cde01e Reviewed-by: Paul Olav Tvete --- src/gui/rhi/qshader.cpp | 13 +- src/gui/rhi/qshader_p_p.h | 3 +- src/gui/rhi/qshaderdescription.cpp | 235 ++++++++++++++++++ src/gui/rhi/qshaderdescription_p.h | 3 + src/gui/rhi/qshaderdescription_p_p.h | 2 + .../rhi/qshader/data/texture_all_v4.frag.qsb | Bin 0 -> 1272 bytes tests/auto/gui/rhi/qshader/tst_qshader.cpp | 132 +++++++++- 7 files changed, 374 insertions(+), 14 deletions(-) create mode 100644 tests/auto/gui/rhi/qshader/data/texture_all_v4.frag.qsb diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp index 9203d63cd2d..69f4a682151 100644 --- a/src/gui/rhi/qshader.cpp +++ b/src/gui/rhi/qshader.cpp @@ -367,7 +367,7 @@ QByteArray QShader::serialized() const ds << QShaderPrivate::QSB_VERSION; ds << int(d->stage); - ds << d->desc.toCbor(); + d->desc.serialize(&ds); ds << d->shaders.count(); for (auto it = d->shaders.cbegin(), itEnd = d->shaders.cend(); it != itEnd; ++it) { const QShaderKey &k(it.key()); @@ -428,6 +428,7 @@ QShader QShader::fromSerialized(const QByteArray &data) ds >> intVal; d->qsbVersion = intVal; if (d->qsbVersion != QShaderPrivate::QSB_VERSION + && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS) { @@ -437,14 +438,18 @@ QShader QShader::fromSerialized(const QByteArray &data) ds >> intVal; d->stage = Stage(intVal); - QByteArray descBin; - ds >> descBin; - if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) { + if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) { + d->desc = QShaderDescription::deserialize(&ds); + } else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) { + QByteArray descBin; + ds >> descBin; d->desc = QShaderDescription::fromCbor(descBin); } else { #if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + QByteArray descBin; + ds >> descBin; d->desc = QShaderDescription::fromBinaryJson(descBin); QT_WARNING_POP #else diff --git a/src/gui/rhi/qshader_p_p.h b/src/gui/rhi/qshader_p_p.h index 8c89f2b45f0..66ef18f3918 100644 --- a/src/gui/rhi/qshader_p_p.h +++ b/src/gui/rhi/qshader_p_p.h @@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE struct Q_GUI_EXPORT QShaderPrivate { - static const int QSB_VERSION = 3; + static const int QSB_VERSION = 4; + static const int QSB_VERSION_WITH_CBOR = 3; static const int QSB_VERSION_WITH_BINARY_JSON = 2; static const int QSB_VERSION_WITHOUT_BINDINGS = 1; diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp index 76c5d0ebefa..96c8d082fcc 100644 --- a/src/gui/rhi/qshaderdescription.cpp +++ b/src/gui/rhi/qshaderdescription.cpp @@ -36,6 +36,7 @@ #include "qshaderdescription_p_p.h" #include +#include #include #include #include @@ -358,6 +359,11 @@ QByteArray QShaderDescription::toJson() const return d->makeDoc().toJson(); } +void QShaderDescription::serialize(QDataStream *stream) const +{ + d->writeToStream(stream); +} + #if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15) /*! \deprecated @@ -396,6 +402,13 @@ QShaderDescription QShaderDescription::fromCbor(const QByteArray &data) return desc; } +QShaderDescription QShaderDescription::deserialize(QDataStream *stream) +{ + QShaderDescription desc; + QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream); + return desc; +} + /*! \return the list of input variables. This includes vertex inputs (sometimes called attributes) for the vertex stage, and inputs for other stages @@ -867,6 +880,15 @@ static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v (*obj)[imageFlagsKey] = int(v.imageFlags); } +static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v) +{ + (*stream) << v.location; + (*stream) << v.binding; + (*stream) << v.descriptorSet; + (*stream) << int(v.imageFormat); + (*stream) << int(v.imageFlags); +} + static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v) { QJsonObject obj; @@ -876,6 +898,13 @@ static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v) return obj; } +static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v) +{ + (*stream) << v.name; + (*stream) << int(v.type); + serializeDecorations(stream, v); +} + static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v) { QJsonObject obj; @@ -904,6 +933,23 @@ static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v) return obj; } +static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescription::BlockVariable &v) +{ + (*stream) << v.name; + (*stream) << int(v.type); + (*stream) << v.offset; + (*stream) << v.size; + (*stream) << v.arrayDims.count(); + for (int dim : v.arrayDims) + (*stream) << dim; + (*stream) << v.arrayStride; + (*stream) << v.matrixStride; + (*stream) << v.matrixIsRowMajor; + (*stream) << v.structMembers.count(); + for (const QShaderDescription::BlockVariable &sv : v.structMembers) + serializeBlockMemberVar(stream, sv); +} + QJsonDocument QShaderDescriptionPrivate::makeDoc() { QJsonObject root; @@ -1002,6 +1048,67 @@ QJsonDocument QShaderDescriptionPrivate::makeDoc() return QJsonDocument(root); } +void QShaderDescriptionPrivate::writeToStream(QDataStream *stream) +{ + (*stream) << inVars.count(); + for (const QShaderDescription::InOutVariable &v : qAsConst(inVars)) + serializeInOutVar(stream, v); + + (*stream) << outVars.count(); + for (const QShaderDescription::InOutVariable &v : qAsConst(outVars)) + serializeInOutVar(stream, v); + + (*stream) << uniformBlocks.count(); + for (const QShaderDescription::UniformBlock &b : uniformBlocks) { + (*stream) << b.blockName; + (*stream) << b.structName; + (*stream) << b.size; + (*stream) << b.binding; + (*stream) << b.descriptorSet; + (*stream) << b.members.count(); + for (const QShaderDescription::BlockVariable &v : b.members) + serializeBlockMemberVar(stream, v); + } + + (*stream) << pushConstantBlocks.count(); + for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) { + (*stream) << b.name; + (*stream) << b.size; + (*stream) << b.members.count(); + for (const QShaderDescription::BlockVariable &v : b.members) + serializeBlockMemberVar(stream, v); + } + + (*stream) << storageBlocks.count(); + for (const QShaderDescription::StorageBlock &b : storageBlocks) { + (*stream) << b.blockName; + (*stream) << b.instanceName; + (*stream) << b.knownSize; + (*stream) << b.binding; + (*stream) << b.descriptorSet; + (*stream) << b.members.count(); + for (const QShaderDescription::BlockVariable &v : b.members) + serializeBlockMemberVar(stream, v); + } + + (*stream) << combinedImageSamplers.count(); + for (const QShaderDescription::InOutVariable &v : qAsConst(combinedImageSamplers)) { + (*stream) << v.name; + (*stream) << int(v.type); + serializeDecorations(stream, v); + } + + (*stream) << storageImages.count(); + for (const QShaderDescription::InOutVariable &v : qAsConst(storageImages)) { + (*stream) << v.name; + (*stream) << int(v.type); + serializeDecorations(stream, v); + } + + for (size_t i = 0; i < 3; ++i) + (*stream) << localSize[i]; +} + static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj) { QShaderDescription::InOutVariable var; @@ -1020,6 +1127,29 @@ static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj) return var; } +static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOutVariable *v) +{ + (*stream) >> v->location; + (*stream) >> v->binding; + (*stream) >> v->descriptorSet; + int f; + (*stream) >> f; + v->imageFormat = QShaderDescription::ImageFormat(f); + (*stream) >> f; + v->imageFlags = QShaderDescription::ImageFlags(f); +} + +static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream) +{ + QShaderDescription::InOutVariable var; + (*stream) >> var.name; + int t; + (*stream) >> t; + var.type = QShaderDescription::VariableType(t); + deserializeDecorations(stream, &var); + return var; +} + static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj) { QShaderDescription::BlockVariable var; @@ -1046,6 +1176,30 @@ static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj) return var; } +static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream) +{ + QShaderDescription::BlockVariable var; + (*stream) >> var.name; + int t; + (*stream) >> t; + var.type = QShaderDescription::VariableType(t); + (*stream) >> var.offset; + (*stream) >> var.size; + int count; + (*stream) >> count; + var.arrayDims.resize(count); + for (int i = 0; i < count; ++i) + (*stream) >> var.arrayDims[i]; + (*stream) >> var.arrayStride; + (*stream) >> var.matrixStride; + (*stream) >> var.matrixIsRowMajor; + (*stream) >> count; + var.structMembers.resize(count); + for (int i = 0; i < count; ++i) + var.structMembers[i] = deserializeBlockMemberVar(stream); + return var; +} + void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc) { if (doc.isNull()) { @@ -1150,6 +1304,87 @@ void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc) } } +void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream) +{ + Q_ASSERT(ref.loadRelaxed() == 1); // must be detached + + int count; + (*stream) >> count; + inVars.resize(count); + for (int i = 0; i < count; ++i) + inVars[i] = deserializeInOutVar(stream); + + (*stream) >> count; + outVars.resize(count); + for (int i = 0; i < count; ++i) + outVars[i] = deserializeInOutVar(stream); + + (*stream) >> count; + uniformBlocks.resize(count); + for (int i = 0; i < count; ++i) { + (*stream) >> uniformBlocks[i].blockName; + (*stream) >> uniformBlocks[i].structName; + (*stream) >> uniformBlocks[i].size; + (*stream) >> uniformBlocks[i].binding; + (*stream) >> uniformBlocks[i].descriptorSet; + int memberCount; + (*stream) >> memberCount; + uniformBlocks[i].members.resize(memberCount); + for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) + uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream); + } + + (*stream) >> count; + pushConstantBlocks.resize(count); + for (int i = 0; i < count; ++i) { + (*stream) >> pushConstantBlocks[i].name; + (*stream) >> pushConstantBlocks[i].size; + int memberCount; + (*stream) >> memberCount; + pushConstantBlocks[i].members.resize(memberCount); + for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) + pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream); + } + + (*stream) >> count; + storageBlocks.resize(count); + for (int i = 0; i < count; ++i) { + (*stream) >> storageBlocks[i].blockName; + (*stream) >> storageBlocks[i].instanceName; + (*stream) >> storageBlocks[i].knownSize; + (*stream) >> storageBlocks[i].binding; + (*stream) >> storageBlocks[i].descriptorSet; + int memberCount; + (*stream) >> memberCount; + storageBlocks[i].members.resize(memberCount); + for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) + storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream); + } + + (*stream) >> count; + combinedImageSamplers.resize(count); + for (int i = 0; i < count; ++i) { + (*stream) >> combinedImageSamplers[i].name; + int t; + (*stream) >> t; + combinedImageSamplers[i].type = QShaderDescription::VariableType(t); + deserializeDecorations(stream, &combinedImageSamplers[i]); + } + + (*stream) >> count; + storageImages.resize(count); + for (int i = 0; i < count; ++i) { + (*stream) >> storageImages[i].name; + int t; + (*stream) >> t; + storageImages[i].type = QShaderDescription::VariableType(t); + deserializeDecorations(stream, &storageImages[i]); + } + + for (size_t i = 0; i < 3; ++i) + (*stream) >> localSize[i]; +} + /*! Returns \c true if the two QShaderDescription objects \a lhs and \a rhs are equal. diff --git a/src/gui/rhi/qshaderdescription_p.h b/src/gui/rhi/qshaderdescription_p.h index 872ee8b1385..108fc32a56f 100644 --- a/src/gui/rhi/qshaderdescription_p.h +++ b/src/gui/rhi/qshaderdescription_p.h @@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE struct QShaderDescriptionPrivate; +class QDataStream; class Q_GUI_EXPORT QShaderDescription { @@ -69,6 +70,7 @@ public: bool isValid() const; QByteArray toCbor() const; + void serialize(QDataStream *stream) const; QByteArray toJson() const; #if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15) @@ -76,6 +78,7 @@ public: static QShaderDescription fromBinaryJson(const QByteArray &data); #endif static QShaderDescription fromCbor(const QByteArray &data); + static QShaderDescription deserialize(QDataStream *stream); enum VariableType { Unknown = 0, diff --git a/src/gui/rhi/qshaderdescription_p_p.h b/src/gui/rhi/qshaderdescription_p_p.h index 1caee249846..69b6e811a11 100644 --- a/src/gui/rhi/qshaderdescription_p_p.h +++ b/src/gui/rhi/qshaderdescription_p_p.h @@ -80,7 +80,9 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; } QJsonDocument makeDoc(); + void writeToStream(QDataStream *stream); void loadDoc(const QJsonDocument &doc); + void loadFromStream(QDataStream *stream); QAtomicInt ref; QVector inVars; diff --git a/tests/auto/gui/rhi/qshader/data/texture_all_v4.frag.qsb b/tests/auto/gui/rhi/qshader/data/texture_all_v4.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..4292d67b7c4ab04f59f4086a6116aeaf8989e76d GIT binary patch literal 1272 zcmV{26u1R&2H+E8mkF_Bpl|5GHJE%1a1X$OozZkV+MSCo1g+#^7vNJ2 zBgU%af8kXGa8(F%YUuvhIPv2oh(dn1VOv%r;)y5t(WGy^v^ZQNS2Xzx;XHLk9GteK zu0M=i!K1P31>&q_owqD&5(fP!9-$$hz?Y#)+|hXG$BjLt>H4Q)68rG_#Es8_aKKM| zuR(8iqbTm-t0?Hf#6eiCkr#uZ^L6YF_FUl}*oVB$h2m-KRWs5}lcvT$k&e_eH!Ta3 zjJyWS#poA+&1%TijL>tLxHRnM^` zIk5O8smB78;DfF68yJ;AYvRlBL7P6rx*H9nm~>a+nZ>De%c)Mr3z`zU1v-csyj_%I zrZB2@44b+v_2@6Yk>MNSb|klosYvszP5H4#e&F>Epo&s1$*SOZ6-JBjDFOn5q^4MY56@s;$pXm?+WQJ6CcV~Nr&@aC%z)#Z!q0E3Xk$K>D~o-g?w9( z`BiycAr7=(C9Yd!zbfa^x&`1+u_NE7B(IZ<_O}U(e4j)9i!9rPFb98u25Z;`Eyi?> z;%QSXH_6}c09BDSP#DyI3A)=dN6M#lvctLFC;iW4_W{|Wej8?9BHiEM=@%;7dfkFh z_{ONjQo4WLyZ1)-uc3PuO+q#Ki-De6Wp3ZcjPB9gU_W^YfgG) zDx0UTlVY+(7i|X;m18iXKREF4S+#42hjT20&@{}Y6-+0IA7f3z%o>?TerU|BMpezn z;qTxe5$?bT>F{uqdr=5tC=2=M;M*1pHlPtM5w0sKq*0%vs6<^VI8{Ku%@Pkd4J?3&pv5=zcZ0h={d z%dS55Roa`myc;fwyI{~!+3g5d_}s~WjxLB{ke~rH8mwh+rX^ds7t<@5y0i1`<7dyE z-8f1T=W#gB_jkTcw|Muf?|1k2pY7SX1~)18Ct`f@8rkBV=T6s+2fiQ*xt}1wxo}f4 zI!2|YIwvV}_Zi3BXJ)-r``AnZxL#5)*8Z4jXq$j~E~(me3PvgBOsohZDJYPs$*mWo znnvH}3C^wjNyC0I4*fr~|CH~)(UayaIaDwoJ(m9SQ@E4m!?vw)?0bQfj)TGRSVi8N iQ3s)zcZ~f1+$s9E^S4G}_DEL0R`Htt?e;J8#(t?`#*j<^ literal 0 HcmV?d00001 diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp index a0082f1e3b1..b90ac8dc53d 100644 --- a/tests/auto/gui/rhi/qshader/tst_qshader.cpp +++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp @@ -43,6 +43,8 @@ private slots: void mslResourceMapping(); void loadV3(); void serializeShaderDesc(); + void comparison(); + void loadV4(); }; static QShader getShader(const QString &name) @@ -353,21 +355,38 @@ void tst_QShader::serializeShaderDesc() QShaderDescription desc; QVERIFY(!desc.isValid()); - const QByteArray data = desc.toCbor(); + QByteArray data; + { + QBuffer buf(&data); + QDataStream ds(&buf); + QVERIFY(buf.open(QIODevice::WriteOnly)); + desc.serialize(&ds); + } QVERIFY(!data.isEmpty()); - QShaderDescription desc2 = QShaderDescription::fromCbor(data); - QVERIFY(!desc2.isValid()); + { + QBuffer buf(&data); + QDataStream ds(&buf); + QVERIFY(buf.open(QIODevice::ReadOnly)); + QShaderDescription desc2 = QShaderDescription::deserialize(&ds); + QVERIFY(!desc2.isValid()); + } } // a QShaderDescription with inputs, outputs, uniform block and combined image sampler { - QShader s = getShader(QLatin1String(":/data/texture_all_v3.frag.qsb")); + QShader s = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb")); QVERIFY(s.isValid()); const QShaderDescription desc = s.description(); QVERIFY(desc.isValid()); - const QByteArray data = desc.toCbor(); + QByteArray data; + { + QBuffer buf(&data); + QDataStream ds(&buf); + QVERIFY(buf.open(QIODevice::WriteOnly)); + desc.serialize(&ds); + } QVERIFY(!data.isEmpty()); QShaderDescription desc2; @@ -375,14 +394,22 @@ void tst_QShader::serializeShaderDesc() QVERIFY(!(desc == desc2)); QVERIFY(desc != desc2); - desc2 = QShaderDescription::fromCbor(data); - QVERIFY(desc2.isValid()); - QCOMPARE(desc, desc2); + { + QBuffer buf(&data); + QDataStream ds(&buf); + QVERIFY(buf.open(QIODevice::ReadOnly)); + QShaderDescription desc2 = QShaderDescription::deserialize(&ds); + QVERIFY(desc2.isValid()); + QCOMPARE(desc, desc2); + } } +} +void tst_QShader::comparison() +{ // exercise QShader and QShaderDescription comparisons { - QShader s1 = getShader(QLatin1String(":/data/texture_all_v3.frag.qsb")); + QShader s1 = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb")); QVERIFY(s1.isValid()); QShader s2 = getShader(QLatin1String(":/data/color_all_v1.vert.qsb")); QVERIFY(s2.isValid()); @@ -393,6 +420,93 @@ void tst_QShader::serializeShaderDesc() QVERIFY(s1 != s2); QVERIFY(s1.description() != s2.description()); } + + { + QShader s1 = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb")); + QVERIFY(s1.isValid()); + QShader s2 = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb")); + QVERIFY(s2.isValid()); + + QVERIFY(s1.description().isValid()); + QVERIFY(s2.description().isValid()); + + QVERIFY(s1 == s2); + QVERIFY(s1.description() == s2.description()); + } +} + +void tst_QShader::loadV4() +{ + // qsb version 4: QShaderDescription is serialized via QDataStream. Ensure the deserialized data is as expected. + QShader s = getShader(QLatin1String(":/data/texture_all_v4.frag.qsb")); + QVERIFY(s.isValid()); + QCOMPARE(QShaderPrivate::get(&s)->qsbVersion, 4); + + const QVector availableShaders = s.availableShaders(); + QCOMPARE(availableShaders.count(), 7); + QVERIFY(availableShaders.contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100)))); + QVERIFY(availableShaders.contains(QShaderKey(QShader::MslShader, QShaderVersion(12)))); + QVERIFY(availableShaders.contains(QShaderKey(QShader::HlslShader, QShaderVersion(50)))); + QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs)))); + QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(120)))); + QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(150)))); + QVERIFY(availableShaders.contains(QShaderKey(QShader::GlslShader, QShaderVersion(330)))); + + const QShaderDescription desc = s.description(); + QVERIFY(desc.isValid()); + QCOMPARE(desc.inputVariables().count(), 1); + for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) { + switch (v.location) { + case 0: + QCOMPARE(v.name, QLatin1String("qt_TexCoord")); + QCOMPARE(v.type, QShaderDescription::Vec2); + break; + default: + QVERIFY(false); + break; + } + } + QCOMPARE(desc.outputVariables().count(), 1); + for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) { + switch (v.location) { + case 0: + QCOMPARE(v.name, QLatin1String("fragColor")); + QCOMPARE(v.type, QShaderDescription::Vec4); + break; + default: + QVERIFY(false); + break; + } + } + QCOMPARE(desc.uniformBlocks().count(), 1); + const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first(); + QCOMPARE(blk.blockName, QLatin1String("buf")); + QCOMPARE(blk.structName, QLatin1String("ubuf")); + QCOMPARE(blk.size, 68); + QCOMPARE(blk.binding, 0); + QCOMPARE(blk.descriptorSet, 0); + QCOMPARE(blk.members.count(), 2); + for (int i = 0; i < blk.members.count(); ++i) { + const QShaderDescription::BlockVariable v = blk.members[i]; + switch (i) { + case 0: + QCOMPARE(v.offset, 0); + QCOMPARE(v.size, 64); + QCOMPARE(v.name, QLatin1String("qt_Matrix")); + QCOMPARE(v.type, QShaderDescription::Mat4); + QCOMPARE(v.matrixStride, 16); + break; + case 1: + QCOMPARE(v.offset, 64); + QCOMPARE(v.size, 4); + QCOMPARE(v.name, QLatin1String("opacity")); + QCOMPARE(v.type, QShaderDescription::Float); + break; + default: + QVERIFY(false); + break; + } + } } #include From 0a93db4d82c051164923a10e4382b12de9049b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 8 Jan 2020 17:48:58 +0100 Subject: [PATCH 14/20] Unify application palette handling between QGuiApplication and QApplication The logic is now mostly handled in QGuiApplication, with QApplication only dealing with the widget-specific palettes and interaction between the style and the palette. The application now picks up changes to the platform theme and will re-resolve the current application palette appropriately. This also works even if an explicit application palette has been set, in which case any missing roles are filled in by the theme. The palette can now also be reset back to the default application palette that's fully based on the theme, by passing in the default constructed palette (or any palette that doesn't have any roles set). This is also correctly reflected in the Qt::AA_SetPalette attribute. Conceptually this means QGuiApplication and QApplication follow the same behavior as QWidget, where the palette falls back to a base or inherited palette for roles that are not set, in this case the theme. Behavior-wise this means that the default application palette of the application does not have any roles set, but clients should not have relied on this, nor does QWidget rely on that internally. It also means that setting a palette on the application and then getting it back again will not produce the same palette as set, since the palette was resolved against the theme in the meantime. This is the same behavior as for QWidget, and although it's a behavior change it's one towards a more sane behavior, so we accept it. [ChangeLog] Application palettes are now resolved against the platform's theme palette, the same way widget palettes are resolved against their parents, and the application palette. This means the application palette reflected through QGuiApplication::palette() may not be exactly the same palette as set via QGuiApplication::setPalette(). Change-Id: I76b99fcd27285e564899548349aa2a5713e5965d Reviewed-by: Vitaly Fanaskov Reviewed-by: Friedemann Kleint --- .../widgets/widgets/styles/widgetgallery.cpp | 8 +- .../widgets/widgets/styles/widgetgallery.h | 2 - src/gui/kernel/qguiapplication.cpp | 117 +++++---- src/gui/kernel/qguiapplication_p.h | 11 +- src/plugins/styles/mac/qmacstyle_mac.mm | 2 +- .../styles/windowsvista/qwindowsxpstyle.cpp | 3 +- src/widgets/kernel/qapplication.cpp | 235 ++++++++---------- src/widgets/kernel/qapplication_p.h | 10 +- .../qguiapplication/tst_qguiapplication.cpp | 51 +++- 9 files changed, 229 insertions(+), 210 deletions(-) diff --git a/examples/widgets/widgets/styles/widgetgallery.cpp b/examples/widgets/widgets/styles/widgetgallery.cpp index d70c503f53a..bf8e93feb46 100644 --- a/examples/widgets/widgets/styles/widgetgallery.cpp +++ b/examples/widgets/widgets/styles/widgetgallery.cpp @@ -75,8 +75,6 @@ WidgetGallery::WidgetGallery(QWidget *parent) : QDialog(parent) { - originalPalette = QApplication::palette(); - styleComboBox = new QComboBox; const QString defaultStyleName = QApplication::style()->objectName(); QStringList styleNames = QStyleFactory::keys(); @@ -162,10 +160,8 @@ void WidgetGallery::changeStyle(const QString &styleName) void WidgetGallery::changePalette() //! [7] //! [8] { - if (useStylePaletteCheckBox->isChecked()) - QApplication::setPalette(QApplication::style()->standardPalette()); - else - QApplication::setPalette(originalPalette); + QApplication::setPalette(useStylePaletteCheckBox->isChecked() ? + QApplication::style()->standardPalette() : QPalette()); } //! [8] diff --git a/examples/widgets/widgets/styles/widgetgallery.h b/examples/widgets/widgets/styles/widgetgallery.h index 4deee6839a1..8c4c880536b 100644 --- a/examples/widgets/widgets/styles/widgetgallery.h +++ b/examples/widgets/widgets/styles/widgetgallery.h @@ -96,8 +96,6 @@ private: void createBottomRightGroupBox(); void createProgressBar(); - QPalette originalPalette; - QLabel *styleLabel; QComboBox *styleComboBox; QCheckBox *useStylePaletteCheckBox; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index ffd5b04276c..445ad6b8354 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -236,21 +236,6 @@ static bool qt_detectRTLLanguage() " and Arabic) to get proper widget layout.") == QLatin1String("RTL")); } -static void initPalette() -{ - if (!QGuiApplicationPrivate::app_pal) - if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette()) - QGuiApplicationPrivate::app_pal = new QPalette(*themePalette); - if (!QGuiApplicationPrivate::app_pal) - QGuiApplicationPrivate::app_pal = new QPalette(Qt::gray); -} - -static inline void clearPalette() -{ - delete QGuiApplicationPrivate::app_pal; - QGuiApplicationPrivate::app_pal = nullptr; -} - static void initFontUnlocked() { if (!QGuiApplicationPrivate::app_font) { @@ -691,7 +676,7 @@ QGuiApplication::~QGuiApplication() d->session_manager = nullptr; #endif //QT_NO_SESSIONMANAGER - clearPalette(); + QGuiApplicationPrivate::clearPalette(); QFontDatabase::removeAllApplicationFonts(); #ifndef QT_NO_CURSOR @@ -1611,7 +1596,7 @@ void QGuiApplicationPrivate::init() if (platform_integration == nullptr) createPlatformIntegration(); - initPalette(); + updatePalette(); QFont::initialize(); initThemeHints(); @@ -3289,46 +3274,97 @@ QClipboard * QGuiApplication::clipboard() */ /*! - Returns the default application palette. + Returns the current application palette. + + Roles that have not been explicitly set will reflect the system's platform theme. \sa setPalette() */ QPalette QGuiApplication::palette() { - initPalette(); + if (!QGuiApplicationPrivate::app_pal) + QGuiApplicationPrivate::updatePalette(); + return *QGuiApplicationPrivate::app_pal; } +void QGuiApplicationPrivate::updatePalette() +{ + if (app_pal) { + if (setPalette(*app_pal) && qGuiApp) + qGuiApp->d_func()->handlePaletteChanged(); + } else { + setPalette(QPalette()); + } +} + +void QGuiApplicationPrivate::clearPalette() +{ + delete app_pal; + app_pal = nullptr; +} + /*! - Changes the default application palette to \a pal. + Changes the application palette to \a pal. + + The color roles from this palette are combined with the system's platform + theme to form the application's final palette. \sa palette() */ void QGuiApplication::setPalette(const QPalette &pal) { - if (!QGuiApplicationPrivate::setPalette(pal)) - return; - - QCoreApplication::setAttribute(Qt::AA_SetPalette); - - if (qGuiApp) - qGuiApp->d_func()->sendApplicationPaletteChange(); + if (QGuiApplicationPrivate::setPalette(pal) && qGuiApp) + qGuiApp->d_func()->handlePaletteChanged(); } bool QGuiApplicationPrivate::setPalette(const QPalette &palette) { - if (app_pal && palette.isCopyOf(*app_pal)) + // Resolve the palette against the theme palette, filling in + // any missing roles, while keeping the original resolve mask. + QPalette basePalette = qGuiApp ? qGuiApp->d_func()->basePalette() : Qt::gray; + basePalette.resolve(0); // The base palette only contributes missing colors roles + QPalette resolvedPalette = palette.resolve(basePalette); + + if (app_pal && resolvedPalette == *app_pal && resolvedPalette.resolve() == app_pal->resolve()) return false; if (!app_pal) - app_pal = new QPalette(palette); + app_pal = new QPalette(resolvedPalette); else - *app_pal = palette; + *app_pal = resolvedPalette; + + QCoreApplication::setAttribute(Qt::AA_SetPalette, app_pal->resolve() != 0); return true; } +/* + Returns the base palette used to fill in missing roles in + the current application palette. + + Normally this is the theme palette, but QApplication + overrides this for compatibility reasons. +*/ +QPalette QGuiApplicationPrivate::basePalette() const +{ + return platformTheme() ? *platformTheme()->palette() : Qt::gray; +} + +void QGuiApplicationPrivate::handlePaletteChanged(const char *className) +{ + if (!className) { + Q_ASSERT(app_pal); + emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal); + } + + if (is_app_running && !is_app_closing) { + QEvent event(QEvent::ApplicationPaletteChange); + QGuiApplication::sendEvent(qGuiApp, &event); + } +} + void QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(QWindow *window) { windowGeometrySpecification.applyTo(window); @@ -4127,11 +4163,8 @@ QPixmap QGuiApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape) void QGuiApplicationPrivate::notifyThemeChanged() { - if (!testAttribute(Qt::AA_SetPalette)) { - clearPalette(); - initPalette(); - sendApplicationPaletteChange(); - } + updatePalette(); + if (!(applicationResourceFlags & ApplicationFontExplicitlySet)) { const auto locker = qt_scoped_lock(applicationFontMutex); clearFontUnlocked(); @@ -4140,20 +4173,6 @@ void QGuiApplicationPrivate::notifyThemeChanged() initThemeHints(); } -void QGuiApplicationPrivate::sendApplicationPaletteChange(bool toAllWidgets, const char *className) -{ - Q_UNUSED(toAllWidgets) - - if (!className) - emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal); - - if (!is_app_running || is_app_closing) - return; - - QEvent event(QEvent::ApplicationPaletteChange); - QGuiApplication::sendEvent(QGuiApplication::instance(), &event); -} - #if QT_CONFIG(draganddrop) void QGuiApplicationPrivate::notifyDragStarted(const QDrag *drag) { diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 2fe4ae02cf6..5239b58c97c 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -323,17 +323,22 @@ public: static void resetCachedDevicePixelRatio(); - static bool setPalette(const QPalette &palette); - protected: virtual void notifyThemeChanged(); - virtual void sendApplicationPaletteChange(bool toAllWidgets = false, const char *className = nullptr); + + static bool setPalette(const QPalette &palette); + virtual QPalette basePalette() const; + virtual void handlePaletteChanged(const char *className = nullptr); + bool tryCloseRemainingWindows(QWindowList processedWindows); #if QT_CONFIG(draganddrop) virtual void notifyDragStarted(const QDrag *); #endif // QT_CONFIG(draganddrop) private: + static void clearPalette(); + static void updatePalette(); + friend class QDragManager; static QGuiApplicationPrivate *self; diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 5aa7befb848..37b658dd767 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -2585,7 +2585,7 @@ QPalette QMacStyle::standardPalette() const auto platformTheme = QGuiApplicationPrivate::platformTheme(); auto styleNames = platformTheme->themeHint(QPlatformTheme::StyleNames); if (styleNames.toStringList().contains("macintosh")) - return *platformTheme->palette(); + return QPalette(); // Inherit everything from theme else return QStyle::standardPalette(); } diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp index bf80138b32a..5d2e8efd682 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp @@ -3774,8 +3774,7 @@ int QWindowsXPStyle::styleHint(StyleHint hint, const QStyleOption *option, const /*! \reimp */ QPalette QWindowsXPStyle::standardPalette() const { - return QWindowsXPStylePrivate::useXP() && QApplicationPrivate::sys_pal - ? *QApplicationPrivate::sys_pal : QWindowsStyle::standardPalette(); + return QWindowsXPStylePrivate::useXP() ? QPalette() : QWindowsStyle::standardPalette(); } /*! diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 4b1daab4cfc..eea97b2c0bc 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -140,30 +140,6 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int QApplicationPrivate *QApplicationPrivate::self = nullptr; -static void initSystemPalette() -{ - if (QApplicationPrivate::sys_pal) - return; // Already initialized - - QPalette defaultPalette; - if (QApplicationPrivate::app_style) - defaultPalette = QApplicationPrivate::app_style->standardPalette(); - - auto *platformTheme = QGuiApplicationPrivate::platformTheme(); - if (const QPalette *themePalette = platformTheme ? platformTheme->palette() : nullptr) { - QApplicationPrivate::setSystemPalette(themePalette->resolve(defaultPalette)); - QApplicationPrivate::initializeWidgetPaletteHash(); - } else { - QApplicationPrivate::setSystemPalette(defaultPalette); - } -} - -static void clearSystemPalette() -{ - delete QApplicationPrivate::sys_pal; - QApplicationPrivate::sys_pal = nullptr; -} - bool QApplicationPrivate::autoSipEnabled = true; QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, int flags) @@ -381,8 +357,6 @@ QString QApplicationPrivate::styleSheet; // default application styles #endif QPointer QApplicationPrivate::leaveAfterRelease = nullptr; -QPalette *QApplicationPrivate::sys_pal = nullptr; // default system palette - QFont *QApplicationPrivate::sys_font = nullptr; // default system font QFont *QApplicationPrivate::set_font = nullptr; // default font set by programmer @@ -545,12 +519,7 @@ void QApplicationPrivate::init() // Must be called before initialize() QColormap::initialize(); - if (sys_pal) { - // Now that we have a platform theme we need to reset - // the system palette to pick up the theme colors. - clearSystemPalette(); - initSystemPalette(); - } + initializeWidgetPalettesFromTheme(); qt_init_tooltip_palette(); QApplicationPrivate::initializeWidgetFontHash(); @@ -629,38 +598,6 @@ void QApplicationPrivate::initialize() is_app_running = true; // no longer starting up } -static void setPossiblePalette(const QPalette *palette, const char *className) -{ - if (palette == nullptr) - return; - QApplicationPrivate::setPalette_helper(*palette, className); -} - -void QApplicationPrivate::initializeWidgetPaletteHash() -{ - QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme(); - if (!platformTheme) - return; - - widgetPalettes.clear(); - - setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit"); -} - void QApplicationPrivate::initializeWidgetFontHash() { const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); @@ -798,9 +735,6 @@ QApplication::~QApplication() delete qt_desktopWidget; qt_desktopWidget = nullptr; - delete QApplicationPrivate::app_pal; - QApplicationPrivate::app_pal = nullptr; - clearSystemPalette(); QApplicationPrivate::widgetPalettes.clear(); delete QApplicationPrivate::sys_font; @@ -1051,10 +985,10 @@ QStyle *QApplication::style() // Take ownership of the style defaultStyle->setParent(qApp); - initSystemPalette(); - if (testAttribute(Qt::AA_SetPalette)) defaultStyle->polish(*QGuiApplicationPrivate::app_pal); + else + QApplicationPrivate::initializeWidgetPalettesFromTheme(); #ifndef QT_NO_STYLE_STYLESHEET if (!QApplicationPrivate::styleSheet.isEmpty()) { @@ -1128,13 +1062,10 @@ void QApplication::setStyle(QStyle *style) // take care of possible palette requirements of certain gui // styles. Do it before polishing the application since the style // might call QApplication::setPalette() itself - if (testAttribute(Qt::AA_SetPalette)) { + if (testAttribute(Qt::AA_SetPalette)) QApplicationPrivate::app_style->polish(*QGuiApplicationPrivate::app_pal); - } else { - if (QApplicationPrivate::sys_pal) - clearSystemPalette(); - initSystemPalette(); - } + else + QApplicationPrivate::initializeWidgetPalettesFromTheme(); // The default widget font hash is based on the platform theme, // not the style, but the widget fonts could in theory have been @@ -1317,6 +1248,22 @@ void QApplication::setGlobalStrut(const QSize& strut) // Widget specific palettes QApplicationPrivate::PaletteHash QApplicationPrivate::widgetPalettes; +QPalette QApplicationPrivate::basePalette() const +{ + // Start out with a palette based on the style, in case there's no theme + // available, or so that we can fill in missing roles in the theme. + QPalette palette = app_style ? app_style->standardPalette() : Qt::gray; + + // Prefer theme palette if available, but fill in missing roles from style + // for compatibility. Note that the style's standard palette is not prioritized + // over the theme palette, as the documented way of applying the style's palette + // is to set it explicitly using QApplication::setPalette(). + if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr) + palette = themePalette->resolve(palette); + + return palette; +} + /*! \fn QPalette QApplication::palette(const QWidget* widget) @@ -1363,35 +1310,8 @@ QPalette QApplication::palette(const char *className) return QGuiApplication::palette(); } -void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char* className) -{ - QPalette pal = palette; - - if (QApplicationPrivate::app_style) - QApplicationPrivate::app_style->polish(pal); // NB: non-const reference - - bool all = false; - if (!className) { - if (!QGuiApplicationPrivate::setPalette(pal)) - return; - - if (!QApplicationPrivate::sys_pal || !palette.isCopyOf(*QApplicationPrivate::sys_pal)) - QCoreApplication::setAttribute(Qt::AA_SetPalette); - - if (!widgetPalettes.isEmpty()) { - all = true; - widgetPalettes.clear(); - } - } else { - widgetPalettes.insert(className, pal); - } - - if (qApp) - qApp->d_func()->sendApplicationPaletteChange(all, className); -} - /*! - Changes the default application palette to \a palette. + Changes the application palette to \a palette. If \a className is passed, the change applies only to widgets that inherit \a className (as reported by QObject::inherits()). If \a className is left @@ -1412,23 +1332,87 @@ void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char* \sa QWidget::setPalette(), palette(), QStyle::polish() */ - void QApplication::setPalette(const QPalette &palette, const char* className) { - QApplicationPrivate::setPalette_helper(palette, className); + QPalette polishedPalette = palette; + + if (QApplicationPrivate::app_style) + QApplicationPrivate::app_style->polish(polishedPalette); + + if (className) { + QApplicationPrivate::widgetPalettes.insert(className, polishedPalette); + if (qApp) + qApp->d_func()->handlePaletteChanged(className); + } else { + QGuiApplication::setPalette(polishedPalette); + } } - - -void QApplicationPrivate::setSystemPalette(const QPalette &pal) +void QApplicationPrivate::handlePaletteChanged(const char *className) { - if (!sys_pal) - sys_pal = new QPalette(pal); - else - *sys_pal = pal; + if (!is_app_running || is_app_closing) + return; - if (!testAttribute(Qt::AA_SetPalette)) - QApplication::setPalette(*sys_pal); + // Setting the global application palette is documented to + // reset any previously set class specific widget palettes. + bool sendPaletteChangeToAllWidgets = false; + if (!className && !widgetPalettes.isEmpty()) { + sendPaletteChangeToAllWidgets = true; + widgetPalettes.clear(); + } + + QGuiApplicationPrivate::handlePaletteChanged(className); + + QEvent event(QEvent::ApplicationPaletteChange); + const QWidgetList widgets = QApplication::allWidgets(); + for (auto widget : widgets) { + if (sendPaletteChangeToAllWidgets || (!className && widget->isWindow()) || (className && widget->inherits(className))) + QCoreApplication::sendEvent(widget, &event); + } + +#if QT_CONFIG(graphicsview) + for (auto scene : qAsConst(scene_list)) + QCoreApplication::sendEvent(scene, &event); +#endif + + // Palette has been reset back to the default application palette, + // so we need to reinitialize the widget palettes from the theme. + if (!className && !testAttribute(Qt::AA_SetPalette)) + initializeWidgetPalettesFromTheme(); +} + +void QApplicationPrivate::initializeWidgetPalettesFromTheme() +{ + QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme(); + if (!platformTheme) + return; + + widgetPalettes.clear(); + + struct ThemedWidget { const char *className; QPlatformTheme::Palette palette; }; + + static const ThemedWidget themedWidgets[] = { + { "QToolButton", QPlatformTheme::ToolButtonPalette }, + { "QAbstractButton", QPlatformTheme::ButtonPalette }, + { "QCheckBox", QPlatformTheme::CheckBoxPalette }, + { "QRadioButton", QPlatformTheme::RadioButtonPalette }, + { "QHeaderView", QPlatformTheme::HeaderPalette }, + { "QAbstractItemView", QPlatformTheme::ItemViewPalette }, + { "QMessageBoxLabel", QPlatformTheme::MessageBoxLabelPalette }, + { "QTabBar", QPlatformTheme::TabBarPalette }, + { "QLabel", QPlatformTheme::LabelPalette }, + { "QGroupBox", QPlatformTheme::GroupBoxPalette }, + { "QMenu", QPlatformTheme::MenuPalette }, + { "QMenuBar", QPlatformTheme::MenuBarPalette }, + { "QTextEdit", QPlatformTheme::TextEditPalette }, + { "QTextControl", QPlatformTheme::TextEditPalette }, + { "QLineEdit", QPlatformTheme::TextLineEditPalette }, + }; + + for (const auto themedWidget : themedWidgets) { + if (auto *palette = platformTheme->palette(themedWidget.palette)) + QApplication::setPalette(*palette, themedWidget.className); + } } /*! @@ -4413,31 +4397,10 @@ void QApplicationPrivate::translateTouchCancel(QTouchDevice *device, ulong times void QApplicationPrivate::notifyThemeChanged() { QGuiApplicationPrivate::notifyThemeChanged(); - clearSystemPalette(); - initSystemPalette(); + qt_init_tooltip_palette(); } -void QApplicationPrivate::sendApplicationPaletteChange(bool toAllWidgets, const char *className) -{ - if (!is_app_running || is_app_closing) - return; - - QGuiApplicationPrivate::sendApplicationPaletteChange(toAllWidgets, className); - - QEvent event(QEvent::ApplicationPaletteChange); - const QWidgetList widgets = QApplication::allWidgets(); - for (auto widget : widgets) { - if (toAllWidgets || (!className && widget->isWindow()) || (className && widget->inherits(className))) - QCoreApplication::sendEvent(widget, &event); - } - -#if QT_CONFIG(graphicsview) - for (auto scene : qAsConst(scene_list)) - QCoreApplication::sendEvent(scene, &event); -#endif // QT_CONFIG(graphicsview) -} - #if QT_CONFIG(draganddrop) void QApplicationPrivate::notifyDragStarted(const QDrag *drag) { diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 71f695cc181..ab6d85aeb9b 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -158,12 +158,12 @@ public: static QSize app_strut; static QWidgetList *popupWidgets; static QStyle *app_style; - static QPalette *sys_pal; protected: void notifyThemeChanged() override; - void sendApplicationPaletteChange(bool toAllWidgets = false, - const char *className = nullptr) override; + + QPalette basePalette() const override; + void handlePaletteChanged(const char *className = nullptr) override; #if QT_CONFIG(draganddrop) void notifyDragStarted(const QDrag *) override; @@ -184,9 +184,7 @@ public: static int enabledAnimations; // Combination of QPlatformTheme::UiEffect static bool widgetCount; // Coupled with -widgetcount switch - static void setSystemPalette(const QPalette &pal); - static void setPalette_helper(const QPalette &palette, const char* className); - static void initializeWidgetPaletteHash(); + static void initializeWidgetPalettesFromTheme(); static void initializeWidgetFontHash(); static void setSystemFont(const QFont &font); diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 5ee25677bfb..a7881b69832 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -506,29 +506,67 @@ void tst_QGuiApplication::keyboardModifiers() window->close(); } +/* + Compare actual against expected but ignore unset roles. + + Comparing palettes via operator== will compare all roles. +*/ +static bool palettesMatch(const QPalette &actual, const QPalette &expected) +{ + if (actual.resolve() != expected.resolve()) + return false; + + for (int i = 0; i < QPalette::NColorGroups; i++) { + for (int j = 0; j < QPalette::NColorRoles; j++) { + const auto g = QPalette::ColorGroup(i); + const auto r = QPalette::ColorRole(j); + if (expected.isBrushSet(g, r)) { + if (actual.brush(g, r) != expected.brush(g, r)) + return false; + } + } + } + return true; +} + void tst_QGuiApplication::palette() { + // Getting the palette before application construction should work + QPalette paletteBeforeAppConstruction = QGuiApplication::palette(); + // And should be reflected in the default constructed palette + QCOMPARE(paletteBeforeAppConstruction, QPalette()); + int argc = 1; char *argv[] = { const_cast("tst_qguiapplication") }; QGuiApplication app(argc, argv); + + // The same should be true after application construction + QCOMPARE(QGuiApplication::palette(), QPalette()); + + // The default application palette is not resolved + QVERIFY(!QGuiApplication::palette().resolve()); + QSignalSpy signalSpy(&app, SIGNAL(paletteChanged(QPalette))); QPalette oldPalette = QGuiApplication::palette(); QPalette newPalette = QPalette(Qt::red); QGuiApplication::setPalette(newPalette); - QCOMPARE(QGuiApplication::palette(), newPalette); + QVERIFY(palettesMatch(QGuiApplication::palette(), newPalette)); QCOMPARE(signalSpy.count(), 1); - QCOMPARE(signalSpy.at(0).at(0), QVariant(newPalette)); + QVERIFY(palettesMatch(signalSpy.at(0).at(0).value(), newPalette)); + QCOMPARE(QGuiApplication::palette(), QPalette()); QGuiApplication::setPalette(oldPalette); - QCOMPARE(QGuiApplication::palette(), oldPalette); + QVERIFY(palettesMatch(QGuiApplication::palette(), oldPalette)); QCOMPARE(signalSpy.count(), 2); - QCOMPARE(signalSpy.at(1).at(0), QVariant(oldPalette)); + QVERIFY(palettesMatch(signalSpy.at(1).at(0).value(), oldPalette)); + QCOMPARE(QGuiApplication::palette(), QPalette()); QGuiApplication::setPalette(oldPalette); - QCOMPARE(QGuiApplication::palette(), oldPalette); + QVERIFY(palettesMatch(QGuiApplication::palette(), oldPalette)); QCOMPARE(signalSpy.count(), 2); + QCOMPARE(QGuiApplication::palette(), QPalette()); } void tst_QGuiApplication::font() @@ -1073,6 +1111,9 @@ void tst_QGuiApplication::testSetPaletteAttribute() QGuiApplication::setPalette(palette); QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette)); + + QGuiApplication::setPalette(QPalette()); + QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette)); } // Test that static functions do not crash if there is no application instance. From ac95c8b686c46fdec40cc5f7e60dfdd0f4a3a60f Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sat, 7 Dec 2019 20:46:31 +0100 Subject: [PATCH 15/20] QStandardItem/QStandardItemModel tests: cleanup Cleanup QStandardItem/QStandardItemModel tests: - use nullptr - remove unused functions - use new signal/slot syntax - style Change-Id: I2feb8550e7f740f9df4b9c1b803c2f250c1ec729 Reviewed-by: Friedemann Kleint --- .../qstandarditem/tst_qstandarditem.cpp | 69 ++- .../tst_qstandarditemmodel.cpp | 453 +++++++----------- 2 files changed, 195 insertions(+), 327 deletions(-) diff --git a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp index b6921fc0bbf..596908d84da 100644 --- a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp +++ b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp @@ -29,7 +29,7 @@ #include -#include +#include class tst_QStandardItem : public QObject { @@ -48,8 +48,6 @@ private slots: void parent(); void insertColumn_data(); void insertColumn(); - void insertColumns_data(); - void insertColumns(); void insertRow_data(); void insertRow(); void insertRows_data(); @@ -312,12 +310,15 @@ void tst_QStandardItem::getSetFlags() QCOMPARE(item.checkState(), Qt::Checked); #if QT_DEPRECATED_SINCE(5, 6) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED // deprecated API item.setTristate(true); QVERIFY(item.isTristate()); QVERIFY(item.flags() & Qt::ItemIsTristate); item.setTristate(false); QVERIFY(!(item.flags() & Qt::ItemIsTristate)); +QT_WARNING_POP #endif } @@ -382,7 +383,7 @@ void tst_QStandardItem::getSetChild() QStandardItem item(rows, columns); bool shouldHaveChildren = (rows > 0) && (columns > 0); QCOMPARE(item.hasChildren(), shouldHaveChildren); - QCOMPARE(item.child(row, column), static_cast(0)); + QCOMPARE(item.child(row, column), nullptr); QStandardItem *child = new QStandardItem; item.setChild(row, column, child); @@ -399,11 +400,11 @@ void tst_QStandardItem::getSetChild() QCOMPARE(item.child(row, column), anotherChild); QCOMPARE(anotherChild->row(), row); QCOMPARE(anotherChild->column(), column); - item.setChild(row, column, 0); + item.setChild(row, column, nullptr); } else { delete child; } - QCOMPARE(item.child(row, column), static_cast(0)); + QCOMPARE(item.child(row, column), nullptr); } void tst_QStandardItem::parent() @@ -411,7 +412,7 @@ void tst_QStandardItem::parent() { QStandardItem item; QStandardItem *child = new QStandardItem; - QCOMPARE(child->parent(), static_cast(0)); + QCOMPARE(child->parent(), nullptr); item.setChild(0, 0, child); QCOMPARE(child->parent(), &item); @@ -425,7 +426,7 @@ void tst_QStandardItem::parent() QStandardItem *item = new QStandardItem; model.appendRow(item); // parent of a top-level item should be 0 - QCOMPARE(item->parent(), static_cast(0)); + QCOMPARE(item->parent(), nullptr); } } @@ -485,7 +486,7 @@ void tst_QStandardItem::insertColumn() for (int i = 0; i < count; ++i) QCOMPARE(item.child(i, column), columnItems.at(i)); for (int i = count; i < item.rowCount(); ++i) - QCOMPARE(item.child(i, column), static_cast(0)); + QCOMPARE(item.child(i, column), nullptr); } else { QCOMPARE(item.columnCount(), columns); QCOMPARE(item.rowCount(), rows); @@ -493,14 +494,6 @@ void tst_QStandardItem::insertColumn() } } -void tst_QStandardItem::insertColumns_data() -{ -} - -void tst_QStandardItem::insertColumns() -{ -} - void tst_QStandardItem::insertRow_data() { QTest::addColumn("rows"); @@ -557,7 +550,7 @@ void tst_QStandardItem::insertRow() for (int i = 0; i < count; ++i) QCOMPARE(item.child(row, i), rowItems.at(i)); for (int i = count; i < item.columnCount(); ++i) - QCOMPARE(item.child(row, i), static_cast(0)); + QCOMPARE(item.child(row, i), nullptr); } else { QCOMPARE(item.columnCount(), columns); QCOMPARE(item.rowCount(), rows); @@ -585,9 +578,8 @@ void tst_QStandardItem::insertRows() QStandardItem item(rows, columns); QList items; - for (int i = 0; i < insertCount; ++i) { + for (int i = 0; i < insertCount; ++i) items.append(new QStandardItem()); - } item.insertRows(insertAt, items); QCOMPARE(item.rowCount(), rows + insertCount); @@ -659,7 +651,7 @@ void tst_QStandardItem::appendColumn() for (int i = 0; i < count; ++i) QCOMPARE(item.child(i, columns), columnItems.at(i)); for (int i = count; i < item.rowCount(); ++i) - QCOMPARE(item.child(i, columns), static_cast(0)); + QCOMPARE(item.child(i, columns), nullptr); // make sure original children remained unchanged for (int i = 0; i < rows; ++i) { @@ -734,7 +726,7 @@ void tst_QStandardItem::appendRow() for (int i = 0; i < count; ++i) QCOMPARE(item.child(rows, i), rowItems.at(i)); for (int i = count; i < item.columnCount(); ++i) - QCOMPARE(item.child(rows, i), static_cast(0)); + QCOMPARE(item.child(rows, i), nullptr); // make sure original children remained unchanged for (int i = 0; i < rows; ++i) { @@ -753,7 +745,7 @@ void tst_QStandardItem::takeChild() for (int i = 0; i < item.rowCount(); ++i) { QCOMPARE(item.takeChild(i), itemList.at(i)); - QCOMPARE(item.takeChild(0, 0), static_cast(0)); + QCOMPARE(item.takeChild(0, 0), nullptr); for (int j = i + 1; j < item.rowCount(); ++j) QCOMPARE(item.child(j), itemList.at(j)); } @@ -938,7 +930,7 @@ void tst_QStandardItem::deleteItem() for (int j = 0; j < model.columnCount(); ++j) { QStandardItem *item = model.item(i, j); delete item; - QCOMPARE(model.item(i, j), static_cast(0)); + QCOMPARE(model.item(i, j), nullptr); } } } @@ -995,9 +987,9 @@ void tst_QStandardItem::sortChildren() item->appendRow(two); QSignalSpy layoutAboutToBeChangedSpy( - model, SIGNAL(layoutAboutToBeChanged())); + model, &QAbstractItemModel::layoutAboutToBeChanged); QSignalSpy layoutChangedSpy( - model, SIGNAL(layoutChanged())); + model, &QAbstractItemModel::layoutChanged); one->sortChildren(0, Qt::DescendingOrder); // verify sorted @@ -1040,19 +1032,16 @@ void tst_QStandardItem::sortChildren() class CustomItem : public QStandardItem { public: - CustomItem(const QString &text) : QStandardItem(text) { } - CustomItem() { } - virtual ~CustomItem() { } + using QStandardItem::QStandardItem; - virtual int type() const { return QStandardItem::UserType + 1; } + int type() const override { return QStandardItem::UserType + 1; } - virtual QStandardItem *clone() const { return QStandardItem::clone(); } - - void emitDataChanged() { QStandardItem::emitDataChanged(); } - - virtual bool operator<(const QStandardItem &other) const { + bool operator<(const QStandardItem &other) const override { return text().length() < other.text().length(); } + + using QStandardItem::clone; + using QStandardItem::emitDataChanged; }; Q_DECLARE_METATYPE(QStandardItem*) @@ -1072,11 +1061,11 @@ void tst_QStandardItem::subclassing() QStandardItemModel model; model.appendRow(item); - QSignalSpy itemChangedSpy(&model, SIGNAL(itemChanged(QStandardItem*))); + QSignalSpy itemChangedSpy(&model, &QStandardItemModel::itemChanged); item->emitDataChanged(); QCOMPARE(itemChangedSpy.count(), 1); QCOMPARE(itemChangedSpy.at(0).count(), 1); - QCOMPARE(qvariant_cast(itemChangedSpy.at(0).at(0)), (QStandardItem*)item); + QCOMPARE(qvariant_cast(itemChangedSpy.at(0).at(0)), item); CustomItem *child0 = new CustomItem("cc"); CustomItem *child1 = new CustomItem("bbb"); @@ -1085,9 +1074,9 @@ void tst_QStandardItem::subclassing() item->appendRow(child1); item->appendRow(child2); item->sortChildren(0); - QCOMPARE(item->child(0), (QStandardItem*)child2); - QCOMPARE(item->child(1), (QStandardItem*)child0); - QCOMPARE(item->child(2), (QStandardItem*)child1); + QCOMPARE(item->child(0), child2); + QCOMPARE(item->child(1), child0); + QCOMPARE(item->child(2), child1); } void tst_QStandardItem::lessThan() diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp index 032f17c0a7d..65c99d34b5e 100644 --- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -29,7 +29,7 @@ #include -#include +#include #include #include @@ -134,28 +134,30 @@ private slots: void setItemPersistentIndex(); private: - QStandardItemModel *m_model; + QStandardItemModel *m_model = nullptr; QPersistentModelIndex persistent; - QVector rcParent; - QVector rcFirst; - QVector rcLast; + QVector rcParent = QVector(8); + QVector rcFirst = QVector(8, 0); + QVector rcLast = QVector(8, 0); QVector currentRoles; //return true if models have the same structure, and all child have the same text - bool compareModels(QStandardItemModel *model1, QStandardItemModel *model2); + static bool compareModels(QStandardItemModel *model1, QStandardItemModel *model2); //return true if models have the same structure, and all child have the same text - bool compareItems(QStandardItem *item1, QStandardItem *item2); + static bool compareItems(QStandardItem *item1, QStandardItem *item2); }; -static const int defaultSize = 3; +static constexpr int defaultSize = 3; Q_DECLARE_METATYPE(QStandardItem*) Q_DECLARE_METATYPE(Qt::Orientation) -tst_QStandardItemModel::tst_QStandardItemModel() : m_model(0), rcParent(8), rcFirst(8,0), rcLast(8,0) +tst_QStandardItemModel::tst_QStandardItemModel() { qRegisterMetaType("QStandardItem*"); qRegisterMetaType("Qt::Orientation"); + qRegisterMetaType("QAbstractItemModel::LayoutChangeHint"); + qRegisterMetaType>("QList"); } /* @@ -171,23 +173,23 @@ tst_QStandardItemModel::tst_QStandardItemModel() : m_model(0), rcParent(8), rcFi void tst_QStandardItemModel::init() { m_model = new QStandardItemModel(defaultSize, defaultSize); - connect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int))); - connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int))); - connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); - connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); + connect(m_model, &QStandardItemModel::rowsAboutToBeInserted, + this, &tst_QStandardItemModel::rowsAboutToBeInserted); + connect(m_model, &QStandardItemModel::rowsInserted, + this, &tst_QStandardItemModel::rowsInserted); + connect(m_model, &QStandardItemModel::rowsAboutToBeRemoved, + this, &tst_QStandardItemModel::rowsAboutToBeRemoved); + connect(m_model, &QStandardItemModel::rowsRemoved, + this, &tst_QStandardItemModel::rowsRemoved); - connect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(columnsAboutToBeInserted(QModelIndex,int,int))); - connect(m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(columnsInserted(QModelIndex,int,int))); - connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(columnsRemoved(QModelIndex,int,int))); + connect(m_model, &QStandardItemModel::columnsAboutToBeInserted, + this, &tst_QStandardItemModel::columnsAboutToBeInserted); + connect(m_model, &QStandardItemModel::columnsInserted, + this, &tst_QStandardItemModel::columnsInserted); + connect(m_model, &QStandardItemModel::columnsAboutToBeRemoved, + this, &tst_QStandardItemModel::columnsAboutToBeRemoved); + connect(m_model, &QStandardItemModel::columnsRemoved, + this, &tst_QStandardItemModel::columnsRemoved); connect(m_model, &QAbstractItemModel::dataChanged, this, [this](const QModelIndex &, const QModelIndex &, const QVector &roles) @@ -201,25 +203,9 @@ void tst_QStandardItemModel::init() void tst_QStandardItemModel::cleanup() { - disconnect(m_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int))); - disconnect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int))); - disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); - - disconnect(m_model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(columnsAboutToBeInserted(QModelIndex,int,int))); - disconnect(m_model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(columnsInserted(QModelIndex,int,int))); - disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(columnsRemoved(QModelIndex,int,int))); + m_model->disconnect(this); delete m_model; - m_model = 0; + m_model = nullptr; } void tst_QStandardItemModel::insertRow_data() @@ -241,9 +227,9 @@ void tst_QStandardItemModel::insertRow() QIcon icon; // default all initial items to DisplayRole: "initalitem" - for (int r=0; r < m_model->rowCount(); ++r) { - for (int c=0; c < m_model->columnCount(); ++c) { - m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole); + for (int r = 0; r < m_model->rowCount(); ++r) { + for (int c = 0; c < m_model->columnCount(); ++c) { + m_model->setData(m_model->index(r, c), "initialitem", Qt::DisplayRole); } } @@ -307,7 +293,7 @@ void tst_QStandardItemModel::insertRowsItems() int rowCount = m_model->rowCount(); QList items; - QStandardItemModel *m = qobject_cast(m_model); + QStandardItemModel *m = m_model; QStandardItem *hiddenRoot = m->invisibleRootItem(); for (int i = 0; i < 3; ++i) items.append(new QStandardItem(QString::number(i + 10))); @@ -318,7 +304,7 @@ void tst_QStandardItemModel::insertRowsItems() QCOMPARE(m_model->index(rowCount + 2, 0).data().toInt(), 12); for (int i = rowCount; i < rowCount + 3; ++i) { QVERIFY(m->item(i)); - QCOMPARE(static_cast(m->item(i)->model()), m_model); + QCOMPARE(m->item(i)->model(), m_model); } } @@ -357,9 +343,9 @@ void tst_QStandardItemModel::insertColumn() QFETCH(int, expectedColumn); // default all initial items to DisplayRole: "initalitem" - for (int r=0; r < m_model->rowCount(); ++r) { - for (int c=0; c < m_model->columnCount(); ++c) { - m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole); + for (int r = 0; r < m_model->rowCount(); ++r) { + for (int c = 0; c < m_model->columnCount(); ++c) { + m_model->setData(m_model->index(r, c), "initialitem", Qt::DisplayRole); } } @@ -475,9 +461,9 @@ void tst_QStandardItemModel::setHeaderData() QCOMPARE(m_model->headerData(i, orient).toString(), QString::number(i + 1)); QSignalSpy headerDataChangedSpy( - m_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int))); + m_model, &QAbstractItemModel::headerDataChanged); QSignalSpy dataChangedSpy( - m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + m_model, &QAbstractItemModel::dataChanged); // insert custom values and check for (int i = 0; i < count; ++i) { QString customString = QString("custom") + QString::number(i); @@ -593,14 +579,14 @@ void tst_QStandardItemModel::removingPersistentIndexes() QVERIFY(m_model->insertRows(0, 10)); QVERIFY(m_model->insertColumns(0, 10)); - QObject::connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(checkAboutToBeRemoved())); - QObject::connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(checkRemoved())); - QObject::connect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(checkAboutToBeRemoved())); - QObject::connect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(checkRemoved())); + connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &tst_QStandardItemModel::checkAboutToBeRemoved); + connect(m_model, &QAbstractItemModel::rowsRemoved, + this, &tst_QStandardItemModel::checkRemoved); + connect(m_model, &QAbstractItemModel::columnsAboutToBeRemoved, + this, &tst_QStandardItemModel::checkAboutToBeRemoved); + connect(m_model, &QAbstractItemModel::columnsRemoved, + this, &tst_QStandardItemModel::checkRemoved); // test removeRow @@ -635,14 +621,14 @@ void tst_QStandardItemModel::removingPersistentIndexes() QVERIFY(m_model->removeColumn(0)); - QObject::disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(checkAboutToBeRemoved())); - QObject::disconnect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(checkRemoved())); - QObject::disconnect(m_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(checkAboutToBeRemoved())); - QObject::disconnect(m_model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(checkRemoved())); + disconnect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &tst_QStandardItemModel::checkAboutToBeRemoved); + disconnect(m_model, &QAbstractItemModel::rowsRemoved, + this, &tst_QStandardItemModel::checkRemoved); + disconnect(m_model, &QAbstractItemModel::columnsAboutToBeRemoved, + this, &tst_QStandardItemModel::checkAboutToBeRemoved); + disconnect(m_model, &QAbstractItemModel::columnsRemoved, + this, &tst_QStandardItemModel::checkRemoved); } void tst_QStandardItemModel::updateRowAboutToBeRemoved() @@ -654,8 +640,8 @@ void tst_QStandardItemModel::updateRowAboutToBeRemoved() void tst_QStandardItemModel::updatingPersistentIndexes() { - QObject::connect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(updateRowAboutToBeRemoved())); + connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &tst_QStandardItemModel::updateRowAboutToBeRemoved); persistent = m_model->index(1, 0); QVERIFY(persistent.isValid()); @@ -664,8 +650,8 @@ void tst_QStandardItemModel::updatingPersistentIndexes() QPersistentModelIndex tmp = m_model->index(0, 0); QCOMPARE(persistent, tmp); - QObject::disconnect(m_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(updateRowAboutToBeRemoved())); + disconnect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &tst_QStandardItemModel::updateRowAboutToBeRemoved); } void tst_QStandardItemModel::modelChanged(ModelChanged change, const QModelIndex &parent, @@ -738,8 +724,8 @@ void tst_QStandardItemModel::data() QCOMPARE(currentRoles, QVector{}); QIcon icon; - for (int r=0; r < m_model->rowCount(); ++r) { - for (int c=0; c < m_model->columnCount(); ++c) { + for (int r = 0; r < m_model->rowCount(); ++r) { + for (int c = 0; c < m_model->columnCount(); ++c) { m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole); QCOMPARE(currentRoles, QVector({Qt::DisplayRole, Qt::EditRole})); m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole); @@ -787,9 +773,9 @@ void tst_QStandardItemModel::clear() QCOMPARE(model.columnCount(), 10); QCOMPARE(model.rowCount(), 10); - QSignalSpy modelResetSpy(&model, SIGNAL(modelReset())); - QSignalSpy layoutChangedSpy(&model, SIGNAL(layoutChanged())); - QSignalSpy rowsRemovedSpy(&model, SIGNAL(rowsRemoved(QModelIndex,int,int))); + QSignalSpy modelResetSpy(&model, &QStandardItemModel::modelReset); + QSignalSpy layoutChangedSpy(&model, &QStandardItemModel::layoutChanged); + QSignalSpy rowsRemovedSpy(&model, &QStandardItemModel::rowsRemoved); QAbstractItemModelTester mt(&model); @@ -806,129 +792,35 @@ void tst_QStandardItemModel::clear() void tst_QStandardItemModel::sort_data() { - QTest::addColumn("sortOrder"); + QTest::addColumn("sortOrder"); QTest::addColumn("initial"); QTest::addColumn("expected"); - QTest::newRow("flat descending") << static_cast(Qt::DescendingOrder) - << (QStringList() - << "delta" - << "yankee" - << "bravo" - << "lima" - << "charlie" - << "juliet" - << "tango" - << "hotel" - << "uniform" - << "alpha" - << "echo" - << "golf" - << "quebec" - << "foxtrot" - << "india" - << "romeo" - << "november" - << "oskar" - << "zulu" - << "kilo" - << "whiskey" - << "mike" - << "papa" - << "sierra" - << "xray" - << "viktor") - << (QStringList() - << "zulu" - << "yankee" - << "xray" - << "whiskey" - << "viktor" - << "uniform" - << "tango" - << "sierra" - << "romeo" - << "quebec" - << "papa" - << "oskar" - << "november" - << "mike" - << "lima" - << "kilo" - << "juliet" - << "india" - << "hotel" - << "golf" - << "foxtrot" - << "echo" - << "delta" - << "charlie" - << "bravo" - << "alpha"); - QTest::newRow("flat ascending") << static_cast(Qt::AscendingOrder) - << (QStringList() - << "delta" - << "yankee" - << "bravo" - << "lima" - << "charlie" - << "juliet" - << "tango" - << "hotel" - << "uniform" - << "alpha" - << "echo" - << "golf" - << "quebec" - << "foxtrot" - << "india" - << "romeo" - << "november" - << "oskar" - << "zulu" - << "kilo" - << "whiskey" - << "mike" - << "papa" - << "sierra" - << "xray" - << "viktor") - << (QStringList() - << "alpha" - << "bravo" - << "charlie" - << "delta" - << "echo" - << "foxtrot" - << "golf" - << "hotel" - << "india" - << "juliet" - << "kilo" - << "lima" - << "mike" - << "november" - << "oskar" - << "papa" - << "quebec" - << "romeo" - << "sierra" - << "tango" - << "uniform" - << "viktor" - << "whiskey" - << "xray" - << "yankee" - << "zulu"); + const QStringList unsorted( + {"delta", "yankee", "bravo", "lima", "charlie", "juliet", + "tango", "hotel", "uniform", "alpha", "echo", "golf", + "quebec", "foxtrot", "india", "romeo", "november", + "oskar", "zulu", "kilo", "whiskey", "mike", "papa", + "sierra", "xray" , "viktor"}); + QStringList sorted = unsorted; + + std::sort(sorted.begin(), sorted.end()); + QTest::newRow("flat ascending") << Qt::AscendingOrder + << unsorted + << sorted; + std::reverse(sorted.begin(), sorted.end()); + QTest::newRow("flat descending") << Qt::DescendingOrder + << unsorted + << sorted; QStringList list; - for (int i=1000; i < 2000; ++i) + for (int i = 1000; i < 2000; ++i) list.append(QStringLiteral("Number: ") + QString::number(i)); - QTest::newRow("large set ascending") << static_cast(Qt::AscendingOrder) << list << list; + QTest::newRow("large set ascending") << Qt::AscendingOrder << list << list; } void tst_QStandardItemModel::sort() { - QFETCH(int, sortOrder); + QFETCH(Qt::SortOrder, sortOrder); QFETCH(QStringList, initial); QFETCH(QStringList, expected); // prepare model @@ -943,12 +835,12 @@ void tst_QStandardItemModel::sort() } QSignalSpy layoutAboutToBeChangedSpy( - &model, SIGNAL(layoutAboutToBeChanged())); + &model, &QStandardItemModel::layoutAboutToBeChanged); QSignalSpy layoutChangedSpy( - &model, SIGNAL(layoutChanged())); + &model, &QStandardItemModel::layoutChanged); // sort - model.sort(0, static_cast(sortOrder)); + model.sort(0, sortOrder); QCOMPARE(layoutAboutToBeChangedSpy.count(), 1); QCOMPARE(layoutChangedSpy.count(), 1); @@ -964,23 +856,23 @@ void tst_QStandardItemModel::sortRole_data() { QTest::addColumn("initialText"); QTest::addColumn("initialData"); - QTest::addColumn("sortRole"); - QTest::addColumn("sortOrder"); + QTest::addColumn("sortRole"); + QTest::addColumn("sortOrder"); QTest::addColumn("expectedText"); QTest::addColumn("expectedData"); QTest::newRow("sort ascending with Qt::DisplayRole") << (QStringList() << "b" << "a" << "c") << (QVariantList() << 2 << 3 << 1) - << static_cast(Qt::DisplayRole) - << static_cast(Qt::AscendingOrder) + << Qt::DisplayRole + << Qt::AscendingOrder << (QStringList() << "a" << "b" << "c") << (QVariantList() << 3 << 2 << 1); QTest::newRow("sort ascending with Qt::UserRole") << (QStringList() << "a" << "b" << "c") << (QVariantList() << 3 << 2 << 1) - << static_cast(Qt::UserRole) - << static_cast(Qt::AscendingOrder) + << Qt::UserRole + << Qt::AscendingOrder << (QStringList() << "c" << "b" << "a") << (QVariantList() << 1 << 2 << 3); } @@ -989,8 +881,8 @@ void tst_QStandardItemModel::sortRole() { QFETCH(QStringList, initialText); QFETCH(QVariantList, initialData); - QFETCH(int, sortRole); - QFETCH(int, sortOrder); + QFETCH(Qt::ItemDataRole, sortRole); + QFETCH(Qt::SortOrder, sortOrder); QFETCH(QStringList, expectedText); QFETCH(QVariantList, expectedData); @@ -1002,7 +894,7 @@ void tst_QStandardItemModel::sortRole() model.appendRow(item); } model.setSortRole(sortRole); - model.sort(0, static_cast(sortOrder)); + model.sort(0, sortOrder); for (int i = 0; i < expectedText.count(); ++i) { QStandardItem *item = model.item(i); QCOMPARE(item->text(), expectedText.at(i)); @@ -1033,23 +925,23 @@ void tst_QStandardItemModel::getSetHeaderItem() { QStandardItemModel model; - QCOMPARE(model.horizontalHeaderItem(0), static_cast(0)); + QCOMPARE(model.horizontalHeaderItem(0), nullptr); QStandardItem *hheader = new QStandardItem(); model.setHorizontalHeaderItem(0, hheader); QCOMPARE(model.columnCount(), 1); QCOMPARE(model.horizontalHeaderItem(0), hheader); QCOMPARE(hheader->model(), &model); - model.setHorizontalHeaderItem(0, 0); - QCOMPARE(model.horizontalHeaderItem(0), static_cast(0)); + model.setHorizontalHeaderItem(0, nullptr); + QCOMPARE(model.horizontalHeaderItem(0), nullptr); - QCOMPARE(model.verticalHeaderItem(0), static_cast(0)); + QCOMPARE(model.verticalHeaderItem(0), nullptr); QStandardItem *vheader = new QStandardItem(); model.setVerticalHeaderItem(0, vheader); QCOMPARE(model.rowCount(), 1); QCOMPARE(model.verticalHeaderItem(0), vheader); QCOMPARE(vheader->model(), &model); - model.setVerticalHeaderItem(0, 0); - QCOMPARE(model.verticalHeaderItem(0), static_cast(0)); + model.setVerticalHeaderItem(0, nullptr); + QCOMPARE(model.verticalHeaderItem(0), nullptr); } void tst_QStandardItemModel::indexFromItem() @@ -1066,7 +958,7 @@ void tst_QStandardItemModel::indexFromItem() QCOMPARE(itemIndex.row(), 10); QCOMPARE(itemIndex.column(), 20); QCOMPARE(itemIndex.parent(), QModelIndex()); - QCOMPARE(itemIndex.model(), (const QAbstractItemModel*)(&model)); + QCOMPARE(itemIndex.model(), &model); QStandardItem *child = new QStandardItem; item->setChild(4, 2, child); @@ -1081,7 +973,7 @@ void tst_QStandardItemModel::indexFromItem() QVERIFY(!noSuchIndex.isValid()); delete dummy; - noSuchIndex = model.indexFromItem(0); + noSuchIndex = model.indexFromItem(nullptr); QVERIFY(!noSuchIndex.isValid()); } @@ -1089,7 +981,7 @@ void tst_QStandardItemModel::itemFromIndex() { QStandardItemModel model; - QCOMPARE(model.itemFromIndex(QModelIndex()), (QStandardItem*)0); + QCOMPARE(model.itemFromIndex(QModelIndex()), nullptr); QStandardItem *item = new QStandardItem; model.setItem(10, 20, item); @@ -1110,35 +1002,31 @@ void tst_QStandardItemModel::itemFromIndex() class CustomItem : public QStandardItem { public: - CustomItem() : QStandardItem() { } - ~CustomItem() { } - int type() const { - return UserType; - } - QStandardItem *clone() const { - return new CustomItem; - } + using QStandardItem::QStandardItem; + + int type() const override { return UserType; } + QStandardItem *clone() const override { return new CustomItem; } }; void tst_QStandardItemModel::getSetItemPrototype() { QStandardItemModel model; - QCOMPARE(model.itemPrototype(), static_cast(0)); + QCOMPARE(model.itemPrototype(), nullptr); const CustomItem *proto = new CustomItem; model.setItemPrototype(proto); - QCOMPARE(model.itemPrototype(), (const QStandardItem*)proto); + QCOMPARE(model.itemPrototype(), proto); model.setRowCount(1); model.setColumnCount(1); QModelIndex index = model.index(0, 0, QModelIndex()); model.setData(index, "foo"); QStandardItem *item = model.itemFromIndex(index); - QVERIFY(item != 0); + QVERIFY(item != nullptr); QCOMPARE(item->type(), static_cast(QStandardItem::UserType)); - model.setItemPrototype(0); - QCOMPARE(model.itemPrototype(), static_cast(0)); + model.setItemPrototype(nullptr); + QCOMPARE(model.itemPrototype(), nullptr); } void tst_QStandardItemModel::getSetItemData() @@ -1175,7 +1063,7 @@ void tst_QStandardItemModel::getSetItemData() QModelIndex idx = model.index(0, 0, QModelIndex()); QSignalSpy modelDataChangedSpy( - &model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); + &model, &QStandardItemModel::dataChanged); QVERIFY(model.setItemData(idx, roles)); QCOMPARE(modelDataChangedSpy.count(), 1); QVERIFY(model.setItemData(idx, roles)); @@ -1187,44 +1075,44 @@ void tst_QStandardItemModel::setHeaderLabels_data() { QTest::addColumn("rows"); QTest::addColumn("columns"); - QTest::addColumn("orientation"); + QTest::addColumn("orientation"); QTest::addColumn("labels"); QTest::addColumn("expectedLabels"); QTest::newRow("horizontal labels") << 1 << 4 - << int(Qt::Horizontal) + << Qt::Horizontal << (QStringList() << "a" << "b" << "c" << "d") << (QStringList() << "a" << "b" << "c" << "d"); QTest::newRow("vertical labels") << 4 << 1 - << int(Qt::Vertical) + << Qt::Vertical << (QStringList() << "a" << "b" << "c" << "d") << (QStringList() << "a" << "b" << "c" << "d"); QTest::newRow("too few (horizontal)") << 1 << 4 - << int(Qt::Horizontal) + << Qt::Horizontal << (QStringList() << "a" << "b") << (QStringList() << "a" << "b" << "3" << "4"); QTest::newRow("too few (vertical)") << 4 << 1 - << int(Qt::Vertical) + << Qt::Vertical << (QStringList() << "a" << "b") << (QStringList() << "a" << "b" << "3" << "4"); QTest::newRow("too many (horizontal)") << 1 << 2 - << int(Qt::Horizontal) + << Qt::Horizontal << (QStringList() << "a" << "b" << "c" << "d") << (QStringList() << "a" << "b" << "c" << "d"); QTest::newRow("too many (vertical)") << 2 << 1 - << int(Qt::Vertical) + << Qt::Vertical << (QStringList() << "a" << "b" << "c" << "d") << (QStringList() << "a" << "b" << "c" << "d"); } @@ -1233,20 +1121,18 @@ void tst_QStandardItemModel::setHeaderLabels() { QFETCH(int, rows); QFETCH(int, columns); - QFETCH(int, orientation); + QFETCH(Qt::Orientation, orientation); QFETCH(QStringList, labels); QFETCH(QStringList, expectedLabels); QStandardItemModel model(rows, columns); - QSignalSpy columnsInsertedSpy( - &model, SIGNAL(columnsInserted(QModelIndex,int,int))); - QSignalSpy rowsInsertedSpy( - &model, SIGNAL(rowsInserted(QModelIndex,int,int))); + QSignalSpy columnsInsertedSpy(&model, &QAbstractItemModel::columnsInserted); + QSignalSpy rowsInsertedSpy(&model, &QAbstractItemModel::rowsInserted); if (orientation == Qt::Horizontal) model.setHorizontalHeaderLabels(labels); else model.setVerticalHeaderLabels(labels); for (int i = 0; i < expectedLabels.count(); ++i) - QCOMPARE(model.headerData(i, Qt::Orientation(orientation)).toString(), expectedLabels.at(i)); + QCOMPARE(model.headerData(i, orientation).toString(), expectedLabels.at(i)); QCOMPARE(columnsInsertedSpy.count(), (orientation == Qt::Vertical) ? 0 : labels.count() > columns); QCOMPARE(rowsInsertedSpy.count(), @@ -1257,10 +1143,8 @@ void tst_QStandardItemModel::itemDataChanged() { QStandardItemModel model(6, 4); QStandardItem item; - QSignalSpy dataChangedSpy( - &model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); - QSignalSpy itemChangedSpy( - &model, SIGNAL(itemChanged(QStandardItem*))); + QSignalSpy dataChangedSpy(&model, &QStandardItemModel::dataChanged); + QSignalSpy itemChangedSpy(&model, &QStandardItemModel::itemChanged); model.setItem(0, &item); QCOMPARE(dataChangedSpy.count(), 1); @@ -1304,19 +1188,17 @@ void tst_QStandardItemModel::takeHeaderItem() { QStandardItemModel model; // set header items - QStandardItem *hheader = new QStandardItem(); - model.setHorizontalHeaderItem(0, hheader); - QStandardItem *vheader = new QStandardItem(); - model.setVerticalHeaderItem(0, vheader); + QScopedPointer hheader(new QStandardItem()); + model.setHorizontalHeaderItem(0, hheader.get()); + QScopedPointer vheader(new QStandardItem()); + model.setVerticalHeaderItem(0, vheader.get()); // take header items - QCOMPARE(model.takeHorizontalHeaderItem(0), hheader); - QCOMPARE(model.takeVerticalHeaderItem(0), vheader); - QCOMPARE(hheader->model(), static_cast(0)); - QCOMPARE(vheader->model(), static_cast(0)); - QCOMPARE(model.takeHorizontalHeaderItem(0), static_cast(0)); - QCOMPARE(model.takeVerticalHeaderItem(0), static_cast(0)); - delete hheader; - delete vheader; + QCOMPARE(model.takeHorizontalHeaderItem(0), hheader.get()); + QCOMPARE(model.takeVerticalHeaderItem(0), vheader.get()); + QCOMPARE(hheader->model(), nullptr); + QCOMPARE(vheader->model(), nullptr); + QCOMPARE(model.takeHorizontalHeaderItem(0), nullptr); + QCOMPARE(model.takeVerticalHeaderItem(0), nullptr); } void tst_QStandardItemModel::useCase1() @@ -1326,7 +1208,7 @@ void tst_QStandardItemModel::useCase1() QStandardItemModel model(rows, columns); for (int i = 0; i < model.rowCount(); ++i) { for (int j = 0; j < model.columnCount(); ++j) { - QCOMPARE(model.item(i, j), static_cast(0)); + QCOMPARE(model.item(i, j), nullptr); QStandardItem *item = new QStandardItem(); model.setItem(i, j, item); @@ -1361,7 +1243,7 @@ static void createChildren(QStandardItemModel *model, QStandardItem *parent, int QStandardItem *theItem = model->itemFromIndex(index); QCOMPARE(theItem, item); QStandardItem *theParent = model->itemFromIndex(parentIndex); - QCOMPARE(theParent, (level == 0) ? (QStandardItem*)0 : parent); + QCOMPARE(theParent, (level == 0) ? static_cast(nullptr) : parent); } { @@ -1382,7 +1264,7 @@ void tst_QStandardItemModel::useCase2() void tst_QStandardItemModel::useCase3() { // create the tree structure first - QStandardItem *childItem = 0; + QStandardItem *childItem = nullptr; for (int i = 0; i < 100; ++i) { QStandardItem *item = new QStandardItem(QStringLiteral("item ") + QString::number(i)); if (childItem) @@ -1395,7 +1277,7 @@ void tst_QStandardItemModel::useCase3() model.appendRow(childItem); // make sure each item has the correct model and parent - QStandardItem *parentItem = 0; + QStandardItem *parentItem = nullptr; while (childItem) { QCOMPARE(childItem->model(), &model); QCOMPARE(childItem->parent(), parentItem); @@ -1406,10 +1288,10 @@ void tst_QStandardItemModel::useCase3() // take the item, make sure model is set to 0, but that parents are the same childItem = model.takeItem(0); { - parentItem = 0; + parentItem = nullptr; QStandardItem *item = childItem; while (item) { - QCOMPARE(item->model(), static_cast(0)); + QCOMPARE(item->model(), nullptr); QCOMPARE(item->parent(), parentItem); parentItem = item; item = item->child(0); @@ -1424,7 +1306,7 @@ void tst_QStandardItemModel::setNullChild() model.setColumnCount(2); createChildren(&model, model.invisibleRootItem(), 0); QStandardItem *item = model.item(0); - QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector))); + QSignalSpy spy(&model, &QAbstractItemModel::dataChanged); item->setChild(0, nullptr); QCOMPARE(item->child(0), nullptr); QCOMPARE(spy.count(), 1); @@ -1436,7 +1318,7 @@ void tst_QStandardItemModel::deleteChild() model.setColumnCount(2); createChildren(&model, model.invisibleRootItem(), 0); QStandardItem *item = model.item(0); - QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector))); + QSignalSpy spy(&model, &QAbstractItemModel::dataChanged); delete item->child(0); QCOMPARE(item->child(0), nullptr); QCOMPARE(spy.count(), 1); @@ -1471,7 +1353,7 @@ bool tst_QStandardItemModel::compareItems(QStandardItem *item1, QStandardItem *i return true; if (!item1 || !item2) return false; - if (item1->text() != item2->text()){ + if (item1->text() != item2->text()) { qDebug() << item1->text() << item2->text(); return false; } @@ -1483,39 +1365,36 @@ bool tst_QStandardItemModel::compareItems(QStandardItem *item1, QStandardItem *i // qDebug() << "ColumnCount" << item1->text() << item1->columnCount() << item2->columnCount(); return false; } - for (int row = 0; row < item1->columnCount(); row++) + for (int row = 0; row < item1->columnCount(); row++) { for (int col = 0; col < item1->columnCount(); col++) { - - if (!compareItems(item1->child(row, col), item2->child(row, col))) - return false; + if (!compareItems(item1->child(row, col), item2->child(row, col))) + return false; + } } return true; } static QStandardItem *itemFromText(QStandardItem *parent, const QString &text) { - QStandardItem *item = 0; - for(int i = 0; i < parent->columnCount(); i++) - for(int j = 0; j < parent->rowCount(); j++) { + QStandardItem *item = nullptr; + for (int i = 0; i < parent->columnCount(); i++) { + for (int j = 0; j < parent->rowCount(); j++) { + QStandardItem *child = parent->child(j, i); + if (!child) + continue; - QStandardItem *child = parent->child(j, i); - - if(!child) - continue; - - if (child->text() == text) { - if (item) { - return 0; + if (child->text() == text) { + if (item) + return nullptr; + item = child; } - item = child; - } - QStandardItem *candidate = itemFromText(child, text); - if(candidate) { - if (item) { - return 0; + QStandardItem *candidate = itemFromText(child, text); + if (candidate) { + if (item) + return nullptr; + item = candidate; } - item = candidate; } } return item; From f494e8b58d8a02508d2809b29b0bd0019018965a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 14 Jan 2020 08:42:50 +0100 Subject: [PATCH 16/20] Build the securesocketclient example for other SSL backends Change-Id: I06b8361c116d2ae2aa2a64f63ac90b6ff1982008 Reviewed-by: Jesus Fernandez --- examples/network/network.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/network/network.pro b/examples/network/network.pro index 1556e26ab16..af3c0df43ef 100644 --- a/examples/network/network.pro +++ b/examples/network/network.pro @@ -29,7 +29,7 @@ qtHaveModule(widgets) { } - qtConfig(openssl): SUBDIRS += securesocketclient + qtConfig(ssl): SUBDIRS += securesocketclient qtConfig(dtls): SUBDIRS += secureudpserver secureudpclient qtConfig(sctp): SUBDIRS += multistreamserver multistreamclient } From 0f568d0a671e9f0667a1b47ffa6fbb9f7a10d9f5 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 14 Jan 2020 10:24:38 +0100 Subject: [PATCH 17/20] Uncomment erroneously commented 'error' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was meant to be deprecated in 5.15, not deleted (yet). Change-Id: I6e3772d6c1d12dc060c1f540e55e756566db22e6 Reviewed-by: Mรฅrten Nordheim --- src/network/access/qnetworkreply.cpp | 2 -- src/network/access/qnetworkreply.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 0a5a17a3b84..c22dce8f1c3 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -565,12 +565,10 @@ QNetworkAccessManager::Operation QNetworkReply::operation() const \sa setError(), networkError() */ -/* QNetworkReply::NetworkError QNetworkReply::error() const { return networkError(); } -*/ #endif // QT_DEPRECATED_SINCE(5, 15) /*! diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 1bcb6d9680f..139009a56ab 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -126,7 +126,7 @@ public: QNetworkRequest request() const; #if QT_DEPRECATED_SINCE(5, 15) - // QT_DEPRECATED_X("Use networkError()") NetworkError error() const; + QT_DEPRECATED_X("Use networkError()") NetworkError error() const; #endif // QT_DEPRECATED_SINCE(5, 15) NetworkError networkError() const; From 052f3db7e68eac7eabaae79991431884de8e835a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 13 Jan 2020 16:45:28 +0100 Subject: [PATCH 18/20] qshader autotest: Avoid variable shadowing Nicer this way. Change-Id: Ia132b8e394f1080623abe4b1452a41c5ca31272c Reviewed-by: Johan Helsing --- tests/auto/gui/rhi/qshader/tst_qshader.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp index b90ac8dc53d..ab7115b74a1 100644 --- a/tests/auto/gui/rhi/qshader/tst_qshader.cpp +++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp @@ -389,10 +389,12 @@ void tst_QShader::serializeShaderDesc() } QVERIFY(!data.isEmpty()); - QShaderDescription desc2; - QVERIFY(!desc2.isValid()); - QVERIFY(!(desc == desc2)); - QVERIFY(desc != desc2); + { + QShaderDescription desc2; + QVERIFY(!desc2.isValid()); + QVERIFY(!(desc == desc2)); + QVERIFY(desc != desc2); + } { QBuffer buf(&data); From 4e93e3b574390829c4c3c87716e0a9bb5ed579e4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 14 Jan 2020 11:32:21 +0100 Subject: [PATCH 19/20] Add documentation for the widget gallery Task-number: PYSIDE-1112 Change-Id: I35fe85d8ac9c2dab9f1260d3736c7f65e8e45d8e Reviewed-by: Paul Wicking --- examples/widgets/doc/src/gallery.qdoc | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 examples/widgets/doc/src/gallery.qdoc diff --git a/examples/widgets/doc/src/gallery.qdoc b/examples/widgets/doc/src/gallery.qdoc new file mode 100644 index 00000000000..a262374ce63 --- /dev/null +++ b/examples/widgets/doc/src/gallery.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example widgets/gallery + \title Widgets Gallery Example + \ingroup examples-widgets + \brief The Widgets Gallery example shows widgets relevant for designing UIs. + + This example demonstrates widgets typically used in dialogs and forms. + It also allows for changing the style. +*/ From 2cbc5f6f7ae8ba580126a7cafc1898377c2a2407 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 3 Jan 2020 12:07:43 +0100 Subject: [PATCH 20/20] Fix -Wdeprecated-copy warning QDBusReply has an user-specified operator= but no copy constructor. Change-Id: If7fcec3193af375f1bf2dd913d82548d6e035b48 Reviewed-by: Thiago Macieira --- src/dbus/qdbusreply.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dbus/qdbusreply.h b/src/dbus/qdbusreply.h index 869687ac85a..8cdc0ae2466 100644 --- a/src/dbus/qdbusreply.h +++ b/src/dbus/qdbusreply.h @@ -64,6 +64,7 @@ public: { *this = reply; } + inline QDBusReply(const QDBusReply &) = default; inline QDBusReply& operator=(const QDBusMessage &reply) { QVariant data(qMetaTypeId(), nullptr);