summaryrefslogtreecommitdiffstats
path: root/src/shadertools/qshaderbatchablerewriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shadertools/qshaderbatchablerewriter.cpp')
-rw-r--r--src/shadertools/qshaderbatchablerewriter.cpp223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/shadertools/qshaderbatchablerewriter.cpp b/src/shadertools/qshaderbatchablerewriter.cpp
new file mode 100644
index 0000000..72b369f
--- /dev/null
+++ b/src/shadertools/qshaderbatchablerewriter.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Shader Tools module
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshaderbatchablerewriter_p.h"
+
+// This is a slightly modified version of qsgshaderrewriter.cpp from
+// qtdeclarative/src/quick/scenegraph/coreapi. Here we insert an extra vertex
+// attribute (_qt_order) at location 7.
+
+QT_BEGIN_NAMESPACE
+
+namespace QShaderBatchableRewriter {
+
+struct Tokenizer {
+
+ enum Token {
+ Token_Void,
+ Token_OpenBrace,
+ Token_CloseBrace,
+ Token_SemiColon,
+ Token_Identifier,
+ Token_Macro,
+ Token_Unspecified,
+
+ Token_EOF
+ };
+
+ static const char *NAMES[];
+
+ void initialize(const QByteArray &input);
+ Token next();
+
+ const char *stream;
+ const char *pos;
+ const char *identifier;
+};
+
+const char *Tokenizer::NAMES[] = {
+ "Void",
+ "OpenBrace",
+ "CloseBrace",
+ "SemiColon",
+ "Identifier",
+ "Macro",
+ "Unspecified",
+ "EOF"
+};
+
+void Tokenizer::initialize(const QByteArray &input)
+{
+ stream = input.constData();
+ pos = input;
+ identifier = input;
+}
+
+Tokenizer::Token Tokenizer::next()
+{
+ while (*pos != 0) {
+ char c = *pos++;
+ switch (c) {
+ case '/':
+
+ if (*pos == '/') {
+ // '//' comment
+ ++pos;
+ while (*pos != 0 && *pos != '\n') ++pos;
+ if (*pos != 0) ++pos; // skip the newline
+
+ } else if (*pos == '*') {
+ // /* */ comment
+ ++pos;
+ while (*pos != 0 && *pos != '*' && pos[1] != '/') ++pos;
+ if (*pos != 0) pos += 2;
+ }
+ break;
+
+ case '#': {
+ while (*pos != 0) {
+ if (*pos == '\n') {
+ ++pos;
+ break;
+ } else if (*pos == '\\') {
+ ++pos;
+ while (*pos != 0 && (*pos == ' ' || *pos == '\t'))
+ ++pos;
+ if (*pos != 0 && (*pos == '\n' || (*pos == '\r' && pos[1] == '\n')))
+ pos+=2;
+ } else {
+ ++pos;
+ }
+ }
+ break;
+ }
+
+ case 'v': {
+ if (*pos == 'o' && pos[1] == 'i' && pos[2] == 'd') {
+ pos += 3;
+ return Token_Void;
+ }
+ Q_FALLTHROUGH();
+ }
+
+ case ';': return Token_SemiColon;
+ case 0: return Token_EOF;
+ case '{': return Token_OpenBrace;
+ case '}': return Token_CloseBrace;
+
+ case ' ':
+ case '\n':
+ case '\r': break;
+ default:
+ // Identifier...
+ if ((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ) || c == '_') {
+ identifier = pos - 1;
+ while (*pos != 0 && ((*pos >= 'a' && *pos <= 'z')
+ || (*pos >= 'A' && *pos <= 'Z')
+ || *pos == '_'
+ || (*pos >= '0' && *pos <= '9'))) {
+ ++pos;
+ }
+ return Token_Identifier;
+ } else {
+ return Token_Unspecified;
+ }
+ }
+ }
+
+ return Token_EOF;
+}
+
+QByteArray addZAdjustment(const QByteArray &input)
+{
+ Tokenizer tok;
+ tok.initialize(input);
+
+ Tokenizer::Token lt = tok.next();
+ Tokenizer::Token t = tok.next();
+
+ // First find "void main() { ... "
+ const char* voidPos = input.constData();
+ while (t != Tokenizer::Token_EOF) {
+ if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+ if (qstrncmp("main", tok.identifier, 4) == 0)
+ break;
+ }
+ voidPos = tok.pos - 4;
+ lt = t;
+ t = tok.next();
+ }
+
+ QByteArray result;
+ result.reserve(1024);
+ result += QByteArray::fromRawData(input.constData(), voidPos - input.constData());
+
+ result += QByteArrayLiteral("layout(location = 7) in float _qt_order;\n");
+
+ // Find first brace '{'
+ while (t != Tokenizer::Token_EOF && t != Tokenizer::Token_OpenBrace) t = tok.next();
+ int braceDepth = 1;
+ t = tok.next();
+
+ // Find matching brace and insert our code there...
+ while (t != Tokenizer::Token_EOF) {
+ switch (t) {
+ case Tokenizer::Token_CloseBrace:
+ braceDepth--;
+ if (braceDepth == 0) {
+ result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos);
+ result += QByteArrayLiteral(" gl_Position.z = _qt_order * gl_Position.w;\n");
+ result += QByteArray(tok.pos - 1);
+ return result;
+ }
+ break;
+ case Tokenizer::Token_OpenBrace:
+ ++braceDepth;
+ break;
+ default:
+ break;
+ }
+ t = tok.next();
+ }
+ return QByteArray();
+}
+
+} // namespace
+
+QT_END_NAMESPACE