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:
|
- MinGW:
|
||||||
* [QTBUG-4155] Added a suffix to debug mode pkgconfig files.
|
* [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:
|
- macOS:
|
||||||
* The drawableSize of Metal layers is no longer updated automatically on
|
* The drawableSize of Metal layers is no longer updated automatically on
|
||||||
|
@ -35,6 +35,7 @@ embed_translations {
|
|||||||
!isEmpty(QM_FILES_INSTALL_PATH) {
|
!isEmpty(QM_FILES_INSTALL_PATH) {
|
||||||
qm_files.files = $$QM_FILES
|
qm_files.files = $$QM_FILES
|
||||||
qm_files.path = $$QM_FILES_INSTALL_PATH
|
qm_files.path = $$QM_FILES_INSTALL_PATH
|
||||||
|
qm_files.CONFIG = no_check_exist
|
||||||
INSTALLS += qm_files
|
INSTALLS += qm_files
|
||||||
}
|
}
|
||||||
lrelease.CONFIG += target_predeps no_clean
|
lrelease.CONFIG += target_predeps no_clean
|
||||||
|
@ -99,7 +99,7 @@ qtConfig(textodfwriter) {
|
|||||||
|
|
||||||
qtConfig(textmarkdownreader) {
|
qtConfig(textmarkdownreader) {
|
||||||
qtConfig(system-textmarkdownreader) {
|
qtConfig(system-textmarkdownreader) {
|
||||||
QMAKE_USE += libmd4c
|
QMAKE_USE_PRIVATE += libmd4c
|
||||||
} else {
|
} else {
|
||||||
include($$PWD/../../3rdparty/md4c.pri)
|
include($$PWD/../../3rdparty/md4c.pri)
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include "qshaderlanguage_p.h"
|
#include "qshaderlanguage_p.h"
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg)
|
Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg)
|
||||||
@ -457,6 +459,13 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
|||||||
QByteArray line = node.rule(format).substitution;
|
QByteArray line = node.rule(format).substitution;
|
||||||
const QVector<QShaderNodePort> ports = node.ports();
|
const QVector<QShaderNodePort> ports = node.ports();
|
||||||
|
|
||||||
|
struct VariableReplacement {
|
||||||
|
QByteArray placeholder;
|
||||||
|
QByteArray variable;
|
||||||
|
};
|
||||||
|
|
||||||
|
QVector<VariableReplacement> variableReplacements;
|
||||||
|
|
||||||
// Generate temporary variable names vN
|
// Generate temporary variable names vN
|
||||||
for (const QShaderNodePort &port : ports) {
|
for (const QShaderNodePort &port : ports) {
|
||||||
const QString portName = port.name;
|
const QString portName = port.name;
|
||||||
@ -472,10 +481,37 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
|
|||||||
if (variableIndex < 0)
|
if (variableIndex < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
|
VariableReplacement replacement;
|
||||||
const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
|
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
|
// Substitute variable names by generated vN variable names
|
||||||
|
@ -123,6 +123,50 @@ namespace
|
|||||||
}
|
}
|
||||||
return targetStatement;
|
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
|
QUuid QShaderGraph::Statement::uuid() const noexcept
|
||||||
@ -248,6 +292,9 @@ QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(result.begin(), result.end());
|
std::reverse(result.begin(), result.end());
|
||||||
|
|
||||||
|
removeNodesWithUnboundInputs(result, enabledEdges);
|
||||||
|
|
||||||
return result;
|
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.
|
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
|
errorString() can be called to get a human readable description
|
||||||
of what happened.
|
of what happened.
|
||||||
|
|
||||||
|
@ -54,6 +54,15 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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.
|
Internal class QAlphaWidget.
|
||||||
|
|
||||||
@ -98,12 +107,9 @@ static QAlphaWidget* q_blend = nullptr;
|
|||||||
/*
|
/*
|
||||||
Constructs a QAlphaWidget.
|
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)
|
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
|
#ifndef Q_OS_WIN
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
#endif
|
#endif
|
||||||
@ -383,7 +389,7 @@ static QRollEffect* q_roll = nullptr;
|
|||||||
Construct a QRollEffect widget.
|
Construct a QRollEffect widget.
|
||||||
*/
|
*/
|
||||||
QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
|
QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
|
||||||
: QWidget(nullptr, f), orientation(orient)
|
: QWidget(effectParent(w), f), orientation(orient)
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
|
@ -198,6 +198,7 @@ private slots:
|
|||||||
void shouldGenerateDifferentCodeDependingOnActiveLayers();
|
void shouldGenerateDifferentCodeDependingOnActiveLayers();
|
||||||
void shouldUseGlobalVariableRatherThanTemporaries();
|
void shouldUseGlobalVariableRatherThanTemporaries();
|
||||||
void shouldGenerateTemporariesWisely();
|
void shouldGenerateTemporariesWisely();
|
||||||
|
void shouldHandlePortNamesPrefixingOneAnother();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QShaderGenerator::shouldHaveDefaultState()
|
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)
|
QTEST_MAIN(tst_QShaderGenerator)
|
||||||
|
|
||||||
#include "tst_qshadergenerator.moc"
|
#include "tst_qshadergenerator.moc"
|
||||||
|
@ -516,12 +516,9 @@ void tst_QShaderGraph::shouldHandleUnboundPortsDuringGraphSerialization()
|
|||||||
const auto statements = graph.createStatements();
|
const auto statements = graph.createStatements();
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
// Note that no edge leads to the unbound input
|
// Note that no statement has any unbound input
|
||||||
const auto expected = QVector<QShaderGraph::Statement>()
|
const auto expected = QVector<QShaderGraph::Statement>()
|
||||||
<< createStatement(input, {}, {0})
|
<< createStatement(input, {}, {0});
|
||||||
<< createStatement(function, {-1, 0, -1}, {2, 3, 4})
|
|
||||||
<< createStatement(unboundOutput, {-1}, {})
|
|
||||||
<< createStatement(output, {3}, {});
|
|
||||||
dumpStatementsIfNeeded(statements, expected);
|
dumpStatementsIfNeeded(statements, expected);
|
||||||
QCOMPARE(statements, expected);
|
QCOMPARE(statements, expected);
|
||||||
}
|
}
|
||||||
@ -568,9 +565,8 @@ void tst_QShaderGraph::shouldSurviveCyclesDuringGraphSerialization()
|
|||||||
const auto statements = graph.createStatements();
|
const auto statements = graph.createStatements();
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
// Obviously will lead to a compile failure later on since it cuts everything beyond the cycle
|
// The cycle is ignored
|
||||||
const auto expected = QVector<QShaderGraph::Statement>()
|
const auto expected = QVector<QShaderGraph::Statement>();
|
||||||
<< createStatement(output, {2}, {});
|
|
||||||
dumpStatementsIfNeeded(statements, expected);
|
dumpStatementsIfNeeded(statements, expected);
|
||||||
QCOMPARE(statements, expected);
|
QCOMPARE(statements, expected);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user