summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure2
-rw-r--r--configure.json1
-rw-r--r--configure.pri30
-rw-r--r--examples/network/network.pro8
-rw-r--r--mkspecs/android-clang/qmake.conf6
-rw-r--r--qmake/doc/src/qmake-manual.qdoc49
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp5
-rw-r--r--qmake/generators/makefile.cpp15
-rw-r--r--qmake/generators/unix/unixmake.cpp58
-rw-r--r--qmake/generators/unix/unixmake.h1
-rw-r--r--qmake/generators/unix/unixmake2.cpp73
-rw-r--r--qmake/generators/win32/mingw_make.cpp36
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp2
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp13
-rw-r--r--qmake/generators/win32/winmakefile.cpp11
-rw-r--r--src/3rdparty/freetype/qt_attribution.json2
-rw-r--r--src/3rdparty/wasm/qt_attribution.json1
-rw-r--r--src/gui/image/qimage.cpp16
-rw-r--r--src/gui/image/qimage_conversions.cpp17
-rw-r--r--src/gui/image/qpixmap_win.cpp5
-rw-r--r--src/gui/painting/qdrawhelper.cpp9
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp159
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp382
-rw-r--r--src/network/access/qnetworkreplywasmimpl_p.h16
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp56
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h3
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json3
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp55
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp3
-rw-r--r--tests/auto/network/ssl/ssl.pro2
32 files changed, 594 insertions, 455 deletions
diff --git a/configure b/configure
index 2830a1b189..ef7bad1bfc 100755
--- a/configure
+++ b/configure
@@ -771,7 +771,7 @@ setBootstrapVariable()
echo "RM_RF = rm -rf" >> "$mkfile"
case `basename "$PLATFORM"` in
- win32-g++*)
+ win32-*g++*)
cat "$in_mkfile.win32" >> "$mkfile"
;;
*)
diff --git a/configure.json b/configure.json
index 85d6a8c31a..3702c24f63 100644
--- a/configure.json
+++ b/configure.json
@@ -730,6 +730,7 @@
"headersclean": {
"label": "Check for clean headers",
"autoDetect": "features.developer-build",
+ "condition": "!config.wasm",
"output": [ "privateConfig" ]
},
"framework": {
diff --git a/configure.pri b/configure.pri
index 3747f96f3d..64ed6b9ed8 100644
--- a/configure.pri
+++ b/configure.pri
@@ -1221,13 +1221,43 @@ defineReplace(qtConfReportArch) {
return("$$arch, CPU features: $$subarch")
}
+defineReplace(qtConfReportCompiler) {
+ clang_cl: {
+ return("clang-cl $${QMAKE_CLANG_MAJOR_VERSION}.$${QMAKE_CLANG_MINOR_VERSION}.$${QMAKE_CLANG_PATCH_VERSION}")
+ } else: clang {
+ !isEmpty(QMAKE_APPLE_CLANG_MAJOR_VERSION) {
+ return("clang (Apple) $${QMAKE_APPLE_CLANG_MAJOR_VERSION}.$${QMAKE_APPLE_CLANG_MINOR_VERSION}.$${QMAKE_APPLE_CLANG_PATCH_VERSION}")
+ } else {
+ return("clang $${QMAKE_CLANG_MAJOR_VERSION}.$${QMAKE_CLANG_MINOR_VERSION}.$${QMAKE_CLANG_PATCH_VERSION}")
+ }
+ } else: intel_icc {
+ return("intel_icc $$QMAKE_ICC_VER")
+ } else: intel_icl {
+ return("intel_icl $$QMAKE_ICC_VER")
+ } else: rim_qcc {
+ return("rim_qcc $${QMAKE_GCC_MAJOR_VERSION}.$${QMAKE_GCC_MINOR_VERSION}.$${QMAKE_GCC_PATCH_VERSION}")
+ } else: gcc {
+ return("gcc $${QMAKE_GCC_MAJOR_VERSION}.$${QMAKE_GCC_MINOR_VERSION}.$${QMAKE_GCC_PATCH_VERSION}")
+ } else: msvc {
+ return("msvc $$QMAKE_MSC_FULL_VER")
+ } else: ghs {
+ return("ghs $$QMAKE_GHS_VERSION")
+ } else {
+ return("unknown ($$QMAKE_COMPILER)")
+ }
+}
+
+
defineTest(qtConfReport_buildTypeAndConfig) {
!$$qtConfEvaluate("features.cross_compile") {
qtConfAddReport("Build type: $$[QMAKE_SPEC] ($$qtConfReportArch(architecture))")
+ qtConfAddReport("Compiler: $$qtConfReportCompiler()")
} else {
qtConfAddReport("Building on: $$[QMAKE_SPEC] ($$qtConfReportArch(host_architecture))")
qtConfAddReport("Building for: $$[QMAKE_XSPEC] ($$qtConfReportArch(architecture))")
+ qtConfAddReport("Target compiler: $$qtConfReportCompiler()")
}
+
qtConfAddReport()
qtConfAddReport("Configuration: $$eval($${currentConfig}.output.privatePro.append.CONFIG) $$eval($${currentConfig}.output.publicPro.append.QT_CONFIG)")
qtConfAddReport()
diff --git a/examples/network/network.pro b/examples/network/network.pro
index 93049014eb..1556e26ab1 100644
--- a/examples/network/network.pro
+++ b/examples/network/network.pro
@@ -29,12 +29,8 @@ qtHaveModule(widgets) {
}
- qtConfig(openssl) {
- SUBDIRS += \
- securesocketclient \
- secureudpserver \
- secureudpclient
- }
+ qtConfig(openssl): SUBDIRS += securesocketclient
+ qtConfig(dtls): SUBDIRS += secureudpserver secureudpclient
qtConfig(sctp): SUBDIRS += multistreamserver multistreamclient
}
diff --git a/mkspecs/android-clang/qmake.conf b/mkspecs/android-clang/qmake.conf
index b665000d00..1f5e690329 100644
--- a/mkspecs/android-clang/qmake.conf
+++ b/mkspecs/android-clang/qmake.conf
@@ -40,7 +40,11 @@ QMAKE_CFLAGS += -DANDROID_HAS_WSTRING --sysroot=$$NDK_ROOT/sysroot \
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++_shared.so
-ANDROID_CXX_STL_LIBS = -lc++
+
+exists($$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so): \
+ ANDROID_CXX_STL_LIBS = -lc++
+else: \
+ ANDROID_CXX_STL_LIBS = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so.$$replace(ANDROID_PLATFORM, "android-", "")
QMAKE_CFLAGS_OPTIMIZE_SIZE = -Oz
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index 409062cf49..7fd9dd9623 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -907,9 +907,9 @@
Platform-specific variables follow the naming pattern of the
variables which they extend or modify, but include the name of the relevant
- platform in their name. For example, \c QMAKE_LIBS can be used to specify a list
- of libraries that a project needs to link against, and \c QMAKE_LIBS_X11 can be
- used to extend or override this list.
+ platform in their name. For example, a makespec may use \c QMAKE_LIBS
+ to specify a list of libraries that each project needs to link against,
+ and \c QMAKE_LIBS_X11 would be used to extend this list.
\target CONFIG
\section1 CONFIG
@@ -1320,6 +1320,19 @@
\snippet code/doc_src_qmake-manual.pro 39
+ \target LIBS_PRIVATE
+ \section1 LIBS_PRIVATE
+
+ Specifies a list of libraries to be linked privately into the project.
+ The behavior of this variable is identical to \l LIBS, except that
+ shared library projects built for Unix do not expose these dependencies
+ in their link interface.
+
+ The effect of this is that if project C depends on library B which
+ depends on library A privately, but C also wants to use symbols from A
+ directly, it needs to link to A explicitly. Put differently, libraries
+ linked privately are not exposed transitively at build time.
+
\target LITERAL_HASH
\section1 LITERAL_HASH
@@ -2048,7 +2061,19 @@
\section1 QMAKE_LIBDIR
- Specifies a list of system library paths.
+ Specifies a list of library search paths for all projects.
+ The value of this variable is typically handled by qmake
+ or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
+ To specify additional search paths in project files,
+ use \l LIBS like that, instead:
+ \badcode
+ LIBS += -L/path/to/libraries
+ \endcode
+
+ \section1 QMAKE_LIBDIR_POST
+
+ Specifies a list of system library search paths for all projects.
The value of this variable is typically handled by qmake
or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
@@ -2098,10 +2123,22 @@
\section1 QMAKE_LIBS
- Specifies all project libraries. The value of this variable
- is typically handled by qmake or
+ Specifies additional libraries each project needs to link against.
+ The value of this variable is typically handled by qmake or
+ \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
+ To specify libraries in a project file, use \l LIBS instead.
+
+ \section1 QMAKE_LIBS_PRIVATE
+
+ Specifies additional private libraries each project needs to
+ link against.
+ The value of this variable is typically handled by qmake or
\l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+ To specify private libraries in a library project file,
+ use \l LIBS_PRIVATE instead.
+
\section1 QMAKE_LIBS_EGL
Specifies all EGL libraries when building Qt with OpenGL/ES
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index 72daa97fe4..5407ed6c69 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -829,7 +829,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
ProStringList &libdirs = project->values("QMAKE_PBX_LIBPATHS"),
&frameworkdirs = project->values("QMAKE_FRAMEWORKPATH");
- static const char * const libs[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
+ static const char * const libs[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; libs[i]; i++) {
tmp = project->values(libs[i]);
for(int x = 0; x < tmp.count();) {
@@ -1695,6 +1696,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t\t\t\t" << writeSettings("OTHER_LDFLAGS",
fixListForOutput("SUBLIBS")
+ fixListForOutput("QMAKE_LFLAGS")
+ + fixListForOutput(fixLibFlags("LIBS"))
+ + fixListForOutput(fixLibFlags("LIBS_PRIVATE"))
+ fixListForOutput(fixLibFlags("QMAKE_LIBS"))
+ fixListForOutput(fixLibFlags("QMAKE_LIBS_PRIVATE")),
SettingsAsList, 6) << ";\n";
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 7c359071bf..e41e391cad 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -1012,12 +1012,10 @@ MakefileGenerator::writePrlFile(QTextStream &t)
t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl;
if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) {
ProStringList libs;
- if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
+ if (!project->isActiveConfig("staticlib"))
+ libs << "LIBS" << "QMAKE_LIBS";
else
- libs << "QMAKE_LIBS"; //obvious one
- if(project->isActiveConfig("staticlib"))
- libs << "QMAKE_LIBS_PRIVATE";
+ libs << "LIBS" << "LIBS_PRIVATE" << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
t << "QMAKE_PRL_LIBS =";
for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
t << qv(project->values((*it).toKey()));
@@ -3348,10 +3346,9 @@ MakefileGenerator::writePkgConfigFile()
if (project->isActiveConfig("staticlib")) {
ProStringList libs;
- if (!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
- else
- libs << "QMAKE_LIBS"; //obvious one
+ libs << "LIBS"; // FIXME: this should not be conditional on staticlib
+ libs << "LIBS_PRIVATE";
+ libs << "QMAKE_LIBS"; // FIXME: this should not be conditional on staticlib
libs << "QMAKE_LIBS_PRIVATE";
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
t << "Libs.private:";
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index 4fe1a54501..50ec8db79e 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -37,6 +37,17 @@
QT_BEGIN_NAMESPACE
+ProStringList UnixMakefileGenerator::libdirToFlags(const ProKey &key)
+{
+ ProStringList results;
+ for (const auto &libdir : qAsConst(project->values(key))) {
+ if (!project->isEmpty("QMAKE_LFLAGS_RPATH") && project->isActiveConfig("rpath_libdirs"))
+ project->values("QMAKE_LFLAGS") += var("QMAKE_LFLAGS_RPATH") + libdir;
+ results.append("-L" + escapeFilePath(libdir));
+ }
+ return results;
+}
+
void
UnixMakefileGenerator::init()
{
@@ -80,8 +91,6 @@ UnixMakefileGenerator::init()
}
project->values("QMAKE_ORIG_DESTDIR") = project->values("DESTDIR");
- project->values("QMAKE_LIBS") += project->values("LIBS");
- project->values("QMAKE_LIBS_PRIVATE") += project->values("LIBS_PRIVATE");
if((!project->isEmpty("QMAKE_LIB_FLAG") && !project->isActiveConfig("staticlib")) ||
(project->isActiveConfig("qt") && project->isActiveConfig("plugin"))) {
if(configs.indexOf("dll") == -1) configs.append("dll");
@@ -95,21 +104,13 @@ UnixMakefileGenerator::init()
project->isActiveConfig("dll"))
project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_PREBIND");
project->values("QMAKE_INCDIR") += project->values("QMAKE_INCDIR_POST");
- project->values("QMAKE_LIBDIR") += project->values("QMAKE_LIBDIR_POST");
project->values("QMAKE_RPATHDIR") += project->values("QMAKE_RPATHDIR_POST");
project->values("QMAKE_RPATHLINKDIR") += project->values("QMAKE_RPATHLINKDIR_POST");
if(!project->isEmpty("QMAKE_INCDIR"))
project->values("INCLUDEPATH") += project->values("QMAKE_INCDIR");
- ProStringList ldadd;
- if(!project->isEmpty("QMAKE_LIBDIR")) {
- const ProStringList &libdirs = project->values("QMAKE_LIBDIR");
- for(int i = 0; i < libdirs.size(); ++i) {
- if(!project->isEmpty("QMAKE_LFLAGS_RPATH") && project->isActiveConfig("rpath_libdirs"))
- project->values("QMAKE_LFLAGS") += var("QMAKE_LFLAGS_RPATH") + libdirs[i];
- project->values("QMAKE_LIBDIR_FLAGS") += "-L" + escapeFilePath(libdirs[i]);
- }
- }
- ldadd += project->values("QMAKE_LIBDIR_FLAGS");
+ // The order of the next two lines is relevant due to side effect on QMAKE_LFLAGS.
+ ProStringList ldadd = project->values("QMAKE_LIBDIR_FLAGS") + libdirToFlags("QMAKE_LIBDIR");
+ ProStringList ldaddpost = libdirToFlags("QMAKE_LIBDIR_POST");
if (project->isActiveConfig("mac")) {
if (!project->isEmpty("QMAKE_FRAMEWORKPATH")) {
const ProStringList &fwdirs = project->values("QMAKE_FRAMEWORKPATH");
@@ -118,8 +119,10 @@ UnixMakefileGenerator::init()
}
ldadd += project->values("QMAKE_FRAMEWORKPATH_FLAGS");
}
- ProStringList &qmklibs = project->values("QMAKE_LIBS");
+ ProStringList &qmklibs = project->values("LIBS");
qmklibs = ldadd + qmklibs;
+ ProStringList &qmklibspost = project->values("QMAKE_LIBS");
+ qmklibspost = ldaddpost + qmklibspost;
if (!project->isEmpty("QMAKE_RPATHDIR") && !project->isEmpty("QMAKE_LFLAGS_RPATH")) {
const ProStringList &rpathdirs = project->values("QMAKE_RPATHDIR");
for (int i = 0; i < rpathdirs.size(); ++i) {
@@ -300,35 +303,11 @@ UnixMakefileGenerator::init()
}
init2();
- project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_LIBS";
ProString target = project->first("TARGET");
int slsh = target.lastIndexOf(Option::dir_sep);
if (slsh != -1)
target.chopFront(slsh + 1);
project->values("LIB_TARGET").prepend(target);
- if(!project->isEmpty("QMAKE_MAX_FILES_PER_AR")) {
- bool ok;
- int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(&ok);
- ProStringList ar_sublibs, objs = project->values("OBJECTS");
- if(ok && max_files > 5 && max_files < (int)objs.count()) {
- QString lib;
- for(int i = 0, obj_cnt = 0, lib_cnt = 0; i != objs.size(); ++i) {
- if((++obj_cnt) >= max_files) {
- if(lib_cnt) {
- lib.sprintf("lib%s-tmp%d.a",
- project->first("QMAKE_ORIG_TARGET").toLatin1().constData(), lib_cnt);
- ar_sublibs << lib;
- obj_cnt = 0;
- }
- lib_cnt++;
- }
- }
- }
- if(!ar_sublibs.isEmpty()) {
- project->values("QMAKE_AR_SUBLIBS") = ar_sublibs;
- project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_AR_SUBLIBS";
- }
- }
}
QStringList
@@ -420,7 +399,8 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
libdirs.append(QMakeLocalFileName(dlib.toQString()));
frameworkdirs.append(QMakeLocalFileName("/System/Library/Frameworks"));
frameworkdirs.append(QMakeLocalFileName("/Library/Frameworks"));
- static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
+ static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
ProStringList &l = project->values(lflags[i]);
for (ProStringList::Iterator it = l.begin(); it != l.end(); ) {
diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h
index c5e42aa1ae..5b0766855b 100644
--- a/qmake/generators/unix/unixmake.h
+++ b/qmake/generators/unix/unixmake.h
@@ -66,6 +66,7 @@ protected:
private:
void init2();
+ ProStringList libdirToFlags(const ProKey &key);
};
inline UnixMakefileGenerator::~UnixMakefileGenerator()
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index ab946fa439..976751b02c 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -213,7 +213,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isActiveConfig("staticlib")) {
t << "LINK = " << var("QMAKE_LINK") << endl;
t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
- t << "LIBS = $(SUBLIBS) " << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
+ t << "LIBS = $(SUBLIBS) " << fixLibFlags("LIBS").join(' ') << ' '
+ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
+ << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
}
@@ -690,56 +692,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
QString destdir_r = project->first("DESTDIR").toQString();
QString destdir_d = escapeDependencyPath(destdir_r);
QString destdir = escapeFilePath(destdir_r);
- allDeps = ' ' + destdir_d + depVar("TARGET")
- + varGlue("QMAKE_AR_SUBLIBS", ' ' + destdir_d, ' ' + destdir_d, "");
- t << "staticlib: " << destdir_d << "$(TARGET)\n\n";
- if(project->isEmpty("QMAKE_AR_SUBLIBS")) {
- t << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS")
- << " $(OBJECTS) $(OBJCOMP) " << depVar("POST_TARGETDEPS") << "\n\t";
- if(!destdir.isEmpty())
- t << mkdir_p_asstring(destdir, false) << "\n\t";
- if (!project->isEmpty("QMAKE_PRE_LINK"))
- t << var("QMAKE_PRE_LINK") << "\n\t";
- t << "-$(DEL_FILE) " << destdir << "$(TARGET)\n\t"
- << var("QMAKE_AR_CMD") << "\n";
- if(!project->isEmpty("QMAKE_POST_LINK"))
- t << "\t" << var("QMAKE_POST_LINK") << "\n";
- if(!project->isEmpty("QMAKE_RANLIB"))
- t << "\t$(RANLIB) " << destdir << "$(TARGET)\n";
- } else {
- int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt();
- ProStringList objs = project->values("OBJECTS") + project->values("OBJCOMP"),
- libs = project->values("QMAKE_AR_SUBLIBS");
- libs.prepend("$(TARGET)");
- for (ProStringList::Iterator libit = libs.begin(), objit = objs.begin();
- libit != libs.end(); ++libit) {
- ProStringList build;
- for(int cnt = 0; cnt < max_files && objit != objs.end(); ++objit, cnt++)
- build << (*objit);
- QString ar;
- ProString lib = destdir + escapeFilePath(*libit);
- if((*libit) == "$(TARGET)") {
- t << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS")
- << ' ' << depVar("POST_TARGETDEPS") << valList(escapeDependencyPaths(build)) << "\n\t";
- ar = project->first("QMAKE_AR_CMD").toQString();
- ar.replace(QLatin1String("$(OBJECTS)"), escapeFilePaths(build).join(' '));
- } else {
- t << destdir_d << escapeDependencyPath(*libit) << ": "
- << valList(escapeDependencyPaths(build)) << "\n\t";
- ar = "$(AR) " + lib + ' ' + escapeFilePaths(build).join(' ');
- }
- if(!destdir.isEmpty())
- t << mkdir_p_asstring(destdir, false) << "\n\t";
- if (!project->isEmpty("QMAKE_PRE_LINK"))
- t << var("QMAKE_PRE_LINK") << "\n\t";
- t << "-$(DEL_FILE) " << lib << "\n\t"
- << ar << "\n";
- if(!project->isEmpty("QMAKE_POST_LINK"))
- t << "\t" << var("QMAKE_POST_LINK") << "\n";
- if(!project->isEmpty("QMAKE_RANLIB"))
- t << "\t$(RANLIB) " << lib << "\n";
- }
- }
+ allDeps = ' ' + destdir_d + depVar("TARGET");
+ t << "staticlib: " << destdir_d << "$(TARGET)\n\n"
+ << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS")
+ << " $(OBJECTS) $(OBJCOMP) " << depVar("POST_TARGETDEPS") << "\n\t";
+ if (!destdir.isEmpty())
+ t << mkdir_p_asstring(destdir, false) << "\n\t";
+ if (!project->isEmpty("QMAKE_PRE_LINK"))
+ t << var("QMAKE_PRE_LINK") << "\n\t";
+ t << "-$(DEL_FILE) " << destdir << "$(TARGET)\n\t"
+ << var("QMAKE_AR_CMD") << "\n";
+ if (!project->isEmpty("QMAKE_POST_LINK"))
+ t << "\t" << var("QMAKE_POST_LINK") << "\n";
+ if (!project->isEmpty("QMAKE_RANLIB"))
+ t << "\t$(RANLIB) " << destdir << "$(TARGET)\n";
t << endl << endl;
}
@@ -1515,10 +1481,7 @@ UnixMakefileGenerator::writeLibtoolFile()
t << "# Libraries that this one depends upon.\n";
ProStringList libs;
- if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
- else
- libs << "QMAKE_LIBS"; //obvious one
+ libs << "LIBS" << "QMAKE_LIBS";
t << "dependency_libs='";
for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it)
t << fixLibFlags((*it).toKey()).join(' ') << ' ';
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index 13412e971a..de7363e51b 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -131,22 +131,25 @@ QString MingwMakefileGenerator::installRoot() const
return QStringLiteral("$(INSTALL_ROOT:@msyshack@%=%)");
}
-void createLdObjectScriptFile(const QString &fileName, const ProStringList &objList)
+void createLdResponseFile(const QString &fileName, const ProStringList &objList)
{
QString filePath = Option::output_dir + QDir::separator() + fileName;
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream t(&file);
- t << "INPUT(\n";
for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
QString path = (*it).toQString();
- // ### quoting?
- if (QDir::isRelativePath(path))
- t << "./" << path << endl;
- else
- t << path << endl;
+ // In response files, whitespace and special characters are
+ // escaped with a backslash; backslashes themselves can either
+ // be escaped into double backslashes, or, as this is a list of
+ // path names, converted to forward slashes.
+ path.replace(QLatin1Char('\\'), QLatin1String("/"))
+ .replace(QLatin1Char(' '), QLatin1String("\\ "))
+ .replace(QLatin1Char('\t'), QLatin1String("\\\t"))
+ .replace(QLatin1Char('"'), QLatin1String("\\\""))
+ .replace(QLatin1Char('\''), QLatin1String("\\'"));
+ t << path << endl;
}
- t << ");\n";
t.flush();
file.close();
}
@@ -206,7 +209,7 @@ void MingwMakefileGenerator::init()
processVars();
- project->values("QMAKE_LIBS") += project->values("RES_FILE");
+ project->values("LIBS") += project->values("RES_FILE");
if (project->isActiveConfig("dll")) {
QString destDir = "";
@@ -282,6 +285,8 @@ void MingwMakefileGenerator::writeLibsPart(QTextStream &t)
t << "LINKER = " << var("QMAKE_LINK") << endl;
t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
t << "LIBS = "
+ << fixLibFlags("LIBS").join(' ') << ' '
+ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
}
@@ -307,14 +312,13 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t)
createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS"));
objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file);
} else {
- QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
- if (!var("BUILD_NAME").isEmpty()) {
- ld_script_file += "." + var("BUILD_NAME");
- }
+ QString ld_response_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
+ if (!var("BUILD_NAME").isEmpty())
+ ld_response_file += "." + var("BUILD_NAME");
if (!var("MAKEFILE").isEmpty())
- ld_script_file += "." + var("MAKEFILE");
- createLdObjectScriptFile(ld_script_file, project->values("OBJECTS"));
- objectsLinkLine = escapeFilePath(ld_script_file);
+ ld_response_file += "." + var("MAKEFILE");
+ createLdResponseFile(ld_response_file, project->values("OBJECTS"));
+ objectsLinkLine = "@" + escapeFilePath(ld_response_file);
}
Win32MakefileGenerator::writeObjectsPart(t);
}
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index fa7ee1b98a..f2cd7c633b 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -383,7 +383,7 @@ void NmakeMakefileGenerator::init()
processVars();
- project->values("QMAKE_LIBS") += project->values("RES_FILE");
+ project->values("LIBS") += project->values("RES_FILE");
if (!project->values("DEF_FILE").isEmpty()) {
QString defFileName = fileFixify(project->first("DEF_FILE").toQString());
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 73f0f35d1b..f7837fc1b4 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -457,9 +457,8 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
newDep->dependencies << "idc.exe";
// Add all unknown libs to the deps
- QStringList where = QStringList() << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
- if (!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- where = tmp_proj.values("QMAKE_INTERNAL_PRL_LIBS").toQStringList();
+ QStringList where = QStringList() << "LIBS" << "LIBS_PRIVATE"
+ << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
for (QStringList::ConstIterator wit = where.begin();
wit != where.end(); ++wit) {
const ProStringList &l = tmp_proj.values(ProKey(*wit));
@@ -750,7 +749,7 @@ void VcprojGenerator::init()
projectTarget = Application;
} else if(project->first("TEMPLATE") == "vclib") {
if(project->isActiveConfig("staticlib")) {
- project->values("QMAKE_LIBS") += project->values("RES_FILE");
+ project->values("LIBS") += project->values("RES_FILE");
projectTarget = StaticLib;
} else
projectTarget = SharedLib;
@@ -1086,7 +1085,8 @@ void VcprojGenerator::initLinkerTool()
if (!project->values("DEF_FILE").isEmpty())
conf.linker.ModuleDefinitionFile = project->first("DEF_FILE").toQString();
- static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
+ static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
const auto libs = fixLibFlags(lflags[i]);
for (const ProString &lib : libs) {
@@ -1181,7 +1181,8 @@ void VcprojGenerator::initDeploymentTool()
if (!dllPaths.isEmpty() &&
!(conf.WinRT && project->first("MSVC_VER").toQString() == "14.0")) {
// FIXME: This code should actually resolve the libraries from all Qt modules.
- ProStringList arg = project->values("QMAKE_LIBS") + project->values("QMAKE_LIBS_PRIVATE");
+ ProStringList arg = project->values("LIBS") + project->values("LIBS_PRIVATE")
+ + project->values("QMAKE_LIBS") + project->values("QMAKE_LIBS_PRIVATE");
bool qpaPluginDeployed = false;
for (ProStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) {
QString dllName = (*it).toQString();
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index 1388e120e7..e0d03ccc1c 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -84,7 +84,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
if (impexts.isEmpty())
impexts = project->values("QMAKE_EXTENSION_STATICLIB");
QList<QMakeLocalFileName> dirs;
- static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
+ static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
ProStringList &l = project->values(lflags[i]);
for (ProStringList::Iterator it = l.begin(); it != l.end();) {
@@ -225,8 +226,8 @@ void Win32MakefileGenerator::processVars()
libs << QLatin1String("-L") + lib;
}
}
- project->values("QMAKE_LIBS") += libs + project->values("LIBS");
- project->values("QMAKE_LIBS_PRIVATE") += project->values("LIBS_PRIVATE");
+ ProStringList &qmklibs = project->values("LIBS");
+ qmklibs = libs + qmklibs;
if (project->values("TEMPLATE").contains("app")) {
project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_APP");
@@ -651,7 +652,9 @@ void Win32MakefileGenerator::writeLibsPart(QTextStream &t)
} else {
t << "LINKER = " << var("QMAKE_LINK") << endl;
t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
- t << "LIBS = " << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
+ t << "LIBS = " << fixLibFlags("LIBS").join(' ') << ' '
+ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
+ << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
}
}
diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json
index 4be86e92b6..f46541cf2e 100644
--- a/src/3rdparty/freetype/qt_attribution.json
+++ b/src/3rdparty/freetype/qt_attribution.json
@@ -7,6 +7,8 @@
"Description": "FreeType is a freely available software library to render fonts.",
"Homepage": "http://www.freetype.org",
+ "Version": "2.6.1",
+
"License": "Freetype Project License or GNU General Public License v2.0 only",
"LicenseId": "FTL OR GPL-2.0",
"LicenseFile": "LICENSE.txt",
diff --git a/src/3rdparty/wasm/qt_attribution.json b/src/3rdparty/wasm/qt_attribution.json
index 184e2968cd..2724008157 100644
--- a/src/3rdparty/wasm/qt_attribution.json
+++ b/src/3rdparty/wasm/qt_attribution.json
@@ -18,4 +18,3 @@
"LicenseFile": "LICENSE",
"Copyright": "Copyright (C) 2003 Bitstream,Inc"
}
-
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 8a4c6b7fda..636cacfb9c 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1454,7 +1454,8 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
return;
detach();
- d->devicePixelRatio = scaleFactor;
+ if (d)
+ d->devicePixelRatio = scaleFactor;
}
/*!
@@ -2240,8 +2241,15 @@ bool QImage::reinterpretAsFormat(Format format)
return true;
if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
return false;
- if (!isDetached()) // Detach only if shared, not for read-only data.
+ if (!isDetached()) { // Detach only if shared, not for read-only data.
+ QImageData *oldD = d;
detach();
+ // In case detach() ran out of memory
+ if (!d) {
+ d = oldD;
+ return false;
+ }
+ }
d->format = format;
return true;
@@ -3288,6 +3296,8 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical)
return;
detach();
+ if (!d)
+ return;
if (!d->own_data)
*this = copy();
@@ -3440,6 +3450,8 @@ void QImage::rgbSwapped_inplace()
return;
detach();
+ if (!d)
+ return;
if (!d->own_data)
*this = copy();
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index e1f66dceee..964dc0d5c6 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -119,6 +119,7 @@ void qGamma_correct_back_to_linear_cs(QImage *image)
*****************************************************************************/
// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion
+#if !defined(__ARM_NEON__)
static void QT_FASTCALL storeRGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
@@ -126,6 +127,7 @@ static void QT_FASTCALL storeRGB32FromARGB32PM(uchar *dest, const uint *src, int
for (int i = 0; i < count; ++i)
d[i] = 0xff000000 | qUnpremultiply(src[i]);
}
+#endif
static void QT_FASTCALL storeRGB32FromARGB32(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
@@ -147,6 +149,9 @@ static const uint *QT_FASTCALL fetchRGB32ToARGB32PM(uint *buffer, const uchar *s
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
extern void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+#elif defined(__ARM_NEON__)
+extern void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
#endif
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags)
@@ -175,8 +180,12 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
if (qCpuHasFeature(SSE4_1))
store = storeRGB32FromARGB32PM_sse4;
else
-#endif
store = storeRGB32FromARGB32PM;
+#elif defined(__ARM_NEON__)
+ store = storeRGB32FromARGB32PM_neon;
+#else
+ store = storeRGB32FromARGB32PM;
+#endif
}
}
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
@@ -261,8 +270,12 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
if (qCpuHasFeature(SSE4_1))
store = storeRGB32FromARGB32PM_sse4;
else
-#endif
store = storeRGB32FromARGB32PM;
+#elif defined(__ARM_NEON__)
+ store = storeRGB32FromARGB32PM_neon;
+#else
+ store = storeRGB32FromARGB32PM;
+#endif
}
}
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index a9e472f8c4..b8d13ac092 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -449,8 +449,7 @@ Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
{
- const QImage image = imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat);
- return QPixmap::fromImage(image);
+ return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat));
}
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
@@ -567,7 +566,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
SelectObject(hdc, oldhdc); //restore state
DeleteObject(winBitmap);
DeleteDC(hdc);
- return QPixmap::fromImage(image);
+ return QPixmap::fromImage(std::move(image));
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 0264059a5c..bbeb9fd9ea 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6505,10 +6505,19 @@ static void qInitDrawhelperFunctions()
const QVector<QRgb> *, QDitherInfo *);
extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA8888FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBXFromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_neon;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_neon;
+ qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_neon;
#endif
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 98995f485a..629dfe2358 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -1081,15 +1081,28 @@ const uint * QT_FASTCALL qt_fetchUntransformed_888_neon(uint *buffer, const Oper
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
-template<bool RGBA>
-static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int count)
+static inline uint32x4_t vrgba2argb(uint32x4_t srcVector)
{
- int i = 0;
#if defined(Q_PROCESSOR_ARM_64)
const uint8x16_t rgbaMask = { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15};
#else
const uint8x8_t rgbaMask = { 2, 1, 0, 3, 6, 5, 4, 7 };
#endif
+#if defined(Q_PROCESSOR_ARM_64)
+ srcVector = vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(srcVector), rgbaMask));
+#else
+ // no vqtbl1q_u8, so use two vtbl1_u8
+ const uint8x8_t low = vtbl1_u8(vreinterpret_u8_u32(vget_low_u32(srcVector)), rgbaMask);
+ const uint8x8_t high = vtbl1_u8(vreinterpret_u8_u32(vget_high_u32(srcVector)), rgbaMask);
+ srcVector = vcombine_u32(vreinterpret_u32_u8(low), vreinterpret_u32_u8(high));
+#endif
+ return srcVector;
+}
+
+template<bool RGBA>
+static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int count)
+{
+ int i = 0;
const uint8x8_t shuffleMask = { 3, 3, 3, 3, 7, 7, 7, 7};
const uint32x4_t blendMask = vdupq_n_u32(0xff000000);
@@ -1105,16 +1118,8 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
#endif
if (alphaSum) {
if (alphaSum != 255 * 4) {
- if (RGBA) {
-#if defined(Q_PROCESSOR_ARM_64)
- srcVector = vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(srcVector), rgbaMask));
-#else
- // no vqtbl1q_u8
- const uint8x8_t low = vtbl1_u8(vreinterpret_u8_u32(vget_low_u32(srcVector)), rgbaMask);
- const uint8x8_t high = vtbl1_u8(vreinterpret_u8_u32(vget_high_u32(srcVector)), rgbaMask);
- srcVector = vcombine_u32(vreinterpret_u32_u8(low), vreinterpret_u32_u8(high));
-#endif
- }
+ if (RGBA)
+ srcVector = vrgba2argb(srcVector);
const uint8x8_t s1 = vreinterpret_u8_u32(vget_low_u32(srcVector));
const uint8x8_t s2 = vreinterpret_u8_u32(vget_high_u32(srcVector));
const uint8x8_t alpha1 = vtbl1_u8(s1, shuffleMask);
@@ -1128,19 +1133,10 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
const uint32x4_t d = vbslq_u32(blendMask, srcVector, vreinterpretq_u32_u8(vcombine_u8(d1, d2)));
vst1q_u32(buffer + i, d);
} else {
- if (RGBA) {
-#if defined(Q_PROCESSOR_ARM_64)
- srcVector = vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(srcVector), rgbaMask));
-#else
- // no vqtbl1q_u8
- const uint8x8_t low = vtbl1_u8(vreinterpret_u8_u32(vget_low_u32(srcVector)), rgbaMask);
- const uint8x8_t high = vtbl1_u8(vreinterpret_u8_u32(vget_high_u32(srcVector)), rgbaMask);
- srcVector = vcombine_u32(vreinterpret_u32_u8(low), vreinterpret_u32_u8(high));
-#endif
- vst1q_u32(buffer + i, srcVector);
- } else if (buffer != src) {
+ if (RGBA)
+ vst1q_u32(buffer + i, vrgba2argb(srcVector));
+ else if (buffer != src)
vst1q_u32(buffer + i, srcVector);
- }
}
} else {
vst1q_u32(buffer + i, vdupq_n_u32(0));
@@ -1153,6 +1149,91 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
}
}
+static inline float32x4_t reciprocal_mul_ps(float32x4_t a, float mul)
+{
+ float32x4_t ia = vrecpeq_f32(a); // estimate 1/a
+ ia = vmulq_f32(vrecpsq_f32(a, ia), vmulq_n_f32(ia, mul)); // estimate improvement step * mul
+ return ia;
+}
+
+template<bool RGBA, bool RGBx>
+static inline void convertARGBFromARGB32PM_neon(uint *buffer, const uint *src, int count)
+{
+ int i = 0;
+ const uint32x4_t alphaMask = vdupq_n_u32(0xff000000);
+
+ for (; i < count - 3; i += 4) {
+ uint32x4_t srcVector = vld1q_u32(src + i);
+ uint32x4_t alphaVector = vshrq_n_u32(srcVector, 24);
+#if defined(Q_PROCESSOR_ARM_64)
+ uint32_t alphaSum = vaddvq_u32(alphaVector);
+#else
+ // no vaddvq_u32
+ uint32x2_t tmp = vpadd_u32(vget_low_u32(alphaVector), vget_high_u32(alphaVector));
+ uint32_t alphaSum = vget_lane_u32(vpadd_u32(tmp, tmp), 0);
+#endif
+ if (alphaSum) {
+ if (alphaSum != 255 * 4) {
+ if (RGBA)
+ srcVector = vrgba2argb(srcVector);
+ const float32x4_t a = vcvtq_f32_u32(alphaVector);
+ const float32x4_t ia = reciprocal_mul_ps(a, 255.0f);
+ // Convert 4x(4xU8) to 4x(4xF32)
+ uint16x8_t tmp1 = vmovl_u8(vget_low_u8(vreinterpretq_u8_u32(srcVector)));
+ uint16x8_t tmp3 = vmovl_u8(vget_high_u8(vreinterpretq_u8_u32(srcVector)));
+ float32x4_t src1 = vcvtq_f32_u32(vmovl_u16(vget_low_u16(tmp1)));
+ float32x4_t src2 = vcvtq_f32_u32(vmovl_u16(vget_high_u16(tmp1)));
+ float32x4_t src3 = vcvtq_f32_u32(vmovl_u16(vget_low_u16(tmp3)));
+ float32x4_t src4 = vcvtq_f32_u32(vmovl_u16(vget_high_u16(tmp3)));
+ src1 = vmulq_lane_f32(src1, vget_low_f32(ia), 0);
+ src2 = vmulq_lane_f32(src2, vget_low_f32(ia), 1);
+ src3 = vmulq_lane_f32(src3, vget_high_f32(ia), 0);
+ src4 = vmulq_lane_f32(src4, vget_high_f32(ia), 1);
+ // Convert 4x(4xF32) back to 4x(4xU8) (over a 8.1 fixed point format to get rounding)
+ tmp1 = vcombine_u16(vrshrn_n_u32(vcvtq_n_u32_f32(src1, 1), 1),
+ vrshrn_n_u32(vcvtq_n_u32_f32(src2, 1), 1));
+ tmp3 = vcombine_u16(vrshrn_n_u32(vcvtq_n_u32_f32(src3, 1), 1),
+ vrshrn_n_u32(vcvtq_n_u32_f32(src4, 1), 1));
+ uint32x4_t dstVector = vreinterpretq_u32_u8(vcombine_u8(vmovn_u16(tmp1), vmovn_u16(tmp3)));
+ // Overwrite any undefined results from alpha==0 with zeros:
+#if defined(Q_PROCESSOR_ARM_64)
+ uint32x4_t srcVectorAlphaMask = vceqzq_u32(alphaVector);
+#else
+ uint32x4_t srcVectorAlphaMask = vceqq_u32(alphaVector, vdupq_n_u32(0));
+#endif
+ dstVector = vbicq_u32(dstVector, srcVectorAlphaMask);
+ // Restore or mask alpha values:
+ if (RGBx)
+ dstVector = vorrq_u32(alphaMask, dstVector);
+ else
+ dstVector = vbslq_u32(alphaMask, srcVector, dstVector);
+ vst1q_u32(&buffer[i], dstVector);
+ } else {
+ // 4xAlpha==255, no change except if we are doing RGBA->ARGB:
+ if (RGBA)
+ vst1q_u32(&buffer[i], vrgba2argb(srcVector));
+ else if (buffer != src)
+ vst1q_u32(&buffer[i], srcVector);
+ }
+ } else {
+ // 4xAlpha==0, always zero, except if output is RGBx:
+ if (RGBx)
+ vst1q_u32(&buffer[i], alphaMask);
+ else
+ vst1q_u32(&buffer[i], vdupq_n_u32(0));
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ uint v = qUnpremultiply(src[i]);
+ if (RGBx)
+ v = 0xff000000 | v;
+ if (RGBA)
+ v = ARGB2RGBA(v);
+ buffer[i] = v;
+ }
+}
+
void QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *)
{
convertARGBToARGB32PM_neon<false>(buffer, buffer, count);
@@ -1177,6 +1258,34 @@ const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *
return buffer;
}
+void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<false,true>(d, src, count);
+}
+
+void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<false,false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBA8888FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<true,false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBXFromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<true,true>(d, src, count);
+}
+
#endif // Q_BYTE_ORDER == Q_LITTLE_ENDIAN
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
index 9c2ff8fb89..23ca62acd4 100644
--- a/src/network/access/qnetworkreplywasmimpl.cpp
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -49,10 +49,135 @@
#include <private/qnetworkaccessmanager_p.h>
#include <private/qnetworkfile_p.h>
-#include <iostream>
+#include <emscripten.h>
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
QT_BEGIN_NAMESPACE
+using namespace emscripten;
+
+static void q_requestErrorCallback(val event)
+{
+ val xhr = event["target"];
+
+ quintptr func = xhr["data-handler"].as<quintptr>();
+ QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(func);
+ Q_ASSERT(reply);
+
+ int statusCode = xhr["status"].as<int>();
+
+ QString reasonStr = QString::fromStdString(xhr["statusText"].as<std::string>());
+
+ reply->setReplyAttributes(func, statusCode, reasonStr);
+
+ if (statusCode >= 400 && !reasonStr.isEmpty())
+ reply->emitReplyError(reply->statusCodeFromHttp(statusCode, reply->request.url()), reasonStr);
+}
+
+static void q_progressCallback(val event)
+{
+ val xhr = event["target"];
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ if (xhr["lengthComputable"].as<bool>() && xhr["status"].as<int>() < 400)
+ reply->emitDataReadProgress(xhr["loaded"].as<qint64>(), xhr["total"].as<qint64>());
+
+}
+
+static void q_loadCallback(val event)
+{
+ val xhr = event["target"];
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ int status = xhr["status"].as<int>();
+ if (status >= 300) {
+ q_requestErrorCallback(event);
+ return;
+ }
+ QString statusText = QString::fromStdString(xhr["statusText"].as<std::string>());
+ if (status == 200 || status == 203) {
+ QString responseString;
+ const std::string responseType = xhr["responseType"].as<std::string>();
+ if (responseType.length() == 0 || responseType == "document" || responseType == "text") {
+ responseString = QString::fromStdWString(xhr["responseText"].as<std::wstring>());
+ } else if (responseType == "json") {
+ responseString =
+ QString::fromStdWString(val::global("JSON").call<std::wstring>("stringify", xhr["response"]));
+ } else if (responseType == "arraybuffer" || responseType == "blob") {
+ // handle this data in the FileReader, triggered by the call to readAsArrayBuffer
+ val reader = val::global("FileReader").new_();
+ reader.set("onload", val::module_property("QNetworkReplyWasmImplPrivate_readBinary"));
+ reader.set("data-handler", xhr["data-handler"]);
+ reader.call<void>("readAsArrayBuffer", xhr["response"]);
+ }
+
+ int readyState = xhr["readyState"].as<int>();
+
+ if (readyState == 4) { // done
+ reply->setReplyAttributes(xhr["data-handler"].as<quintptr>(), status, statusText);
+ if (!responseString.isEmpty())
+ reply->dataReceived(responseString.toUtf8(), responseString.size());
+ }
+ }
+ if (status >= 400 && !statusText.isEmpty())
+ reply->emitReplyError(reply->statusCodeFromHttp(status, reply->request.url()), statusText);
+}
+
+static void q_responseHeadersCallback(val event)
+{
+ val xhr = event["target"];
+
+ if (xhr["readyState"].as<int>() == 2) { // HEADERS_RECEIVED
+ std::string responseHeaders = xhr.call<std::string>("getAllResponseHeaders");
+ if (!responseHeaders.empty()) {
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ reply->headersReceived(QString::fromStdString(responseHeaders));
+ }
+ }
+}
+
+static void q_readBinary(val event)
+{
+ val fileReader = event["target"];
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fileReader["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ // Set up source typed array
+ val result = fileReader["result"]; // ArrayBuffer
+ val Uint8Array = val::global("Uint8Array");
+ val sourceTypedArray = Uint8Array.new_(result);
+
+ // Allocate and set up destination typed array
+ const quintptr size = result["byteLength"].as<quintptr>();
+ QByteArray buffer(size, Qt::Uninitialized);
+
+ val destinationTypedArray = Uint8Array.new_(val::module_property("HEAPU8")["buffer"],
+ reinterpret_cast<quintptr>(buffer.data()), size);
+ destinationTypedArray.call<void>("set", sourceTypedArray);
+ reply->dataReceived(buffer, buffer.size());
+}
+
+
+EMSCRIPTEN_BINDINGS(network_module) {
+ function("QNetworkReplyWasmImplPrivate_requestErrorCallback", q_requestErrorCallback);
+ function("QNetworkReplyWasmImplPrivate_progressCallback", q_progressCallback);
+ function("QNetworkReplyWasmImplPrivate_loadCallback", q_loadCallback);
+ function("QNetworkReplyWasmImplPrivate_responseHeadersCallback", q_responseHeadersCallback);
+ function("QNetworkReplyWasmImplPrivate_readBinary", q_readBinary);
+}
+
QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
: QNetworkReplyPrivate()
, managerPrivate(0)
@@ -172,226 +297,80 @@ void QNetworkReplyWasmImplPrivate::setup(QNetworkAccessManager::Operation op, co
doSendRequest();
}
-void QNetworkReplyWasmImplPrivate::onLoadCallback(void *data, int statusCode, int statusReason, int readyState, int buffer, int bufferSize)
-{
- QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
-
- const QString reasonStr = QString::fromUtf8(reinterpret_cast<char *>(statusReason));
-
- switch (readyState) {
- case 0://unsent
- break;
- case 1://opened
- break;
- case 2://headers received
- break;
- case 3://loading
- break;
- case 4: {//done
- handler->q_func()->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
- if (!reasonStr.isEmpty())
- handler->q_func()->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonStr);
-
- if (statusCode >= 400) {
- if (!reasonStr.isEmpty())
- handler->emitReplyError(handler->statusCodeFromHttp(statusCode, handler->request.url()), reasonStr);
- } else {
- handler->dataReceived(reinterpret_cast<char *>(buffer), bufferSize);
- }
- }
- break;
- };
- }
-
-void QNetworkReplyWasmImplPrivate::onProgressCallback(void* data, int bytesWritten, int total, uint timestamp)
-{
- Q_UNUSED(timestamp);
-
- QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
- handler->emitDataReadProgress(bytesWritten, total);
-}
-
-void QNetworkReplyWasmImplPrivate::onRequestErrorCallback(void* data, int statusCode, int statusReason)
+void QNetworkReplyWasmImplPrivate::setReplyAttributes(quintptr data, int statusCode, const QString &statusReason)
{
- QString reasonStr = QString::fromUtf8(reinterpret_cast<char *>(statusReason));
-
QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
+ Q_ASSERT(handler);
handler->q_func()->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
- if (!reasonStr.isEmpty())
- handler->q_func()->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonStr);
-
- if (statusCode >= 400) {
- if (!reasonStr.isEmpty())
- handler->emitReplyError(handler->statusCodeFromHttp(statusCode, handler->request.url()), reasonStr);
- }
-}
-
-void QNetworkReplyWasmImplPrivate::onResponseHeadersCallback(void* data, int headers)
-{
- QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
- handler->headersReceived(reinterpret_cast<char *>(headers));
+ if (!statusReason.isEmpty())
+ handler->q_func()->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, statusReason);
}
void QNetworkReplyWasmImplPrivate::doSendRequest()
{
Q_Q(QNetworkReplyWasmImpl);
totalDownloadSize = 0;
- jsRequest(QString::fromUtf8(q->methodName()), // GET POST
- request.url().toString(),
- (void *)&onLoadCallback,
- (void *)&onProgressCallback,
- (void *)&onRequestErrorCallback,
- (void *)&onResponseHeadersCallback);
-}
-
-/* const QString &body, const QList<QPair<QByteArray, QByteArray> > &headers ,*/
-void QNetworkReplyWasmImplPrivate::jsRequest(const QString &verb, const QString &url,
- void *loadCallback, void *progressCallback,
- void *errorCallback, void *onResponseHeadersCallback)
-{
- QString extraDataString;
-
- QByteArray extraData;
- if (outgoingData)
- extraData = outgoingData->readAll();
- if (extraData.size() > 0)
- extraDataString.fromUtf8(extraData);
+ val xhr = val::global("XMLHttpRequest").new_();
+ std::string verb = q->methodName().toStdString();
- if (extraDataString.size() >= 0 && verb == QStringLiteral("POST") && extraDataString.startsWith(QStringLiteral("?")))
- extraDataString.remove(QStringLiteral("?"));
+ QUrl url;
+ QString extraDataString;
- // Probably a good idea to save any shared pointers as members in C++
- // so the objects they point to survive as long as you need them
+ if (request.url().hasQuery()) { //strip query from url
+ extraDataString = request.url().query(QUrl::FullyEncoded);
+ QString urlStr = request.url().toString();
+ url.setUrl(urlStr.left(urlStr.indexOf("?")));
+ } else {
+ url = request.url();
+ }
+ xhr.call<void>("open", verb, url.toString().toStdString());
- QStringList headersList;
- for (auto header : request.rawHeaderList())
- headersList << QString::fromUtf8(header + ":" + request.rawHeader(header));
+ xhr.set("onerror", val::module_property("QNetworkReplyWasmImplPrivate_requestErrorCallback"));
+ xhr.set("onload", val::module_property("QNetworkReplyWasmImplPrivate_loadCallback"));
+ xhr.set("onprogress", val::module_property("QNetworkReplyWasmImplPrivate_progressCallback"));
+ xhr.set("onreadystatechange", val::module_property("QNetworkReplyWasmImplPrivate_responseHeadersCallback"));
- EM_ASM_ARGS({
- var verb = Pointer_stringify($0);
- var url = Pointer_stringify($1);
- var onLoadCallbackPointer = $2;
- var onProgressCallbackPointer = $3;
- var onErrorCallbackPointer = $4;
- var onHeadersCallback = $5;
- var handler = $8;
+ xhr.set("data-handler", val(quintptr(reinterpret_cast<void *>(this))));
- var dataToSend;
- var extraRequestData = Pointer_stringify($6); // request parameters
- var headersData = Pointer_stringify($7);
+ QByteArray contentType = request.rawHeader("Content-Type");
- var xhr;
- xhr = new XMLHttpRequest();
- xhr.responseType = 'arraybuffer';
+ // handle extra data
+ val dataToSend = val::null();
+ QByteArray extraData;
- xhr.open(verb, url, true); //async
+ if (outgoingData) // data from post request
+ extraData = outgoingData->readAll();
- function handleError(xhrStatusCode, xhrStatusText) {
- var errorPtr = allocate(intArrayFromString(xhrStatusText), 'i8', ALLOC_NORMAL);
- Runtime.dynCall('viii', onErrorCallbackPointer, [handler, xhrStatusCode, errorPtr]);
- _free(errorPtr);
+ if (contentType.contains("text") ||
+ contentType.contains("json") ||
+ contentType.contains("form")) {
+ if (extraData.size() > 0)
+ extraDataString.fromUtf8(extraData);
+ }
+ if (contentType.contains("json")) {
+ if (!extraDataString.isEmpty()) {
+ xhr.set("responseType", val("json"));
+ dataToSend = val(extraDataString.toStdString());
}
+ }
+ if (contentType.contains("form")) { //construct form data
+ if (!extraDataString.isEmpty()) {
+ val formData = val::global("FormData").new_();
+ QStringList formList = extraDataString.split('&');
- if (headersData) {
- var headers = headersData.split("&");
- for (var i = 0; i < headers.length; i++) {
- var header = headers[i].split(":")[0];
- var value = headers[i].split(":")[1];
-
- if (verb === 'POST' && value.toLowerCase().includes('json')) {
- if (extraRequestData) {
- xhr.responseType = 'json';
- dataToSend = extraRequestData;
- }
- }
- if (verb === 'POST' && value.toLowerCase().includes('form')) {
- if (extraRequestData) {
- var formData = new FormData();
- var extra = extraRequestData.split("&");
- for (var i = 0; i < extra.length; i++) {
- formData.append(extra[i].split("=")[0],extra[i].split("=")[1]);
- }
- dataToSend = formData;
- }
- }
- xhr.setRequestHeader(header, value);
+ for (auto formEntry : formList) {
+ formData.call<void>("append", formEntry.split('=')[0].toStdString(), formEntry.split('=')[1].toStdString());
}
+ dataToSend = formData;
}
-
- xhr.onprogress = function(e) {
- switch (xhr.status) {
- case 200:
- case 206:
- case 300:
- case 301:
- case 302: {
- var date = xhr.getResponseHeader('Last-Modified');
- date = ((date != null) ? new Date(date).getTime() / 1000 : 0);
- Runtime.dynCall('viiii', onProgressCallbackPointer, [handler, e.loaded, e.total, date]);
- }
- break;
- }
- };
-
- xhr.onreadystatechange = function() {
- if (this.readyState == this.HEADERS_RECEIVED) {
- var responseStr = this.getAllResponseHeaders();
- if (responseStr.length > 0) {
- var ptr = allocate(intArrayFromString(responseStr), 'i8', ALLOC_NORMAL);
- Runtime.dynCall('vii', onHeadersCallback, [handler, ptr]);
- _free(ptr);
- }
- }
- };
-
- xhr.onload = function(e) {
- if (xhr.status >= 300) { //error
- handleError(xhr.status, xhr.statusText);
- } else {
- if (this.status == 200 || this.status == 203) {
- var datalength;
- var byteArray = 0;
- var buffer;
- if (this.responseType.length === 0 || this.responseType === 'document') {
- byteArray = new Uint8Array(this.responseText);
- } else if (this.responseType === 'json') {
- var jsonResponse = JSON.stringify(this.response);
- buffer = allocate(intArrayFromString(jsonResponse), 'i8', ALLOC_NORMAL);
- datalength = jsonResponse.length;
- } else if (this.responseType === 'arraybuffer') {
- byteArray = new Uint8Array(xhr.response);
- }
- if (byteArray != 0 ) {
- datalength = byteArray.length;
- buffer = _malloc(datalength);
- HEAPU8.set(byteArray, buffer);
- }
- var reasonPtr = allocate(intArrayFromString(this.statusText), 'i8', ALLOC_NORMAL);
- Runtime.dynCall('viiiiii', onLoadCallbackPointer, [handler, this.status, reasonPtr, this.readyState, buffer, datalength]);
- _free(buffer);
- _free(reasonPtr);
- }
- }
- };
-
- xhr.onerror = function(e) {
- handleError(xhr.status, xhr.statusText);
- };
- //TODO other operations, handle user/pass, handle binary data, data streaming
- xhr.send(dataToSend);
-
- }, verb.toLatin1().data(),
- url.toLatin1().data(),
- loadCallback,
- progressCallback,
- errorCallback,
- onResponseHeadersCallback,
- extraDataString.size() > 0 ? extraDataString.toLatin1().data() : extraData.data(),
- headersList.join(QStringLiteral("&")).toLatin1().data(),
- this
- );
+ }
+ // set request headers
+ for (auto header : request.rawHeaderList()) {
+ xhr.call<void>("setRequestHeader", header.toStdString(), request.rawHeader(header).toStdString());
+ }
+ xhr.call<void>("send", dataToSend);
}
void QNetworkReplyWasmImplPrivate::emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString)
@@ -414,10 +393,10 @@ void QNetworkReplyWasmImplPrivate::emitDataReadProgress(qint64 bytesReceived, qi
percentFinished = (bytesReceived / bytesTotal) * 100;
- emit q->downloadProgress(bytesReceived, totalDownloadSize);
+ emit q->downloadProgress(bytesReceived, bytesTotal);
}
-void QNetworkReplyWasmImplPrivate::dataReceived(char *buffer, int bufferSize)
+void QNetworkReplyWasmImplPrivate::dataReceived(const QByteArray &buffer, int bufferSize)
{
Q_Q(QNetworkReplyWasmImpl);
@@ -481,11 +460,10 @@ static int parseHeaderName(const QByteArray &headerName)
}
-void QNetworkReplyWasmImplPrivate::headersReceived(char *buffer)
+void QNetworkReplyWasmImplPrivate::headersReceived(const QString &bufferString)
{
Q_Q(QNetworkReplyWasmImpl);
- QString bufferString = QString::fromUtf8(buffer);
if (!bufferString.isEmpty()) {
QStringList headers = bufferString.split(QString::fromUtf8("\r\n"), QString::SkipEmptyParts);
diff --git a/src/network/access/qnetworkreplywasmimpl_p.h b/src/network/access/qnetworkreplywasmimpl_p.h
index a707390503..69c90de41a 100644
--- a/src/network/access/qnetworkreplywasmimpl_p.h
+++ b/src/network/access/qnetworkreplywasmimpl_p.h
@@ -95,7 +95,6 @@ public:
private:
QByteArray methodName() const;
-
};
class QNetworkReplyWasmImplPrivate: public QNetworkReplyPrivate
@@ -106,19 +105,12 @@ public:
QNetworkAccessManagerPrivate *managerPrivate;
void doSendRequest();
-
- void jsRequest(const QString &verb, const QString &url, void *, void *, void *, void *);
-
- static void onLoadCallback(void *data, int statusCode, int statusReason, int readyState, int textBuffer, int size);
- static void onProgressCallback(void *data, int done, int bytesTotal, uint timestamp);
- static void onRequestErrorCallback(void *data, int statusCode, int statusReason);
- static void onStateChangedCallback(int status);
- static void onResponseHeadersCallback(void *data, int headers);
+ static void setReplyAttributes(quintptr data, int statusCode, const QString &statusReason);
void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &);
void emitDataReadProgress(qint64 done, qint64 total);
- void dataReceived(char *buffer, int bufferSize);
- void headersReceived(char *buffer);
+ void dataReceived(const QByteArray &buffer, int bufferSize);
+ void headersReceived(const QString &bufferString);
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
@@ -148,6 +140,4 @@ public:
QT_END_NAMESPACE
-//Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders)
-
#endif // QNETWORKREPLYWASMIMPL_H
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
index 06f0aa6747..dc4785071f 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
@@ -48,26 +48,78 @@
QT_BEGIN_NAMESPACE
+struct GUserEventSource
+{
+ GSource source;
+ QPAEventDispatcherGlib *q;
+};
+
+static gboolean userEventSourcePrepare(GSource *source, gint *timeout)
+{
+ Q_UNUSED(timeout)
+ GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
+ QPAEventDispatcherGlib *dispatcher = userEventSource->q;
+ if (dispatcher->m_flags & QEventLoop::ExcludeUserInputEvents)
+ return QWindowSystemInterface::nonUserInputEventsQueued();
+ else
+ return QWindowSystemInterface::windowSystemEventsQueued() > 0;
+}
+
+static gboolean userEventSourceCheck(GSource *source)
+{
+ return userEventSourcePrepare(source, 0);
+}
+
+static gboolean userEventSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
+ QPAEventDispatcherGlib *dispatcher = userEventSource->q;
+ QWindowSystemInterface::sendWindowSystemEvents(dispatcher->m_flags);
+ return true;
+}
+
+static GSourceFuncs userEventSourceFuncs = {
+ userEventSourcePrepare,
+ userEventSourceCheck,
+ userEventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context)
: QEventDispatcherGlibPrivate(context)
{
+ Q_Q(QPAEventDispatcherGlib);
+ userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs,
+ sizeof(GUserEventSource)));
+ userEventSource->q = q;
+ g_source_set_can_recurse(&userEventSource->source, true);
+ g_source_attach(&userEventSource->source, mainContext);
}
+
QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent)
: QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent)
, m_flags(QEventLoop::AllEvents)
{
+ Q_D(QPAEventDispatcherGlib);
+ d->userEventSource->q = this;
}
QPAEventDispatcherGlib::~QPAEventDispatcherGlib()
{
+ Q_D(QPAEventDispatcherGlib);
+
+ g_source_destroy(&d->userEventSource->source);
+ g_source_unref(&d->userEventSource->source);
+ d->userEventSource = 0;
}
bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
{
m_flags = flags;
- const bool didSendEvents = QEventDispatcherGlib::processEvents(m_flags);
- return QWindowSystemInterface::sendWindowSystemEvents(m_flags) || didSendEvents;
+ return QEventDispatcherGlib::processEvents(m_flags);
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
index 5930dc68e7..085a1c52f3 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
@@ -71,11 +71,14 @@ public:
QEventLoop::ProcessEventsFlags m_flags;
};
+struct GUserEventSource;
+
class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
{
Q_DECLARE_PUBLIC(QPAEventDispatcherGlib)
public:
QPAEventDispatcherGlibPrivate(GMainContext *context = 0);
+ GUserEventSource *userEventSource;
};
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
index b618d8567a..3cfa7e3856 100644
--- a/src/plugins/platforms/windows/openglblacklists/default.json
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -144,9 +144,8 @@
},
{
"id": 12,
- "description": "Intel HD Graphics 620 crash in conjunction with shader caches (QTBUG-64697)",
+ "description": "Intel HD Graphics crash in conjunction with shader caches (QTBUG-64697) - disable for all Intel GPUs",
"vendor_id": "0x8086",
- "device_id": [ "0x5916" ],
"os": {
"type": "win"
},
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
index b3bf52f09b..c23d48b2dd 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
@@ -118,11 +118,14 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion &region, const QPo
if (d->size.isEmpty())
return;
+ const QRect bounds = region.boundingRect() & d->paintDevice.rect();
+ if (bounds.isEmpty())
+ return;
+
const bool ok = d->context->makeCurrent(window);
if (!ok)
qWarning("unable to flush");
- const QRect bounds = region.boundingRect();
glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
// TODO: when ANGLE GLES3 support is finished, use the glPixelStorei functions to minimize upload
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), d->size.width(), bounds.height(),
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 6dda6487c8..4e24c970b4 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -90,25 +90,6 @@
#include <xcb/render.h>
#endif
-#if defined(Q_CC_GNU) && defined(Q_OF_ELF)
-static xcb_generic_event_t *local_xcb_poll_for_queued_event(xcb_connection_t *c)
- __attribute__((weakref("xcb_poll_for_queued_event")));
-
-static inline void checkXcbPollForQueuedEvent()
-{ }
-#else
-#include <dlfcn.h>
-typedef xcb_generic_event_t * (*XcbPollForQueuedEventFunctionPointer)(xcb_connection_t *c);
-static XcbPollForQueuedEventFunctionPointer local_xcb_poll_for_queued_event;
-
-static inline void checkXcbPollForQueuedEvent()
-{
-#ifdef RTLD_DEFAULT
- local_xcb_poll_for_queued_event = (XcbPollForQueuedEventFunctionPointer)dlsym(RTLD_DEFAULT, "xcb_poll_for_queued_event");
-#endif
-}
-#endif
-
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input")
@@ -1365,39 +1346,19 @@ bool QXcbConnection::peekEventQueue(PeekerCallback peeker, void *peekerData,
QXcbEventReader::QXcbEventReader(QXcbConnection *connection)
: m_connection(connection)
{
- checkXcbPollForQueuedEvent();
}
void QXcbEventReader::start()
{
- if (local_xcb_poll_for_queued_event) {
- connect(this, SIGNAL(eventPending()), m_connection, SLOT(processXcbEvents()), Qt::QueuedConnection);
- connect(this, SIGNAL(finished()), m_connection, SLOT(processXcbEvents()));
- QThread::start();
- } else {
- // Must be done after we have an event-dispatcher. By posting a method invocation
- // we are sure that by the time the method is called we have an event-dispatcher.
- QMetaObject::invokeMethod(this, "registerForEvents", Qt::QueuedConnection);
- }
-}
-
-void QXcbEventReader::registerForEvents()
-{
- QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection->xcb_connection()), QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)), m_connection, SLOT(processXcbEvents()));
-
- QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
- connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(processXcbEvents()));
- connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents()));
+ connect(this, &QXcbEventReader::eventPending, m_connection, &QXcbConnection::processXcbEvents, Qt::QueuedConnection);
+ connect(this, &QXcbEventReader::finished, m_connection, &QXcbConnection::processXcbEvents);
+ QThread::start();
}
void QXcbEventReader::registerEventDispatcher(QAbstractEventDispatcher *dispatcher)
{
- // flush the xcb connection before the EventDispatcher is going to block
- // In the non-threaded case processXcbEvents is called before going to block,
- // which flushes the connection.
- if (local_xcb_poll_for_queued_event)
- connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(flush()));
+ // Flush the xcb connection before the event dispatcher is going to block.
+ connect(dispatcher, &QAbstractEventDispatcher::aboutToBlock, m_connection, &QXcbConnection::flush);
}
void QXcbEventReader::run()
@@ -1406,7 +1367,7 @@ void QXcbEventReader::run()
while (m_connection && (event = xcb_wait_for_event(m_connection->xcb_connection()))) {
m_mutex.lock();
addEvent(event);
- while (m_connection && (event = local_xcb_poll_for_queued_event(m_connection->xcb_connection())))
+ while (m_connection && (event = xcb_poll_for_queued_event(m_connection->xcb_connection())))
addEvent(event);
m_mutex.unlock();
emit eventPending();
@@ -1430,10 +1391,6 @@ void QXcbEventReader::addEvent(xcb_generic_event_t *event)
QXcbEventArray *QXcbEventReader::lock()
{
m_mutex.lock();
- if (!local_xcb_poll_for_queued_event) {
- while (xcb_generic_event_t *event = xcb_poll_for_event(m_connection->xcb_connection()))
- m_events << event;
- }
return &m_events;
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 1e28ef8fac..db45031cf4 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -326,9 +326,6 @@ public:
signals:
void eventPending();
-private slots:
- void registerForEvents();
-
private:
void addEvent(xcb_generic_event_t *event);
@@ -493,8 +490,6 @@ public:
bool hasShmFd() const { return has_shm_fd; }
bool hasXSync() const { return has_sync_extension; }
- bool threadedEventHandling() const { return m_reader->isRunning(); }
-
xcb_timestamp_t getTimestamp();
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
xcb_window_t getQtSelectionOwner();
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 9fc1189181..db8dc09025 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -308,8 +308,7 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
const auto *connection = qAsConst(m_connections).first();
if (const auto *integration = connection->glIntegration())
- return cap != ThreadedOpenGL
- || (connection->threadedEventHandling() && integration->supportsThreadedOpenGL());
+ return cap != ThreadedOpenGL || integration->supportsThreadedOpenGL();
return false;
}
diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro
index a2d9159579..e89443ef4e 100644
--- a/tests/auto/network/ssl/ssl.pro
+++ b/tests/auto/network/ssl/ssl.pro
@@ -16,7 +16,7 @@ qtConfig(ssl) {
qsslsocket_onDemandCertificates_member \
qsslsocket_onDemandCertificates_static
- qtConfig(openssl) {
+ qtConfig(dtls) {
SUBDIRS += \
qdtlscookie \
qdtls