Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"

This commit is contained in:
Friedemann Kleint 2020-02-20 08:34:46 +01:00
commit e0225d8bee
9 changed files with 177 additions and 18 deletions

3
dist/changes-5.14.0 vendored
View File

@ -476,6 +476,9 @@ information about a particular change.
- MinGW:
* [QTBUG-4155] Added a suffix to debug mode pkgconfig files.
* MinGW does not built with -debug-and-release mode anymore.
Instead, the binaries are built with -release -force-debug-info
-separate-debug-info.
- macOS:
* The drawableSize of Metal layers is no longer updated automatically on

View File

@ -35,6 +35,7 @@ embed_translations {
!isEmpty(QM_FILES_INSTALL_PATH) {
qm_files.files = $$QM_FILES
qm_files.path = $$QM_FILES_INSTALL_PATH
qm_files.CONFIG = no_check_exist
INSTALLS += qm_files
}
lrelease.CONFIG += target_predeps no_clean

View File

@ -99,7 +99,7 @@ qtConfig(textodfwriter) {
qtConfig(textmarkdownreader) {
qtConfig(system-textmarkdownreader) {
QMAKE_USE += libmd4c
QMAKE_USE_PRIVATE += libmd4c
} else {
include($$PWD/../../3rdparty/md4c.pri)
}

View File

@ -42,6 +42,8 @@
#include "qshaderlanguage_p.h"
#include <QRegularExpression>
#include <cctype>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg)
@ -457,6 +459,13 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
QByteArray line = node.rule(format).substitution;
const QVector<QShaderNodePort> ports = node.ports();
struct VariableReplacement {
QByteArray placeholder;
QByteArray variable;
};
QVector<VariableReplacement> variableReplacements;
// Generate temporary variable names vN
for (const QShaderNodePort &port : ports) {
const QString portName = port.name;
@ -472,10 +481,37 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
if (variableIndex < 0)
continue;
const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
VariableReplacement replacement;
replacement.placeholder = QByteArrayLiteral("$") + portName.toUtf8();
replacement.variable = QByteArrayLiteral("v") + QByteArray::number(variableIndex);
line.replace(placeholder, variable);
variableReplacements.append(std::move(replacement));
}
int begin = 0;
while ((begin = line.indexOf('$', begin)) != -1) {
int end = begin + 1;
char endChar = line.at(end);
const int size = line.size();
while (end < size && (std::isalnum(endChar) || endChar == '_')) {
++end;
endChar = line.at(end);
}
const int placeholderLength = end - begin;
const QByteArray variableName = line.mid(begin, placeholderLength);
const auto replacementIt = std::find_if(variableReplacements.cbegin(), variableReplacements.cend(),
[&variableName](const VariableReplacement &replacement) {
return variableName == replacement.placeholder;
});
if (replacementIt != variableReplacements.cend()) {
line.replace(begin, placeholderLength, replacementIt->variable);
begin += replacementIt->variable.length();
} else {
begin = end;
}
}
// Substitute variable names by generated vN variable names

View File

@ -123,6 +123,50 @@ namespace
}
return targetStatement;
}
void removeNodesWithUnboundInputs(QVector<QShaderGraph::Statement> &statements,
const QVector<QShaderGraph::Edge> &allEdges)
{
// A node is invalid if any of its input ports is disconected
// or connected to the output port of another invalid node.
// Keeps track of the edges from the nodes we know to be valid
// to unvisited nodes
auto currentEdges = QVector<QShaderGraph::Edge>();
statements.erase(std::remove_if(statements.begin(),
statements.end(),
[&currentEdges, &allEdges] (const QShaderGraph::Statement &statement) {
const QShaderNode &node = statement.node;
const QVector<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, node.uuid());
const QVector<QShaderNodePort> ports = node.ports();
bool allInputsConnected = true;
for (const QShaderNodePort &port : node.ports()) {
if (port.direction == QShaderNodePort::Output)
continue;
const auto edgeIt = std::find_if(outgoing.cbegin(),
outgoing.cend(),
[&port] (const QShaderGraph::Edge &edge) {
return edge.targetPortName == port.name;
});
if (edgeIt != outgoing.cend())
currentEdges.removeAll(*edgeIt);
else
allInputsConnected = false;
}
if (allInputsConnected) {
const QVector<QShaderGraph::Edge> incoming = incomingEdges(allEdges, node.uuid());
currentEdges.append(incoming);
}
return !allInputsConnected;
}),
statements.end());
}
}
QUuid QShaderGraph::Statement::uuid() const noexcept
@ -248,6 +292,9 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringLis
}
std::reverse(result.begin(), result.end());
removeNodesWithUnboundInputs(result, enabledEdges);
return result;
}

View File

@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
On Windows this is a named pipe and on Unix this is a local domain socket.
If an error occurs, socketError() returns the type of error, and
If an error occurs, error() returns the type of error, and
errorString() can be called to get a human readable description
of what happened.

View File

