Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
This commit is contained in:
commit
e0225d8bee
3
dist/changes-5.14.0
vendored
3
dist/changes-5.14.0
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -99,7 +99,7 @@ qtConfig(textodfwriter) {
|
||||
|
||||
qtConfig(textmarkdownreader) {
|
||||
qtConfig(system-textmarkdownreader) {
|
||||
QMAKE_USE += libmd4c
|
||||
QMAKE_USE_PRIVATE += libmd4c
|
||||
} else {
|
||||
include($$PWD/../../3rdparty/md4c.pri)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
[¤tEdges, &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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user