From fcb78b500076bf3917e5d8bf8507395bbc33a1a5 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 17 Sep 2019 09:56:14 +0300 Subject: Android: Fix plugins naming Android 5 doesn't extract the files from libs folder unless they are prefixed with "lib". This patch sets a proper name for the plugin which will make gdb happy and it will also avoid any name clashes. If we rename the plugins when we copy them, gdb won't find them, therefore it can't load their symbols. On Android all the libs are in a single folder, so to make sure we don't have any name clashes, we are prefixing the plugin name with it's relative path to qt folder (we replace / with _). Fixes: QTBUG-78616 Change-Id: I7e0e67d65448532769d69f46b1856c029e2cf5cb Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/corelib.pro | 2 +- src/corelib/plugin/qfactoryloader.cpp | 2 +- src/network/network.pro | 2 +- src/tools/androiddeployqt/main.cpp | 20 +++++++++++--------- 4 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index ba5f5adf8d..452d2db0fd 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -21,7 +21,7 @@ CONFIG += simd optimize_full QMAKE_DOCS = $$PWD/doc/qtcore.qdocconf ANDROID_LIB_DEPENDENCIES = \ - plugins/platforms/libqtforandroid.so + plugins/platforms/libplugins_platforms_qtforandroid.so ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtAndroid.jar ANDROID_PERMISSIONS = \ diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 79315ae50f..18f10c9b43 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -209,7 +209,7 @@ void QFactoryLoader::update() #if defined(Q_OS_WIN) QStringList(QStringLiteral("*.dll")), #elif defined(Q_OS_ANDROID) - QStringList(QLatin1String("plugins_%1_*.so").arg(d->suffix)), + QStringList(QLatin1String("libplugins_%1_*.so").arg(d->suffix)), #endif QDir::Files); QLibraryPrivate *library = 0; diff --git a/src/network/network.pro b/src/network/network.pro index 9082439f1c..d8453e879c 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -26,7 +26,7 @@ qtConfig(bearermanagement) { ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtAndroidBearer.jar ANDROID_LIB_DEPENDENCIES = \ - plugins/bearer/libqandroidbearer.so + plugins/bearer/libplugins_bearer_qandroidbearer.so MODULE_PLUGIN_TYPES = \ bearer ANDROID_PERMISSIONS += \ diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 794e3b49ae..6a32a659e6 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -314,10 +314,8 @@ static QString shellQuote(const QString &arg) QString architecureFromName(const QString &name) { - const QFileInfo fi(name); - const QString extractedFileName = fi.fileName(); - QRegExp architecture(QStringLiteral(".*_(.*)\\.so")); - if (!architecture.exactMatch(extractedFileName)) + QRegExp architecture(QStringLiteral(".*_(armeabi-v7a|arm64-v8a|x86|x86_64).so")); + if (!architecture.exactMatch(name)) return {}; return architecture.capturedTexts().last(); } @@ -1177,7 +1175,7 @@ bool copyAndroidExtraResources(Options *options) } else { if (!checkArchitecture(*options, originFile)) continue; - destinationFile = libsDir + QLatin1String("/lib") + QString(resourceDir.dirName() + QLatin1Char('/') + resourceFile).replace(QLatin1Char('/'), QLatin1Char('_')); + destinationFile = libsDir + resourceFile; options->archExtraPlugins[options->currentArchitecture] += resourceFile; } if (!copyFileIfNewer(originFile, destinationFile, *options)) @@ -1330,9 +1328,13 @@ bool updateLibsXml(Options *options) if (options->verbose) fprintf(stdout, " -- Using platform plugin %s\n", qPrintable(plugin)); } - allLocalLibs += QLatin1String(" %1;%2\n").arg(it.key(), localLibs.join(QLatin1Char(':')) - .replace(QLatin1String("lib/"), QString{}) - .replace(QLatin1Char('/'), QLatin1Char('_'))); + + // remove all paths + for (auto &lib : localLibs) { + if (lib.endsWith(QLatin1String(".so"))) + lib = lib.mid(lib.lastIndexOf(QLatin1Char('/')) + 1); + } + allLocalLibs += QLatin1String(" %1;%2\n").arg(it.key(), localLibs.join(QLatin1Char(':'))); } QHash replacements; @@ -2033,7 +2035,7 @@ bool copyQtFiles(Options *options) if (qtDependency.relativePath.startsWith(QLatin1String("lib/"))) { garbledFileName = qtDependency.relativePath.mid(sizeof("lib/") - 1); } else { - garbledFileName = QString(qtDependency.relativePath).replace(QLatin1Char('/'), QLatin1Char('_')); + garbledFileName = qtDependency.relativePath.mid(qtDependency.relativePath.lastIndexOf(QLatin1Char('/')) + 1); } destinationFileName = libsDirectory + options->currentArchitecture + QLatin1Char('/') + garbledFileName; } else if (qtDependency.relativePath.startsWith(QLatin1String("jar/"))) { -- cgit v1.2.3 From 72d62144ab2bf67266aa0474515b54999b459d32 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 30 Sep 2019 16:36:30 +0200 Subject: tslib plugin: remove debug print on old tslib versions This introduces a dependency on ts_get_eventpath(), which is only available in tslib 1.15 and newer. This raises the required version to an unneeded level, so just drop the debug message if the API is not available. Change-Id: I4a1cd7abec8d139e70555506d9d21edacf0f4d71 Fixes: QTBUG-78867 Reviewed-by: Shawn Rutledge Reviewed-by: Fabian Vogt --- src/platformsupport/input/tslib/qtslib.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/platformsupport/input/tslib/qtslib.cpp b/src/platformsupport/input/tslib/qtslib.cpp index df57147af6..e105f5ea98 100644 --- a/src/platformsupport/input/tslib/qtslib.cpp +++ b/src/platformsupport/input/tslib/qtslib.cpp @@ -68,7 +68,9 @@ QTsLibMouseHandler::QTsLibMouseHandler(const QString &key, return; } +#ifdef TSLIB_VERSION_EVENTPATH /* also introduced in 1.15 */ qCDebug(qLcTsLib) << "tslib device is" << ts_get_eventpath(m_dev); +#endif m_notify = new QSocketNotifier(ts_fd(m_dev), QSocketNotifier::Read, this); connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData); } -- cgit v1.2.3 From 6e203824a22bfb424032f27e11a5914c26bf0068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 1 Oct 2019 12:13:47 +0200 Subject: Move away from recently deprecated HTTP2 attributes Amends f59f67287fa17e8d4edf6a231c010f768d1b76e8 Change-Id: I74045c558e9d20f9f45f150a91f181a04e9b8c69 Reviewed-by: Friedemann Kleint --- src/network/access/qnetworkaccessmanager.cpp | 2 +- src/network/access/qnetworkreplyhttpimpl.cpp | 8 ++++---- src/network/access/qnetworkrequest.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 76b95b5823..98c82c81ae 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1240,7 +1240,7 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin // There is no way to enable SPDY/HTTP2 via a request, so we need to check // the ssl configuration whether SPDY/HTTP2 is allowed here. if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::ALPNProtocolHTTP2)) - request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); + request.setAttribute(QNetworkRequest::Http2AllowedAttribute, true); else if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::NextProtocolSpdy3_0)) request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 8ac81d1780..44c1d3e422 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -777,7 +777,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq if (request.attribute(QNetworkRequest::SpdyAllowedAttribute).toBool()) httpRequest.setSPDYAllowed(true); - if (request.attribute(QNetworkRequest::HTTP2AllowedAttribute).toBool()) + if (request.attribute(QNetworkRequest::Http2AllowedAttribute).toBool()) httpRequest.setHTTP2Allowed(true); if (request.attribute(QNetworkRequest::Http2DirectAttribute).toBool()) { @@ -1280,15 +1280,15 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QListsetAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu); - const QVariant http2Allowed = request.attribute(QNetworkRequest::HTTP2AllowedAttribute); + const QVariant http2Allowed = request.attribute(QNetworkRequest::Http2AllowedAttribute); const QVariant http2Direct = request.attribute(QNetworkRequest::Http2DirectAttribute); if ((http2Allowed.isValid() && http2Allowed.toBool()) || (http2Direct.isValid() && http2Direct.toBool())) { - q->setAttribute(QNetworkRequest::HTTP2WasUsedAttribute, spdyWasUsed); + q->setAttribute(QNetworkRequest::Http2WasUsedAttribute, spdyWasUsed); q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, false); } else { q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, spdyWasUsed); - q->setAttribute(QNetworkRequest::HTTP2WasUsedAttribute, false); + q->setAttribute(QNetworkRequest::Http2WasUsedAttribute, false); } // reconstruct the HTTP header diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index cedb1597de..7899bce32b 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -336,7 +336,7 @@ QT_BEGIN_NAMESPACE server supports HTTP/2. The attribute works with SSL or 'cleartext' HTTP/2. If a server turns out to not support HTTP/2, when HTTP/2 direct was specified, QNetworkAccessManager gives up, without attempting to - fall back to HTTP/1.1. If both HTTP2AllowedAttribute and + fall back to HTTP/1.1. If both Http2AllowedAttribute and Http2DirectAttribute are set, Http2DirectAttribute takes priority. (This value was introduced in 5.11.) -- cgit v1.2.3 From fb09a8bfcfb9caeb9066946a7340f60d1d6f169c Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 17 Sep 2019 09:56:07 +0300 Subject: Android: rework assets support The new version fix QDirIterators and it lists all the files and dirs. Change-Id: I5a30eedb61ab2397a84365d00f308cda0c194de2 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../src/org/qtproject/qt5/android/QtNative.java | 19 ++ src/plugins/platforms/android/androidjnimain.cpp | 11 +- src/plugins/platforms/android/androidjnimain.h | 1 + .../android/qandroidassetsfileenginehandler.cpp | 356 ++++++++++----------- .../android/qandroidassetsfileenginehandler.h | 8 - 5 files changed, 203 insertions(+), 192 deletions(-) (limited to 'src') diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index c33d5016ce..7db16002ff 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -1013,6 +1013,25 @@ public class QtNative }); } + private static String[] listAssetContent(android.content.res.AssetManager asset, String path) { + String [] list; + ArrayList res = new ArrayList(); + try { + list = asset.list(path); + if (list.length > 0) { + for (String file : list) { + try { + String[] isDir = asset.list(path.length() > 0 ? path + "/" + file : file); + if (isDir != null && isDir.length > 0) + file += "/"; + res.add(file); + } catch (Exception e) {} + } + } + } catch (Exception e) {} + return res.toArray(new String[res.size()]); + } + // screen methods public static native void setDisplayMetrics(int screenWidthPixels, int screenHeightPixels, diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 27eb337aaa..13ea9468df 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -75,6 +75,7 @@ static jclass m_applicationClass = nullptr; static jobject m_classLoaderObject = nullptr; static jmethodID m_loadClassMethodID = nullptr; static AAssetManager *m_assetManager = nullptr; +static jobject m_assets = nullptr; static jobject m_resourcesObj = nullptr; static jobject m_activityObject = nullptr; static jmethodID m_createSurfaceMethodID = nullptr; @@ -439,6 +440,11 @@ namespace QtAndroid return block; } + jobject assets() + { + return m_assets; + } + } // namespace QtAndroid static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring paramsString, jstring environmentString) @@ -588,6 +594,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/) env->DeleteGlobalRef(m_RGB_565_BitmapConfigValue); if (m_bitmapDrawableClass) env->DeleteGlobalRef(m_bitmapDrawableClass); + if (m_assets) + env->DeleteGlobalRef(m_assets); m_androidPlatformIntegration = nullptr; delete m_androidAssetsFileEngineHandler; m_androidAssetsFileEngineHandler = nullptr; @@ -840,7 +848,8 @@ static int registerNatives(JNIEnv *env) if (object) { FIND_AND_CHECK_CLASS("android/content/ContextWrapper"); GET_AND_CHECK_METHOD(methodID, clazz, "getAssets", "()Landroid/content/res/AssetManager;"); - m_assetManager = AAssetManager_fromJava(env, env->CallObjectMethod(object, methodID)); + m_assets = env->NewGlobalRef(env->CallObjectMethod(object, methodID)); + m_assetManager = AAssetManager_fromJava(env, m_assets); GET_AND_CHECK_METHOD(methodID, clazz, "getResources", "()Landroid/content/res/Resources;"); m_resourcesObj = env->NewGlobalRef(env->CallObjectMethod(object, methodID)); diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index 08f1d50fe3..17ae30a1be 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -82,6 +82,7 @@ namespace QtAndroid double scaledDensity(); double pixelDensity(); JavaVM *javaVM(); + jobject assets(); AAssetManager *assetManager(); jclass applicationClass(); jobject activity(); diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index e1dcebfa4c..26e72a480f 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -39,40 +39,139 @@ #include "qandroidassetsfileenginehandler.h" #include "androidjnimain.h" +#include #include #include +#include QT_BEGIN_NAMESPACE -typedef QVector FilesList; +static const QLatin1String assetsPrefix("assets:"); +const static int prefixSize = 7; -struct AndroidAssetDir +static inline QString cleanedAssetPath(QString file) { - AndroidAssetDir(AAssetDir* ad) + if (file.startsWith(assetsPrefix)) + file.remove(0, prefixSize); + file.replace(QLatin1String("//"), QLatin1String("/")); + if (file.startsWith(QLatin1Char('/'))) + file.remove(0, 1); + if (file.endsWith(QLatin1Char('/'))) + file.chop(1); + return file; +} + +static inline QString prefixedPath(QString path) +{ + path = assetsPrefix + QLatin1Char('/') + path; + path.replace(QLatin1String("//"), QLatin1String("/")); + return path; +} + +struct AssetItem { + enum class Type { + File, + Folder + }; + + AssetItem (const QString &rawName) + : name(rawName) + { + if (name.endsWith(QLatin1Char('/'))) { + type = Type::Folder; + name.chop(1); + } + } + Type type = Type::File; + QString name; +}; + +using AssetItemList = QVector; + +class FolderIterator : public AssetItemList +{ +public: + static QSharedPointer fromCache(const QString &path) { - if (ad) { - const char *fileName; - while ((fileName = AAssetDir_getNextFileName(ad))) - m_items.push_back(QString::fromUtf8(fileName)); - AAssetDir_close(ad); + QMutexLocker lock(&m_assetsCacheMutex); + QSharedPointer *folder = m_assetsCache.object(path); + if (!folder) { + folder = new QSharedPointer{new FolderIterator{path}}; + if (!m_assetsCache.insert(path, folder)) { + QSharedPointer res = *folder; + delete folder; + return res; + } } + return *folder; + } + + FolderIterator(const QString &path) + : m_path(path) + { + QJNIObjectPrivate files = QJNIObjectPrivate::callStaticObjectMethod(QtAndroid::applicationClass(), + "listAssetContent", + "(Landroid/content/res/AssetManager;Ljava/lang/String;)[Ljava/lang/String;", + QtAndroid::assets(), QJNIObjectPrivate::fromString(path).object()); + if (files.isValid()) { + QJNIEnvironmentPrivate env; + jobjectArray jFiles = static_cast(files.object()); + const jint nFiles = env->GetArrayLength(jFiles); + for (int i = 0; i < nFiles; ++i) + push_back({QJNIObjectPrivate(env->GetObjectArrayElement(jFiles, i)).toString()}); + } + m_path = assetsPrefix + QLatin1Char('/') + m_path + QLatin1Char('/'); + m_path.replace(QLatin1String("//"), QLatin1String("/")); + } + + QString currentFileName() const + { + if (m_index < 0 || m_index >= size()) + return {}; + return at(m_index).name; + } + QString currentFilePath() const + { + if (m_index < 0 || m_index >= size()) + return {}; + return m_path + at(m_index).name; + } + + bool hasNext() const + { + return !empty() && m_index + 1 < size(); + } + + std::optional> next() + { + if (!hasNext()) + return {}; + ++m_index; + return std::pair(currentFileName(), at(m_index)); } - FilesList m_items; + +private: + int m_index = -1; + QString m_path; + static QCache> m_assetsCache; + static QMutex m_assetsCacheMutex; }; +QCache> FolderIterator::m_assetsCache(std::max(50, qEnvironmentVariableIntValue("QT_ANDROID_MAX_ASSETS_CACHE_SIZE"))); +QMutex FolderIterator::m_assetsCacheMutex; + class AndroidAbstractFileEngineIterator: public QAbstractFileEngineIterator { public: AndroidAbstractFileEngineIterator(QDir::Filters filters, const QStringList &nameFilters, - QSharedPointer asset, const QString &path) : QAbstractFileEngineIterator(filters, nameFilters) { - m_items = asset->m_items; - m_index = -1; - m_path = path; + m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(path))); + if (m_stack.last()->empty()) + m_stack.pop_back(); } QFileInfo currentFileInfo() const override @@ -82,54 +181,59 @@ public: QString currentFileName() const override { - if (m_index < 0 || m_index >= m_items.size()) - return QString(); - QString fileName = m_items[m_index]; - if (fileName.endsWith(QLatin1Char('/'))) - fileName.chop(1); - return fileName; + if (!m_currentIterator) + return {}; + return m_currentIterator->currentFileName(); } virtual QString currentFilePath() const { - return m_path + currentFileName(); + if (!m_currentIterator) + return {}; + return m_currentIterator->currentFilePath(); } bool hasNext() const override { - return m_items.size() && (m_index < m_items.size() - 1); + if (m_stack.empty()) + return false; + if (!m_stack.last()->hasNext()) { + m_stack.pop_back(); + return hasNext(); + } + return true; } QString next() override { - if (!hasNext()) - return QString(); - m_index++; - return currentFileName(); + if (m_stack.empty()) { + m_currentIterator.reset(); + return {}; + } + m_currentIterator = m_stack.last(); + auto res = m_currentIterator->next(); + if (!res) + return {}; + if (res->second.type == AssetItem::Type::Folder) { + m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(currentFilePath()))); + if (m_stack.last()->empty()) + m_stack.pop_back(); + } + return res->first; } private: - QString m_path; - FilesList m_items; - int m_index; + mutable QSharedPointer m_currentIterator; + mutable QVector> m_stack; }; class AndroidAbstractFileEngine: public QAbstractFileEngine { public: - explicit AndroidAbstractFileEngine(AAsset *asset, const QString &fileName) - { - m_assetFile = asset; - m_fileName = fileName; - } - - explicit AndroidAbstractFileEngine(QSharedPointer asset, const QString &fileName) + explicit AndroidAbstractFileEngine(AAssetManager *assetManager, const QString &fileName) + : m_assetManager(assetManager) { - m_assetFile = 0; - m_assetDir = asset; - m_fileName = fileName; - if (!m_fileName.endsWith(QLatin1Char('/'))) - m_fileName += QLatin1Char('/'); + setFileName(fileName); } ~AndroidAbstractFileEngine() @@ -139,7 +243,11 @@ public: bool open(QIODevice::OpenMode openMode) override { - return m_assetFile != 0 && (openMode & QIODevice::WriteOnly) == 0; + if (m_isFolder || (openMode & QIODevice::WriteOnly)) + return false; + close(); + m_assetFile = AAssetManager_open(m_assetManager, m_fileName.toUtf8(), AASSET_MODE_BUFFER); + return m_assetFile; } bool close() override @@ -200,7 +308,7 @@ public: FileFlags flags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag); if (m_assetFile) flags |= FileType; - if (!m_assetDir.isNull()) + else if (m_isFolder) flags |= DirectoryType; return type & flags; @@ -213,19 +321,19 @@ public: case DefaultName: case AbsoluteName: case CanonicalName: - return m_fileName; + return prefixedPath(m_fileName); case BaseName: if ((pos = m_fileName.lastIndexOf(QChar(QLatin1Char('/')))) != -1) - return m_fileName.mid(pos); + return prefixedPath(m_fileName.mid(pos)); else - return m_fileName; + return prefixedPath(m_fileName); case PathName: case AbsolutePathName: case CanonicalPathName: if ((pos = m_fileName.lastIndexOf(QChar(QLatin1Char('/')))) != -1) - return m_fileName.left(pos); + return prefixedPath(m_fileName.left(pos)); else - return m_fileName; + return prefixedPath(m_fileName); default: return QString(); } @@ -233,164 +341,46 @@ public: void setFileName(const QString &file) override { - if (file == m_fileName) - return; - - m_fileName = file; - if (!m_fileName.endsWith(QLatin1Char('/'))) - m_fileName += QLatin1Char('/'); - close(); + m_fileName = cleanedAssetPath(file); + m_isFolder = !open(QIODevice::ReadOnly) && !FolderIterator::fromCache(m_fileName)->empty(); } Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override { - if (!m_assetDir.isNull()) - return new AndroidAbstractFileEngineIterator(filters, filterNames, m_assetDir, m_fileName); - return 0; + if (m_isFolder) + return new AndroidAbstractFileEngineIterator(filters, filterNames, m_fileName); + return nullptr; } private: - AAsset *m_assetFile; - QSharedPointer m_assetDir; + AAsset *m_assetFile = nullptr; + AAssetManager *m_assetManager; QString m_fileName; + bool m_isFolder; }; AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler() - : m_assetsCache(std::max(5, qEnvironmentVariableIntValue("QT_ANDROID_MAX_ASSETS_CACHE_SIZE"))) - , m_hasPrepopulatedCache(false) - , m_hasTriedPrepopulatingCache(false) { m_assetManager = QtAndroid::assetManager(); } -AndroidAssetsFileEngineHandler::~AndroidAssetsFileEngineHandler() -{ -} - -void AndroidAssetsFileEngineHandler::prepopulateCache() const -{ - Q_ASSERT(!m_hasTriedPrepopulatingCache); - m_hasTriedPrepopulatingCache = true; - - Q_ASSERT(m_assetsCache.isEmpty()); - - // Failsafe: Don't read cache files that are larger than 1MB - static qint64 maxPrepopulatedCacheSize = qMax(1024LL * 1024LL, - qgetenv("QT_ANDROID_MAX_PREPOPULATED_ASSETS_CACHE_SIZE").toLongLong()); - - const char *fileName = "--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list"; - AAsset *asset = AAssetManager_open(m_assetManager, fileName, AASSET_MODE_BUFFER); - if (asset) { - m_hasPrepopulatedCache = true; - AndroidAbstractFileEngine fileEngine(asset, QString::fromLatin1(fileName)); - if (fileEngine.open(QIODevice::ReadOnly)) { - qint64 size = fileEngine.size(); - - if (size <= maxPrepopulatedCacheSize) { - QByteArray bytes(size, Qt::Uninitialized); - qint64 read = fileEngine.read(bytes.data(), size); - if (read != size) { - qWarning("Failed to read prepopulated cache"); - return; - } - - QDataStream stream(&bytes, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_5_3); - if (stream.status() != QDataStream::Ok) { - qWarning("Failed to read prepopulated cache"); - return; - } - - while (!stream.atEnd()) { - QString directoryName; - stream >> directoryName; - - int fileCount; - stream >> fileCount; - - QVector fileList; - fileList.reserve(fileCount); - while (fileCount--) { - QString fileName; - stream >> fileName; - fileList.append(fileName); - } - - QSharedPointer *aad = new QSharedPointer(new AndroidAssetDir(0)); - (*aad)->m_items = fileList; - - // Cost = 0, because we should always cache everything if there's a prepopulated cache - QByteArray key = directoryName != QLatin1String("/") - ? QByteArray("assets:/") + directoryName.toUtf8() - : QByteArray("assets:"); - - bool ok = m_assetsCache.insert(key, aad, 0); - if (!ok) - qWarning("Failed to insert in cache: %s", qPrintable(directoryName)); - } - } else { - qWarning("Prepopulated cache is too large to read.\n" - "Use environment variable QT_ANDROID_MAX_PREPOPULATED_ASSETS_CACHE_SIZE to adjust size."); - } - } - } -} - QAbstractFileEngine * AndroidAssetsFileEngineHandler::create(const QString &fileName) const { if (fileName.isEmpty()) - return 0; + return nullptr; - static QLatin1String assetsPrefix("assets:"); if (!fileName.startsWith(assetsPrefix)) - return 0; - - static int prefixSize = assetsPrefix.size() + 1; - - QByteArray path; - if (!fileName.endsWith(QLatin1Char('/'))) { - path = fileName.toUtf8(); - if (path.size() > prefixSize) { - AAsset *asset = AAssetManager_open(m_assetManager, - path.constData() + prefixSize, - AASSET_MODE_BUFFER); - if (asset) - return new AndroidAbstractFileEngine(asset, fileName); - } - } - - if (!path.size()) - path = fileName.left(fileName.length() - 1).toUtf8(); - - - m_assetsCacheMutext.lock(); - if (!m_hasTriedPrepopulatingCache) - prepopulateCache(); - - QSharedPointer *aad = m_assetsCache.object(path); - m_assetsCacheMutext.unlock(); - if (!aad) { - if (!m_hasPrepopulatedCache && path.size() > prefixSize) { - AAssetDir *assetDir = AAssetManager_openDir(m_assetManager, path.constData() + prefixSize); - if (assetDir) { - if (AAssetDir_getNextFileName(assetDir)) { - AAssetDir_rewind(assetDir); - aad = new QSharedPointer(new AndroidAssetDir(assetDir)); - m_assetsCacheMutext.lock(); - m_assetsCache.insert(path, aad); - m_assetsCacheMutext.unlock(); - return new AndroidAbstractFileEngine(*aad, fileName); - } else { - AAssetDir_close(assetDir); - } - } - } - } else { - return new AndroidAbstractFileEngine(*aad, fileName); - } - return 0; + return nullptr; + + QString path = fileName.mid(prefixSize); + path.replace(QLatin1String("//"), QLatin1String("/")); + if (path.startsWith(QLatin1Char('/'))) + path.remove(0, 1); + if (path.endsWith(QLatin1Char('/'))) + path.chop(1); + return new AndroidAbstractFileEngine(m_assetManager, path); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h index f99dc9a11a..51cc5b07a8 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.h +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.h @@ -49,22 +49,14 @@ QT_BEGIN_NAMESPACE -struct AndroidAssetDir; class AndroidAssetsFileEngineHandler: public QAbstractFileEngineHandler { public: AndroidAssetsFileEngineHandler(); - virtual ~AndroidAssetsFileEngineHandler(); QAbstractFileEngine *create(const QString &fileName) const override; private: - void prepopulateCache() const; - AAssetManager *m_assetManager; - mutable QCache> m_assetsCache; - mutable QMutex m_assetsCacheMutext; - mutable bool m_hasPrepopulatedCache; - mutable bool m_hasTriedPrepopulatingCache; }; QT_END_NAMESPACE -- cgit v1.2.3 From c8b07f7da3ff55f92378a1e98522f318bbc43077 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 15 Aug 2019 08:25:30 +0300 Subject: Android: Do not extract QML assets data Instead to extract the assets QML file, we create a .rcc bundle file which is register by android qpa plugin before the it invokes the main function. Thsi way we avoid extracting the QML files from assets as they can be accessed directly from resources. [ChangeLog][Android] Instead of bundling QML resources in assets and extracting them on first start, Qt now creates an .rcc file and register it before invoking the main function. Change-Id: Icb2fda79d82c5af102cc9a0276ff26bb0d1599e8 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qtproject/qt5/android/bindings/QtLoader.java | 295 +-------------------- src/android/templates/AndroidManifest.xml | 2 - src/android/templates/build.gradle | 5 + src/android/templates/res/values/libs.xml | 10 +- src/plugins/platforms/android/androidjnimain.cpp | 5 + src/tools/androiddeployqt/main.cpp | 168 +++++------- 6 files changed, 87 insertions(+), 398 deletions(-) (limited to 'src') diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java index 45941e8ed8..1e72aa3841 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java @@ -44,8 +44,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ComponentInfo; -import android.content.pm.PackageInfo; -import android.content.res.AssetManager; import android.os.Build; import android.os.Bundle; import android.os.IBinder; @@ -55,15 +53,8 @@ import android.util.Log; import org.kde.necessitas.ministro.IMinistro; import org.kde.necessitas.ministro.IMinistroCallback; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -88,8 +79,6 @@ public abstract class QtLoader { public static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables"; public static final String APPLICATION_PARAMETERS_KEY = "application.parameters"; public static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries"; - public static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id"; - public static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id"; public static final String MAIN_LIBRARY_KEY = "main.library"; public static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; public static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level"; @@ -141,7 +130,6 @@ public abstract class QtLoader { public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme. public static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded. - public static final int BUFFER_SIZE = 1024; public String[] m_sources = {"https://download.qt-project.org/ministro/android/qt5/qt-5.7"}; // Make sure you are using ONLY secure locations public String m_repository = "default"; // Overwrites the default Ministro repository @@ -368,263 +356,6 @@ public abstract class QtLoader { errorDialog.show(); } - static private void copyFile(InputStream inputStream, OutputStream outputStream) - throws IOException - { - byte[] buffer = new byte[BUFFER_SIZE]; - - int count; - while ((count = inputStream.read(buffer)) > 0) - outputStream.write(buffer, 0, count); - } - - private void copyAsset(String source, String destination) - throws IOException - { - // Already exists, we don't have to do anything - File destinationFile = new File(destination); - if (destinationFile.exists()) - return; - - File parentDirectory = destinationFile.getParentFile(); - if (!parentDirectory.exists()) - parentDirectory.mkdirs(); - - destinationFile.createNewFile(); - - AssetManager assetsManager = m_context.getAssets(); - InputStream inputStream = null; - FileOutputStream outputStream = null; - try { - inputStream = assetsManager.open(source); - outputStream = new FileOutputStream(destinationFile); - copyFile(inputStream, outputStream); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (inputStream != null) - inputStream.close(); - - if (outputStream != null) - // Ensure that the buffered data is flushed to the OS for writing. - outputStream.flush(); - } - // Mark the output stream as still needing to be written to physical disk. - // The output stream will be closed after this sync completes. - m_fileOutputStreams.add(outputStream); - } - - private static void createBundledBinary(String source, String destination) - throws IOException - { - // Already exists, we don't have to do anything - File destinationFile = new File(destination); - if (destinationFile.exists()) - return; - - File parentDirectory = destinationFile.getParentFile(); - if (!parentDirectory.exists()) - parentDirectory.mkdirs(); - - destinationFile.createNewFile(); - - InputStream inputStream = null; - FileOutputStream outputStream = null; - try { - inputStream = new FileInputStream(source); - outputStream = new FileOutputStream(destinationFile); - copyFile(inputStream, outputStream); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (inputStream != null) - inputStream.close(); - - if (outputStream != null) - // Ensure that the buffered data is flushed to the OS for writing. - outputStream.flush(); - } - // Mark the output stream as still needing to be written to physical disk. - // The output stream will be closed after this sync completes. - m_fileOutputStreams.add(outputStream); - } - - private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion) - { - File versionFile = new File(pluginsPrefix + "cache.version"); - - long cacheVersion = 0; - if (versionFile.exists() && versionFile.canRead()) { - DataInputStream inputStream = null; - try { - inputStream = new DataInputStream(new FileInputStream(versionFile)); - cacheVersion = inputStream.readLong(); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - if (cacheVersion != packageVersion) { - deleteRecursively(new File(pluginsPrefix)); - return true; - } else { - return false; - } - } - - private void extractBundledPluginsAndImports(String pluginsPrefix, String libsDir) - throws IOException - { - long packageVersion = -1; - try { - PackageInfo packageInfo = m_context.getPackageManager().getPackageInfo(m_context.getPackageName(), 0); - packageVersion = packageInfo.lastUpdateTime; - } catch (Exception e) { - e.printStackTrace(); - } - - if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion)) - return; - - { - // why can't we load the plugins directly from libs ?!?! - String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY; - if (m_contextInfo.metaData.containsKey(key)) { - int resourceId = m_contextInfo.metaData.getInt(key); - ArrayList list = prefferedAbiLibs(m_context.getResources().getStringArray(resourceId)); - - for (String bundledImportBinary : list) { - String[] split = bundledImportBinary.split(":"); - String sourceFileName = libsDir + split[0]; - String destinationFileName = pluginsPrefix + split[1]; - createBundledBinary(sourceFileName, destinationFileName); - } - } - } - - { - String key = BUNDLED_IN_ASSETS_RESOURCE_ID_KEY; - if (m_contextInfo.metaData.containsKey(key)) { - String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key)); - - for (String fileName : list) { - String[] split = fileName.split(":"); - String sourceFileName = split[0]; - String destinationFileName = pluginsPrefix + split[1]; - copyAsset(sourceFileName, destinationFileName); - } - } - - } - - // The Java compiler must be assured that variables belonging to this parent thread will not - // go out of scope during the runtime of the spawned thread (since in general spawned - // threads can outlive their parent threads). Copy variables and declare as 'final' before - // passing into the spawned thread. - final String pluginsPrefixFinal = pluginsPrefix; - final long packageVersionFinal = packageVersion; - - // Spawn a worker thread to write all installed files to physical disk and indicate - // successful installation by creating the 'cache.version' file. - new Thread(new Runnable() { - @Override - public void run() { - try { - finalizeInstallation(pluginsPrefixFinal, packageVersionFinal); - } catch (Exception e) { - Log.e(QtApplication.QtTAG, e.getMessage()); - e.printStackTrace(); - return; - } - } - }).start(); - } - - private void finalizeInstallation(String pluginsPrefix, long packageVersion) - throws IOException - { - { - // Write all installed files to physical disk and close each output stream - for (FileOutputStream fileOutputStream : m_fileOutputStreams) { - fileOutputStream.getFD().sync(); - fileOutputStream.close(); - } - - m_fileOutputStreams.clear(); - } - - { - // Create 'cache.version' file - - File versionFile = new File(pluginsPrefix + "cache.version"); - - File parentDirectory = versionFile.getParentFile(); - if (!parentDirectory.exists()) - parentDirectory.mkdirs(); - - versionFile.createNewFile(); - - DataOutputStream outputStream = null; - try { - outputStream = new DataOutputStream(new FileOutputStream(versionFile)); - outputStream.writeLong(packageVersion); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (outputStream != null) - outputStream.close(); - } - } - - } - - private void deleteRecursively(File directory) - { - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) - deleteRecursively(file); - else - file.delete(); - } - - directory.delete(); - } - } - - private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix) - { - File newCache = new File(localPrefix); - if (!newCache.exists()) { - { - File oldPluginsCache = new File(oldLocalPrefix + "plugins/"); - if (oldPluginsCache.exists() && oldPluginsCache.isDirectory()) - deleteRecursively(oldPluginsCache); - } - - { - File oldImportsCache = new File(oldLocalPrefix + "imports/"); - if (oldImportsCache.exists() && oldImportsCache.isDirectory()) - deleteRecursively(oldImportsCache); - } - - { - File oldQmlCache = new File(oldLocalPrefix + "qml/"); - if (oldQmlCache.exists() && oldQmlCache.isDirectory()) - deleteRecursively(oldQmlCache); - } - } - } - public void startApp(final boolean firstStart) { try { @@ -688,29 +419,13 @@ public abstract class QtLoader { if (m_contextInfo.metaData.containsKey("android.app.bundle_local_qt_libs") && m_contextInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) { - File dataDir = new File(m_context.getApplicationInfo().dataDir); - String dataPath = dataDir.getCanonicalPath() + "/"; - String pluginsPrefix = dataPath + "qt-reserved-files/"; - - if (libsDir == null) - throw new Exception("Invalid libsDir"); - - cleanOldCacheIfNecessary(dataPath, pluginsPrefix); - extractBundledPluginsAndImports(pluginsPrefix, libsDir); - - if (m_contextInfo.metaData.containsKey(BUNDLED_IN_LIB_RESOURCE_ID_KEY)) { - int resourceId = m_contextInfo.metaData.getInt("android.app.load_local_libs_resource_id"); - for (String libs : prefferedAbiLibs(m_context.getResources().getStringArray(resourceId))) { - for (String lib : libs.split(":")) { - if (!lib.isEmpty()) - libraryList.add(libsDir + lib); - } + int resourceId = m_contextInfo.metaData.getInt("android.app.load_local_libs_resource_id"); + for (String libs : prefferedAbiLibs(m_context.getResources().getStringArray(resourceId))) { + for (String lib : libs.split(":")) { + if (!lib.isEmpty()) + libraryList.add(libsDir + lib); } } - - ENVIRONMENT_VARIABLES += "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml" - + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports" - + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins"; if (bundledLibsDir != null) ENVIRONMENT_VARIABLES += "\tQT_BUNDLED_LIBS_PATH=" + bundledLibsDir; } diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml index 75da314c2b..6d0f4e0d45 100644 --- a/src/android/templates/AndroidManifest.xml +++ b/src/android/templates/AndroidManifest.xml @@ -34,8 +34,6 @@ - - diff --git a/src/android/templates/build.gradle b/src/android/templates/build.gradle index d2da115936..3087d08c83 100644 --- a/src/android/templates/build.gradle +++ b/src/android/templates/build.gradle @@ -54,4 +54,9 @@ android { lintOptions { abortOnError false } + + // Do not compress Qt binary resources file + aaptOptions { + noCompress 'rcc' + } } diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml index db777bf433..6b1a4a2a02 100644 --- a/src/android/templates/res/values/libs.xml +++ b/src/android/templates/res/values/libs.xml @@ -11,20 +11,12 @@ - + - - - - - - - - diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 13ea9468df..fd2644717e 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -60,6 +60,7 @@ #include "qandroideventdispatcher.h" #include +#include #include #include #include @@ -525,6 +526,10 @@ static jboolean startQtApplication(JNIEnv */*env*/, jclass /*clazz*/) vm->AttachCurrentThread(&env, &args); } + // Register resources if they are available + if (QFile{QStringLiteral("assets:/android_rcc_bundle.rcc")}.exists()) + QResource::registerResource(QStringLiteral("assets:/android_rcc_bundle.rcc")); + QVarLengthArray params(m_applicationParams.size()); for (int i = 0; i < m_applicationParams.size(); i++) params[i] = static_cast(m_applicationParams[i].constData()); diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 6a32a659e6..7101a2bf3c 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -116,7 +116,6 @@ struct Options : helpRequested(false) , verbose(false) , timing(false) - , generateAssetsFileList(true) , build(true) , auxMode(false) , deploymentMechanism(Bundled) @@ -146,7 +145,6 @@ struct Options bool helpRequested; bool verbose; bool timing; - bool generateAssetsFileList; bool build; bool auxMode; ActionTimer timer; @@ -521,8 +519,6 @@ Options parseOptions() options.protectedAuthenticationPath = true; } else if (argument.compare(QLatin1String("--jarsigner"), Qt::CaseInsensitive) == 0) { options.jarSigner = true; - } else if (argument.compare(QLatin1String("--no-generated-assets-cache"), Qt::CaseInsensitive) == 0) { - options.generateAssetsFileList = false; } else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) { options.auxMode = true; } @@ -1242,8 +1238,6 @@ bool updateLibsXml(Options *options) } QString qtLibs; - QString bundledInLibs; - QString bundledInAssets; QString allLocalLibs; QString extraLibs; @@ -1256,33 +1250,6 @@ bool updateLibsXml(Options *options) QString s = bundledFile.second.mid(sizeof("lib/lib") - 1); s.chop(sizeof(".so") - 1); qtLibs += QLatin1String(" %1;%2\n").arg(it.key(), s); - } else if (bundledFile.first.startsWith(libsPath)) { - QString s = bundledFile.first.mid(libsPath.length()); - bundledInLibs += QString::fromLatin1(" %1;%2:%3\n") - .arg(it.key(), s, bundledFile.second); - } else if (bundledFile.first.startsWith(QLatin1String("assets/"))) { - QString s = bundledFile.first.mid(sizeof("assets/") - 1); - bundledInAssets += QString::fromLatin1(" %1:%2\n") - .arg(s, bundledFile.second); - } - } - - if (!options->archExtraPlugins[it.key()].isEmpty()) { - for (const QString &extraRes : options->archExtraPlugins[it.key()]) { - QDir resourceDir(extraRes); - const QStringList files = allFilesInside(resourceDir, resourceDir); - for (const QString &file : files) { - QString destinationPath = resourceDir.dirName() + QLatin1Char('/') + file; - if (!file.endsWith(QLatin1String(".so"))) { - bundledInAssets += QLatin1String(" %1:%1\n") - .arg(destinationPath); - } else { - bundledInLibs += QLatin1String(" %1;lib%2:%3\n") - .arg(it.key(), - QString(destinationPath).replace(QLatin1Char('/'), QLatin1Char('_')), - destinationPath); - } - } } } @@ -1342,11 +1309,6 @@ bool updateLibsXml(Options *options) replacements[QStringLiteral("")] = allLocalLibs.trimmed(); replacements[QStringLiteral("")] = extraLibs.trimmed(); - if (options->deploymentMechanism == Options::Bundled) { - replacements[QStringLiteral("")] += bundledInLibs.trimmed(); - replacements[QStringLiteral("")] += bundledInAssets.trimmed(); - } - if (!updateFile(fileName, replacements)) return false; @@ -1871,6 +1833,70 @@ bool scanImports(Options *options, QSet *usedDependencies) return true; } +bool runCommand(const Options &options, const QString &command) +{ + if (options.verbose) + fprintf(stdout, "Running command '%s'\n", qPrintable(command)); + + FILE *runCommand = openProcess(command); + if (runCommand == nullptr) { + fprintf(stderr, "Cannot run command '%s'\n", qPrintable(command)); + return false; + } + char buffer[4096]; + while (fgets(buffer, sizeof(buffer), runCommand) != nullptr) { + if (options.verbose) + fprintf(stdout, "%s", buffer); + } + pclose(runCommand); + fflush(stdout); + fflush(stderr); + return true; +} + +bool createRcc(const Options &options) +{ + auto assetsDir = QLatin1String("%1/assets").arg(options.outputDirectory); + if (!QDir{QLatin1String("%1/android_rcc_bundle").arg(assetsDir)}.exists()) { + fprintf(stdout, "Skipping createRCC\n"); + return true; + } + + if (options.verbose) + fprintf(stdout, "Create rcc bundle.\n"); + + QString rcc = options.qtInstallDirectory + QLatin1String("/bin/rcc"); +#if defined(Q_OS_WIN32) + rcc += QLatin1String(".exe"); +#endif + + if (!QFile::exists(rcc)) { + fprintf(stderr, "rcc not found: %s\n", qPrintable(rcc)); + return false; + } + auto currentDir = QDir::currentPath(); + if (!QDir::setCurrent(QLatin1String("%1/android_rcc_bundle").arg(assetsDir))) { + fprintf(stderr, "Cannot set current dir to: %s\n", qPrintable(QLatin1String("%1/android_rcc_bundle").arg(assetsDir))); + return false; + } + + bool res = runCommand(options, QLatin1String("%1 --project -o %2").arg(rcc, shellQuote(QLatin1String("%1/android_rcc_bundle.qrc").arg(assetsDir)))); + if (!res) + return false; + + QFile::rename(QLatin1String("%1/android_rcc_bundle.qrc").arg(assetsDir), QLatin1String("%1/android_rcc_bundle/android_rcc_bundle.qrc").arg(assetsDir)); + + res = runCommand(options, QLatin1String("%1 %2 --binary -o %3 android_rcc_bundle.qrc").arg(rcc, shellQuote(QLatin1String("--root=/android_rcc_bundle/")), + shellQuote(QLatin1String("%1/android_rcc_bundle.rcc").arg(assetsDir)))); + if (!QDir::setCurrent(currentDir)) { + fprintf(stderr, "Cannot set current dir to: %s\n", qPrintable(currentDir)); + return false; + } + QFile::remove(QLatin1String("%1/android_rcc_bundle.qrc").arg(assetsDir)); + QDir{QLatin1String("%1/android_rcc_bundle").arg(assetsDir)}.removeRecursively(); + return res; +} + bool readDependencies(Options *options) { if (options->verbose) @@ -2025,7 +2051,7 @@ bool copyQtFiles(Options *options) QString libsDirectory = QLatin1String("libs/"); // Copy other Qt dependencies - auto assetsDestinationDirectory = QLatin1String("assets/--Added-by-androiddeployqt--/"); + auto assetsDestinationDirectory = QLatin1String("assets/android_rcc_bundle/"); for (const QtDependency &qtDependency : qAsConst(options->qtDependencies[options->currentArchitecture])) { QString sourceFileName = qtDependency.absolutePath; QString destinationFileName; @@ -2681,57 +2707,6 @@ bool signPackage(const Options &options) return apkSignerRunner() && QFile::remove(packagePath(options, UnsignedAPK)); } -bool generateAssetsFileList(const Options &options) -{ - if (options.verbose) - fprintf(stdout, "Pregenerating entry list for assets file engine.\n"); - - QString assetsPath = options.outputDirectory + QLatin1String("/assets/"); - QString addedByAndroidDeployQtPath = assetsPath + QLatin1String("--Added-by-androiddeployqt--/"); - if (!QDir().mkpath(addedByAndroidDeployQtPath)) { - fprintf(stderr, "Failed to create directory '%s'", qPrintable(addedByAndroidDeployQtPath)); - return false; - } - - QFile file(addedByAndroidDeployQtPath + QLatin1String("/qt_cache_pregenerated_file_list")); - if (file.open(QIODevice::WriteOnly)) { - QDirIterator dirIterator(assetsPath, - QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, - QDirIterator::Subdirectories); - - QHash directoryContents; - while (dirIterator.hasNext()) { - const QString name = dirIterator.next().mid(assetsPath.length()); - - int slashIndex = name.lastIndexOf(QLatin1Char('/')); - QString pathName = slashIndex >= 0 ? name.left(slashIndex) : QStringLiteral("/"); - QString fileName = slashIndex >= 0 ? name.mid(pathName.length() + 1) : name; - - if (!fileName.isEmpty() && dirIterator.fileInfo().isDir() && !fileName.endsWith(QLatin1Char('/'))) - fileName += QLatin1Char('/'); - - if (fileName.isEmpty() && !directoryContents.contains(pathName)) - directoryContents[pathName] = QStringList(); - else if (!fileName.isEmpty()) - directoryContents[pathName].append(fileName); - } - - QDataStream stream(&file); - stream.setVersion(QDataStream::Qt_5_3); - for (auto it = directoryContents.cbegin(), end = directoryContents.cend(); it != end; ++it) { - const QStringList &entryList = it.value(); - stream << it.key() << entryList.size(); - for (const QString &entry : entryList) - stream << entry; - } - } else { - fprintf(stderr, "Pregenerating entry list for assets file engine failed!\n"); - return false; - } - - return true; -} - enum ErrorCode { Success, @@ -2749,9 +2724,9 @@ enum ErrorCode CannotBuildAndroidProject = 14, CannotSignPackage = 15, CannotInstallApk = 16, - CannotGenerateAssetsFileList = 18, CannotCopyAndroidExtraResources = 19, - CannotCopyApk = 20 + CannotCopyApk = 20, + CannotCreateRcc = 21 }; int main(int argc, char *argv[]) @@ -2848,14 +2823,16 @@ int main(int argc, char *argv[]) } } + if (!createRcc(options)) + return CannotCreateRcc; + if (options.auxMode) { if (!updateAndroidFiles(options)) return CannotUpdateAndroidFiles; - if (options.generateAssetsFileList && !generateAssetsFileList(options)) - return CannotGenerateAssetsFileList; return 0; } + if (options.build) { if (!copyAndroidSources(options)) return CannotCopyAndroidSources; @@ -2866,9 +2843,6 @@ int main(int argc, char *argv[]) if (!updateAndroidFiles(options)) return CannotUpdateAndroidFiles; - if (options.generateAssetsFileList && !generateAssetsFileList(options)) - return CannotGenerateAssetsFileList; - if (Q_UNLIKELY(options.timing)) fprintf(stdout, "[TIMING] %d ms: Updated files\n", options.timer.elapsed()); -- cgit v1.2.3 From ad86c2f0abb4fab5bf871fe49b37e0a2f4a346bc Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 2 Oct 2019 14:08:34 +0200 Subject: Quiet several more warnings about QWheelEvent deprecations We want to ensure that the qt4D and qt4O members are still initialized the same way whenever deprecated constructors are used; and we want to be able to verify it using qDebug. So we merely suppress these warnings. Change-Id: Ic2e5f0dd6feeabe81f06f9c31693c550ac0781e3 Reviewed-by: Thiago Macieira --- src/gui/kernel/qevent.cpp | 14 ++++++++++++-- src/gui/kernel/qguiapplication.cpp | 3 +++ src/widgets/kernel/qapplication.cpp | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index d41e3e5e3c..2b28052dd5 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -791,37 +791,44 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta \obsolete This constructor has been deprecated. */ - +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) : QWheelEvent(pos, globalPos, pixelDelta, angleDelta, qt4Delta, qt4Orientation, buttons, modifiers, Qt::NoScrollPhase) {} +QT_WARNING_POP /*! \obsolete This constructor has been deprecated. */ - +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase) : QWheelEvent(pos, globalPos, pixelDelta, angleDelta, qt4Delta, qt4Orientation, buttons, modifiers, phase, Qt::MouseEventNotSynthesized) {} +QT_WARNING_POP /*! \obsolete This constructor has been deprecated. */ +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source) : QWheelEvent(pos, globalPos, pixelDelta, angleDelta, qt4Delta, qt4Orientation, buttons, modifiers, phase, source, false) {} +QT_WARNING_POP /*! \obsolete @@ -3930,12 +3937,15 @@ QDebug operator<<(QDebug dbg, const QEvent *e) case QEvent::Wheel: { const QWheelEvent *we = static_cast(e); dbg << "QWheelEvent(" << we->phase(); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED // delta() and orientation() if (!we->pixelDelta().isNull() || !we->angleDelta().isNull()) dbg << ", pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta(); #if QT_DEPRECATED_SINCE(5, 14) else if (int qt4Delta = we->delta()) dbg << ", delta=" << qt4Delta << ", orientation=" << we->orientation(); #endif +QT_WARNING_POP dbg << ')'; } break; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 83ca337aaa..fe73278c62 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2245,8 +2245,11 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh } #if QT_DEPRECATED_SINCE(5, 14) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation, mouse_buttons, e->modifiers, e->phase, e->source, e->inverted); +QT_WARNING_POP #else QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, mouse_buttons, e->modifiers, e->phase, e->inverted, e->source); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 629c696544..3223781b63 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3224,8 +3224,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); #if QT_DEPRECATED_SINCE(5, 14) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), phase, wheel->source(), wheel->inverted()); +QT_WARNING_POP #else QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), wheel->modifiers(), phase, wheel->inverted(), wheel->source()); @@ -3266,8 +3269,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // the end of the natural scrolling sequence. const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPosition().toPoint()); #if QT_DEPRECATED_SINCE(5, 0) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->source()); +QT_WARNING_POP #else QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->inverted(), wheel->source()); -- cgit v1.2.3 From 1a8f4a3c8fa30265e7f184373c738dbc3574663a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Mon, 30 Sep 2019 16:56:01 +0200 Subject: GSSAPI: strengthen configure test and make it a library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we can actually filter out times in sitatuations where it proved to not be available and as a library we can simply "use" it. Added in the pkgConfig source as well to make sure we can pick it up on systems where it has a different name. Fixes: QTBUG-78765 Change-Id: I4754923ddafd9274105e4f93d66a4039872e310c Reviewed-by: Joerg Bornemann Reviewed-by: André Klitzing --- src/network/configure.json | 25 +++++++++++++++---------- src/network/kernel/kernel.pri | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/network/configure.json b/src/network/configure.json index bebe592088..a1cb77b6d1 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -98,6 +98,20 @@ "condition": "!config.msvc" } ] + }, + "gssapi": { + "label": "KRB5 GSSAPI Support", + "test": { + "main": [ + "gss_ctx_id_t ctx;", + "gss_context_time(nullptr, ctx, nullptr);" + ] + }, + "headers": [ "gssapi/gssapi.h" ], + "sources": [ + { "type": "pkgConfig", "args": "krb5-gssapi" }, + "-lgssapi_krb5" + ] } }, @@ -200,15 +214,6 @@ }, "use": "openssl" }, - "gssapi": { - "label": "KRB5 GSSAPI support", - "type": "compile", - "test": { - "include": [ "gssapi/gssapi.h" ], - "main": ["gss_ctx_id_t ctx;"], - "qmake": "LIBS += -lgssapi_krb5" - } - }, "netlistmgr": { "label": "Network List Manager", "type": "compile", @@ -408,7 +413,7 @@ "label": "GSSAPI", "purpose": "Enable SPNEGO authentication through GSSAPI", "section": "Networking", - "condition": "!config.win32 && tests.gssapi", + "condition": "!config.win32 && libs.gssapi", "output": [ "publicFeature", "feature" ] }, "sspi": { diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index a55648dbc7..110d9f56bf 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -83,7 +83,7 @@ macos | ios { SOURCES += kernel/qnetconmonitor_stub.cpp } -qtConfig(gssapi): LIBS_PRIVATE += -lgssapi_krb5 +qtConfig(gssapi): QMAKE_USE_PRIVATE += gssapi uikit:HEADERS += kernel/qnetworkinterface_uikit_p.h osx:SOURCES += kernel/qnetworkproxy_mac.cpp -- cgit v1.2.3 From f1c7814a55903dad5a5e77683bdcca5fc3805394 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 2 Oct 2019 10:58:44 +0200 Subject: rhi: Remove QVectors from the data description structs as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As usual, keep some QVector overloads around to allow Qt Quick to compile. Color attachments and vertex input bindings get an at(index) type of accessor, unlike any other of similar lists. This is because there the index is significant, and sequential iteration is not the only type of operation that is performed. Sometimes a lookup based on an index will be needed as well. Task-number: QTBUG-78883 Change-Id: I3882941f09e94ee2f179e0e9b8161551f0d5dae7 Reviewed-by: Christian Strømme Reviewed-by: Paul Olav Tvete --- src/gui/rhi/qrhi.cpp | 38 +++++++--------- src/gui/rhi/qrhi_p.h | 72 ++++++++++++++++++++++++------ src/gui/rhi/qrhi_p_p.h | 5 +-- src/gui/rhi/qrhid3d11.cpp | 69 +++++++++++++++-------------- src/gui/rhi/qrhigles2.cpp | 69 +++++++++++++++-------------- src/gui/rhi/qrhimetal.mm | 88 +++++++++++++++++++----------------- src/gui/rhi/qrhinull.cpp | 7 ++- src/gui/rhi/qrhivulkan.cpp | 103 ++++++++++++++++++++++--------------------- src/gui/rhi/qrhivulkan_p_p.h | 3 +- 9 files changed, 254 insertions(+), 200 deletions(-) (limited to 'src') diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 08bafebdec..e4f6da6d46 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -1199,8 +1199,7 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a) */ bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW { - return a.bindings() == b.bindings() - && a.attributes() == b.attributes(); + return a.m_bindings == b.m_bindings && a.m_attributes == b.m_attributes; } /*! @@ -1221,15 +1220,21 @@ bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) */ uint qHash(const QRhiVertexInputLayout &v, uint seed) Q_DECL_NOTHROW { - return qHash(v.bindings(), seed) + qHash(v.attributes(), seed); + return qHash(v.m_bindings, seed) + qHash(v.m_attributes, seed); } #ifndef QT_NO_DEBUG_STREAM +template +QDebug operator<<(QDebug dbg, const QVarLengthArray &vla) +{ + return QtPrivate::printSequentialContainer(dbg, "VLA", vla); +} + QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v) { QDebugStateSaver saver(dbg); - dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.bindings() - << " attributes=" << v.attributes() + dbg.nospace() << "QRhiVertexInputLayout(bindings=" << v.m_bindings + << " attributes=" << v.m_attributes << ')'; return dbg; } @@ -1630,25 +1635,17 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUplo } /*! - Constructs a texture upload description with the specified list of \a entries. + Constructs a texture upload description with the specified \a list of entries. - \note \a entries can also contain multiple QRhiTextureUploadEntry elements + \note \a list can also contain multiple QRhiTextureUploadEntry elements with the the same layer and level. This makes sense when those uploads are partial, meaning their subresource description has a source size or image smaller than the subresource dimensions, and can be more efficient than issuing separate uploadTexture()'s. */ -QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QVector &entries) - : m_entries(entries) -{ -} - -/*! - Adds \a entry to the list of subresource uploads. - */ -void QRhiTextureUploadDescription::append(const QRhiTextureUploadEntry &entry) +QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list list) + : m_entries(list) { - m_entries.append(entry); } /*! @@ -3056,11 +3053,6 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b) #endif #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QVarLengthArray &bindings) -{ - return QtPrivate::printSequentialContainer(dbg, "Bindings", bindings); -} - QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb) { QDebugStateSaver saver(dbg); @@ -4215,7 +4207,7 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *da */ void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc) { - if (!desc.entries().isEmpty()) + if (desc.cbeginEntries() != desc.cendEntries()) d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::textureUpload(tex, desc)); } diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index f8f922cfdb..95e9213cac 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -240,15 +240,42 @@ class Q_GUI_EXPORT QRhiVertexInputLayout public: QRhiVertexInputLayout() = default; - QVector bindings() const { return m_bindings; } - void setBindings(const QVector &v) { m_bindings = v; } + void setBindings(std::initializer_list list) { m_bindings = list; } + template + void setBindings(InputIterator first, InputIterator last) + { + m_bindings.clear(); + std::copy(first, last, std::back_inserter(m_bindings)); + } + void setBindings(const QVector &bindings) // compat., to be removed + { + setBindings(bindings.cbegin(), bindings.cend()); + } + const QRhiVertexInputBinding *cbeginBindings() const { return m_bindings.cbegin(); } + const QRhiVertexInputBinding *cendBindings() const { return m_bindings.cend(); } + const QRhiVertexInputBinding *bindingAt(int index) const { return &m_bindings.at(index); } - QVector attributes() const { return m_attributes; } - void setAttributes(const QVector &v) { m_attributes = v; } + void setAttributes(std::initializer_list list) { m_attributes = list; } + template + void setAttributes(InputIterator first, InputIterator last) + { + m_attributes.clear(); + std::copy(first, last, std::back_inserter(m_attributes)); + } + void setAttributes(const QVector &attributes) // compat., to be removed + { + setAttributes(attributes.cbegin(), attributes.cend()); + } + const QRhiVertexInputAttribute *cbeginAttributes() const { return m_attributes.cbegin(); } + const QRhiVertexInputAttribute *cendAttributes() const { return m_attributes.cend(); } private: - QVector m_bindings; - QVector m_attributes; + QVarLengthArray m_bindings; + QVarLengthArray m_attributes; + + friend Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) Q_DECL_NOTHROW; + friend Q_GUI_EXPORT uint qHash(const QRhiVertexInputLayout &v, uint seed) Q_DECL_NOTHROW; + friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &); }; Q_DECLARE_TYPEINFO(QRhiVertexInputLayout, Q_MOVABLE_TYPE); @@ -439,8 +466,16 @@ public: QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer); QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture); - QVector colorAttachments() const { return m_colorAttachments; } - void setColorAttachments(const QVector &att) { m_colorAttachments = att; } + void setColorAttachments(std::initializer_list list) { m_colorAttachments = list; } + template + void setColorAttachments(InputIterator first, InputIterator last) + { + m_colorAttachments.clear(); + std::copy(first, last, std::back_inserter(m_colorAttachments)); + } + const QRhiColorAttachment *cbeginColorAttachments() const { return m_colorAttachments.cbegin(); } + const QRhiColorAttachment *cendColorAttachments() const { return m_colorAttachments.cend(); } + const QRhiColorAttachment *colorAttachmentAt(int index) const { return &m_colorAttachments.at(index); } QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; } void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; } @@ -449,7 +484,7 @@ public: void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; } private: - QVector m_colorAttachments; + QVarLengthArray m_colorAttachments; QRhiRenderBuffer *m_depthStencilBuffer = nullptr; QRhiTexture *m_depthTexture = nullptr; }; @@ -516,14 +551,23 @@ class Q_GUI_EXPORT QRhiTextureUploadDescription public: QRhiTextureUploadDescription() = default; QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry); - QRhiTextureUploadDescription(const QVector &entries); + QRhiTextureUploadDescription(std::initializer_list list); + QRhiTextureUploadDescription(const QVector &entries) // compat., to be removed + : m_entries(entries.cbegin(), entries.cend()) + { } - QVector entries() const { return m_entries; } - void setEntries(const QVector &entries) { m_entries = entries; } - void append(const QRhiTextureUploadEntry &entry); + void setEntries(std::initializer_list list) { m_entries = list; } + template + void setEntries(InputIterator first, InputIterator last) + { + m_entries.clear(); + std::copy(first, last, std::back_inserter(m_entries)); + } + const QRhiTextureUploadEntry *cbeginEntries() const { return m_entries.cbegin(); } + const QRhiTextureUploadEntry *cendEntries() const { return m_entries.cend(); } private: - QVector m_entries; + QVarLengthArray m_entries; }; Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE); diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index 822da528f1..80a95e2fcc 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -328,9 +328,8 @@ public: TextureOp op; op.type = Upload; op.upload.tex = tex; - const QVector &entries(desc.entries()); - for (const QRhiTextureUploadEntry &entry : entries) - op.upload.subresDesc[entry.layer()][entry.level()].append(entry.description()); + for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) + op.upload.subresDesc[it->layer()][it->level()].append(it->description()); return op; } diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index b82a68f3dd..36c95f2306 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -742,13 +742,14 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, cmd.cmd = QD3D11CommandBuffer::Command::BindVertexBuffers; cmd.args.bindVertexBuffers.startSlot = startBinding; cmd.args.bindVertexBuffers.slotCount = bindingCount; - const QVector inputBindings = - QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline)->m_vertexInputLayout.bindings(); - for (int i = 0, ie = qMin(bindingCount, inputBindings.count()); i != ie; ++i) { + QD3D11GraphicsPipeline *psD = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); + const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout); + const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings(); + for (int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) { QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first); cmd.args.bindVertexBuffers.buffers[i] = bufD->buffer; cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second; - cmd.args.bindVertexBuffers.strides[i] = inputBindings[i].stride(); + cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride(); } cbD->commands.append(cmd); } @@ -1606,9 +1607,10 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) { QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, cbD->currentTarget); - const QVector colorAttachments = rtTex->m_desc.colorAttachments(); - for (int att = 0, attCount = colorAttachments.count(); att != attCount; ++att) { - const QRhiColorAttachment &colorAtt(colorAttachments[att]); + for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments(); + it != itEnd; ++it) + { + const QRhiColorAttachment &colorAtt(*it); if (!colorAtt.resolveTexture()) continue; @@ -2953,17 +2955,20 @@ bool QD3D11TextureRenderTarget::build() if (rtv[0] || dsv) release(); - const QVector colorAttachments = m_desc.colorAttachments(); - Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture()); + const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments(); + Q_ASSERT(hasColorAttachments || m_desc.depthTexture()); Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture()); const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture(); QRHI_RES_RHI(QRhiD3D11); - d.colorAttCount = colorAttachments.count(); - for (int i = 0; i < d.colorAttCount; ++i) { - QRhiTexture *texture = colorAttachments[i].texture(); - QRhiRenderBuffer *rb = colorAttachments[i].renderBuffer(); + d.colorAttCount = 0; + int attIndex = 0; + for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) { + d.colorAttCount += 1; + const QRhiColorAttachment &colorAtt(*it); + QRhiTexture *texture = colorAtt.texture(); + QRhiRenderBuffer *rb = colorAtt.renderBuffer(); Q_ASSERT(texture || rb); if (texture) { QD3D11Texture *texD = QRHI_RES(QD3D11Texture, texture); @@ -2972,32 +2977,32 @@ bool QD3D11TextureRenderTarget::build() rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags()); if (texD->flags().testFlag(QRhiTexture::CubeMap)) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = UINT(colorAttachments[i].level()); - rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAttachments[i].layer()); + rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level()); + rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer()); rtvDesc.Texture2DArray.ArraySize = 1; } else { if (texD->sampleDesc.Count > 1) { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; } else { rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = UINT(colorAttachments[i].level()); + rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level()); } } - HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->tex, &rtvDesc, &rtv[i]); + HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->tex, &rtvDesc, &rtv[attIndex]); if (FAILED(hr)) { qWarning("Failed to create rtv: %s", qPrintable(comErrorMessage(hr))); return false; } - ownsRtv[i] = true; - if (i == 0) { + ownsRtv[attIndex] = true; + if (attIndex == 0) { d.pixelSize = texD->pixelSize(); d.sampleCount = int(texD->sampleDesc.Count); } } else if (rb) { QD3D11RenderBuffer *rbD = QRHI_RES(QD3D11RenderBuffer, rb); - ownsRtv[i] = false; - rtv[i] = rbD->rtv; - if (i == 0) { + ownsRtv[attIndex] = false; + rtv[attIndex] = rbD->rtv; + if (attIndex == 0) { d.pixelSize = rbD->pixelSize(); d.sampleCount = int(rbD->sampleDesc.Count); } @@ -3542,22 +3547,22 @@ bool QD3D11GraphicsPipeline::build() d3dTopology = toD3DTopology(m_topology); if (!vsByteCode.isEmpty()) { - const QVector bindings = m_vertexInputLayout.bindings(); - const QVector attributes = m_vertexInputLayout.attributes(); QVarLengthArray inputDescs; - for (const QRhiVertexInputAttribute &attribute : attributes) { + for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes(); + it != itEnd; ++it) + { D3D11_INPUT_ELEMENT_DESC desc; memset(&desc, 0, sizeof(desc)); // the output from SPIRV-Cross uses TEXCOORD as the semantic desc.SemanticName = "TEXCOORD"; - desc.SemanticIndex = UINT(attribute.location()); - desc.Format = toD3DAttributeFormat(attribute.format()); - desc.InputSlot = UINT(attribute.binding()); - desc.AlignedByteOffset = attribute.offset(); - const QRhiVertexInputBinding &binding(bindings[attribute.binding()]); - if (binding.classification() == QRhiVertexInputBinding::PerInstance) { + desc.SemanticIndex = UINT(it->location()); + desc.Format = toD3DAttributeFormat(it->format()); + desc.InputSlot = UINT(it->binding()); + desc.AlignedByteOffset = it->offset(); + const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding()); + if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) { desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA; - desc.InstanceDataStepRate = UINT(binding.instanceStepRate()); + desc.InstanceDataStepRate = UINT(inputBinding->instanceStepRate()); } else { desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; } diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 190385d5de..17b40777b3 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1898,21 +1898,22 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) { QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.bindVertexBuffer.ps); if (psD) { - const QVector bindings = psD->m_vertexInputLayout.bindings(); - const QVector attributes = psD->m_vertexInputLayout.attributes(); - for (const QRhiVertexInputAttribute &a : attributes) { - const int bindingIdx = a.binding(); + for (auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes(); + it != itEnd; ++it) + { + const int bindingIdx = it->binding(); if (bindingIdx != cmd.args.bindVertexBuffer.binding) continue; // we do not support more than one vertex buffer f->glBindBuffer(GL_ARRAY_BUFFER, cmd.args.bindVertexBuffer.buffer); - const int stride = int(bindings[bindingIdx].stride()); + const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx); + const int stride = int(inputBinding->stride()); int size = 1; GLenum type = GL_FLOAT; bool normalize = false; - switch (a.format()) { + switch (it->format()) { case QRhiVertexInputAttribute::Float4: type = GL_FLOAT; size = 4; @@ -1948,16 +1949,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) break; } - const int locationIdx = a.location(); - quint32 ofs = a.offset() + cmd.args.bindVertexBuffer.offset; + const int locationIdx = it->location(); + quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset; f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride, reinterpret_cast(quintptr(ofs))); f->glEnableVertexAttribArray(GLuint(locationIdx)); - if (bindings[bindingIdx].classification() == QRhiVertexInputBinding::PerInstance - && caps.instancing) - { - f->glVertexAttribDivisor(GLuint(locationIdx), GLuint(bindings[bindingIdx].instanceStepRate())); - } + if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) + f->glVertexAttribDivisor(GLuint(locationIdx), GLuint(inputBinding->instanceStepRate())); } } else { qWarning("No graphics pipeline active for setVertexInput; ignored"); @@ -2510,10 +2508,12 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer; fbCmd.args.bindFramebuffer.colorAttCount = rtD->colorAttCount; - const QVector colorAttachments = rtTex->m_desc.colorAttachments(); - for (const QRhiColorAttachment &colorAttachment : colorAttachments) { - QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAttachment.texture()); - QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAttachment.resolveTexture()); + for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments(); + it != itEnd; ++it) + { + const QRhiColorAttachment &colorAtt(*it); + QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture()); + QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture()); if (texD) { trackedRegisterTexture(&passResTracker, texD, QRhiPassResourceTracker::TexColorOutput, @@ -2602,10 +2602,9 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) { QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, cbD->currentTarget); - const QVector colorAttachments = rtTex->m_desc.colorAttachments(); - if (!colorAttachments.isEmpty()) { + if (rtTex->m_desc.cbeginColorAttachments() != rtTex->m_desc.cendColorAttachments()) { // handle only 1 color attachment and only (msaa) renderbuffer - const QRhiColorAttachment &colorAtt(colorAttachments[0]); + const QRhiColorAttachment &colorAtt(*rtTex->m_desc.cbeginColorAttachments()); if (colorAtt.resolveTexture()) { Q_ASSERT(colorAtt.renderBuffer()); QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, colorAtt.renderBuffer()); @@ -3446,14 +3445,18 @@ bool QGles2TextureRenderTarget::build() if (framebuffer) release(); - const QVector colorAttachments = m_desc.colorAttachments(); - Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture()); + const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments(); + Q_ASSERT(hasColorAttachments || m_desc.depthTexture()); Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture()); const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture(); - if (colorAttachments.count() > rhiD->caps.maxDrawBuffers) - qWarning("QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)", - colorAttachments.count(), rhiD->caps.maxDrawBuffers); + if (hasColorAttachments) { + const int count = m_desc.cendColorAttachments() - m_desc.cbeginColorAttachments(); + if (count > rhiD->caps.maxDrawBuffers) { + qWarning("QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)", + count, rhiD->caps.maxDrawBuffers); + } + } if (m_desc.depthTexture() && !rhiD->caps.depthTexture) qWarning("QGles2TextureRenderTarget: Depth texture is not supported and will be ignored"); @@ -3463,9 +3466,11 @@ bool QGles2TextureRenderTarget::build() rhiD->f->glGenFramebuffers(1, &framebuffer); rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - d.colorAttCount = colorAttachments.count(); - for (int i = 0; i < d.colorAttCount; ++i) { - const QRhiColorAttachment &colorAtt(colorAttachments[i]); + d.colorAttCount = 0; + int attIndex = 0; + for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) { + d.colorAttCount += 1; + const QRhiColorAttachment &colorAtt(*it); QRhiTexture *texture = colorAtt.texture(); QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer(); Q_ASSERT(texture || renderBuffer); @@ -3473,16 +3478,16 @@ bool QGles2TextureRenderTarget::build() QGles2Texture *texD = QRHI_RES(QGles2Texture, texture); Q_ASSERT(texD->texture && texD->specified); const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target; - rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(i), faceTargetBase + uint(colorAtt.layer()), + rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()), texD->texture, colorAtt.level()); - if (i == 0) { + if (attIndex == 0) { d.pixelSize = texD->pixelSize(); d.sampleCount = 1; } } else if (renderBuffer) { QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer); - rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(i), GL_RENDERBUFFER, rbD->renderbuffer); - if (i == 0) { + rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer); + if (attIndex == 0) { d.pixelSize = rbD->pixelSize(); d.sampleCount = rbD->samples; } diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 4dc12f0691..344be44d48 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -1775,14 +1775,15 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb, cbD->d->currentPassRpDesc.depthAttachment.loadAction = MTLLoadActionLoad; cbD->d->currentPassRpDesc.stencilAttachment.loadAction = MTLLoadActionLoad; } - const QVector colorAttachments = rtTex->m_desc.colorAttachments(); - for (const QRhiColorAttachment &colorAttachment : colorAttachments) { - if (colorAttachment.texture()) - QRHI_RES(QMetalTexture, colorAttachment.texture())->lastActiveFrameSlot = currentFrameSlot; - else if (colorAttachment.renderBuffer()) - QRHI_RES(QMetalRenderBuffer, colorAttachment.renderBuffer())->lastActiveFrameSlot = currentFrameSlot; - if (colorAttachment.resolveTexture()) - QRHI_RES(QMetalTexture, colorAttachment.resolveTexture())->lastActiveFrameSlot = currentFrameSlot; + for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments(); + it != itEnd; ++it) + { + if (it->texture()) + QRHI_RES(QMetalTexture, it->texture())->lastActiveFrameSlot = currentFrameSlot; + else if (it->renderBuffer()) + QRHI_RES(QMetalRenderBuffer, it->renderBuffer())->lastActiveFrameSlot = currentFrameSlot; + if (it->resolveTexture()) + QRHI_RES(QMetalTexture, it->resolveTexture())->lastActiveFrameSlot = currentFrameSlot; } if (rtTex->m_desc.depthStencilBuffer()) QRHI_RES(QMetalRenderBuffer, rtTex->m_desc.depthStencilBuffer())->lastActiveFrameSlot = currentFrameSlot; @@ -2647,14 +2648,15 @@ void QMetalTextureRenderTarget::release() QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDescriptor() { - const QVector colorAttachments = m_desc.colorAttachments(); + const int colorAttachmentCount = m_desc.cendColorAttachments() - m_desc.cbeginColorAttachments(); QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi); - rpD->colorAttachmentCount = colorAttachments.count(); + rpD->colorAttachmentCount = colorAttachmentCount; rpD->hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture(); - for (int i = 0, ie = colorAttachments.count(); i != ie; ++i) { - QMetalTexture *texD = QRHI_RES(QMetalTexture, colorAttachments[i].texture()); - QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, colorAttachments[i].renderBuffer()); + for (int i = 0; i < colorAttachmentCount; ++i) { + const QRhiColorAttachment *colorAtt = m_desc.colorAttachmentAt(i); + QMetalTexture *texD = QRHI_RES(QMetalTexture, colorAtt->texture()); + QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, colorAtt->renderBuffer()); rpD->colorFormat[i] = int(texD ? texD->d->format : rbD->d->format); } @@ -2668,39 +2670,41 @@ QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDesc bool QMetalTextureRenderTarget::build() { - const QVector colorAttachments = m_desc.colorAttachments(); - Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture()); + const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments(); + Q_ASSERT(hasColorAttachments || m_desc.depthTexture()); Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture()); const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture(); - d->colorAttCount = colorAttachments.count(); - for (int i = 0; i < d->colorAttCount; ++i) { - QMetalTexture *texD = QRHI_RES(QMetalTexture, colorAttachments[i].texture()); - QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, colorAttachments[i].renderBuffer()); + d->colorAttCount = 0; + int attIndex = 0; + for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) { + d->colorAttCount += 1; + QMetalTexture *texD = QRHI_RES(QMetalTexture, it->texture()); + QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, it->renderBuffer()); Q_ASSERT(texD || rbD); id dst = nil; if (texD) { dst = texD->d->tex; - if (i == 0) { + if (attIndex == 0) { d->pixelSize = texD->pixelSize(); d->sampleCount = texD->samples; } } else if (rbD) { dst = rbD->d->tex; - if (i == 0) { + if (attIndex == 0) { d->pixelSize = rbD->pixelSize(); d->sampleCount = rbD->samples; } } QMetalRenderTargetData::ColorAtt colorAtt; colorAtt.tex = dst; - colorAtt.layer = colorAttachments[i].layer(); - colorAtt.level = colorAttachments[i].level(); - QMetalTexture *resTexD = QRHI_RES(QMetalTexture, colorAttachments[i].resolveTexture()); + colorAtt.layer = it->layer(); + colorAtt.level = it->level(); + QMetalTexture *resTexD = QRHI_RES(QMetalTexture, it->resolveTexture()); colorAtt.resolveTex = resTexD ? resTexD->d->tex : nil; - colorAtt.resolveLayer = colorAttachments[i].resolveLayer(); - colorAtt.resolveLevel = colorAttachments[i].resolveLevel(); - d->fb.colorAtt[i] = colorAtt; + colorAtt.resolveLayer = it->resolveLayer(); + colorAtt.resolveLevel = it->resolveLevel(); + d->fb.colorAtt[attIndex] = colorAtt; } d->dpr = 1; @@ -3119,22 +3123,24 @@ bool QMetalGraphicsPipeline::build() const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, m_shaderResourceBindings)->maxBinding + 1; MTLVertexDescriptor *inputLayout = [MTLVertexDescriptor vertexDescriptor]; - const QVector attributes = m_vertexInputLayout.attributes(); - for (const QRhiVertexInputAttribute &attribute : attributes) { - const uint loc = uint(attribute.location()); - inputLayout.attributes[loc].format = toMetalAttributeFormat(attribute.format()); - inputLayout.attributes[loc].offset = NSUInteger(attribute.offset()); - inputLayout.attributes[loc].bufferIndex = NSUInteger(firstVertexBinding + attribute.binding()); - } - const QVector bindings = m_vertexInputLayout.bindings(); - for (int i = 0, ie = bindings.count(); i != ie; ++i) { - const QRhiVertexInputBinding &binding(bindings[i]); - const uint layoutIdx = uint(firstVertexBinding + i); + for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes(); + it != itEnd; ++it) + { + const uint loc = uint(it->location()); + inputLayout.attributes[loc].format = toMetalAttributeFormat(it->format()); + inputLayout.attributes[loc].offset = NSUInteger(it->offset()); + inputLayout.attributes[loc].bufferIndex = NSUInteger(firstVertexBinding + it->binding()); + } + int bindingIndex = 0; + for (auto it = m_vertexInputLayout.cbeginBindings(), itEnd = m_vertexInputLayout.cendBindings(); + it != itEnd; ++it, ++bindingIndex) + { + const uint layoutIdx = uint(firstVertexBinding + bindingIndex); inputLayout.layouts[layoutIdx].stepFunction = - binding.classification() == QRhiVertexInputBinding::PerInstance + it->classification() == QRhiVertexInputBinding::PerInstance ? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex; - inputLayout.layouts[layoutIdx].stepRate = NSUInteger(binding.instanceStepRate()); - inputLayout.layouts[layoutIdx].stride = binding.stride(); + inputLayout.layouts[layoutIdx].stepRate = NSUInteger(it->instanceStepRate()); + inputLayout.layouts[layoutIdx].stride = it->stride(); } MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc] init]; diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index 60d620813b..487afd3ed1 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -628,10 +628,9 @@ QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescr bool QNullTextureRenderTarget::build() { d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc); - const QVector colorAttachments = m_desc.colorAttachments(); - if (!colorAttachments.isEmpty()) { - QRhiTexture *tex = colorAttachments.first().texture(); - QRhiRenderBuffer *rb = colorAttachments.first().renderBuffer(); + if (m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments()) { + QRhiTexture *tex = m_desc.cbeginColorAttachments()->texture(); + QRhiRenderBuffer *rb = m_desc.cbeginColorAttachments()->renderBuffer(); d.pixelSize = tex ? tex->pixelSize() : rb->pixelSize(); } else if (m_desc.depthStencilBuffer()) { d.pixelSize = m_desc.depthStencilBuffer()->pixelSize(); diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 7e2e914af3..3a2c35b589 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1111,7 +1111,8 @@ bool QRhiVulkan::createDefaultRenderPass(VkRenderPass *rp, bool hasDepthStencil, } bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp, - const QVector &colorAttachments, + const QRhiColorAttachment *firstColorAttachment, + const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, QRhiRenderBuffer *depthStencilBuffer, @@ -1120,13 +1121,12 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp, QVarLengthArray attDescs; QVarLengthArray colorRefs; QVarLengthArray resolveRefs; - const int colorAttCount = colorAttachments.count(); // attachment list layout is color (0-8), ds (0-1), resolve (0-8) - for (int i = 0; i < colorAttCount; ++i) { - QVkTexture *texD = QRHI_RES(QVkTexture, colorAttachments[i].texture()); - QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, colorAttachments[i].renderBuffer()); + for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) { + QVkTexture *texD = QRHI_RES(QVkTexture, it->texture()); + QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, it->renderBuffer()); Q_ASSERT(texD || rbD); const VkFormat vkformat = texD ? texD->vkformat : rbD->vkformat; const VkSampleCountFlagBits samples = texD ? texD->samples : rbD->samples; @@ -1136,7 +1136,7 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp, attDesc.format = vkformat; attDesc.samples = samples; attDesc.loadOp = preserveColor ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc.storeOp = colorAttachments[i].resolveTexture() ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; + attDesc.storeOp = it->resolveTexture() ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // this has to interact correctly with activateTextureRenderTarget(), hence leaving in COLOR_ATT @@ -1170,9 +1170,9 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp, } VkAttachmentReference dsRef = { uint32_t(attDescs.count() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - for (int i = 0; i < colorAttCount; ++i) { - if (colorAttachments[i].resolveTexture()) { - QVkTexture *rtexD = QRHI_RES(QVkTexture, colorAttachments[i].resolveTexture()); + for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) { + if (it->resolveTexture()) { + QVkTexture *rtexD = QRHI_RES(QVkTexture, it->resolveTexture()); if (rtexD->samples > VK_SAMPLE_COUNT_1_BIT) qWarning("Resolving into a multisample texture is not supported"); @@ -1979,11 +1979,10 @@ void QRhiVulkan::activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRe rtD->lastActiveFrameSlot = currentFrameSlot; rtD->d.rp->lastActiveFrameSlot = currentFrameSlot; QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]); - const QVector colorAttachments = rtD->m_desc.colorAttachments(); - for (const QRhiColorAttachment &colorAttachment : colorAttachments) { - QVkTexture *texD = QRHI_RES(QVkTexture, colorAttachment.texture()); - QVkTexture *resolveTexD = QRHI_RES(QVkTexture, colorAttachment.resolveTexture()); - QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, colorAttachment.renderBuffer()); + for (auto it = rtD->m_desc.cbeginColorAttachments(), itEnd = rtD->m_desc.cendColorAttachments(); it != itEnd; ++it) { + QVkTexture *texD = QRHI_RES(QVkTexture, it->texture()); + QVkTexture *resolveTexD = QRHI_RES(QVkTexture, it->resolveTexture()); + QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, it->renderBuffer()); if (texD) { trackedRegisterTexture(&passResTracker, texD, QRhiPassResourceTracker::TexColorOutput, @@ -5487,7 +5486,8 @@ QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescrip QRHI_RES_RHI(QRhiVulkan); QVkRenderPassDescriptor *rp = new QVkRenderPassDescriptor(m_rhi); if (!rhiD->createOffscreenRenderPass(&rp->rp, - m_desc.colorAttachments(), + m_desc.cbeginColorAttachments(), + m_desc.cendColorAttachments(), m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents), m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents), m_desc.depthStencilBuffer(), @@ -5507,18 +5507,20 @@ bool QVkTextureRenderTarget::build() if (d.fb) release(); - const QVector colorAttachments = m_desc.colorAttachments(); - Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture()); + const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments(); + Q_ASSERT(hasColorAttachments || m_desc.depthTexture()); Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture()); const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture(); QRHI_RES_RHI(QRhiVulkan); QVarLengthArray views; - d.colorAttCount = colorAttachments.count(); - for (int i = 0; i < d.colorAttCount; ++i) { - QVkTexture *texD = QRHI_RES(QVkTexture, colorAttachments[i].texture()); - QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, colorAttachments[i].renderBuffer()); + d.colorAttCount = 0; + int attIndex = 0; + for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) { + d.colorAttCount += 1; + QVkTexture *texD = QRHI_RES(QVkTexture, it->texture()); + QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, it->renderBuffer()); Q_ASSERT(texD || rbD); if (texD) { Q_ASSERT(texD->flags().testFlag(QRhiTexture::RenderTarget)); @@ -5533,24 +5535,24 @@ bool QVkTextureRenderTarget::build() viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.subresourceRange.baseMipLevel = uint32_t(colorAttachments[i].level()); + viewInfo.subresourceRange.baseMipLevel = uint32_t(it->level()); viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = uint32_t(colorAttachments[i].layer()); + viewInfo.subresourceRange.baseArrayLayer = uint32_t(it->layer()); viewInfo.subresourceRange.layerCount = 1; - VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &rtv[i]); + VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &rtv[attIndex]); if (err != VK_SUCCESS) { qWarning("Failed to create render target image view: %d", err); return false; } - views.append(rtv[i]); - if (i == 0) { + views.append(rtv[attIndex]); + if (attIndex == 0) { d.pixelSize = texD->pixelSize(); d.sampleCount = texD->samples; } } else if (rbD) { Q_ASSERT(rbD->backingTexture); views.append(rbD->backingTexture->imageView); - if (i == 0) { + if (attIndex == 0) { d.pixelSize = rbD->pixelSize(); d.sampleCount = rbD->samples; } @@ -5580,9 +5582,10 @@ bool QVkTextureRenderTarget::build() } d.resolveAttCount = 0; - for (int i = 0; i < d.colorAttCount; ++i) { - if (colorAttachments[i].resolveTexture()) { - QVkTexture *resTexD = QRHI_RES(QVkTexture, colorAttachments[i].resolveTexture()); + attIndex = 0; + for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) { + if (it->resolveTexture()) { + QVkTexture *resTexD = QRHI_RES(QVkTexture, it->resolveTexture()); Q_ASSERT(resTexD->flags().testFlag(QRhiTexture::RenderTarget)); d.resolveAttCount += 1; @@ -5597,16 +5600,16 @@ bool QVkTextureRenderTarget::build() viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.subresourceRange.baseMipLevel = uint32_t(colorAttachments[i].resolveLevel()); + viewInfo.subresourceRange.baseMipLevel = uint32_t(it->resolveLevel()); viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = uint32_t(colorAttachments[i].resolveLayer()); + viewInfo.subresourceRange.baseArrayLayer = uint32_t(it->resolveLayer()); viewInfo.subresourceRange.layerCount = 1; - VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[i]); + VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[attIndex]); if (err != VK_SUCCESS) { qWarning("Failed to create render target resolve image view: %d", err); return false; } - views.append(resrtv[i]); + views.append(resrtv[attIndex]); } } @@ -5828,22 +5831,21 @@ bool QVkGraphicsPipeline::build() pipelineInfo.stageCount = uint32_t(shaderStageCreateInfos.count()); pipelineInfo.pStages = shaderStageCreateInfos.constData(); - const QVector bindings = m_vertexInputLayout.bindings(); QVarLengthArray vertexBindings; QVarLengthArray nonOneStepRates; - for (int i = 0, ie = bindings.count(); i != ie; ++i) { - const QRhiVertexInputBinding &binding(bindings[i]); + int bindingIndex = 0; + for (auto it = m_vertexInputLayout.cbeginBindings(), itEnd = m_vertexInputLayout.cendBindings(); + it != itEnd; ++it, ++bindingIndex) + { VkVertexInputBindingDescription bindingInfo = { - uint32_t(i), - binding.stride(), - binding.classification() == QRhiVertexInputBinding::PerVertex + uint32_t(bindingIndex), + it->stride(), + it->classification() == QRhiVertexInputBinding::PerVertex ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE }; - if (binding.classification() == QRhiVertexInputBinding::PerInstance - && binding.instanceStepRate() != 1) - { + if (it->classification() == QRhiVertexInputBinding::PerInstance && it->instanceStepRate() != 1) { if (rhiD->vertexAttribDivisorAvailable) { - nonOneStepRates.append({ uint32_t(i), uint32_t(binding.instanceStepRate()) }); + nonOneStepRates.append({ uint32_t(bindingIndex), uint32_t(it->instanceStepRate()) }); } else { qWarning("QRhiVulkan: Instance step rates other than 1 not supported without " "VK_EXT_vertex_attribute_divisor on the device and " @@ -5852,14 +5854,15 @@ bool QVkGraphicsPipeline::build() } vertexBindings.append(bindingInfo); } - const QVector attributes = m_vertexInputLayout.attributes(); QVarLengthArray vertexAttributes; - for (const QRhiVertexInputAttribute &attribute : attributes) { + for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes(); + it != itEnd; ++it) + { VkVertexInputAttributeDescription attributeInfo = { - uint32_t(attribute.location()), - uint32_t(attribute.binding()), - toVkAttributeFormat(attribute.format()), - attribute.offset() + uint32_t(it->location()), + uint32_t(it->binding()), + toVkAttributeFormat(it->format()), + it->offset() }; vertexAttributes.append(attributeInfo); } diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index d83a338acd..7bd20b3671 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -732,7 +732,8 @@ public: VkSampleCountFlagBits samples, VkFormat colorFormat); bool createOffscreenRenderPass(VkRenderPass *rp, - const QVector &colorAttachments, + const QRhiColorAttachment *firstColorAttachment, + const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, QRhiRenderBuffer *depthStencilBuffer, -- cgit v1.2.3 From 5bc972a4118927be7d2b81e4ff66be5bc274fdaa Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 1 Oct 2019 14:36:29 +0200 Subject: rhi: vulkan: Disable vkmemalloc's own synchronization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need for those mutexes. Task-number: QTBUG-78908 Change-Id: I60c32df1f8729098f1894eff7c71e7fbcbd23ecf Reviewed-by: Christian Strømme --- src/gui/rhi/qrhivulkan.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 3a2c35b589..c7d28a4f18 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -568,6 +568,9 @@ bool QRhiVulkan::create(QRhi::Flags flags) VmaAllocatorCreateInfo allocatorInfo; memset(&allocatorInfo, 0, sizeof(allocatorInfo)); + // A QRhi is supposed to be used from one single thread only. Disable + // the allocator's own mutexes. This gives a performance boost. + allocatorInfo.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT; allocatorInfo.physicalDevice = physDev; allocatorInfo.device = dev; allocatorInfo.pVulkanFunctions = &afuncs; -- cgit v1.2.3 From 2e068c7f2aca6a40bcf1e4c5bc85c26f478fe786 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 1 Oct 2019 15:19:37 +0200 Subject: Add TriangleFan pipeline topology Triangle fan drawing is only supported on some platforms. The feature flag QRhi::TriangleFanTopology is set accordingly. In general, TriangleStrip topology will be more efficient on most GPUs. However, if polygon data is already stored as triangle fans, the CPU savings may be more significant. Change-Id: I9704fad751d2119eac8791074f58942dd9315601 Reviewed-by: Laszlo Agocs --- src/gui/rhi/qrhi.cpp | 6 +++++- src/gui/rhi/qrhi_p.h | 4 +++- src/gui/rhi/qrhid3d11.cpp | 2 ++ src/gui/rhi/qrhigles2.cpp | 4 ++++ src/gui/rhi/qrhimetal.mm | 2 ++ src/gui/rhi/qrhivulkan.cpp | 4 ++++ 6 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index e4f6da6d46..c8ec8c7410 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -563,7 +563,10 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general") \value BaseInstance Indicates that instanced draw commands support the \c firstInstance argument. When reported as not supported, the firstInstance value is ignored and the instance ID starts from 0. - */ + + \value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology() + supports QRhiGraphicsPipeline::TriangleFan. +*/ /*! \enum QRhi::BeginFrameFlag @@ -3123,6 +3126,7 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb) \value Triangles (default) \value TriangleStrip + \value TriangleFan (only available if QRhi::TriangleFanTopology is supported) \value Lines \value LineStrip \value Points diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 95e9213cac..5b371af727 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1017,6 +1017,7 @@ public: enum Topology { Triangles, TriangleStrip, + TriangleFan, Lines, LineStrip, Points @@ -1426,7 +1427,8 @@ public: WideLines, VertexShaderPointSize, BaseVertex, - BaseInstance + BaseInstance, + TriangleFanTopology }; enum BeginFrameFlag { diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 36c95f2306..f011d68ada 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -469,6 +469,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const return true; case QRhi::BaseInstance: return true; + case QRhi::TriangleFanTopology: + return false; default: Q_UNREACHABLE(); return false; diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 17b40777b3..277cf12fd2 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -732,6 +732,8 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const return caps.baseVertex; case QRhi::BaseInstance: return false; // not in ES 3.2, so won't bother + case QRhi::TriangleFanTopology: + return true; default: Q_UNREACHABLE(); return false; @@ -1539,6 +1541,8 @@ static inline GLenum toGlTopology(QRhiGraphicsPipeline::Topology t) return GL_TRIANGLES; case QRhiGraphicsPipeline::TriangleStrip: return GL_TRIANGLE_STRIP; + case QRhiGraphicsPipeline::TriangleFan: + return GL_TRIANGLE_FAN; case QRhiGraphicsPipeline::Lines: return GL_LINES; case QRhiGraphicsPipeline::LineStrip: diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 344be44d48..f9d9cdc01a 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -550,6 +550,8 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const return true; case QRhi::BaseInstance: return true; + case QRhi::TriangleFanTopology: + return false; default: Q_UNREACHABLE(); return false; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index c7d28a4f18..cb32aa08f3 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -3727,6 +3727,8 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const return true; case QRhi::BaseInstance: return true; + case QRhi::TriangleFanTopology: + return true; default: Q_UNREACHABLE(); return false; @@ -4572,6 +4574,8 @@ static inline VkPrimitiveTopology toVkTopology(QRhiGraphicsPipeline::Topology t) return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; case QRhiGraphicsPipeline::TriangleStrip: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + case QRhiGraphicsPipeline::TriangleFan: + return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; case QRhiGraphicsPipeline::Lines: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; case QRhiGraphicsPipeline::LineStrip: -- cgit v1.2.3 From c9478e90ff7abef1f019805f0846e651c484ebc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 24 Sep 2019 17:25:57 +0200 Subject: Export lcEventDispatcher in private namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The category is used outside of QtCore, and needs to be exported for shared library builds. Change-Id: I9bba477d37b823146eaec4e1e53197651f09c013 Reviewed-by: Timur Pocheptsov Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qeventdispatcher_cf.mm | 11 ++++++++--- src/corelib/kernel/qeventdispatcher_cf_p.h | 6 ++++-- src/plugins/platforms/ios/qioseventdispatcher.mm | 2 ++ 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index b9e334f1f4..177551467c 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -56,6 +56,14 @@ # include #endif +QT_BEGIN_NAMESPACE +namespace QtPrivate { +Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher"); +Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers"); +} +using namespace QtPrivate; +QT_END_NAMESPACE + QT_USE_NAMESPACE /* @@ -148,9 +156,6 @@ static CFStringRef runLoopMode(NSDictionary *dictionary) QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher"); -Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers"); - class RunLoopDebugger : public QObject { Q_OBJECT diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h index 26191d520c..a2cecd9a93 100644 --- a/src/corelib/kernel/qeventdispatcher_cf_p.h +++ b/src/corelib/kernel/qeventdispatcher_cf_p.h @@ -98,8 +98,10 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker)); QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher); -Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers) +namespace QtPrivate { +Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher); +Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers) +} class QEventDispatcherCoreFoundation; diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index 776343c5aa..c5856051de 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -211,6 +211,8 @@ namespace } logActivity; } +using namespace QT_PREPEND_NAMESPACE(QtPrivate); + extern "C" int qt_main_wrapper(int argc, char *argv[]) { @autoreleasepool { -- cgit v1.2.3 From dabc33bf9543e552d8627eda4977e82d340e9bcf Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Mon, 30 Sep 2019 22:25:33 +0200 Subject: QPainter: don't print deprecated warnings for HighQualityAntialiasing Add pragmas to not print warnings about the usage of the deprecated warnings inside QtCore. Change-Id: I2cd9f111cdf13cddff527ab3bac7fa80417d1445 Reviewed-by: Allan Sandfeld Jensen --- src/gui/opengl/qopenglpaintengine.cpp | 3 +++ src/gui/painting/qpaintengine_raster.cpp | 3 +++ src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 3 +++ src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp | 3 +++ 4 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index c087326068..47394999c6 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -1474,6 +1474,8 @@ void QOpenGL2PaintEngineEx::renderHintsChanged() #ifndef QT_OPENGL_ES_2 if (!QOpenGLContext::currentContext()->isOpenGLES()) { Q_D(QOpenGL2PaintEngineEx); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED if ((state()->renderHints & QPainter::Antialiasing) #if QT_DEPRECATED_SINCE(5, 14) || (state()->renderHints & QPainter::HighQualityAntialiasing) @@ -1482,6 +1484,7 @@ void QOpenGL2PaintEngineEx::renderHintsChanged() d->funcs.glEnable(GL_MULTISAMPLE); else d->funcs.glDisable(GL_MULTISAMPLE); +QT_WARNING_POP } #endif // QT_OPENGL_ES_2 diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 447ecb358a..8c51981120 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -906,8 +906,11 @@ void QRasterPaintEngine::renderHintsChanged() s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing); #if QT_DEPRECATED_SINCE(5, 14) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED if (s->renderHints & QPainter::HighQualityAntialiasing) s->flags.antialiased = true; +QT_WARNING_POP #endif s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform); s->flags.legacy_rounding = !bool(s->renderHints & QPainter::Antialiasing) && bool(s->renderHints & QPainter::Qt4CompatiblePainting); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index e8ff40304e..2546f6dc13 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1391,6 +1391,8 @@ void QGL2PaintEngineEx::renderHintsChanged() state()->renderHintsChanged = true; #if !defined(QT_OPENGL_ES_2) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED if (!d->ctx->contextHandle()->isOpenGLES()) { if ((state()->renderHints & QPainter::Antialiasing) #if QT_DEPRECATED_SINCE(5, 14) @@ -1401,6 +1403,7 @@ void QGL2PaintEngineEx::renderHintsChanged() else d->glDisable(GL_MULTISAMPLE); } +QT_WARNING_POP #endif d->lastTextureUsed = GLuint(-1); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index d7aba66b2f..03be44e095 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -941,6 +941,8 @@ public: { Q_Q(QWindowsDirect2DPaintEngine); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED // Default path (no optimization) if (!(path.shape() == QVectorPath::LinesHint || path.shape() == QVectorPath::PolygonHint) || !pen.dashBrush @@ -948,6 +950,7 @@ public: || q->state()->renderHints.testFlag(QPainter::HighQualityAntialiasing) #endif || q->state()->renderHints.testFlag(QPainter::Antialiasing)) { +QT_WARNING_POP ComPtr geometry = vectorPathToID2D1PathGeometry(path); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); -- cgit v1.2.3 From a978d21dac57697ae9557b99062bc804b005b9d4 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 29 Sep 2019 21:28:52 +0200 Subject: PSQL: don't recreate QSqlField in loop in QPSQLResult::record() Move out the QSqlField variable out of the loop to avoid useless (de)allocations of QSqlField. Change-Id: I2c9e4c84f75e994d5eb1438839d502f6da531841 Reviewed-by: Robert Szefner Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index 28be7bdc38..3803f05b9f 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -812,8 +812,8 @@ QSqlRecord QPSQLResult::record() const return info; int count = PQnfields(d->result); + QSqlField f; for (int i = 0; i < count; ++i) { - QSqlField f; if (d->drv_d_func()->isUtf8) f.setName(QString::fromUtf8(PQfname(d->result, i))); else @@ -833,6 +833,8 @@ QSqlRecord QPSQLResult::record() const } } f.setTableName(tableName); + } else { + f.setTableName(QString()); } int ptype = PQftype(d->result, i); f.setType(qDecodePSQLType(ptype)); -- cgit v1.2.3 From 0392a744530ac4868e33d5345c7197ac14d7320d Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Tue, 24 Sep 2019 11:22:50 +0200 Subject: QItemViews: hide ToolTip/What's this when cell has no data for it A QToolTip/QWhatsThis was not hidden when the cursor moved to a cell which does not return valid data for Qt::ToolTip/WhatsThisRole or when the index is not valid. Therefore a wrong information was shown e.g. when the cursor moved from a cell with a tooltip to one without. Fix it by passing an empty string to QToolTip/QWhatsThis::showText(). This syncs the behavior with QGraphicsScene::helpEvent(). Fixes: QTBUG-78722 Change-Id: Ie99fe3b1d35d2f5be41dd65e2fe3173b0cc551b2 Reviewed-by: Richard Moe Gustavsen --- src/widgets/itemviews/qabstractitemdelegate.cpp | 42 +++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp index 31dde8832b..eecc18e5c7 100644 --- a/src/widgets/itemviews/qabstractitemdelegate.cpp +++ b/src/widgets/itemviews/qabstractitemdelegate.cpp @@ -387,44 +387,46 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, const QStyleOptionViewItem &option, const QModelIndex &index) { - Q_D(QAbstractItemDelegate); - Q_UNUSED(d); - Q_UNUSED(index); - Q_UNUSED(option); - if (!event || !view) return false; + Q_D(QAbstractItemDelegate); switch (event->type()) { #ifndef QT_NO_TOOLTIP case QEvent::ToolTip: { QHelpEvent *he = static_cast(event); const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp - const QString tooltip = d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision); - if (!tooltip.isEmpty()) { - QToolTip::showText(he->globalPos(), tooltip, view); - return true; + const QString tooltip = index.isValid() ? + d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision) : + QString(); + QRect rect; + if (index.isValid()) { + const QRect r = view->visualRect(index); + rect = QRect(view->mapToGlobal(r.topLeft()), r.size()); + } + QToolTip::showText(he->globalPos(), tooltip, view, rect); + event->setAccepted(!tooltip.isEmpty()); + break; } - break;} #endif #if QT_CONFIG(whatsthis) - case QEvent::QueryWhatsThis: { - if (index.data(Qt::WhatsThisRole).isValid()) - return true; - break; } + case QEvent::QueryWhatsThis: + event->setAccepted(index.data(Qt::WhatsThisRole).isValid()); + break; case QEvent::WhatsThis: { QHelpEvent *he = static_cast(event); const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp - const QString whatsthis = d->textForRole(Qt::WhatsThisRole, index.data(Qt::WhatsThisRole), option.locale, precision); - if (!whatsthis.isEmpty()) { - QWhatsThis::showText(he->globalPos(), whatsthis, view); - return true; + const QString whatsthis = index.isValid() ? + d->textForRole(Qt::WhatsThisRole, index.data(Qt::WhatsThisRole), option.locale, precision) : + QString(); + QWhatsThis::showText(he->globalPos(), whatsthis, view); + event->setAccepted(!whatsthis.isEmpty()); + break; } - break ; } #endif default: break; } - return false; + return event->isAccepted(); } /*! -- cgit v1.2.3 From 127ed7e6e0f8939861cce7349e28a1dec9a7d6ed Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 27 Sep 2019 16:27:58 +0200 Subject: QTableWidget: Fix -Wdeprecated-copy warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In file included from ../../include/QtCore/qlist.h:1, from ../../include/QtCore/../../../qtbase_dev_de_verdad/src/corelib/kernel/qobject.h:49, from ../../include/QtCore/qobject.h:1, from ../../include/QtCore/../../../qtbase_dev_de_verdad/src/corelib/kernel/qcoreapplication.h:46, from ../../include/QtCore/qcoreapplication.h:1, from /src/widgets/kernel/../../gui/kernel/../../corelib/global/qt_pch.h:66, from /src/widgets/kernel/../../gui/kernel/qt_gui_pch.h:48, from /src/widgets/kernel/qt_widgets_pch.h:48: ../../include/QtCore/../../../qtbase_dev_de_verdad/src/corelib/tools/qlist.h: In instantiation of ‘void QList::node_construct(QList::Node*, const T&) [with T = QTableWidgetSelectionRange]’: ../../include/QtCore/../../../qtbase_dev_de_verdad/src/corelib/tools/qlist.h:614:13: required from ‘void QList::append(const T&) [with T = QTableWidgetSelectionRange]’ /src/widgets/itemviews/qtablewidget.cpp:2416:71: required from here ../../include/QtCore/../../../qtbase_dev_de_verdad/src/corelib/tools/qlist.h:471:35: warning: implicitly-declared ‘constexpr QTableWidgetSelectionRange& QTableWidgetSelectionRange::operator=(const QTableWidgetSelectionRange&)’ is deprecated [-Wdeprecated-copy] 471 | else *reinterpret_cast(n) = t; | ~~~~~~~~~~~~~~~~~~~~~~~~~^~~ In file included from /src/widgets/itemviews/qtablewidget.cpp:40: /src/widgets/itemviews/qtablewidget.h:52:24: note: because ‘QTableWidgetSelectionRange’ has user-provided ‘QTableWidgetSelectionRange::QTableWidgetSelectionRange(const QTableWidgetSelectionRange&)’ 52 | class Q_WIDGETS_EXPORT QTableWidgetSelectionRange | ^~~~~~~~~~~~~~~~~~~~~~~~~~ Change-Id: I72ca2dbf1d46a0f51a6fc7b7df80c79f937657de Reviewed-by: Christian Ehrlicher Reviewed-by: Friedemann Kleint Reviewed-by: Volker Hilsheimer --- src/widgets/itemviews/qtablewidget.cpp | 6 ++---- src/widgets/itemviews/qtablewidget.h | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index a25a582881..b1dbafa997 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -923,10 +923,8 @@ QTableWidgetSelectionRange::QTableWidgetSelectionRange(int top, int left, int bo Constructs a the table selection range by copying the given \a other table selection range. */ -QTableWidgetSelectionRange::QTableWidgetSelectionRange(const QTableWidgetSelectionRange &other) - : top(other.top), left(other.left), bottom(other.bottom), right(other.right) -{ -} +QTableWidgetSelectionRange::QTableWidgetSelectionRange(const QTableWidgetSelectionRange &other) = default; +QTableWidgetSelectionRange &QTableWidgetSelectionRange::operator=(const QTableWidgetSelectionRange &other) = default; /*! Destroys the table selection range. diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h index d93032f3f0..0d93a0a075 100644 --- a/src/widgets/itemviews/qtablewidget.h +++ b/src/widgets/itemviews/qtablewidget.h @@ -49,14 +49,17 @@ QT_REQUIRE_CONFIG(tablewidget); QT_BEGIN_NAMESPACE +// ### Qt6 unexport the class, remove the user-defined special 3 and make it a literal type. class Q_WIDGETS_EXPORT QTableWidgetSelectionRange { public: QTableWidgetSelectionRange(); QTableWidgetSelectionRange(int top, int left, int bottom, int right); - QTableWidgetSelectionRange(const QTableWidgetSelectionRange &other); ~QTableWidgetSelectionRange(); + QTableWidgetSelectionRange(const QTableWidgetSelectionRange &other); + QTableWidgetSelectionRange &operator=(const QTableWidgetSelectionRange &other); + inline int topRow() const { return top; } inline int bottomRow() const { return bottom; } inline int leftColumn() const { return left; } -- cgit v1.2.3 From a3790681a58ff0ff5f3a7dd53c473013a792e949 Mon Sep 17 00:00:00 2001 From: Timo Aarnipuro Date: Fri, 4 Oct 2019 11:51:38 +0300 Subject: qhighdpiscaling: Add missing parameter to logicalDpi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes build with -no-feature-highdpiscaling. Change-Id: Ie3208992f739ac1a2ddea54bcca067666e9367e8 Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qhighdpiscaling_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index f58944a7d2..3c85481495 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -313,7 +313,7 @@ public: static inline QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *) { return pos; } static inline QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; } static inline QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window) { return pos; } - static inline QDpi logicalDpi() { return QDpi(-1,-1); } + static inline QDpi logicalDpi(const QScreen *screen) { return QDpi(-1,-1); } }; namespace QHighDpi { -- cgit v1.2.3