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

Change-Id: Iace12004afdfe765a3068dfcf6f1320c1123c539
This commit is contained in:
Qt Forward Merge Bot 2020-02-22 01:00:07 +01:00
commit 65cafea797
6 changed files with 175 additions and 29 deletions

View File

@ -532,7 +532,7 @@ struct Q_CORE_EXPORT QMetaObject
static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
&& QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
&& !std::is_convertible<Func, const char*>::value, bool>::type
invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
invokeMethod(QObject *context, Func function, decltype(function()) *ret)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),

View File

@ -7519,6 +7519,8 @@ float QString::toFloat(bool *ok) const
The formatting always uses QLocale::C, i.e., English/UnitedStates.
To get a localized string representation of a number, use
QLocale::toString() with the appropriate locale.
\sa number()
*/
/*! \fn QString &QString::setNum(uint n, int base)
@ -7576,6 +7578,8 @@ QString &QString::setNum(qulonglong n, int base)
The formatting always uses QLocale::C, i.e., English/UnitedStates.
To get a localized string representation of a number, use
QLocale::toString() with the appropriate locale.
\sa number()
*/
QString &QString::setNum(double n, char f, int prec)
@ -7594,6 +7598,8 @@ QString &QString::setNum(double n, char f, int prec)
The formatting always uses QLocale::C, i.e., English/UnitedStates.
To get a localized string representation of a number, use
QLocale::toString() with the appropriate locale.
\sa number()
*/

View File

@ -904,6 +904,9 @@ int QTextDocument::lineCount() const
Returns the number of characters of this document.
\note As a QTextDocument always contains at least one
QChar::ParagraphSeparator, this method will return at least 1.
\sa blockCount(), characterAt()
*/
int QTextDocument::characterCount() const

View File

@ -346,10 +346,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
code << QByteArrayLiteral("void main()");
code << QByteArrayLiteral("{");
const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*((?:\\w+\\(.*\\))|(?:\\w+)).*;$"));
const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("^(.*\\s+(v\\d+))\\s*=\\s*(.*);$"));
const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);"));
const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*"));
const QRegularExpression outputToTemporaryAssignmentRegExp(QStringLiteral("^\\s*(\\w+)\\s*=\\s*(.*);$"));
const QRegularExpression statementRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);"));
struct Variable;
@ -517,14 +516,29 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
// Substitute variable names by generated vN variable names
const QByteArray substitutionedLine = replaceParameters(line, node, format);
Variable *v = nullptr;
QRegularExpressionMatchIterator matches;
switch (node.type()) {
// Record name of temporary variable that possibly references a global input
// We will replace the temporary variables by the matching global variables later
case QShaderNode::Input: {
const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine));
if (match.hasMatch()) {
case QShaderNode::Input:
case QShaderNode::Output:
matches = statementRegExp.globalMatch(QString::fromUtf8(substitutionedLine));
break;
case QShaderNode::Function:
matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine));
break;
case QShaderNode::Invalid:
break;
}
while (matches.hasNext()) {
QRegularExpressionMatch match = matches.next();
Variable *v = nullptr;
switch (node.type()) {
// Record name of temporary variable that possibly references a global input
// We will replace the temporary variables by the matching global variables later
case QShaderNode::Input: {
const QString localVariable = match.captured(1);
const QString globalVariable = match.captured(2);
@ -535,13 +549,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
Assignment assignment;
assignment.expression = globalVariable;
v->assignment = assignment;
break;
}
break;
}
case QShaderNode::Function: {
const QRegularExpressionMatch match = temporaryVariableToAssignmentRegExp.match(QString::fromUtf8(substitutionedLine));
if (match.hasMatch()) {
case QShaderNode::Function: {
const QString localVariableDeclaration = match.captured(1);
const QString localVariableName = match.captured(2);
const QString assignmentContent = match.captured(3);
@ -554,13 +565,10 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
// Find variables that may be referenced in the assignment
gatherTemporaryVariablesFromAssignment(v, assignmentContent);
break;
}
break;
}
case QShaderNode::Output: {
const QRegularExpressionMatch match = outputToTemporaryAssignmentRegExp.match(QString::fromUtf8(substitutionedLine));
if (match.hasMatch()) {
case QShaderNode::Output: {
const QString outputDeclaration = match.captured(1);
const QString assignmentContent = match.captured(2);
@ -575,17 +583,17 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
// Find variables that may be referenced in the assignment
gatherTemporaryVariablesFromAssignment(v, assignmentContent);
break;
}
case QShaderNode::Invalid:
break;
}
break;
}
case QShaderNode::Invalid:
break;
}
LineContent lineContent;
lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine);
lineContent.var = v;
lines << lineContent;
LineContent lineContent;
lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine);
lineContent.var = v;
lines << lineContent;
}
}
// Go through all lines

