Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: I2715ee7c694e5579bcedc7bab0ae68e79d5fd0b6bb10
commit
fedcaf0256
|
|
@ -771,7 +771,7 @@ setBootstrapVariable()
|
|||
echo "RM_RF = rm -rf" >> "$mkfile"
|
||||
|
||||
case `basename "$PLATFORM"` in
|
||||
win32-g++*)
|
||||
win32-*g++*)
|
||||
cat "$in_mkfile.win32" >> "$mkfile"
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -730,6 +730,7 @@
|
|||
"headersclean": {
|
||||
"label": "Check for clean headers",
|
||||
"autoDetect": "features.developer-build",
|
||||
"condition": "!config.wasm",
|
||||
"output": [ "privateConfig" ]
|
||||
},
|
||||
"framework": {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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:";
|
||||
|
|
|
|||
|
|
@ -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(); ) {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ protected:
|
|||
|
||||
private:
|
||||
void init2();
|
||||
ProStringList libdirToFlags(const ProKey &key);
|
||||
};
|
||||
|
||||
inline UnixMakefileGenerator::~UnixMakefileGenerator()
|
||||
|
|
|
|||
|
|
@ -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(' ') << ' ';
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -18,4 +18,3 @@
|
|||
"LicenseFile": "LICENSE",
|
||||
"Copyright": "Copyright (C) 2003 Bitstream,Inc"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
if (RGBA)
|
||||
vst1q_u32(buffer + i, vrgba2argb(srcVector));
|
||||
else if (buffer != src)
|
||||
vst1q_u32(buffer + i, 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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
void QNetworkReplyWasmImplPrivate::setReplyAttributes(quintptr data, int statusCode, const QString &statusReason)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
val xhr = val::global("XMLHttpRequest").new_();
|
||||
std::string verb = q->methodName().toStdString();
|
||||
|
||||
QUrl url;
|
||||
QString extraDataString;
|
||||
|
||||
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());
|
||||
|
||||
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"));
|
||||
|
||||
xhr.set("data-handler", val(quintptr(reinterpret_cast<void *>(this))));
|
||||
|
||||
QByteArray contentType = request.rawHeader("Content-Type");
|
||||
|
||||
// handle extra data
|
||||
val dataToSend = val::null();
|
||||
QByteArray extraData;
|
||||
if (outgoingData)
|
||||
|
||||
if (outgoingData) // data from post request
|
||||
extraData = outgoingData->readAll();
|
||||
|
||||
if (extraData.size() > 0)
|
||||
extraDataString.fromUtf8(extraData);
|
||||
|
||||
if (extraDataString.size() >= 0 && verb == QStringLiteral("POST") && extraDataString.startsWith(QStringLiteral("?")))
|
||||
extraDataString.remove(QStringLiteral("?"));
|
||||
|
||||
// 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
|
||||
|
||||
QStringList headersList;
|
||||
for (auto header : request.rawHeaderList())
|
||||
headersList << QString::fromUtf8(header + ":" + request.rawHeader(header));
|
||||
|
||||
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;
|
||||
|
||||
var dataToSend;
|
||||
var extraRequestData = Pointer_stringify($6); // request parameters
|
||||
var headersData = Pointer_stringify($7);
|
||||
|
||||
var xhr;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'arraybuffer';
|
||||
|
||||
xhr.open(verb, url, true); //async
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -118,11 +118,14 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, 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(),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ qtConfig(ssl) {
|
|||
qsslsocket_onDemandCertificates_member \
|
||||
qsslsocket_onDemandCertificates_static
|
||||
|
||||
qtConfig(openssl) {
|
||||
qtConfig(dtls) {
|
||||
SUBDIRS += \
|
||||
qdtlscookie \
|
||||
qdtls
|
||||
|
|
|
|||
Loading…
Reference in New Issue