Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: I43393cf47675fd6c14972df1221986335c6f493cbb10
commit
3a1613c227
|
|
@ -818,6 +818,7 @@
|
|||
"rpath": {
|
||||
"label": "Build with RPATH",
|
||||
"autoDetect": "var.QMAKE_LFLAGS_RPATH != '' && features.shared",
|
||||
"condition": "!config.android",
|
||||
"output": [ "publicFeature", "publicQtConfig" ]
|
||||
},
|
||||
"rpath_dir": {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ FlowLayout::FlowLayout(QGraphicsLayoutItem *parent) : QGraphicsLayout(parent)
|
|||
void FlowLayout::insertItem(int index, QGraphicsLayoutItem *item)
|
||||
{
|
||||
item->setParentLayoutItem(this);
|
||||
if (index > m_items.count())
|
||||
if (index > m_items.count() || index < 0)
|
||||
index = m_items.count();
|
||||
m_items.insert(index, item);
|
||||
invalidate();
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ INSTALLS += target
|
|||
|
||||
# Some final setup
|
||||
|
||||
TARGET = $$qt5LibraryTarget($$TARGET)
|
||||
TARGET = $$qt5LibraryTarget($$TARGET, "qml/$$TARGETPATH/")
|
||||
|
||||
load(qt_targets)
|
||||
load(qt_common)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,13 @@ defineReplace(qtLibraryTarget) {
|
|||
}
|
||||
|
||||
defineReplace(qt5LibraryTarget) {
|
||||
LIBRARY_NAME = $$qtLibraryTarget($$1)
|
||||
android {
|
||||
LIBRARY_NAME_PREFIX = $$2
|
||||
LIBRARY_NAME_PREFIX = $$replace(LIBRARY_NAME_PREFIX, "//", "/")
|
||||
LIBRARY_NAME_PREFIX = $$replace(LIBRARY_NAME_PREFIX, "/", "_")
|
||||
LIBRARY_NAME = $$LIBRARY_NAME_PREFIX$$qtLibraryTarget($$1)
|
||||
unset(LIBRARY_NAME_PREFIX)
|
||||
} else: LIBRARY_NAME = $$qtLibraryTarget($$1)
|
||||
isEmpty(QMAKE_FRAMEWORK_BUNDLE_NAME) {
|
||||
# Insert the major version of Qt in the library name
|
||||
# unless it's a framework build.
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ target.path = $$[QT_INSTALL_PLUGINS]/$$PLUGIN_TYPE
|
|||
INSTALLS += target
|
||||
|
||||
qt_libinfix_plugins: TARGET = $$TARGET$$QT_LIBINFIX
|
||||
TARGET = $$qt5LibraryTarget($$TARGET)
|
||||
TARGET = $$qt5LibraryTarget($$TARGET, "plugins/$$PLUGIN_TYPE/")
|
||||
|
||||
CONFIG += create_cmake
|
||||
|
||||
|
|
|
|||
|
|
@ -448,15 +448,21 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
|
|||
opt.remove(suffixMarker); // Apply suffix by removing marker
|
||||
}
|
||||
for (const QMakeLocalFileName &dir : qAsConst(frameworkdirs)) {
|
||||
auto processPrlIfFound = [&](QString directory) {
|
||||
QString suffixedPrl = directory + opt;
|
||||
if (processPrlFile(suffixedPrl, true))
|
||||
return true;
|
||||
if (hasSuffix) {
|
||||
QString unsuffixedPrl = directory + frameworkName;
|
||||
if (processPrlFile(unsuffixedPrl, true))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
QString frameworkDirectory = dir.local() + "/" + frameworkName + + ".framework/";
|
||||
QString suffixedPrl = frameworkDirectory + opt;
|
||||
if (processPrlFile(suffixedPrl, true))
|
||||
if (processPrlIfFound(frameworkDirectory + "Resources/")
|
||||
|| processPrlIfFound(frameworkDirectory))
|
||||
break;
|
||||
if (hasSuffix) {
|
||||
QString unsuffixedPrl = frameworkDirectory + frameworkName;
|
||||
if (processPrlFile(unsuffixedPrl, true))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (opt.length() == 10)
|
||||
|
|
|
|||
|
|
@ -1230,8 +1230,9 @@ void UnixMakefileGenerator::init2()
|
|||
else
|
||||
ar_cmd.append("$(AR) $(TARGETA) $(OBJECTS)");
|
||||
if (!project->isEmpty("QMAKE_BUNDLE")) {
|
||||
project->values("PRL_TARGET").prepend(
|
||||
project->first("QMAKE_BUNDLE") + Option::dir_sep + project->first("TARGET"));
|
||||
project->values("PRL_TARGET").prepend(project->first("QMAKE_BUNDLE") +
|
||||
"/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") +
|
||||
"/Resources/" + project->first("TARGET"));
|
||||
ProString bundle_loc = project->first("QMAKE_BUNDLE_LOCATION");
|
||||
if(!bundle_loc.isEmpty() && !bundle_loc.startsWith("/"))
|
||||
bundle_loc.prepend("/");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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%% --"/>
|
||||
|
|
|
|||
|
|
@ -54,4 +54,9 @@ android {
|
|||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
// Do not compress Qt binary resources file
|
||||
aaptOptions {
|
||||
noCompress 'rcc'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 = \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -791,37 +791,44 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta
|
|||
\obsolete
|
||||
This constructor has been deprecated.
|
||||
*/
|
||||
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
|
||||
QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
|
||||
: QWheelEvent(pos, globalPos, pixelDelta, angleDelta, qt4Delta, qt4Orientation,
|
||||
buttons, modifiers, Qt::NoScrollPhase)
|
||||
{}
|
||||
QT_WARNING_POP
|
||||
|
||||
/*!
|
||||
\obsolete
|
||||
This constructor has been deprecated.
|
||||
*/
|
||||
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
|
||||
QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase)
|
||||
: QWheelEvent(pos, globalPos, pixelDelta, angleDelta, qt4Delta, qt4Orientation,
|
||||
buttons, modifiers, phase, Qt::MouseEventNotSynthesized)
|
||||
{}
|
||||
QT_WARNING_POP
|
||||
|
||||
/*!
|
||||
\obsolete
|
||||
This constructor has been deprecated.
|
||||
*/
|
||||
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_DEPRECATED
|
||||
QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
|
||||
QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation,
|
||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source)
|
||||
: QWheelEvent(pos, globalPos, pixelDelta, angleDelta, qt4Delta, qt4Orientation,
|
||||
buttons, modifiers, phase, source, false)
|
||||
{}
|
||||
QT_WARNING_POP
|
||||
|
||||
/*!
|
||||
\obsolete
|
||||
|
|
@ -3930,12 +3937,15 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
|
|||
case QEvent::Wheel: {
|
||||
const QWheelEvent *we = static_cast<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;
|
||||
|
|
|
|||
|
|
@ -2247,8 +2247,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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,27 +1638,19 @@ 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
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
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());
|
||||
}
|
||||
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);
|
||||
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];
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 += \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ namespace QtAndroid
|
|||
double scaledDensity();
|
||||
double pixelDensity();
|
||||
JavaVM *javaVM();
|
||||
jobject assets();
|
||||
AAssetManager *assetManager();
|
||||
jclass applicationClass();
|
||||
jobject activity();
|
||||
|
|
|
|||
|
|
@ -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 (ad) {
|
||||
const char *fileName;
|
||||
while ((fileName = AAssetDir_getNextFileName(ad)))
|
||||
m_items.push_back(QString::fromUtf8(fileName));
|
||||
AAssetDir_close(ad);
|
||||
if (name.endsWith(QLatin1Char('/'))) {
|
||||
type = Type::Folder;
|
||||
name.chop(1);
|
||||
}
|
||||
}
|
||||
FilesList m_items;
|
||||
Type type = Type::File;
|
||||
QString name;
|
||||
};
|
||||
|
||||
using AssetItemList = QVector<AssetItem>;
|
||||
|
||||
class FolderIterator : public AssetItemList
|
||||
{
|
||||
public:
|
||||
static QSharedPointer<FolderIterator> fromCache(const QString &path)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
explicit AndroidAbstractFileEngine(AAssetManager *assetManager, const QString &fileName)
|
||||
: m_assetManager(assetManager)
|
||||
{
|
||||
m_assetFile = asset;
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
explicit AndroidAbstractFileEngine(QSharedPointer<AndroidAssetDir> asset, const QString &fileName)
|
||||
{
|
||||
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;
|
||||
return nullptr;
|
||||
|
||||
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;
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__);
|
||||
|
|
|
|||
|
|
@ -211,6 +211,8 @@ namespace
|
|||
} logActivity;
|
||||
}
|
||||
|
||||
using namespace QT_PREPEND_NAMESPACE(QtPrivate);
|
||||
|
||||
extern "C" int qt_main_wrapper(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ struct Options
|
|||
: helpRequested(false)
|
||||
, verbose(false)
|
||||
, timing(false)
|
||||
, generateAssetsFileList(true)
|
||||
, build(true)
|
||||
, auxMode(false)
|
||||
, deploymentMechanism(Bundled)
|
||||
|
|
@ -146,7 +145,6 @@ struct Options
|
|||
bool helpRequested;
|
||||
bool verbose;
|
||||
bool timing;
|
||||
bool generateAssetsFileList;
|
||||
bool build;
|
||||
bool auxMode;
|
||||
ActionTimer timer;
|
||||
|
|
@ -314,10 +312,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();
|
||||
}
|
||||
|
|
@ -523,8 +519,6 @@ Options parseOptions()
|
|||
options.protectedAuthenticationPath = true;
|
||||
} else if (argument.compare(QLatin1String("--jarsigner"), Qt::CaseInsensitive) == 0) {
|
||||
options.jarSigner = true;
|
||||
} else if (argument.compare(QLatin1String("--no-generated-assets-cache"), Qt::CaseInsensitive) == 0) {
|
||||
options.generateAssetsFileList = false;
|
||||
} else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) {
|
||||
options.auxMode = true;
|
||||
}
|
||||
|
|
@ -1177,7 +1171,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))
|
||||
|
|
@ -1244,8 +1238,6 @@ bool updateLibsXml(Options *options)
|
|||
}
|
||||
|
||||
QString qtLibs;
|
||||
QString bundledInLibs;
|
||||
QString bundledInAssets;
|
||||
QString allLocalLibs;
|
||||
QString extraLibs;
|
||||
|
||||
|
|
@ -1258,33 +1250,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1330,9 +1295,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;
|
||||
|
|
@ -1340,11 +1309,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;
|
||||
|
||||
|
|
@ -1869,6 +1833,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)
|
||||
|
|
@ -2023,7 +2051,7 @@ bool copyQtFiles(Options *options)
|
|||
QString libsDirectory = QLatin1String("libs/");
|
||||
|
||||
// Copy other Qt dependencies
|
||||
auto assetsDestinationDirectory = QLatin1String("assets/--Added-by-androiddeployqt--/");
|
||||
auto assetsDestinationDirectory = QLatin1String("assets/android_rcc_bundle/");
|
||||
for (const QtDependency &qtDependency : qAsConst(options->qtDependencies[options->currentArchitecture])) {
|
||||
QString sourceFileName = qtDependency.absolutePath;
|
||||
QString destinationFileName;
|
||||
|
|
@ -2033,7 +2061,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/"))) {
|
||||
|
|
@ -2679,57 +2707,6 @@ bool signPackage(const Options &options)
|
|||
return apkSignerRunner() && QFile::remove(packagePath(options, UnsignedAPK));
|
||||
}
|
||||
|
||||
bool generateAssetsFileList(const Options &options)
|
||||
{
|
||||
if (options.verbose)
|
||||
fprintf(stdout, "Pregenerating entry list for assets file engine.\n");
|
||||
|
||||
QString assetsPath = options.outputDirectory + QLatin1String("/assets/");
|
||||
QString addedByAndroidDeployQtPath = assetsPath + QLatin1String("--Added-by-androiddeployqt--/");
|
||||
if (!QDir().mkpath(addedByAndroidDeployQtPath)) {
|
||||
fprintf(stderr, "Failed to create directory '%s'", qPrintable(addedByAndroidDeployQtPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(addedByAndroidDeployQtPath + QLatin1String("/qt_cache_pregenerated_file_list"));
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
QDirIterator dirIterator(assetsPath,
|
||||
QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot,
|
||||
QDirIterator::Subdirectories);
|
||||
|
||||
QHash<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,
|
||||
|
|
@ -2747,9 +2724,9 @@ enum ErrorCode
|
|||
CannotBuildAndroidProject = 14,
|
||||
CannotSignPackage = 15,
|
||||
CannotInstallApk = 16,
|
||||
CannotGenerateAssetsFileList = 18,
|
||||
CannotCopyAndroidExtraResources = 19,
|
||||
CannotCopyApk = 20
|
||||
CannotCopyApk = 20,
|
||||
CannotCreateRcc = 21
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
@ -2846,14 +2823,16 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if (!createRcc(options))
|
||||
return CannotCreateRcc;
|
||||
|
||||
if (options.auxMode) {
|
||||
if (!updateAndroidFiles(options))
|
||||
return CannotUpdateAndroidFiles;
|
||||
if (options.generateAssetsFileList && !generateAssetsFileList(options))
|
||||
return CannotGenerateAssetsFileList;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (options.build) {
|
||||
if (!copyAndroidSources(options))
|
||||
return CannotCopyAndroidSources;
|
||||
|
|
@ -2864,9 +2843,6 @@ int main(int argc, char *argv[])
|
|||
if (!updateAndroidFiles(options))
|
||||
return CannotUpdateAndroidFiles;
|
||||
|
||||
if (options.generateAssetsFileList && !generateAssetsFileList(options))
|
||||
return CannotGenerateAssetsFileList;
|
||||
|
||||
if (Q_UNLIKELY(options.timing))
|
||||
fprintf(stdout, "[TIMING] %d ms: Updated files\n", options.timer.elapsed());
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ private slots:
|
|||
void fuzzyCompare();
|
||||
void ltgt_data();
|
||||
void ltgt();
|
||||
void qNan();
|
||||
void qNaN();
|
||||
void infinity();
|
||||
void float_cast();
|
||||
void float_cast_data();
|
||||
void promotionTests();
|
||||
|
|
@ -49,6 +50,9 @@ private slots:
|
|||
void arithOps();
|
||||
void floatToFloat16();
|
||||
void floatFromFloat16();
|
||||
void finite_data();
|
||||
void finite();
|
||||
void properties();
|
||||
void limits();
|
||||
};
|
||||
|
||||
|
|
@ -154,38 +158,66 @@ void tst_qfloat16::ltgt()
|
|||
# pragma GCC optimize "no-fast-math"
|
||||
#endif
|
||||
|
||||
void tst_qfloat16::qNan()
|
||||
void tst_qfloat16::qNaN()
|
||||
{
|
||||
#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404)
|
||||
QSKIP("Non-conformant fast math mode is enabled, cannot run test");
|
||||
#endif
|
||||
qfloat16 nan = qQNaN();
|
||||
QVERIFY(!(0. > nan));
|
||||
QVERIFY(!(0. < nan));
|
||||
using Bounds = std::numeric_limits<qfloat16>;
|
||||
const qfloat16 nan = Bounds::quiet_NaN();
|
||||
const qfloat16 zero(0), one(1);
|
||||
QVERIFY(!(zero > nan));
|
||||
QVERIFY(!(zero < nan));
|
||||
QVERIFY(!(zero == nan));
|
||||
QVERIFY(!qIsInf(nan));
|
||||
QVERIFY(qIsNaN(nan));
|
||||
QVERIFY(qIsNaN(nan + 1.f));
|
||||
QVERIFY(qIsNaN(nan + one));
|
||||
QVERIFY(qIsNaN(-nan));
|
||||
qfloat16 inf = qInf();
|
||||
QVERIFY(inf > qfloat16(0));
|
||||
QVERIFY(-inf < qfloat16(0));
|
||||
QVERIFY(!qIsNaN(inf));
|
||||
QVERIFY(qIsInf(inf));
|
||||
QVERIFY(qIsInf(-inf));
|
||||
QVERIFY(qIsInf(2.f*inf));
|
||||
QVERIFY(qIsInf(inf*2.f));
|
||||
// QTBUG-75812: QEMU/arm64 compiler over-optimizes, so flakily fails 1/inf == 0 :-(
|
||||
if (qfloat16(9.785e-4f) == qfloat16(9.794e-4f))
|
||||
QCOMPARE(qfloat16(1.f) / inf, qfloat16(0.f));
|
||||
#ifdef Q_CC_INTEL
|
||||
QEXPECT_FAIL("", "ICC optimizes zero * anything to zero", Continue);
|
||||
#endif
|
||||
QVERIFY(qIsNaN(nan*0.f));
|
||||
QVERIFY(qIsNaN(nan * zero));
|
||||
#ifdef Q_CC_INTEL
|
||||
QEXPECT_FAIL("", "ICC optimizes zero * anything to zero", Continue);
|
||||
#endif
|
||||
QVERIFY(qIsNaN(inf*0.f));
|
||||
QVERIFY(qFuzzyCompare(qfloat16(1.f/inf), qfloat16(0.0)));
|
||||
QVERIFY(qIsNaN(Bounds::infinity() * zero));
|
||||
|
||||
QVERIFY(!nan.isNormal());
|
||||
QVERIFY(!qIsFinite(nan));
|
||||
QVERIFY(!(nan == nan));
|
||||
QCOMPARE(nan, nan); // Despite the preceding
|
||||
QCOMPARE(qFpClassify(nan), FP_NAN);
|
||||
}
|
||||
|
||||
void tst_qfloat16::infinity()
|
||||
{
|
||||
const qfloat16 huge = std::numeric_limits<qfloat16>::infinity();
|
||||
const qfloat16 zero(0), one(1), two(2);
|
||||
QVERIFY(huge > -huge);
|
||||
QVERIFY(huge > zero);
|
||||
QVERIFY(-huge < zero);
|
||||
QCOMPARE(huge, huge);
|
||||
QCOMPARE(-huge, -huge);
|
||||
|
||||
// QTBUG-75812 - see overOptimized in the limits() test.
|
||||
if (qfloat16(9.785e-4f) == qfloat16(9.794e-4f)) {
|
||||
QCOMPARE(one / huge, zero);
|
||||
QVERIFY(qFuzzyCompare(one / huge, zero)); // (same thing)
|
||||
}
|
||||
|
||||
QVERIFY(qIsInf(huge));
|
||||
QVERIFY(qIsInf(-huge));
|
||||
QVERIFY(qIsInf(two * huge));
|
||||
QVERIFY(qIsInf(huge * two));
|
||||
|
||||
QVERIFY(!huge.isNormal());
|
||||
QVERIFY(!(-huge).isNormal());
|
||||
QVERIFY(!qIsNaN(huge));
|
||||
QVERIFY(!qIsNaN(-huge));
|
||||
QVERIFY(!qIsFinite(huge));
|
||||
QVERIFY(!qIsFinite(-huge));
|
||||
QCOMPARE(qFpClassify(huge), FP_INFINITE);
|
||||
QCOMPARE(qFpClassify(-huge), FP_INFINITE);
|
||||
}
|
||||
|
||||
void tst_qfloat16::float_cast_data()
|
||||
|
|
@ -366,10 +398,40 @@ static qfloat16 powf16(qfloat16 base, int raise)
|
|||
return answer;
|
||||
}
|
||||
|
||||
void tst_qfloat16::limits()
|
||||
void tst_qfloat16::finite_data()
|
||||
{
|
||||
using Bounds = std::numeric_limits<qfloat16>;
|
||||
QTest::addColumn<qfloat16>("value");
|
||||
QTest::addColumn<int>("mode");
|
||||
|
||||
QTest::newRow("zero") << qfloat16(0) << FP_ZERO;
|
||||
QTest::newRow("one") << qfloat16(1) << FP_NORMAL;
|
||||
QTest::newRow("-one") << qfloat16(-1) << FP_NORMAL;
|
||||
QTest::newRow("ten") << qfloat16(10) << FP_NORMAL;
|
||||
QTest::newRow("-ten") << qfloat16(-10) << FP_NORMAL;
|
||||
QTest::newRow("max") << Bounds::max() << FP_NORMAL;
|
||||
QTest::newRow("lowest") << Bounds::lowest() << FP_NORMAL;
|
||||
QTest::newRow("min") << Bounds::min() << FP_NORMAL;
|
||||
QTest::newRow("-min") << -Bounds::min() << FP_NORMAL;
|
||||
QTest::newRow("denorm_min") << Bounds::denorm_min() << FP_SUBNORMAL;
|
||||
QTest::newRow("-denorm_min") << -Bounds::denorm_min() << FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
void tst_qfloat16::finite()
|
||||
{
|
||||
QFETCH(qfloat16, value);
|
||||
QFETCH(int, mode);
|
||||
QCOMPARE(value.isNormal(), mode != FP_SUBNORMAL);
|
||||
QCOMPARE(value, value); // Fuzzy
|
||||
QVERIFY(value == value); // Exact
|
||||
QVERIFY(qIsFinite(value));
|
||||
QVERIFY(!qIsInf(value));
|
||||
QVERIFY(!qIsNaN(value));
|
||||
QCOMPARE(qFpClassify(value), mode);
|
||||
}
|
||||
|
||||
void tst_qfloat16::properties()
|
||||
{
|
||||
// *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy
|
||||
// comparison, and we need exact here.
|
||||
using Bounds = std::numeric_limits<qfloat16>;
|
||||
QVERIFY(Bounds::is_specialized);
|
||||
QVERIFY(Bounds::is_signed);
|
||||
|
|
@ -386,21 +448,16 @@ void tst_qfloat16::limits()
|
|||
QCOMPARE(Bounds::round_style, std::round_to_nearest);
|
||||
QCOMPARE(Bounds::radix, 2);
|
||||
// Untested: has_denorm_loss
|
||||
}
|
||||
|
||||
// A few common values:
|
||||
void tst_qfloat16::limits() // See also: qNaN() and infinity()
|
||||
{
|
||||
// *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy
|
||||
// comparison, and we need exact here.
|
||||
using Bounds = std::numeric_limits<qfloat16>;
|
||||
|
||||
// A few useful values:
|
||||
const qfloat16 zero(0), one(1), ten(10);
|
||||
QVERIFY(qIsFinite(zero));
|
||||
QVERIFY(!qIsInf(zero));
|
||||
QVERIFY(!qIsNaN(zero));
|
||||
QCOMPARE(qFpClassify(zero), FP_ZERO);
|
||||
QVERIFY(qIsFinite(one));
|
||||
QVERIFY(!qIsInf(one));
|
||||
QCOMPARE(qFpClassify(one), FP_NORMAL);
|
||||
QVERIFY(!qIsNaN(one));
|
||||
QVERIFY(qIsFinite(ten));
|
||||
QVERIFY(!qIsInf(ten));
|
||||
QVERIFY(!qIsNaN(ten));
|
||||
QCOMPARE(qFpClassify(ten), FP_NORMAL);
|
||||
|
||||
// digits in the mantissa, including the implicit 1 before the binary dot at its left:
|
||||
QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1)));
|
||||
|
|
@ -436,12 +493,12 @@ void tst_qfloat16::limits()
|
|||
// How many digits are significant ? (Casts avoid linker errors ...)
|
||||
QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits:
|
||||
qfloat16 below(9.785e-4f), above(9.794e-4f);
|
||||
#if 0 // Sadly, the QEMU x-compile for arm64 "optimises" comparisons:
|
||||
const bool overOptimised = false;
|
||||
#if 0 // Sadly, the QEMU x-compile for arm64 "optimizes" comparisons:
|
||||
const bool overOptimized = false;
|
||||
#else
|
||||
const bool overOptimised = (below != above);
|
||||
if (overOptimised)
|
||||
QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
|
||||
const bool overOptimized = (below != above);
|
||||
if (overOptimized)
|
||||
QEXPECT_FAIL("", "Over-optimized on ARM", Continue);
|
||||
#endif // (but it did, so should, pass everywhere else, confirming digits10 is indeed 3).
|
||||
QVERIFY(below == above);
|
||||
QCOMPARE(int(Bounds::max_digits10), 5); // we need 5 to distinguish these two:
|
||||
|
|
@ -450,62 +507,23 @@ void tst_qfloat16::limits()
|
|||
// Actual limiting values of the type:
|
||||
const qfloat16 rose(one + Bounds::epsilon());
|
||||
QVERIFY(rose > one);
|
||||
if (overOptimised)
|
||||
QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
|
||||
if (overOptimized)
|
||||
QEXPECT_FAIL("", "Over-optimized on ARM", Continue);
|
||||
QVERIFY(one + Bounds::epsilon() / rose == one);
|
||||
QVERIFY(qIsInf(Bounds::infinity()));
|
||||
QVERIFY(!qIsNaN(Bounds::infinity()));
|
||||
QVERIFY(!qIsFinite(Bounds::infinity()));
|
||||
QCOMPARE(Bounds::infinity(), Bounds::infinity());
|
||||
QCOMPARE(qFpClassify(Bounds::infinity()), FP_INFINITE);
|
||||
|
||||
QVERIFY(Bounds::infinity() > -Bounds::infinity());
|
||||
QVERIFY(Bounds::infinity() > zero);
|
||||
QVERIFY(qIsInf(-Bounds::infinity()));
|
||||
QVERIFY(!qIsNaN(-Bounds::infinity()));
|
||||
QVERIFY(!qIsFinite(-Bounds::infinity()));
|
||||
QCOMPARE(-Bounds::infinity(), -Bounds::infinity());
|
||||
QCOMPARE(qFpClassify(-Bounds::infinity()), FP_INFINITE);
|
||||
|
||||
QVERIFY(-Bounds::infinity() < zero);
|
||||
QVERIFY(qIsNaN(Bounds::quiet_NaN()));
|
||||
QVERIFY(!qIsInf(Bounds::quiet_NaN()));
|
||||
QVERIFY(!qIsFinite(Bounds::quiet_NaN()));
|
||||
QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN()));
|
||||
QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN());
|
||||
QCOMPARE(qFpClassify(Bounds::quiet_NaN()), FP_NAN);
|
||||
|
||||
QVERIFY(Bounds::max() > zero);
|
||||
QVERIFY(qIsFinite(Bounds::max()));
|
||||
QVERIFY(!qIsInf(Bounds::max()));
|
||||
QVERIFY(!qIsNaN(Bounds::max()));
|
||||
QVERIFY(qIsInf(Bounds::max() * rose));
|
||||
QCOMPARE(qFpClassify(Bounds::max()), FP_NORMAL);
|
||||
|
||||
QVERIFY(Bounds::lowest() < zero);
|
||||
QVERIFY(qIsFinite(Bounds::lowest()));
|
||||
QVERIFY(!qIsInf(Bounds::lowest()));
|
||||
QVERIFY(!qIsNaN(Bounds::lowest()));
|
||||
QVERIFY(qIsInf(Bounds::lowest() * rose));
|
||||
QCOMPARE(qFpClassify(Bounds::lowest()), FP_NORMAL);
|
||||
|
||||
QVERIFY(Bounds::min() > zero);
|
||||
QVERIFY(Bounds::min().isNormal());
|
||||
QVERIFY(!(Bounds::min() / rose).isNormal());
|
||||
QVERIFY(qIsFinite(Bounds::min()));
|
||||
QVERIFY(!qIsInf(Bounds::min()));
|
||||
QVERIFY(!qIsNaN(Bounds::min()));
|
||||
QCOMPARE(qFpClassify(Bounds::min()), FP_NORMAL);
|
||||
|
||||
QVERIFY(Bounds::denorm_min() > zero);
|
||||
QVERIFY(!Bounds::denorm_min().isNormal());
|
||||
QVERIFY(qIsFinite(Bounds::denorm_min()));
|
||||
QVERIFY(!qIsInf(Bounds::denorm_min()));
|
||||
QVERIFY(!qIsNaN(Bounds::denorm_min()));
|
||||
if (overOptimised)
|
||||
QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
|
||||
if (overOptimized)
|
||||
QEXPECT_FAIL("", "Over-optimized on ARM", Continue);
|
||||
QCOMPARE(Bounds::denorm_min() / rose, zero);
|
||||
QCOMPARE(qFpClassify(Bounds::denorm_min()), FP_SUBNORMAL);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_qfloat16)
|
||||
|
|
|
|||
|
|
@ -165,11 +165,13 @@ void Window::customRender()
|
|||
u->updateDynamicBuffer(d.ubuf, 64, 4, &flip);
|
||||
}
|
||||
if (!d.compressedData.isEmpty()) {
|
||||
QRhiTextureUploadDescription desc;
|
||||
QVarLengthArray<QRhiTextureUploadEntry, 16> descEntries;
|
||||
for (int i = 0; i < d.compressedData.count(); ++i) {
|
||||
QRhiTextureSubresourceUploadDescription image(d.compressedData[i].constData(), d.compressedData[i].size());
|
||||
desc.append({ 0, i, image });
|
||||
descEntries.append({ 0, i, image });
|
||||
}
|
||||
QRhiTextureUploadDescription desc;
|
||||
desc.setEntries(descEntries.cbegin(), descEntries.cend());
|
||||
u->uploadTexture(d.tex, desc);
|
||||
d.compressedData.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,10 +143,10 @@ void Window::customInit()
|
|||
}
|
||||
|
||||
QRhiTextureRenderTargetDescription rtDesc;
|
||||
QVector<QRhiColorAttachment> att;
|
||||
QRhiColorAttachment att[ATTCOUNT];
|
||||
for (int i = 0; i < ATTCOUNT; ++i)
|
||||
att.append(QRhiColorAttachment(d.colData[i].tex));
|
||||
rtDesc.setColorAttachments(att);
|
||||
att[i] = QRhiColorAttachment(d.colData[i].tex);
|
||||
rtDesc.setColorAttachments(att, att + ATTCOUNT);
|
||||
d.rt = m_r->newTextureRenderTarget(rtDesc);
|
||||
d.releasePool << d.rt;
|
||||
d.rtRp = d.rt->newCompatibleRenderPassDescriptor();
|
||||
|
|
|
|||
|
|
@ -181,16 +181,18 @@ void TexturedCubeRenderer::queueResourceUpdates(QRhiResourceUpdateBatch *resourc
|
|||
|
||||
if (!m_image.isNull()) {
|
||||
if (MIPMAP) {
|
||||
QRhiTextureUploadDescription desc;
|
||||
QVarLengthArray<QRhiTextureUploadEntry, 16> descEntries;
|
||||
if (!AUTOGENMIPMAP) {
|
||||
// the ghetto mipmap generator...
|
||||
for (int i = 0, ie = m_r->mipLevelsForSize(m_image.size()); i != ie; ++i) {
|
||||
QImage image = m_image.scaled(m_r->sizeForMipLevel(i, m_image.size()));
|
||||
desc.append({ 0, i, image });
|
||||
descEntries.append({ 0, i, image });
|
||||
}
|
||||
} else {
|
||||
desc.append({ 0, 0, m_image });
|
||||
descEntries.append({ 0, 0, m_image });
|
||||
}
|
||||
QRhiTextureUploadDescription desc;
|
||||
desc.setEntries(descEntries.cbegin(), descEntries.cend());
|
||||
resourceUpdates->uploadTexture(m_tex, desc);
|
||||
if (AUTOGENMIPMAP)
|
||||
resourceUpdates->generateMips(m_tex);
|
||||
|
|
|
|||
Loading…
Reference in New Issue