@ -54,6 +54,15 @@
QT_BEGIN_NAMESPACE
static QWidget *effectParent(const QWidget* w)
{
const int screenNumber = w ? QGuiApplication::screens().indexOf(w->screen()) : 0;
QT_WARNING_PUSH // ### Qt 6: Find a replacement for QDesktopWidget::screen()
QT_WARNING_DISABLE_DEPRECATED
return QApplication::desktop()->screen(screenNumber);
QT_WARNING_POP
}
/*
Internal class QAlphaWidget.
@ -98,12 +107,9 @@ static QAlphaWidget* q_blend = nullptr;
/*
Constructs a QAlphaWidget.
*/
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED // ### Qt 6: Find a replacement for QDesktopWidget::screen()
QAlphaWidget::QAlphaWidget(QWidget* w, Qt::WindowFlags f)
: QWidget(QApplication::desktop()->screen(QDesktopWidgetPrivate::screenNumber(w)), f)
: QWidget(effectParent(w), f)
{
QT_WARNING_POP
#ifndef Q_OS_WIN
setEnabled(false);
#endif
@ -383,7 +389,7 @@ static QRollEffect* q_roll = nullptr;
Construct a QRollEffect widget.
*/
QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
: QWidget(nullptr, f), orientation(orient)
: QWidget(effectParent(w), f), orientation(orient)
{
#ifndef Q_OS_WIN
setEnabled(false);

View File

@ -198,6 +198,7 @@ private slots:
void shouldGenerateDifferentCodeDependingOnActiveLayers();
void shouldUseGlobalVariableRatherThanTemporaries();
void shouldGenerateTemporariesWisely();
void shouldHandlePortNamesPrefixingOneAnother();
};
void tst_QShaderGenerator::shouldHaveDefaultState()
@ -1229,6 +1230,75 @@ void tst_QShaderGenerator::shouldGenerateTemporariesWisely()
}
}
void tst_QShaderGenerator::shouldHandlePortNamesPrefixingOneAnother()
{
// GIVEN
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
auto color1 = createNode({
createPort(QShaderNodePort::Output, "output")
});
color1.addRule(gl4, QShaderNode::Rule("vec4 $output = color1;",
QByteArrayList() << "in vec4 color1;"));
auto color2 = createNode({
createPort(QShaderNodePort::Output, "output")
});
color2.addRule(gl4, QShaderNode::Rule("vec4 $output = color2;",
QByteArrayList() << "in vec4 color2;"));
auto addColor = createNode({
createPort(QShaderNodePort::Output, "color"),
createPort(QShaderNodePort::Input, "color1"),
createPort(QShaderNodePort::Input, "color2"),
});
addColor.addRule(gl4, QShaderNode::Rule("vec4 $color = $color1 + $color2;"));
auto shaderOutput = createNode({
createPort(QShaderNodePort::Input, "input")
});
shaderOutput.addRule(gl4, QShaderNode::Rule("shaderOutput = $input;",
QByteArrayList() << "out vec4 shaderOutput;"));
// WHEN
const auto graph = [=] {
auto res = QShaderGraph();
res.addNode(color1);
res.addNode(color2);
res.addNode(addColor);
res.addNode(shaderOutput);
res.addEdge(createEdge(color1.uuid(), "output", addColor.uuid(), "color1"));
res.addEdge(createEdge(color2.uuid(), "output", addColor.uuid(), "color2"));
res.addEdge(createEdge(addColor.uuid(), "color", shaderOutput.uuid(), "input"));
return res;
}();
auto generator = QShaderGenerator();
generator.graph = graph;
generator.format = gl4;
const auto code = generator.createShaderCode();
// THEN
const auto expected = QByteArrayList()
<< "#version 400 core"
<< ""
<< "in vec4 color1;"
<< "in vec4 color2;"
<< "out vec4 shaderOutput;"
<< ""
<< "void main()"
<< "{"
<< " shaderOutput = ((color1 + color2));"
<< "}"
<< "";
QCOMPARE(code, expected.join("\n"));
}
QTEST_MAIN(tst_QShaderGenerator)
#include "tst_qshadergenerator.moc"

View File

@ -516,12 +516,9 @@ void tst_QShaderGraph::shouldHandleUnboundPortsDuringGraphSerialization()
const auto statements = graph.createStatements();
// THEN
// Note that no edge leads to the unbound input
// Note that no statement has any unbound input
const auto expected = QVector<QShaderGraph::Statement>()
<< createStatement(input, {}, {0})
<< createStatement(function, {-1, 0, -1}, {2, 3, 4})
<< createStatement(unboundOutput, {-1}, {})
<< createStatement(output, {3}, {});
<< createStatement(input, {}, {0});
dumpStatementsIfNeeded(statements, expected);
QCOMPARE(statements, expected);
}
@ -568,9 +565,8 @@ void tst_QShaderGraph::shouldSurviveCyclesDuringGraphSerialization()
const auto statements = graph.createStatements();
// THEN
// Obviously will lead to a compile failure later on since it cuts everything beyond the cycle
const auto expected = QVector<QShaderGraph::Statement>()
<< createStatement(output, {2}, {});
// The cycle is ignored
const auto expected = QVector<QShaderGraph::Statement>();
dumpStatementsIfNeeded(statements, expected);
QCOMPARE(statements, expected);
}