View File

@ -101,7 +101,13 @@ Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option)
if (option)
return option->fontMetrics.fontDpi();
// Fall back to historical Qt behavior: hardocded 72 DPI on mac,
// primary screen DPI on other platforms.
#ifdef Q_OS_DARWIN
return qstyleBaseDpi;
#else
return qt_defaultDpiX();
#endif
}
Q_WIDGETS_EXPORT qreal dpiScaled(qreal value, qreal dpi)

View File

@ -199,6 +199,8 @@ private slots:
void shouldUseGlobalVariableRatherThanTemporaries();
void shouldGenerateTemporariesWisely();
void shouldHandlePortNamesPrefixingOneAnother();
void shouldHandleNodesWithMultipleOutputPorts();
void shouldHandleExpressionsInInputNodes();
};
void tst_QShaderGenerator::shouldHaveDefaultState()
@ -1299,6 +1301,127 @@ void tst_QShaderGenerator::shouldHandlePortNamesPrefixingOneAnother()
QCOMPARE(code, expected.join("\n"));
}
void tst_QShaderGenerator::shouldHandleNodesWithMultipleOutputPorts()
{
// GIVEN
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
auto input = createNode({
createPort(QShaderNodePort::Output, "output0"),
createPort(QShaderNodePort::Output, "output1")
});
input.addRule(gl4, QShaderNode::Rule("vec4 $output0 = globalIn0;"
"float $output1 = globalIn1;",
QByteArrayList() << "in vec4 globalIn0;" << "in float globalIn1;"));
auto function = createNode({
createPort(QShaderNodePort::Input, "input0"),
createPort(QShaderNodePort::Input, "input1"),
createPort(QShaderNodePort::Output, "output0"),
createPort(QShaderNodePort::Output, "output1")
});
function.addRule(gl4, QShaderNode::Rule("vec4 $output0 = $input0;"
"float $output1 = $input1;"));
auto output = createNode({
createPort(QShaderNodePort::Input, "input0"),
createPort(QShaderNodePort::Input, "input1")
});
output.addRule(gl4, QShaderNode::Rule("globalOut0 = $input0;"
"globalOut1 = $input1;",
QByteArrayList() << "out vec4 globalOut0;" << "out float globalOut1;"));
// WHEN
const auto graph = [=] {
auto res = QShaderGraph();
res.addNode(input);
res.addNode(function);
res.addNode(output);
res.addEdge(createEdge(input.uuid(), "output0", function.uuid(), "input0"));
res.addEdge(createEdge(input.uuid(), "output1", function.uuid(), "input1"));
res.addEdge(createEdge(function.uuid(), "output0", output.uuid(), "input0"));
res.addEdge(createEdge(function.uuid(), "output1", output.uuid(), "input1"));
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 globalIn0;"
<< "in float globalIn1;"
<< "out vec4 globalOut0;"
<< "out float globalOut1;"
<< ""
<< "void main()"
<< "{"
<< " globalOut0 = globalIn0;"
<< " globalOut1 = globalIn1;"
<< "}"
<< "";
QCOMPARE(code, expected.join("\n"));
}
void tst_QShaderGenerator::shouldHandleExpressionsInInputNodes()
{
// GIVEN
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
auto input = createNode({
createPort(QShaderNodePort::Output, "output")
});
input.addRule(gl4, QShaderNode::Rule("float $output = 3 + 4;"));
auto output = createNode({
createPort(QShaderNodePort::Input, "input")
});
output.addRule(gl4, QShaderNode::Rule("globalOut = $input;",
QByteArrayList() << "out float globalOut;"));
// WHEN
const auto graph = [=] {
auto res = QShaderGraph();
res.addNode(input);
res.addNode(output);
res.addEdge(createEdge(input.uuid(), "output", output.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"
<< ""
<< "out float globalOut;"
<< ""
<< "void main()"
<< "{"
<< " globalOut = 3 + 4;"
<< "}"
<< "";
QCOMPARE(code, expected.join("\n"));
}
QTEST_MAIN(tst_QShaderGenerator)
#include "tst_qshadergenerator.moc"