Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: src/corelib/tools/qlocale.qdoc tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp Done-with: Edward Welbourne <edward.welbourne@qt.io> Done-with: Volker Hilsheimer <volker.hilsheimer@qt.io> Change-Id: I88e0757b2d020f0a244714c87844631df4b3fd13
This commit is contained in:
commit
9d67bf6e96
@ -26,20 +26,29 @@ contains(CMAKE_INSTALL_LIBS_DIR, ^(/usr)?/lib(64)?.*): CMAKE_USR_MOVE_WORKAROUND
|
||||
|
||||
CMAKE_OUT_DIR = $$MODULE_BASE_OUTDIR/lib/cmake
|
||||
|
||||
# Core, Network, an external module named Foo
|
||||
CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE})
|
||||
|
||||
# QtCore, QtNetwork, still Foo
|
||||
CMAKE_INCLUDE_NAME = $$eval(QT.$${MODULE}.name)
|
||||
|
||||
# TARGET here is the one changed at the end of qt_module.prf,
|
||||
# which already contains the Qt5 prefix and QT_LIBINFIX suffix :
|
||||
# Qt5Core_suffix, Qt5Network_suffix, Foo_suffix
|
||||
# (or QtCore_suffix, Foo_suffix on macos with -framework)
|
||||
CMAKE_QT_STEM = $${TARGET}
|
||||
|
||||
!generated_privates {
|
||||
isEmpty(SYNCQT.INJECTED_PRIVATE_HEADER_FILES):isEmpty(SYNCQT.PRIVATE_HEADER_FILES): \
|
||||
CMAKE_NO_PRIVATE_INCLUDES = true
|
||||
}
|
||||
|
||||
split_incpath {
|
||||
CMAKE_ADD_SOURCE_INCLUDE_DIRS = true
|
||||
CMAKE_SOURCE_INCLUDES = \
|
||||
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME})
|
||||
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME})
|
||||
CMAKE_SOURCE_PRIVATE_INCLUDES = \
|
||||
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
|
||||
$$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME})
|
||||
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
|
||||
$$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME}/$$eval(QT.$${MODULE}.VERSION)/$${CMAKE_INCLUDE_NAME})
|
||||
|
||||
cmake_extra_source_includes.input = $$PWD/data/cmake/ExtraSourceIncludes.cmake.in
|
||||
cmake_extra_source_includes.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/ExtraSourceIncludes.cmake
|
||||
@ -200,10 +209,6 @@ CMAKE_QT5_MODULE_DEPS = $$join(lib_deps, ";")
|
||||
CMAKE_INTERFACE_MODULE_DEPS = $$join(aux_mod_deps, ";")
|
||||
CMAKE_INTERFACE_QT5_MODULE_DEPS = $$join(aux_lib_deps, ";")
|
||||
|
||||
# TARGET here is the one changed at the end of qt_module.prf,
|
||||
# which already contains the Qt5 prefix and QT_LIBINFIX suffix
|
||||
CMAKE_QT_STEM = $${TARGET}
|
||||
|
||||
mac {
|
||||
!isEmpty(CMAKE_STATIC_TYPE) {
|
||||
CMAKE_LIB_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.a
|
||||
@ -213,8 +218,8 @@ mac {
|
||||
CMAKE_PRL_FILE_LOCATION_RELEASE = lib$${CMAKE_QT_STEM}.prl
|
||||
} else {
|
||||
qt_framework {
|
||||
CMAKE_LIB_FILE_LOCATION_DEBUG = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
|
||||
CMAKE_LIB_FILE_LOCATION_RELEASE = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
|
||||
CMAKE_LIB_FILE_LOCATION_DEBUG = $${CMAKE_QT_STEM}.framework/$${CMAKE_QT_STEM}
|
||||
CMAKE_LIB_FILE_LOCATION_RELEASE = $${CMAKE_QT_STEM}.framework/$${CMAKE_QT_STEM}
|
||||
CMAKE_BUILD_IS_FRAMEWORK = "true"
|
||||
} else {
|
||||
CMAKE_LIB_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.$$eval(QT.$${MODULE}.VERSION).dylib
|
||||
|
@ -157,13 +157,13 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
|
||||
!!IF !no_module_headers
|
||||
!!IF !isEmpty(CMAKE_BUILD_IS_FRAMEWORK)
|
||||
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework\"
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Headers\"
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework\"
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Headers\"
|
||||
)
|
||||
!!IF isEmpty(CMAKE_NO_PRIVATE_INCLUDES)
|
||||
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/\"
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/$${MODULE_INCNAME}\"
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/\"
|
||||
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/$${MODULE_INCNAME}\"
|
||||
)
|
||||
!!ELSE
|
||||
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"\")
|
||||
@ -180,7 +180,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
|
||||
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"\")
|
||||
!!ENDIF
|
||||
!!ELSE
|
||||
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS \"$$CMAKE_INCLUDE_DIR\" \"$${CMAKE_INCLUDE_DIR}Qt$${CMAKE_MODULE_NAME}\")
|
||||
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS \"$$CMAKE_INCLUDE_DIR\" \"$${CMAKE_INCLUDE_DIR}$${CMAKE_INCLUDE_NAME}\")
|
||||
!!IF isEmpty(CMAKE_NO_PRIVATE_INCLUDES)
|
||||
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
|
||||
\"$${CMAKE_INCLUDE_DIR}$${MODULE_INCNAME}/$$VERSION\"
|
||||
|
@ -145,14 +145,16 @@ import_plugins:qtConfig(static) {
|
||||
# the plugin path. Unknown plugins must rely on the default link path.
|
||||
plug_type = $$eval(QT_PLUGIN.$${plug}.TYPE)
|
||||
!isEmpty(plug_type) {
|
||||
plug_name = $$QMAKE_PREFIX_STATICLIB$${plug}$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
|
||||
plug_path = $$eval(QT_PLUGIN.$${plug}.PATH)
|
||||
isEmpty(plug_path): \
|
||||
plug_path = $$[QT_INSTALL_PLUGINS/get]
|
||||
LIBS += -L$$plug_path/$$plug_type
|
||||
}
|
||||
LIBS += $$plug_path/$$plug_type/$$plug_name
|
||||
} else {
|
||||
LIBS += -l$${plug}$$qtPlatformTargetSuffix()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# target variable, flag source variable
|
||||
defineTest(qtProcessModuleFlags) {
|
||||
@ -195,8 +197,6 @@ for(ever) {
|
||||
qtProcessModuleFlags(DEFINES, QT.$${QTLIB}.DEFINES)
|
||||
|
||||
MODULE_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS
|
||||
MODULE_LIBS_ADD = $$MODULE_LIBS
|
||||
MODULE_LIBS_ADD -= $$QMAKE_DEFAULT_LIBDIRS
|
||||
|
||||
# Frameworks shouldn't need include paths, but much code does not use
|
||||
# module-qualified #includes, so by default we add paths which point
|
||||
@ -209,23 +209,17 @@ for(ever) {
|
||||
!isEmpty(MODULE_MODULE) {
|
||||
contains(MODULE_CONFIG, lib_bundle) {
|
||||
framework = $$MODULE_MODULE
|
||||
# Linking frameworks by absolute path does not work.
|
||||
LIBS$$var_sfx += -framework $$framework
|
||||
} else {
|
||||
!isEmpty(MODULE_LIBS_ADD): \
|
||||
LIBS$$var_sfx += -L$$MODULE_LIBS_ADD
|
||||
|
||||
lib = $$MODULE_MODULE$$qtPlatformTargetSuffix()
|
||||
LIBS$$var_sfx += -l$$lib
|
||||
|
||||
contains(MODULE_CONFIG, staticlib): \
|
||||
PRE_TARGETDEPS *= $$MODULE_LIBS/$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB}
|
||||
|
||||
!isEmpty(QMAKE_LSB) {
|
||||
!isEmpty(MODULE_LIBS_ADD): \
|
||||
QMAKE_LFLAGS *= --lsb-libpath=$$MODULE_LIBS_ADD
|
||||
QMAKE_LFLAGS *= --lsb-shared-libs=$$lib
|
||||
QMAKE_LIBDIR *= /opt/lsb/lib
|
||||
win32|contains(MODULE_CONFIG, staticlib) {
|
||||
lib = $$MODULE_LIBS/$$QMAKE_PREFIX_STATICLIB$${lib}.$$QMAKE_EXTENSION_STATICLIB
|
||||
PRE_TARGETDEPS += $$lib
|
||||
} else {
|
||||
lib = $$MODULE_LIBS/$$QMAKE_PREFIX_SHLIB$${lib}.$$QMAKE_EXTENSION_SHLIB
|
||||
}
|
||||
LIBS$$var_sfx += $$lib
|
||||
}
|
||||
}
|
||||
QMAKE_USE$$var_sfx += $$MODULE_USES
|
||||
@ -295,7 +289,8 @@ contains(all_qt_module_deps, qml): \
|
||||
for (key, IMPORTS._KEYS_) {
|
||||
PATH = $$eval(IMPORTS.$${key}.path)
|
||||
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
|
||||
!isEmpty(PATH):!isEmpty(PLUGIN): LIBS *= -L$$PATH -l$${PLUGIN}$$qtPlatformTargetSuffix()
|
||||
!isEmpty(PATH):!isEmpty(PLUGIN): \
|
||||
LIBS += $$PATH/$$QMAKE_PREFIX_STATICLIB$${PLUGIN}$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
|
||||
}
|
||||
|
||||
# create qml_plugin_import.cpp
|
||||
|
@ -1,13 +1,21 @@
|
||||
QT_FOR_CONFIG += gui
|
||||
|
||||
defineTest(prependOpenGlLib) {
|
||||
path = $$QT.core.libs/$$QMAKE_PREFIX_STATICLIB$$1
|
||||
ext = .$$QMAKE_EXTENSION_STATICLIB
|
||||
QMAKE_LIBS_OPENGL_ES2 = $${path}$${ext} $$QMAKE_LIBS_OPENGL_ES2
|
||||
QMAKE_LIBS_OPENGL_ES2_DEBUG = $${path}d$${ext} $$QMAKE_LIBS_OPENGL_ES2_DEBUG
|
||||
export(QMAKE_LIBS_OPENGL_ES2)
|
||||
export(QMAKE_LIBS_OPENGL_ES2_DEBUG)
|
||||
}
|
||||
|
||||
qtConfig(opengles2) {
|
||||
# Depending on the configuration we use libQtANGLE or libEGL and libGLESv2
|
||||
qtConfig(combined-angle-lib) {
|
||||
QMAKE_LIBS_OPENGL_ES2 = -l$${LIBQTANGLE_NAME} $$QMAKE_LIBS_OPENGL_ES2
|
||||
QMAKE_LIBS_OPENGL_ES2_DEBUG = -l$${LIBQTANGLE_NAME}d $$QMAKE_LIBS_OPENGL_ES2_DEBUG
|
||||
prependOpenGlLib($$LIBQTANGLE_NAME)
|
||||
} else {
|
||||
QMAKE_LIBS_OPENGL_ES2 = -l$${LIBEGL_NAME} -l$${LIBGLESV2_NAME} $$QMAKE_LIBS_OPENGL_ES2
|
||||
QMAKE_LIBS_OPENGL_ES2_DEBUG = -l$${LIBEGL_NAME}d -l$${LIBGLESV2_NAME}d $$QMAKE_LIBS_OPENGL_ES2_DEBUG
|
||||
prependOpenGlLib($$LIBGLESV2_NAME)
|
||||
prependOpenGlLib($$LIBEGL_NAME)
|
||||
}
|
||||
# For Desktop, use the ANGLE library location passed on from configure.
|
||||
INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2
|
||||
|
@ -6,10 +6,9 @@ contains(TEMPLATE, ".*app") {
|
||||
|
||||
qt:for(entryLib, $$list($$unique(QMAKE_LIBS_QT_ENTRY))) {
|
||||
isEqual(entryLib, -lqtmain) {
|
||||
!contains(QMAKE_DEFAULT_LIBDIRS, $$QT.core.libs): \
|
||||
QMAKE_LIBS += -L$$QT.core.libs
|
||||
CONFIG(debug, debug|release): QMAKE_LIBS += $${entryLib}$${QT_LIBINFIX}d
|
||||
else: QMAKE_LIBS += $${entryLib}$${QT_LIBINFIX}
|
||||
lib = $$QT.core.libs/$${QMAKE_PREFIX_STATICLIB}qtmain$$QT_LIBINFIX$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
|
||||
PRE_TARGETDEPS += $$lib
|
||||
QMAKE_LIBS += $$lib
|
||||
} else {
|
||||
QMAKE_LIBS += $${entryLib}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ load(qt_config)
|
||||
|
||||
QMAKE_LIBS_THREAD += -lrt
|
||||
|
||||
QMAKE_LSB = 1
|
||||
QMAKE_CC = lsbcc
|
||||
QMAKE_CXX = lsbc++
|
||||
|
||||
|
@ -310,9 +310,18 @@ static QString readSymLink(const QFileSystemEntry &link)
|
||||
const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
|
||||
result = QString::fromWCharArray(PathBuffer, length);
|
||||
}
|
||||
// cut-off "//?/" and "/??/"
|
||||
if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
|
||||
// cut-off "\\?\" and "\??\"
|
||||
if (result.size() > 4
|
||||
&& result.at(0) == QLatin1Char('\\')
|
||||
&& result.at(2) == QLatin1Char('?')
|
||||
&& result.at(3) == QLatin1Char('\\')) {
|
||||
result = result.mid(4);
|
||||
// cut off UNC in addition when the link points at a UNC share
|
||||
// in which case we need to prepend another backslash to get \\server\share
|
||||
if (result.leftRef(3) == QLatin1String("UNC")) {
|
||||
result.replace(0, 3, QLatin1Char('\\'));
|
||||
}
|
||||
}
|
||||
}
|
||||
free(rdb);
|
||||
CloseHandle(handle);
|
||||
|
@ -523,7 +523,7 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
|
||||
{
|
||||
return invokeMethodImpl(context,
|
||||
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
|
||||
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
|
||||
type,
|
||||
ret);
|
||||
}
|
||||
@ -535,7 +535,7 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
|
||||
{
|
||||
return invokeMethodImpl(context,
|
||||
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
|
||||
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
|
||||
Qt::AutoConnection,
|
||||
ret);
|
||||
}
|
||||
|
@ -2482,6 +2482,17 @@ QString QLocale::toString(double i, char f, int prec) const
|
||||
|
||||
Returns a QLocale object initialized to the "C" locale.
|
||||
|
||||
This locale is based on en_US but with various quirks of its own, such as
|
||||
simplified number formatting and its own date formatting. It implements the
|
||||
POSIX standards that describe the behavior of standard library functions of
|
||||
the "C" programming language.
|
||||
|
||||
Among other things, this means its collation order is based on the ASCII
|
||||
values of letters, so that (for case-sensitive sorting) all upper-case
|
||||
letters sort before any lower-case one (rather than each letter's upper- and
|
||||
lower-case forms sorting adjacent to one another, before the next letter's
|
||||
two forms).
|
||||
|
||||
\sa system()
|
||||
*/
|
||||
|
||||
|
@ -104,7 +104,7 @@
|
||||
This enumerated type is used to specify a language.
|
||||
|
||||
\value AnyLanguage
|
||||
\value C The "C" locale is identical in behavior to English/UnitedStates.
|
||||
\value C A simplified English locale; see QLocale::c()
|
||||
|
||||
\value Abkhazian
|
||||
\value Afan Obsolete, please use Oromo
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include "qwindow.h"
|
||||
#include "qplatformwindow.h"
|
||||
|
||||
#include <private/qwindow_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
@ -199,12 +201,18 @@ void QOffscreenSurface::create()
|
||||
if (QThread::currentThread() != qGuiApp->thread())
|
||||
qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.");
|
||||
d->offscreenWindow = new QWindow(d->screen);
|
||||
// Make the window frameless to prevent Windows from enlarging it, should it
|
||||
// violate the minimum title bar width on the platform.
|
||||
d->offscreenWindow->setFlags(d->offscreenWindow->flags()
|
||||
| Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
|
||||
d->offscreenWindow->setObjectName(QLatin1String("QOffscreenSurface"));
|
||||
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
|
||||
// The QOffscreenSurface has to be usable even after exiting the event loop.
|
||||
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
|
||||
d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface);
|
||||
d->offscreenWindow->setFormat(d->requestedFormat);
|
||||
// Prevent QPlatformWindow::initialGeometry() and platforms from setting a default geometry.
|
||||
qt_window_private(d->offscreenWindow)->setAutomaticPositionAndResizeEnabled(false);
|
||||
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
|
||||
d->offscreenWindow->create();
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
QShaderFormat::QShaderFormat() Q_DECL_NOTHROW
|
||||
: m_api(NoApi)
|
||||
, m_shaderType(Fragment)
|
||||
{
|
||||
}
|
||||
|
||||
@ -106,6 +107,9 @@ bool QShaderFormat::supports(const QShaderFormat &other) const Q_DECL_NOTHROW
|
||||
if (m_version < other.m_version)
|
||||
return false;
|
||||
|
||||
if (m_shaderType != other.m_shaderType)
|
||||
return false;
|
||||
|
||||
const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
|
||||
m_extensions.constEnd(),
|
||||
other.m_extensions.constBegin(),
|
||||
@ -119,12 +123,23 @@ bool QShaderFormat::supports(const QShaderFormat &other) const Q_DECL_NOTHROW
|
||||
return true;
|
||||
}
|
||||
|
||||
QShaderFormat::ShaderType QShaderFormat::shaderType() const Q_DECL_NOTHROW
|
||||
{
|
||||
return m_shaderType;
|
||||
}
|
||||
|
||||
void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) Q_DECL_NOTHROW
|
||||
{
|
||||
m_shaderType = shaderType;
|
||||
}
|
||||
|
||||
bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
|
||||
{
|
||||
return lhs.api() == rhs.api()
|
||||
&& lhs.version() == rhs.version()
|
||||
&& lhs.extensions() == rhs.extensions()
|
||||
&& lhs.vendor() == rhs.vendor();
|
||||
&& lhs.vendor() == rhs.vendor()
|
||||
&& lhs.shaderType() == rhs.shaderType();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -69,6 +69,15 @@ public:
|
||||
OpenGLES
|
||||
};
|
||||
|
||||
enum ShaderType : int {
|
||||
Vertex = 0,
|
||||
TessellationControl,
|
||||
TessellationEvaluation,
|
||||
Geometry,
|
||||
Fragment,
|
||||
Compute
|
||||
};
|
||||
|
||||
Q_GUI_EXPORT QShaderFormat() Q_DECL_NOTHROW;
|
||||
|
||||
Q_GUI_EXPORT Api api() const Q_DECL_NOTHROW;
|
||||
@ -86,11 +95,15 @@ public:
|
||||
Q_GUI_EXPORT bool isValid() const Q_DECL_NOTHROW;
|
||||
Q_GUI_EXPORT bool supports(const QShaderFormat &other) const Q_DECL_NOTHROW;
|
||||
|
||||
Q_GUI_EXPORT ShaderType shaderType() const Q_DECL_NOTHROW;
|
||||
Q_GUI_EXPORT void setShaderType(ShaderType shaderType) Q_DECL_NOTHROW;
|
||||
|
||||
private:
|
||||
Api m_api;
|
||||
QVersionNumber m_version;
|
||||
QStringList m_extensions;
|
||||
QString m_vendor;
|
||||
ShaderType m_shaderType;
|
||||
};
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "qshadergenerator_p.h"
|
||||
|
||||
#include "qshaderlanguage_p.h"
|
||||
#include <QRegularExpression>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -56,6 +57,9 @@ namespace
|
||||
case QShaderLanguage::Const:
|
||||
return "const";
|
||||
case QShaderLanguage::Input:
|
||||
if (format.shaderType() == QShaderFormat::Vertex)
|
||||
return "attribute";
|
||||
else
|
||||
return "varying";
|
||||
case QShaderLanguage::Output:
|
||||
return ""; // Although fragment shaders for <=2 only have fixed outputs
|
||||
@ -314,12 +318,22 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
||||
[enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
|
||||
};
|
||||
|
||||
QVector<QString> globalInputVariables;
|
||||
const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$"));
|
||||
|
||||
const QVector<QShaderNode> nodes = graph.nodes();
|
||||
for (const QShaderNode &node : nodes) {
|
||||
if (intersectsEnabledLayers(node.layers())) {
|
||||
const QByteArrayList headerSnippets = node.rule(format).headerSnippets;
|
||||
for (const QByteArray &snippet : headerSnippets) {
|
||||
code << replaceParameters(snippet, node, format);
|
||||
|
||||
// If node is an input, record the variable name into the globalInputVariables vector
|
||||
if (node.type() == QShaderNode::Input) {
|
||||
const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last()));
|
||||
if (match.hasMatch())
|
||||
globalInputVariables.push_back(match.captured(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -328,6 +342,14 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
||||
code << QByteArrayLiteral("void main()");
|
||||
code << QByteArrayLiteral("{");
|
||||
|
||||
// Table to store temporary variables that should be replaced by global
|
||||
// variables. This avoids having vec3 v56 = vertexPosition; when we could
|
||||
// just use vertexPosition directly.
|
||||
// The added benefit is when having arrays, we don't try to create
|
||||
// mat4 v38 = skinningPalelette[100] which would be invalid
|
||||
QHash<QString, QString> localReferencesToGlobalInputs;
|
||||
const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*(\\w+).*;$"));
|
||||
|
||||
for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) {
|
||||
const QShaderNode node = statement.node;
|
||||
QByteArray line = node.rule(format).substitution;
|
||||
@ -338,6 +360,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
||||
const bool isInput = port.direction == QShaderNodePort::Input;
|
||||
|
||||
const int portIndex = statement.portIndex(portDirection, portName);
|
||||
|
||||
Q_ASSERT(portIndex >= 0);
|
||||
|
||||
const int variableIndex = isInput ? statement.inputs.at(portIndex)
|
||||
: statement.outputs.at(portIndex);
|
||||
if (variableIndex < 0)
|
||||
@ -345,15 +370,51 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
||||
|
||||
const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
|
||||
const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
|
||||
|
||||
line.replace(placeholder, variable);
|
||||
}
|
||||
|
||||
code << QByteArrayLiteral(" ") + replaceParameters(line, node, format);
|
||||
const QByteArray substitutionedLine = replaceParameters(line, node, format);
|
||||
|
||||
// Record name of temporary variable that possibly references a global input
|
||||
// We will replace the temporary variables by the matching global variables later
|
||||
bool isAGlobalInputVariable = false;
|
||||
if (node.type() == QShaderNode::Input) {
|
||||
const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine));
|
||||
if (match.hasMatch()) {
|
||||
const QString globalVariable = match.captured(2);
|
||||
if (globalInputVariables.contains(globalVariable)) {
|
||||
const QString localVariable = match.captured(1);
|
||||
// TO DO: Clean globalVariable (remove brackets ...)
|
||||
localReferencesToGlobalInputs.insert(localVariable, globalVariable);
|
||||
isAGlobalInputVariable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only insert content for lines aren't inputs or have not matching
|
||||
// globalVariables for now
|
||||
if (!isAGlobalInputVariable)
|
||||
code << QByteArrayLiteral(" ") + substitutionedLine;
|
||||
}
|
||||
|
||||
code << QByteArrayLiteral("}");
|
||||
code << QByteArray();
|
||||
return code.join('\n');
|
||||
|
||||
// Replace occurrences of local variables which reference a global variable
|
||||
// by the global variables directly
|
||||
auto it = localReferencesToGlobalInputs.cbegin();
|
||||
const auto end = localReferencesToGlobalInputs.cend();
|
||||
QString codeString = QString::fromUtf8(code.join('\n'));
|
||||
|
||||
while (it != end) {
|
||||
const QRegularExpression r(QStringLiteral("\\b(%1)([\\b|\\.|;|\\)|\\[|\\s|\\*|\\+|\\/|\\-|,])").arg(it.key()),
|
||||
QRegularExpression::MultilineOption);
|
||||
codeString.replace(r, QStringLiteral("%1\\2").arg(it.value()));
|
||||
++it;
|
||||
}
|
||||
|
||||
return codeString.toUtf8();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -251,6 +251,17 @@ void QShaderNodesLoader::load(const QJsonObject &prototypesObject)
|
||||
break;
|
||||
}
|
||||
|
||||
// We default out to a Fragment ShaderType if nothing is specified
|
||||
// as that was the initial behavior we introduced
|
||||
const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString();
|
||||
format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment
|
||||
: shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex
|
||||
: shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl
|
||||
: shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation
|
||||
: shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry
|
||||
: shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute
|
||||
: QShaderFormat::Fragment);
|
||||
|
||||
const QByteArray substitution = substitutionValue.toString().toUtf8();
|
||||
|
||||
const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));
|
||||
|
@ -268,7 +268,7 @@ EGLConfig QEglConfigChooser::chooseConfig()
|
||||
configureAttributes.append(EGL_OPENGL_ES_BIT);
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
Q_FALLTHROUGH();
|
||||
default:
|
||||
needsES2Plus = true;
|
||||
break;
|
||||
|
@ -134,7 +134,7 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
|
||||
|
||||
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
|
||||
{
|
||||
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
|
||||
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format);
|
||||
// m_format now has the renderableType() resolved (it cannot be Default anymore)
|
||||
// but does not yet contain version, profile, options.
|
||||
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
|
||||
@ -248,6 +248,12 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
|
||||
value = 0;
|
||||
eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
|
||||
if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) {
|
||||
// if EGL config supports both OpenGL and OpenGL ES render type,
|
||||
// q_glFormatFromConfig() with the default "referenceFormat" parameter
|
||||
// will always figure it out as OpenGL render type.
|
||||
// We can override it to match user's real render type.
|
||||
if (value == EGL_OPENGL_ES_API)
|
||||
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
m_api = value;
|
||||
eglBindAPI(m_api);
|
||||
} else {
|
||||
|
@ -114,8 +114,8 @@ void QTsLibMouseHandler::readMouseData()
|
||||
int x = sample.x;
|
||||
int y = sample.y;
|
||||
|
||||
// work around missing coordinates on mouse release
|
||||
if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) {
|
||||
// coordinates on release events can contain arbitrary values, just ignore them
|
||||
if (sample.pressure == 0) {
|
||||
x = m_x;
|
||||
y = m_y;
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ enum OutputConfiguration {
|
||||
OutputConfigOff,
|
||||
OutputConfigPreferred,
|
||||
OutputConfigCurrent,
|
||||
OutputConfigSkip,
|
||||
OutputConfigMode,
|
||||
OutputConfigModeline
|
||||
};
|
||||
@ -191,6 +192,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
|
||||
configuration = OutputConfigPreferred;
|
||||
} else if (mode == "current") {
|
||||
configuration = OutputConfigCurrent;
|
||||
} else if (mode == "skip") {
|
||||
configuration = OutputConfigSkip;
|
||||
} else if (sscanf(mode.constData(), "%dx%d@%d", &configurationSize.rwidth(), &configurationSize.rheight(),
|
||||
&configurationRefresh) == 3)
|
||||
{
|
||||
@ -229,6 +232,11 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (configuration == OutputConfigSkip) {
|
||||
qCDebug(qLcKmsDebug) << "Skipping output" << connectorName;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the current mode on the current crtc
|
||||
drmModeModeInfo crtc_mode;
|
||||
memset(&crtc_mode, 0, sizeof crtc_mode);
|
||||
|
@ -300,7 +300,7 @@ void QGenericEngine::doRequestUpdate()
|
||||
if (interface.flags() & QNetworkInterface::IsLoopBack)
|
||||
continue;
|
||||
|
||||
#ifndef Q_OS_WINRT
|
||||
#ifndef Q_OS_WIN
|
||||
// ignore WLAN interface handled in separate engine
|
||||
if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN)
|
||||
continue;
|
||||
|
@ -154,6 +154,7 @@
|
||||
<< "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
|
||||
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
|
||||
[super setLayer:layer];
|
||||
layer.delegate = self;
|
||||
}
|
||||
|
||||
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
|
||||
|
@ -1087,7 +1087,10 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
|
||||
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
|
||||
if (image.isNull())
|
||||
return false;
|
||||
return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
|
||||
// QTBUG-64322: Use PNG only for transparent images as otherwise MS PowerPoint
|
||||
// cannot handle it.
|
||||
return cf == CF_DIBV5 || cf == CF_DIB
|
||||
|| (cf == int(CF_PNG) && image.hasAlphaChannel());
|
||||
}
|
||||
|
||||
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
|
||||
|
@ -113,6 +113,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
|
||||
case QAccessible::ValueChanged:
|
||||
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
|
||||
break;
|
||||
case QAccessible::SelectionAdd:
|
||||
QWindowsUiaMainProvider::notifySelectionChange(event);
|
||||
break;
|
||||
case QAccessible::TextAttributeChanged:
|
||||
case QAccessible::TextColumnChanged:
|
||||
case QAccessible::TextInserted:
|
||||
|
@ -146,9 +146,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
|
||||
void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
|
||||
{
|
||||
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
||||
if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
|
||||
// Notifies changes in values of controls supporting the value interface.
|
||||
if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
|
||||
QAccessibleInterface *listacc = accessible->child(0);
|
||||
if (listacc && listacc->role() == QAccessible::List) {
|
||||
int count = listacc->childCount();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
QAccessibleInterface *item = listacc->child(i);
|
||||
if (item && item->text(QAccessible::Name) == event->value()) {
|
||||
if (!item->state().selected) {
|
||||
if (QAccessibleActionInterface *actionInterface = item->actionInterface())
|
||||
actionInterface->doAction(QAccessibleActionInterface::toggleAction());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event->value().type() == QVariant::String) {
|
||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
||||
// Notifies changes in string values.
|
||||
VARIANT oldVal, newVal;
|
||||
clearVariant(&oldVal);
|
||||
setVariantString(event->value().toString(), &newVal);
|
||||
QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
|
||||
}
|
||||
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
|
||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
||||
// Notifies changes in values of controls supporting the value interface.
|
||||
VARIANT oldVal, newVal;
|
||||
clearVariant(&oldVal);
|
||||
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
|
||||
@ -158,6 +182,15 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
|
||||
{
|
||||
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
||||
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
|
||||
QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notifies changes in text content and selection state of text controls.
|
||||
void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
|
||||
{
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
static void notifyFocusChange(QAccessibleEvent *event);
|
||||
static void notifyStateChange(QAccessibleStateChangeEvent *event);
|
||||
static void notifyValueChange(QAccessibleValueChangeEvent *event);
|
||||
static void notifySelectionChange(QAccessibleEvent *event);
|
||||
static void notifyTextChange(QAccessibleEvent *event);
|
||||
|
||||
// IUnknown
|
||||
|
@ -1156,66 +1156,6 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
|
||||
}
|
||||
#endif
|
||||
|
||||
static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color)
|
||||
{
|
||||
Q_ASSERT(color);
|
||||
Q_ASSERT(context);
|
||||
|
||||
CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context);
|
||||
NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace];
|
||||
NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace];
|
||||
[targetNSColorSpace release];
|
||||
|
||||
return adjusted;
|
||||
}
|
||||
|
||||
static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4])
|
||||
{
|
||||
Q_ASSERT(context);
|
||||
|
||||
auto colorSpace = CGBitmapContextGetColorSpace(context);
|
||||
if (!colorSpace)
|
||||
return nil;
|
||||
|
||||
return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]);
|
||||
}
|
||||
|
||||
static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect)
|
||||
{
|
||||
Q_ASSERT(context);
|
||||
|
||||
static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97};
|
||||
static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9};
|
||||
|
||||
NSColor *fillColor = qt_colorForContext(context, selected ? white : gray);
|
||||
[fillColor setFill];
|
||||
|
||||
if (state == NSOffState) {
|
||||
static NSBezierPath *triangle = [[NSBezierPath alloc] init];
|
||||
[triangle removeAllPoints];
|
||||
// In off state, a disclosure button is an equilateral triangle
|
||||
// ('pointing' to the right) with a bound rect that can be described
|
||||
// as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by
|
||||
// (2, 4).
|
||||
[triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)];
|
||||
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)];
|
||||
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)];
|
||||
[triangle closePath];
|
||||
[triangle fill];
|
||||
} else {
|
||||
static NSBezierPath *openTriangle = [[NSBezierPath alloc] init];
|
||||
[openTriangle removeAllPoints];
|
||||
// In 'on' state, the button is an equilateral triangle (looking down)
|
||||
// with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect'
|
||||
// it's translated by (1, 4).
|
||||
[openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)];
|
||||
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)];
|
||||
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)];
|
||||
[openTriangle closePath];
|
||||
[openTriangle fill];
|
||||
}
|
||||
}
|
||||
|
||||
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
|
||||
{
|
||||
QPainterPath focusRingPath;
|
||||
@ -3301,15 +3241,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
|
||||
CGContextScaleCTM(cg, 1, -1);
|
||||
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
|
||||
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) {
|
||||
// When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme,
|
||||
// under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark'
|
||||
// code path and is becoming transparent, thus 'invisible' on the white background. To workaround this,
|
||||
// we draw the disclose triangle manually:
|
||||
qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect);
|
||||
} else {
|
||||
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
|
||||
}
|
||||
|
||||
d->restoreNSGraphicsContext(cg);
|
||||
break; }
|
||||
|
||||
|
@ -11343,7 +11343,7 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
|
||||
}
|
||||
|
||||
// sourceRect must be in the given coordinate system
|
||||
QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
|
||||
QRectF QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
|
||||
{
|
||||
QRectF effectRectF;
|
||||
|
||||
@ -11371,7 +11371,7 @@ QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem sy
|
||||
*unpadded = true;
|
||||
}
|
||||
|
||||
return effectRectF.toAlignedRect();
|
||||
return effectRectF;
|
||||
}
|
||||
|
||||
QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
|
||||
@ -11389,7 +11389,8 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
|
||||
|
||||
bool unpadded;
|
||||
const QRectF sourceRect = boundingRect(system);
|
||||
QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded);
|
||||
QRectF effectRectF = paddedEffectRect(system, mode, sourceRect, &unpadded);
|
||||
QRect effectRect = effectRectF.toAlignedRect();
|
||||
|
||||
if (offset)
|
||||
*offset = effectRect.topLeft();
|
||||
@ -11405,7 +11406,9 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
|
||||
if (effectRect.isEmpty())
|
||||
return QPixmap();
|
||||
|
||||
QPixmap pixmap(effectRect.size());
|
||||
const auto dpr = info ? info->painter->device()->devicePixelRatioF() : 1.0;
|
||||
QPixmap pixmap(QRectF(effectRectF.topLeft(), effectRectF.size() * dpr).toAlignedRect().size());
|
||||
pixmap.setDevicePixelRatio(dpr);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter pixmapPainter(&pixmap);
|
||||
pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
|
||||
|
@ -644,7 +644,7 @@ public:
|
||||
QPixmap pixmap(Qt::CoordinateSystem system,
|
||||
QPoint *offset,
|
||||
QGraphicsEffect::PixmapPadMode mode) const override;
|
||||
QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const;
|
||||
QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const;
|
||||
|
||||
QGraphicsItem *item;
|
||||
QGraphicsItemPaintInfo *info;
|
||||
|
@ -4852,7 +4852,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
|
||||
&& painter->worldTransform().type() <= QTransform::TxTranslate)
|
||||
{
|
||||
QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
|
||||
QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);
|
||||
QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
|
||||
|
||||
sourced->setCachedOffset(effectRect.topLeft());
|
||||
} else {
|
||||
|
@ -1448,6 +1448,7 @@ bool QOpenGLWidget::event(QEvent *e)
|
||||
{
|
||||
// Special case: did grabFramebuffer() for a hidden widget that then became visible.
|
||||
// Recreate all resources since the context now needs to share with the TLW's.
|
||||
if (!qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts))
|
||||
d->reset();
|
||||
}
|
||||
if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
|
||||
|
@ -2908,7 +2908,10 @@ void QStyleSheetStyle::polish(QPalette &pal)
|
||||
|
||||
void QStyleSheetStyle::repolish(QWidget *w)
|
||||
{
|
||||
QList<const QObject *> children = w->findChildren<const QObject *>(QString());
|
||||
QList<const QObject *> children;
|
||||
children.reserve(w->children().size() + 1);
|
||||
for (auto child: qAsConst(w->children()))
|
||||
children.append(child);
|
||||
children.append(w);
|
||||
styleSheetCaches->styleSheetCache.remove(w);
|
||||
updateObjects(children);
|
||||
|
@ -1239,6 +1239,8 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
|
||||
|
||||
This property gets and sets the plain text editor's contents. The previous
|
||||
contents are removed and undo/redo history is reset when this property is set.
|
||||
currentCharFormat() is also reset, unless textCursor() is already at the
|
||||
beginning of the document.
|
||||
|
||||
By default, for an editor with no contents, this property contains an empty string.
|
||||
*/
|
||||
@ -1518,7 +1520,12 @@ void QPlainTextEdit::paste()
|
||||
/*!
|
||||
Deletes all the text in the text edit.
|
||||
|
||||
Note that the undo/redo history is cleared by this function.
|
||||
Notes:
|
||||
\list
|
||||
\li The undo/redo history is also cleared.
|
||||
\li currentCharFormat() is reset, unless textCursor()
|
||||
is already at the beginning of the document.
|
||||
\endlist
|
||||
|
||||
\sa cut(), setPlainText()
|
||||
*/
|
||||
@ -1651,7 +1658,12 @@ void QPlainTextEdit::timerEvent(QTimerEvent *e)
|
||||
|
||||
\a text is interpreted as plain text.
|
||||
|
||||
Note that the undo/redo history is cleared by this function.
|
||||
Notes:
|
||||
\list
|
||||
\li The undo/redo history is also cleared.
|
||||
\li currentCharFormat() is reset, unless textCursor()
|
||||
is already at the beginning of the document.
|
||||
\endlist
|
||||
|
||||
\sa toPlainText()
|
||||
*/
|
||||
|
@ -556,7 +556,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
|
||||
|
||||
This property gets and sets the text editor's contents as plain
|
||||
text. Previous contents are removed and undo/redo history is reset
|
||||
when the property is set.
|
||||
when the property is set. currentCharFormat() is also reset, unless
|
||||
textCursor() is already at the beginning of the document.
|
||||
|
||||
If the text edit has another content type, it will not be replaced
|
||||
by plain text if you call toPlainText(). The only exception to this
|
||||
@ -1034,7 +1035,12 @@ void QTextEdit::paste()
|
||||
/*!
|
||||
Deletes all the text in the text edit.
|
||||
|
||||
Note that the undo/redo history is cleared by this function.
|
||||
Notes:
|
||||
\list
|
||||
\li The undo/redo history is also cleared.
|
||||
\li currentCharFormat() is reset, unless textCursor()
|
||||
is already at the beginning of the document.
|
||||
\endlist
|
||||
|
||||
\sa cut(), setPlainText(), setHtml()
|
||||
*/
|
||||
@ -1139,9 +1145,13 @@ void QTextEdit::timerEvent(QTimerEvent *e)
|
||||
Changes the text of the text edit to the string \a text.
|
||||
Any previous text is removed.
|
||||
|
||||
\a text is interpreted as plain text.
|
||||
|
||||
Note that the undo/redo history is cleared by this function.
|
||||
Notes:
|
||||
\list
|
||||
\li \a text is interpreted as plain text.
|
||||
\li The undo/redo history is also cleared.
|
||||
\li currentCharFormat() is reset, unless textCursor()
|
||||
is already at the beginning of the document.
|
||||
\endlist
|
||||
|
||||
\sa toPlainText()
|
||||
*/
|
||||
@ -1175,7 +1185,8 @@ QString QTextEdit::toPlainText() const
|
||||
|
||||
setHtml() changes the text of the text edit. Any previous text is
|
||||
removed and the undo/redo history is cleared. The input text is
|
||||
interpreted as rich text in html format.
|
||||
interpreted as rich text in html format. currentCharFormat() is also
|
||||
reset, unless textCursor() is already at the beginning of the document.
|
||||
|
||||
\note It is the responsibility of the caller to make sure that the
|
||||
text is correctly decoded when a QString containing HTML is created
|
||||
|
@ -1559,6 +1559,16 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
|
||||
<< NtfsTestResource(NtfsTestResource::SymLink, relToRelSymlink, relToRelTarget)
|
||||
<< relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
|
||||
}
|
||||
{
|
||||
// Symlink to UNC share
|
||||
pwd.mkdir("unc");
|
||||
QString errorMessage;
|
||||
QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
|
||||
QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
|
||||
QTest::newRow("UNC symlink")
|
||||
<< NtfsTestResource(NtfsTestResource::SymLink, uncSymlink, uncTarget)
|
||||
<< QDir::fromNativeSeparators(uncSymlink) << true << QDir::fromNativeSeparators(uncTarget) << uncTarget;
|
||||
}
|
||||
|
||||
//Junctions
|
||||
QString target = "target";
|
||||
@ -1630,7 +1640,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
|
||||
// Ensure that junctions, mountpoints are removed. If this fails, do not remove
|
||||
// temporary directory to prevent it from trashing the system.
|
||||
if (fi.isDir()) {
|
||||
if (!QDir().rmdir(fi.fileName())) {
|
||||
if (!QDir().rmdir(fi.filePath())) {
|
||||
qWarning("Unable to remove NTFS junction '%s'', keeping '%s'.",
|
||||
qPrintable(fi.fileName()), qPrintable(QDir::toNativeSeparators(m_dir.path())));
|
||||
m_dir.setAutoRemove(false);
|
||||
|
@ -1,4 +1,5 @@
|
||||
CONFIG += testcase
|
||||
qtConfig(c++14): CONFIG += c++14
|
||||
TARGET = tst_qmetaobject
|
||||
QT = core-private testlib
|
||||
SOURCES = tst_qmetaobject.cpp
|
||||
|
@ -816,6 +816,15 @@ void tst_QMetaObject::invokePointer()
|
||||
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
|
||||
}
|
||||
QCOMPARE(countedStructObjectsCount, 0);
|
||||
#ifdef __cpp_init_captures
|
||||
{
|
||||
CountedStruct str;
|
||||
std::unique_ptr<int> ptr( new int );
|
||||
QVERIFY(QMetaObject::invokeMethod(&obj, [str, &t1, &obj, p = std::move(ptr)]() { obj.sl1(t1); }));
|
||||
QCOMPARE(obj.slotResult, QString("sl1:1"));
|
||||
}
|
||||
QCOMPARE(countedStructObjectsCount, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QMetaObject::invokeQueuedMetaMember()
|
||||
@ -1121,6 +1130,15 @@ void tst_QMetaObject::invokeBlockingQueuedPointer()
|
||||
QCOMPARE(exp, QString("yessir"));
|
||||
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
|
||||
}
|
||||
#ifdef __cpp_init_captures
|
||||
{
|
||||
std::unique_ptr<int> ptr(new int);
|
||||
QVERIFY(QMetaObject::invokeMethod(&obj,
|
||||
[&obj, p = std::move(ptr)]() { return obj.sl1("hehe"); },
|
||||
Qt::BlockingQueuedConnection));
|
||||
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
|
||||
}
|
||||
#endif
|
||||
QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection));
|
||||
t.quit();
|
||||
QVERIFY(t.wait());
|
||||
|
@ -35,11 +35,13 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion)
|
||||
QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion,
|
||||
QShaderFormat::ShaderType shaderType= QShaderFormat::Fragment)
|
||||
{
|
||||
auto format = QShaderFormat();
|
||||
format.setApi(api);
|
||||
format.setVersion(QVersionNumber(majorVersion, minorVersion));
|
||||
format.setShaderType(shaderType);
|
||||
return format;
|
||||
}
|
||||
|
||||
@ -74,7 +76,7 @@ namespace
|
||||
return edge;
|
||||
}
|
||||
|
||||
QShaderGraph createGraph()
|
||||
QShaderGraph createFragmentShaderGraph()
|
||||
{
|
||||
const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
|
||||
const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
|
||||
@ -194,6 +196,7 @@ private slots:
|
||||
void shouldProcessLanguageQualifierAndTypeEnums_data();
|
||||
void shouldProcessLanguageQualifierAndTypeEnums();
|
||||
void shouldGenerateDifferentCodeDependingOnActiveLayers();
|
||||
void shouldUseGlobalVariableRatherThanTemporaries();
|
||||
};
|
||||
|
||||
void tst_QShaderGenerator::shouldHaveDefaultState()
|
||||
@ -213,7 +216,7 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
|
||||
QTest::addColumn<QShaderFormat>("format");
|
||||
QTest::addColumn<QByteArray>("expectedCode");
|
||||
|
||||
const auto graph = createGraph();
|
||||
const auto graph = createFragmentShaderGraph();
|
||||
|
||||
const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
|
||||
const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
|
||||
@ -234,14 +237,9 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " highp vec2 v2 = texCoord;"
|
||||
<< " sampler2D v1 = texture;"
|
||||
<< " highp float v3 = lightIntensity;"
|
||||
<< " highp vec4 v5 = texture2D(v1, v2);"
|
||||
<< " highp vec3 v0 = worldPosition;"
|
||||
<< " highp float v4 = exposure;"
|
||||
<< " highp vec4 v6 = lightModel(v5, v0, v3);"
|
||||
<< " highp vec4 v7 = v6 * pow(2.0, v4);"
|
||||
<< " highp vec4 v5 = texture2D(texture, texCoord);"
|
||||
<< " highp vec4 v6 = lightModel(v5, worldPosition, lightIntensity);"
|
||||
<< " highp vec4 v7 = v6 * pow(2.0, exposure);"
|
||||
<< " gl_fragColor = v7;"
|
||||
<< "}"
|
||||
<< "";
|
||||
@ -256,14 +254,9 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " vec2 v2 = texCoord;"
|
||||
<< " sampler2D v1 = texture;"
|
||||
<< " float v3 = lightIntensity;"
|
||||
<< " vec4 v5 = texture2D(v1, v2);"
|
||||
<< " vec3 v0 = worldPosition;"
|
||||
<< " float v4 = exposure;"
|
||||
<< " vec4 v6 = lightModel(v5, v0, v3);"
|
||||
<< " vec4 v7 = v6 * pow(2.0, v4);"
|
||||
<< " vec4 v5 = texture2D(texture, texCoord);"
|
||||
<< " vec4 v6 = lightModel(v5, worldPosition, lightIntensity);"
|
||||
<< " vec4 v7 = v6 * pow(2.0, exposure);"
|
||||
<< " fragColor = v7;"
|
||||
<< "}"
|
||||
<< "";
|
||||
@ -580,6 +573,7 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
QTest::addColumn<QShaderFormat>("format");
|
||||
QTest::addColumn<QByteArray>("expectedCode");
|
||||
|
||||
{
|
||||
const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
|
||||
const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0);
|
||||
const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0);
|
||||
@ -633,8 +627,7 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
|
||||
<< " gl_fragColor = v0;"
|
||||
<< " gl_fragColor = worldPosition;"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto gl3Code = (QByteArrayList() << "#version 130"
|
||||
@ -646,8 +639,7 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
|
||||
<< " fragColor = v0;"
|
||||
<< " fragColor = worldPosition;"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto gl4Code = (QByteArrayList() << "#version 400 core"
|
||||
@ -659,8 +651,7 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
|
||||
<< " fragColor = v0;"
|
||||
<< " fragColor = worldPosition;"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto es2Code = (QByteArrayList() << "#version 100"
|
||||
@ -671,8 +662,7 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
|
||||
<< " gl_fragColor = v0;"
|
||||
<< " gl_fragColor = worldPosition;"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto es3Code = (QByteArrayList() << "#version 300 es"
|
||||
@ -683,8 +673,7 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
|
||||
<< " gl_fragColor = v0;"
|
||||
<< " gl_fragColor = worldPosition;"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
|
||||
@ -697,6 +686,80 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0, QShaderFormat::Vertex);
|
||||
const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0, QShaderFormat::Vertex);
|
||||
const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0, QShaderFormat::Vertex);
|
||||
const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, QShaderFormat::Vertex);
|
||||
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0, QShaderFormat::Vertex);
|
||||
|
||||
auto graph = QShaderGraph();
|
||||
|
||||
auto vertexPosition = createNode({
|
||||
createPort(QShaderNodePort::Output, "value")
|
||||
});
|
||||
vertexPosition.setParameter("name", "vertexPosition");
|
||||
vertexPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Input));
|
||||
vertexPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec4));
|
||||
|
||||
vertexPosition.addRule(es2, QShaderNode::Rule("",
|
||||
QByteArrayList() << "$qualifier highp $type $name;"));
|
||||
vertexPosition.addRule(gl2, QShaderNode::Rule("",
|
||||
QByteArrayList() << "$qualifier $type $name;"));
|
||||
vertexPosition.addRule(gl3, QShaderNode::Rule("",
|
||||
QByteArrayList() << "$qualifier $type $name;"));
|
||||
|
||||
graph.addNode(vertexPosition);
|
||||
|
||||
const auto gl2Code = (QByteArrayList() << "#version 110"
|
||||
<< ""
|
||||
<< "attribute vec4 vertexPosition;"
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto gl3Code = (QByteArrayList() << "#version 130"
|
||||
<< ""
|
||||
<< "in vec4 vertexPosition;"
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto gl4Code = (QByteArrayList() << "#version 400 core"
|
||||
<< ""
|
||||
<< "in vec4 vertexPosition;"
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto es2Code = (QByteArrayList() << "#version 100"
|
||||
<< ""
|
||||
<< "attribute highp vec4 vertexPosition;"
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
const auto es3Code = (QByteArrayList() << "#version 300 es"
|
||||
<< ""
|
||||
<< "in highp vec4 vertexPosition;"
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< "}"
|
||||
<< "").join("\n");
|
||||
|
||||
QTest::addRow("Attribute header substitution ES2") << graph << es2 << es2Code;
|
||||
QTest::addRow("Attribute header substitution ES3") << graph << es3 << es3Code;
|
||||
QTest::addRow("Attribute header substitution GL2") << graph << gl2 << gl2Code;
|
||||
QTest::addRow("Attribute header substitution GL3") << graph << gl3 << gl3Code;
|
||||
QTest::addRow("Attribute header substitution GL4") << graph << gl4 << gl4Code;
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums()
|
||||
{
|
||||
// GIVEN
|
||||
@ -806,9 +869,7 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " vec3 v1 = normalUniform;"
|
||||
<< " vec4 v0 = diffuseUniform;"
|
||||
<< " vec4 v2 = lightModel(v0, v1);"
|
||||
<< " vec4 v2 = lightModel(diffuseUniform, normalUniform);"
|
||||
<< " fragColor = v2;"
|
||||
<< "}"
|
||||
<< "";
|
||||
@ -831,10 +892,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " vec2 v0 = texCoord;"
|
||||
<< " vec3 v2 = texture2D(normalTexture, v0).rgb;"
|
||||
<< " vec4 v1 = diffuseUniform;"
|
||||
<< " vec4 v3 = lightModel(v1, v2);"
|
||||
<< " vec3 v2 = texture2D(normalTexture, texCoord).rgb;"
|
||||
<< " vec4 v3 = lightModel(diffuseUniform, v2);"
|
||||
<< " fragColor = v3;"
|
||||
<< "}"
|
||||
<< "";
|
||||
@ -857,10 +916,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " vec2 v0 = texCoord;"
|
||||
<< " vec3 v2 = normalUniform;"
|
||||
<< " vec4 v1 = texture2D(diffuseTexture, v0);"
|
||||
<< " vec4 v3 = lightModel(v1, v2);"
|
||||
<< " vec4 v1 = texture2D(diffuseTexture, texCoord);"
|
||||
<< " vec4 v3 = lightModel(v1, normalUniform);"
|
||||
<< " fragColor = v3;"
|
||||
<< "}"
|
||||
<< "";
|
||||
@ -883,9 +940,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " vec2 v0 = texCoord;"
|
||||
<< " vec3 v2 = texture2D(normalTexture, v0).rgb;"
|
||||
<< " vec4 v1 = texture2D(diffuseTexture, v0);"
|
||||
<< " vec3 v2 = texture2D(normalTexture, texCoord).rgb;"
|
||||
<< " vec4 v1 = texture2D(diffuseTexture, texCoord);"
|
||||
<< " vec4 v3 = lightModel(v1, v2);"
|
||||
<< " fragColor = v3;"
|
||||
<< "}"
|
||||
@ -894,6 +950,133 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QShaderGenerator::shouldUseGlobalVariableRatherThanTemporaries()
|
||||
{
|
||||
// GIVEN
|
||||
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
|
||||
|
||||
{
|
||||
// WHEN
|
||||
auto vertexPosition = createNode({
|
||||
createPort(QShaderNodePort::Output, "vertexPosition")
|
||||
});
|
||||
vertexPosition.addRule(gl4, QShaderNode::Rule("vec4 $vertexPosition = vertexPosition;",
|
||||
QByteArrayList() << "in vec4 vertexPosition;"));
|
||||
|
||||
auto fakeMultiPlyNoSpace = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeMultiPlyNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName*v11;"));
|
||||
|
||||
auto fakeMultiPlySpace = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeMultiPlySpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName * v11;"));
|
||||
|
||||
auto fakeJoinNoSpace = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeJoinNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz,$varName.w);"));
|
||||
|
||||
auto fakeJoinSpace = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeJoinSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz, $varName.w);"));
|
||||
|
||||
auto fakeAdd = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeAdd.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw + $varName;"));
|
||||
|
||||
auto fakeSub = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeSub.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw - $varName;"));
|
||||
|
||||
auto fakeDiv = createNode({
|
||||
createPort(QShaderNodePort::Input, "varName"),
|
||||
createPort(QShaderNodePort::Output, "out")
|
||||
});
|
||||
fakeDiv.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName / v0;"));
|
||||
|
||||
auto fragColor = createNode({
|
||||
createPort(QShaderNodePort::Input, "input1"),
|
||||
createPort(QShaderNodePort::Input, "input2"),
|
||||
createPort(QShaderNodePort::Input, "input3"),
|
||||
createPort(QShaderNodePort::Input, "input4"),
|
||||
createPort(QShaderNodePort::Input, "input5"),
|
||||
createPort(QShaderNodePort::Input, "input6"),
|
||||
createPort(QShaderNodePort::Input, "input7")
|
||||
});
|
||||
fragColor.addRule(gl4, QShaderNode::Rule("fragColor = $input1 + $input2 + $input3 + $input4 + $input5 + $input6 + $input7;",
|
||||
QByteArrayList() << "out vec4 fragColor;"));
|
||||
|
||||
const auto graph = [=] {
|
||||
auto res = QShaderGraph();
|
||||
|
||||
res.addNode(vertexPosition);
|
||||
res.addNode(fakeMultiPlyNoSpace);
|
||||
res.addNode(fakeMultiPlySpace);
|
||||
res.addNode(fakeJoinNoSpace);
|
||||
res.addNode(fakeJoinSpace);
|
||||
res.addNode(fakeAdd);
|
||||
res.addNode(fakeSub);
|
||||
res.addNode(fakeDiv);
|
||||
res.addNode(fragColor);
|
||||
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlyNoSpace.uuid(), "varName"));
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlySpace.uuid(), "varName"));
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinNoSpace.uuid(), "varName"));
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinSpace.uuid(), "varName"));
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeAdd.uuid(), "varName"));
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeSub.uuid(), "varName"));
|
||||
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeDiv.uuid(), "varName"));
|
||||
res.addEdge(createEdge(fakeMultiPlyNoSpace.uuid(), "out", fragColor.uuid(), "input1"));
|
||||
res.addEdge(createEdge(fakeMultiPlySpace.uuid(), "out", fragColor.uuid(), "input2"));
|
||||
res.addEdge(createEdge(fakeJoinNoSpace.uuid(), "out", fragColor.uuid(), "input3"));
|
||||
res.addEdge(createEdge(fakeJoinSpace.uuid(), "out", fragColor.uuid(), "input4"));
|
||||
res.addEdge(createEdge(fakeAdd.uuid(), "out", fragColor.uuid(), "input5"));
|
||||
res.addEdge(createEdge(fakeSub.uuid(), "out", fragColor.uuid(), "input6"));
|
||||
res.addEdge(createEdge(fakeDiv.uuid(), "out", fragColor.uuid(), "input7"));
|
||||
|
||||
return res;
|
||||
}();
|
||||
|
||||
auto generator = QShaderGenerator();
|
||||
generator.graph = graph;
|
||||
generator.format = gl4;
|
||||
|
||||
const auto code = generator.createShaderCode({"diffuseUniform", "normalUniform"});
|
||||
|
||||
// THEN
|
||||
const auto expected = QByteArrayList()
|
||||
<< "#version 400 core"
|
||||
<< ""
|
||||
<< "in vec4 vertexPosition;"
|
||||
<< "out vec4 fragColor;"
|
||||
<< ""
|
||||
<< "void main()"
|
||||
<< "{"
|
||||
<< " vec4 v7 = vertexPosition / vertexPosition;"
|
||||
<< " vec4 v6 = vertexPosition.xyzw - vertexPosition;"
|
||||
<< " vec4 v5 = vertexPosition.xyzw + vertexPosition;"
|
||||
<< " vec4 v4 = vec4(vertexPosition.xyz, vertexPosition.w);"
|
||||
<< " vec4 v3 = vec4(vertexPosition.xyz,vertexPosition.w);"
|
||||
<< " vec4 v2 = vertexPosition * v11;"
|
||||
<< " vec4 v1 = vertexPosition*v11;"
|
||||
<< " fragColor = v1 + v2 + v3 + v4 + v5 + v6 + v7;"
|
||||
<< "}"
|
||||
<< "";
|
||||
QCOMPARE(code, expected.join("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QShaderGenerator)
|
||||
|
||||
#include "tst_qshadergenerator.moc"
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
private slots:
|
||||
void init();
|
||||
void repolish();
|
||||
void repolish_without_crashing();
|
||||
void numinstances();
|
||||
void widgetsBeforeAppStyleSheet();
|
||||
void widgetsAfterAppStyleSheet();
|
||||
@ -367,6 +368,26 @@ void tst_QStyleSheetStyle::repolish()
|
||||
QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1));
|
||||
}
|
||||
|
||||
void tst_QStyleSheetStyle::repolish_without_crashing()
|
||||
{
|
||||
// This used to crash, QTBUG-69204
|
||||
QMainWindow w;
|
||||
QScopedPointer<QSplitter> splitter1(new QSplitter(w.centralWidget()));
|
||||
QScopedPointer<QSplitter> splitter2(new QSplitter);
|
||||
QScopedPointer<QSplitter> splitter3(new QSplitter);
|
||||
splitter2->addWidget(splitter3.data());
|
||||
|
||||
splitter2->setStyleSheet("color: red");
|
||||
QScopedPointer<QLabel> label(new QLabel);
|
||||
label->setTextFormat(Qt::RichText);
|
||||
splitter3->addWidget(label.data());
|
||||
label->setText("hey");
|
||||
|
||||
splitter1->addWidget(splitter2.data());
|
||||
w.show();
|
||||
QCOMPARE(COLOR(*label), QColor(Qt::red));
|
||||
}
|
||||
|
||||
void tst_QStyleSheetStyle::widgetStyle()
|
||||
{
|
||||
qApp->setStyleSheet(QString());
|
||||
|
Loading…
x
Reference in New Issue
Block a user