diff options
author | Liang Qi <liang.qi@qt.io> | 2019-10-04 15:27:15 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-10-04 15:27:15 +0200 |
commit | 96a20440093aff70e78d01d6f014630bda5b0713 (patch) | |
tree | b9e6b6da88b8a0b909d3fa51ac0d191c61efc2ce /src | |
parent | 3598ffcc26dbae14d88c32fabfc8be465eed8f61 (diff) | |
parent | a3790681a58ff0ff5f3a7dd53c473013a792e949 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts:
src/network/access/qnetworkaccessmanager.cpp
src/network/access/qnetworkreplyhttpimpl.cpp
Change-Id: I059be651604623616fd31e8616be8ae61b4f8883
Diffstat (limited to 'src')
41 files changed, 679 insertions, 850 deletions
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<String> res = new ArrayList<String>(); + 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/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<String> 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 @@ <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> <!-- Deploy Qt libs as part of package --> <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/> - <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/> - <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/> <!-- Run with local libs --> <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/> 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 @@ <!-- %%INSERT_EXTRA_LIBS%% --> </array> - <array name="qt_libs"> + <array name="qt_libs"> <!-- %%INSERT_QT_LIBS%% --> - </array> - - <array name="bundled_in_lib"> - <!-- %%INSERT_BUNDLED_IN_LIB%% --> </array> <array name="load_local_libs"> <!-- %%INSERT_LOCAL_LIBS%% --> </array> - <array name="bundled_in_assets"> - <!-- %%INSERT_BUNDLED_IN_ASSETS%% --> - </array> - </resources> 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/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 <UIKit/UIApplication.h> #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/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/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 5791432ba6..f2f083c277 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 @@ -3919,12 +3926,15 @@ QDebug operator<<(QDebug dbg, const QEvent *e) case QEvent::Wheel: { const QWheelEvent *we = static_cast<const QWheelEvent *>(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 4b3d94b97f..a9c194afce 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2251,8 +2251,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/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 { 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/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 08bafebdec..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 @@ -1199,8 +1202,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 +1223,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<typename T, int N> +QDebug operator<<(QDebug dbg, const QVarLengthArray<T, N> &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,28 +1638,20 @@ 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<QRhiTextureUploadEntry> &entries) - : m_entries(entries) +QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list) + : m_entries(list) { } /*! - Adds \a entry to the list of subresource uploads. - */ -void QRhiTextureUploadDescription::append(const QRhiTextureUploadEntry &entry) -{ - m_entries.append(entry); -} - -/*! \class QRhiTextureCopyDescription \internal \inmodule QtGui @@ -3056,11 +3056,6 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b) #endif #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QVarLengthArray<QRhiShaderResourceBinding, 8> &bindings) -{ - return QtPrivate::printSequentialContainer(dbg, "Bindings", bindings); -} - QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb) { QDebugStateSaver saver(dbg); @@ -3131,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 @@ -4215,7 +4211,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..5b371af727 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<QRhiVertexInputBinding> bindings() const { return m_bindings; } - void setBindings(const QVector<QRhiVertexInputBinding> &v) { m_bindings = v; } + void setBindings(std::initializer_list<QRhiVertexInputBinding> list) { m_bindings = list; } + template<typename InputIterator> + void setBindings(InputIterator first, InputIterator last) + { + m_bindings.clear(); + std::copy(first, last, std::back_inserter(m_bindings)); + } + void setBindings(const QVector<QRhiVertexInputBinding> &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<QRhiVertexInputAttribute> attributes() const { return m_attributes; } - void setAttributes(const QVector<QRhiVertexInputAttribute> &v) { m_attributes = v; } + void setAttributes(std::initializer_list<QRhiVertexInputAttribute> list) { m_attributes = list; } + template<typename InputIterator> + void setAttributes(InputIterator first, InputIterator last) + { + m_attributes.clear(); + std::copy(first, last, std::back_inserter(m_attributes)); + } + void setAttributes(const QVector<QRhiVertexInputAttribute> &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<QRhiVertexInputBinding> m_bindings; - QVector<QRhiVertexInputAttribute> m_attributes; + QVarLengthArray<QRhiVertexInputBinding, 8> m_bindings; + QVarLengthArray<QRhiVertexInputAttribute, 8> 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<QRhiColorAttachment> colorAttachments() const { return m_colorAttachments; } - void setColorAttachments(const QVector<QRhiColorAttachment> &att) { m_colorAttachments = att; } + void setColorAttachments(std::initializer_list<QRhiColorAttachment> list) { m_colorAttachments = list; } + template<typename InputIterator> + 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<QRhiColorAttachment> m_colorAttachments; + QVarLengthArray<QRhiColorAttachment, 8> 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<QRhiTextureUploadEntry> &entries); + QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list); + QRhiTextureUploadDescription(const QVector<QRhiTextureUploadEntry> &entries) // compat., to be removed + : m_entries(entries.cbegin(), entries.cend()) + { } - QVector<QRhiTextureUploadEntry> entries() const { return m_entries; } - void setEntries(const QVector<QRhiTextureUploadEntry> &entries) { m_entries = entries; } - void append(const QRhiTextureUploadEntry &entry); + void setEntries(std::initializer_list<QRhiTextureUploadEntry> list) { m_entries = list; } + template<typename InputIterator> + 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<QRhiTextureUploadEntry> m_entries; + QVarLengthArray<QRhiTextureUploadEntry, 16> m_entries; }; Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_MOVABLE_TYPE); @@ -973,6 +1017,7 @@ public: enum Topology { Triangles, TriangleStrip, + TriangleFan, Lines, LineStrip, Points @@ -1382,7 +1427,8 @@ public: WideLines, VertexShaderPointSize, BaseVertex, - BaseInstance + BaseInstance, + TriangleFanTopology }; enum BeginFrameFlag { 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<QRhiTextureUploadEntry> &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..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; @@ -742,13 +744,14 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, cmd.cmd = QD3D11CommandBuffer::Command::BindVertexBuffers; cmd.args.bindVertexBuffers.startSlot = startBinding; cmd.args.bindVertexBuffers.slotCount = bindingCount; - const QVector<QRhiVertexInputBinding> 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 +1609,10 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) { QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, cbD->currentTarget); - const QVector<QRhiColorAttachment> 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 +2957,20 @@ bool QD3D11TextureRenderTarget::build() if (rtv[0] || dsv) release(); - const QVector<QRhiColorAttachment> 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 +2979,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 +3549,22 @@ bool QD3D11GraphicsPipeline::build() d3dTopology = toD3DTopology(m_topology); if (!vsByteCode.isEmpty()) { - const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings(); - const QVector<QRhiVertexInputAttribute> attributes = m_vertexInputLayout.attributes(); QVarLengthArray<D3D11_INPUT_ELEMENT_DESC, 4> 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<location> 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..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: @@ -1898,21 +1902,22 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) { QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.bindVertexBuffer.ps); if (psD) { - const QVector<QRhiVertexInputBinding> bindings = psD->m_vertexInputLayout.bindings(); - const QVector<QRhiVertexInputAttribute> 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 +1953,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<const GLvoid *>(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 +2512,12 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer; fbCmd.args.bindFramebuffer.colorAttCount = rtD->colorAttCount; - const QVector<QRhiColorAttachment> 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 +2606,9 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) { QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, cbD->currentTarget); - const QVector<QRhiColorAttachment> 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 +3449,18 @@ bool QGles2TextureRenderTarget::build() if (framebuffer) release(); - const QVector<QRhiColorAttachment> 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 +3470,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 +3482,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..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; @@ -1775,14 +1777,15 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb, cbD->d->currentPassRpDesc.depthAttachment.loadAction = MTLLoadActionLoad; cbD->d->currentPassRpDesc.stencilAttachment.loadAction = MTLLoadActionLoad; } - const QVector<QRhiColorAttachment> 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 +2650,15 @@ void QMetalTextureRenderTarget::release() QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDescriptor() { - const QVector<QRhiColorAttachment> 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 +2672,41 @@ QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDesc bool QMetalTextureRenderTarget::build() { - const QVector<QRhiColorAttachment> 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<MTLTexture> 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 +3125,24 @@ bool QMetalGraphicsPipeline::build() const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, m_shaderResourceBindings)->maxBinding + 1; MTLVertexDescriptor *inputLayout = [MTLVertexDescriptor vertexDescriptor]; - const QVector<QRhiVertexInputAttribute> 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<QRhiVertexInputBinding> 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<QRhiColorAttachment> 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..cb32aa08f3 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; @@ -1111,7 +1114,8 @@ bool QRhiVulkan::createDefaultRenderPass(VkRenderPass *rp, bool hasDepthStencil, } bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp, - const QVector<QRhiColorAttachment> &colorAttachments, + const QRhiColorAttachment *firstColorAttachment, + const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, QRhiRenderBuffer *depthStencilBuffer, @@ -1120,13 +1124,12 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp, QVarLengthArray<VkAttachmentDescription, 8> attDescs; QVarLengthArray<VkAttachmentReference, 8> colorRefs; QVarLengthArray<VkAttachmentReference, 8> 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 +1139,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 +1173,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 +1982,10 @@ void QRhiVulkan::activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRe rtD->lastActiveFrameSlot = currentFrameSlot; rtD->d.rp->lastActiveFrameSlot = currentFrameSlot; QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]); - const QVector<QRhiColorAttachment> 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, @@ -3725,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; @@ -4570,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: @@ -5487,7 +5493,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 +5514,20 @@ bool QVkTextureRenderTarget::build() if (d.fb) release(); - const QVector<QRhiColorAttachment> 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<VkImageView, 8> 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 +5542,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 +5589,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 +5607,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 +5838,21 @@ bool QVkGraphicsPipeline::build() pipelineInfo.stageCount = uint32_t(shaderStageCreateInfos.count()); pipelineInfo.pStages = shaderStageCreateInfos.constData(); - const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings(); QVarLengthArray<VkVertexInputBindingDescription, 4> vertexBindings; QVarLengthArray<VkVertexInputBindingDivisorDescriptionEXT> 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 +5861,15 @@ bool QVkGraphicsPipeline::build() } vertexBindings.append(bindingInfo); } - const QVector<QRhiVertexInputAttribute> attributes = m_vertexInputLayout.attributes(); QVarLengthArray<VkVertexInputAttributeDescription, 4> 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<QRhiColorAttachment> &colorAttachments, + const QRhiColorAttachment *firstColorAttachment, + const QRhiColorAttachment *lastColorAttachment, bool preserveColor, bool preserveDs, QRhiRenderBuffer *depthStencilBuffer, diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index af1e0b7278..1deaa03f71 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -318,7 +318,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.) 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 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/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/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); } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 27eb337aaa..fd2644717e 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -60,6 +60,7 @@ #include "qandroideventdispatcher.h" #include <android/api-level.h> +#include <QtCore/qresource.h> #include <QtCore/qthread.h> #include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjni_p.h> @@ -75,6 +76,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 +441,11 @@ namespace QtAndroid return block; } + jobject assets() + { + return m_assets; + } + } // namespace QtAndroid static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring paramsString, jstring environmentString) @@ -519,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<const char *> params(m_applicationParams.size()); for (int i = 0; i < m_applicationParams.size(); i++) params[i] = static_cast<const char *>(m_applicationParams[i].constData()); @@ -588,6 +599,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 +853,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 <optional> #include <QCoreApplication> #include <QVector> +#include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE -typedef QVector<QString> 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<AssetItem>; + +class FolderIterator : public AssetItemList +{ +public: + static QSharedPointer<FolderIterator> 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<FolderIterator> *folder = m_assetsCache.object(path); + if (!folder) { + folder = new QSharedPointer<FolderIterator>{new FolderIterator{path}}; + if (!m_assetsCache.insert(path, folder)) { + QSharedPointer<FolderIterator> 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<jobjectArray>(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<std::pair<QString, AssetItem>> next() + { + if (!hasNext()) + return {}; + ++m_index; + return std::pair<QString, AssetItem>(currentFileName(), at(m_index)); } - FilesList m_items; + +private: + int m_index = -1; + QString m_path; + static QCache<QString, QSharedPointer<FolderIterator>> m_assetsCache; + static QMutex m_assetsCacheMutex; }; +QCache<QString, QSharedPointer<FolderIterator>> 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<AndroidAssetDir> 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<FolderIterator> m_currentIterator; + mutable QVector<QSharedPointer<FolderIterator>> m_stack; }; class AndroidAbstractFileEngine: public QAbstractFileEngine { public: - explicit AndroidAbstractFileEngine(AAsset *asset, const QString &fileName) - { - m_assetFile = asset; - m_fileName = fileName; - } - - explicit AndroidAbstractFileEngine(QSharedPointer<AndroidAssetDir> 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<AndroidAssetDir> 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<QString> fileList; - fileList.reserve(fileCount); - while (fileCount--) { - QString fileName; - stream >> fileName; - fileList.append(fileName); - } - - QSharedPointer<AndroidAssetDir> *aad = new QSharedPointer<AndroidAssetDir>(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<AndroidAssetDir> *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<AndroidAssetDir>(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<QByteArray, QSharedPointer<AndroidAssetDir>> m_assetsCache; - mutable QMutex m_assetsCacheMutext; - mutable bool m_hasPrepopulatedCache; - mutable bool m_hasTriedPrepopulatingCache; }; QT_END_NAMESPACE 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<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path); if (!geometry) { qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); 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 { diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index 5f325db81e..b85a1ac4c7 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)); diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 705a9904b4..5ede55ecf2 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) @@ -147,7 +146,6 @@ struct Options bool helpRequested; bool verbose; bool timing; - bool generateAssetsFileList; bool build; bool auxMode; ActionTimer timer; @@ -318,10 +316,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(); } @@ -527,8 +523,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; } else if (argument.compare(QLatin1String("--qml-importscanner-binary"), Qt::CaseInsensitive) == 0) { @@ -1193,7 +1187,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)) @@ -1260,8 +1254,6 @@ bool updateLibsXml(Options *options) } QString qtLibs; - QString bundledInLibs; - QString bundledInAssets; QString allLocalLibs; QString extraLibs; @@ -1274,33 +1266,6 @@ bool updateLibsXml(Options *options) QString s = bundledFile.second.mid(sizeof("lib/lib") - 1); s.chop(sizeof(".so") - 1); qtLibs += QLatin1String(" <item>%1;%2</item>\n").arg(it.key(), s); - } else if (bundledFile.first.startsWith(libsPath)) { - QString s = bundledFile.first.mid(libsPath.length()); - bundledInLibs += QString::fromLatin1(" <item>%1;%2:%3</item>\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(" <item>%1:%2</item>\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(" <item>%1:%1</item>\n") - .arg(destinationPath); - } else { - bundledInLibs += QLatin1String(" <item>%1;lib%2:%3</item>\n") - .arg(it.key(), - QString(destinationPath).replace(QLatin1Char('/'), QLatin1Char('_')), - destinationPath); - } - } } } @@ -1346,9 +1311,13 @@ bool updateLibsXml(Options *options) if (options->verbose) fprintf(stdout, " -- Using platform plugin %s\n", qPrintable(plugin)); } - allLocalLibs += QLatin1String(" <item>%1;%2</item>\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(" <item>%1;%2</item>\n").arg(it.key(), localLibs.join(QLatin1Char(':'))); } QHash<QString, QString> replacements; @@ -1356,11 +1325,6 @@ bool updateLibsXml(Options *options) replacements[QStringLiteral("<!-- %%INSERT_LOCAL_LIBS%% -->")] = allLocalLibs.trimmed(); replacements[QStringLiteral("<!-- %%INSERT_EXTRA_LIBS%% -->")] = extraLibs.trimmed(); - if (options->deploymentMechanism == Options::Bundled) { - replacements[QStringLiteral("<!-- %%INSERT_BUNDLED_IN_LIB%% -->")] += bundledInLibs.trimmed(); - replacements[QStringLiteral("<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->")] += bundledInAssets.trimmed(); - } - if (!updateFile(fileName, replacements)) return false; @@ -1890,6 +1854,70 @@ bool scanImports(Options *options, QSet<QString> *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) @@ -2044,7 +2072,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; @@ -2054,7 +2082,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/"))) { @@ -2700,57 +2728,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<QString, QStringList> 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, @@ -2768,9 +2745,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[]) @@ -2867,14 +2844,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; @@ -2885,9 +2864,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()); 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<QHelpEvent*>(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<QHelpEvent*>(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(); } /*! 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; } 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()); |