source: trunk/src/opengl/util/generator.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 15.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QFile>
43#include <QList>
44#include <QMap>
45#include <QPair>
46#include <QSet>
47#include <QString>
48#include <QTextStream>
49
50#include <QtDebug>
51#include <cstdlib>
52
53QT_BEGIN_NAMESPACE
54
55QT_USE_NAMESPACE
56
57#define TAB " "
58
59typedef QPair<QString, QString> QStringPair;
60
61QString readSourceFile(const QString &sourceFile, bool fragmentProgram = false)
62{
63 QFile file(sourceFile);
64
65 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
66 qDebug() << "Missing source file" << sourceFile;
67 exit(0);
68 }
69
70 QString source;
71
72 QTextStream in(&file);
73 while (!in.atEnd()) {
74 QString line = in.readLine();
75
76 if (fragmentProgram && line[0] == '#' && !line.startsWith("#var"))
77 continue;
78
79 if (fragmentProgram)
80 source.append(" \"");
81
82 source.append(line);
83
84 if (fragmentProgram)
85 source.append("\\n\"");
86
87 source.append('\n');
88 }
89
90 if (fragmentProgram)
91 source.append(" ;\n");
92
93 return source;
94}
95
96QList<QStringPair> readConf(const QString &confFile)
97{
98 QFile file(confFile);
99
100 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
101 qDebug() << "Missing file" << confFile;
102 exit(0);
103 }
104
105 QList<QStringPair> result;
106
107 QTextStream in(&file);
108 while (!in.atEnd()) {
109 QString line = in.readLine();
110
111 if (line.startsWith('#'))
112 continue;
113
114 QTextStream lineStream(&line);
115
116 QString enumerator;
117 QString sourceFile;
118
119 lineStream >> enumerator;
120
121 if (lineStream.atEnd()) {
122 qDebug() << "Error in file" << confFile << '(' << enumerator << ')';
123 exit(0);
124 }
125
126 lineStream >> sourceFile;
127
128 result << QStringPair(enumerator, readSourceFile(sourceFile));
129 }
130
131 return result;
132}
133
134QString compileSource(const QString &source)
135{
136 {
137 QFile tempSourceFile("__tmp__.glsl");
138 if (!tempSourceFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
139 qDebug() << "Failed opening __tmp__.glsl";
140 exit(0);
141 }
142
143 QTextStream out(&tempSourceFile);
144 out << source;
145 }
146
147 if (std::system("cgc -quiet -oglsl -profile arbfp1 __tmp__.glsl >__tmp__.frag") == -1) {
148 qDebug() << "Failed running cgc";
149 exit(0);
150 }
151
152 return readSourceFile("__tmp__.frag", true);
153}
154
155QString getWord(QString line, int word)
156{
157 QTextStream in(&line);
158
159 QString result;
160
161 for (int i = 0; i < word; ++i)
162 in >> result;
163
164 return result;
165}
166
167static int toInt(const QByteArray &str)
168{
169 int value = 0;
170
171 for (int i = 0; i < str.size(); ++i) {
172 if (str[i] < '0' || str[i] > '9')
173 break;
174
175 value *= 10;
176 value += (str[i] - '0');
177 }
178
179 return value;
180}
181QList<int> getLocations(const QSet<QString> &variables, QString source)
182{
183 QTextStream in(&source);
184
185 QMap<QString, int> locations;
186
187 foreach (QString variable, variables)
188 locations[variable] = -1;
189
190 while (!in.atEnd()) {
191 QString line = in.readLine().trimmed();
192
193 line = line.right(line.size() - 1);
194
195 if (line.startsWith("#var")) {
196 QByteArray temp;
197 QByteArray name;
198
199 QTextStream lineStream(&line);
200
201 lineStream >> temp >> temp >> name;
202
203 int location = -1;
204
205 while (!lineStream.atEnd()) {
206 lineStream >> temp;
207
208 if (temp.startsWith("c[")) {
209 location = toInt(temp.right(temp.size() - 2));
210 break;
211 }
212
213 if (temp == "texunit") {
214 lineStream >> temp;
215 location = toInt(temp);
216 break;
217 }
218 }
219
220 locations[name] = location;
221 }
222 }
223
224 QList<int> result;
225
226 foreach (QString variable, variables)
227 result << locations[variable];
228
229 return result;
230}
231
232// remove #var statements
233QString trimmed(QString source)
234{
235 QTextStream in(&source);
236
237 QString result;
238
239 while (!in.atEnd()) {
240 QString line = in.readLine();
241 if (!line.trimmed().startsWith("\"#"))
242 result += line + '\n';
243 }
244
245 return result;
246}
247
248void writeVariablesEnum(QTextStream &out, const char *name, const QSet<QString> &s)
249{
250 out << "enum " << name << " {";
251 QSet<QString>::const_iterator it = s.begin();
252 if (it != s.end()) {
253 out << "\n" TAB "VAR_" << it->toUpper();
254 for (++it; it != s.end(); ++it)
255 out << ",\n" TAB "VAR_" << it->toUpper();
256 }
257 out << "\n};\n\n";
258}
259
260void writeTypesEnum(QTextStream &out, const char *name, const QList<QStringPair> &s)
261{
262 out << "enum " << name << " {";
263 QList<QStringPair>::const_iterator it = s.begin();
264 if (it != s.end()) {
265 out << "\n" TAB << it->first;
266 for (++it; it != s.end(); ++it)
267 out << ",\n" TAB << it->first;
268 }
269 out << "\n};\n\n";
270}
271
272void writeIncludeFile(const QSet<QString> &variables,
273 const QList<QStringPair> &brushes,
274 const QList<QStringPair> &compositionModes,
275 const QList<QStringPair> &masks,
276 const QMap<QString, QMap<QString, QString> > &compiled)
277{
278 QFile includeFile("fragmentprograms_p.h");
279 if (!includeFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
280 qDebug() << "Failed opening fragmentprograms_p.h";
281 exit(0);
282 }
283
284 QTextStream out(&includeFile);
285
286 QLatin1String tab(TAB);
287
288 out << "/****************************************************************************\n"
289 "**\n"
290 "** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n"
291 "** All rights reserved.\n"
292 "** Contact: Nokia Corporation ([email protected])\n"
293 "**\n"
294 "** This file is part of the QtOpenGL module of the Qt Toolkit.\n"
295 "**\n"
296 "** $QT_BEGIN_LICENSE:LGPL$\n"
297 "** Commercial Usage\n"
298 "** Licensees holding valid Qt Commercial licenses may use this file in\n"
299 "** accordance with the Qt Commercial License Agreement provided with the\n"
300 "** Software or, alternatively, in accordance with the terms contained in\n"
301 "** a written agreement between you and Nokia.\n"
302 "**\n"
303 "** GNU Lesser General Public License Usage\n"
304 "** Alternatively, this file may be used under the terms of the GNU Lesser\n"
305 "** General Public License version 2.1 as published by the Free Software\n"
306 "** Foundation and appearing in the file LICENSE.LGPL included in the\n"
307 "** packaging of this file. Please review the following information to\n"
308 "** ensure the GNU Lesser General Public License version 2.1 requirements\n"
309 "** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n"
310 "**\n"
311 "** In addition, as a special exception, Nokia gives you certain additional\n"
312 "** rights. These rights are described in the Nokia Qt LGPL Exception\n"
313 "** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n"
314 "**\n"
315 "** GNU General Public License Usage\n"
316 "** Alternatively, this file may be used under the terms of the GNU\n"
317 "** General Public License version 3.0 as published by the Free Software\n"
318 "** Foundation and appearing in the file LICENSE.GPL included in the\n"
319 "** packaging of this file. Please review the following information to\n"
320 "** ensure the GNU General Public License version 3.0 requirements will be\n"
321 "** met: http://www.gnu.org/copyleft/gpl.html.\n"
322 "**\n"
323 "** If you have questions regarding the use of this file, please contact\n"
324 "** Nokia at [email protected].\n"
325 "** $QT_END_LICENSE$\n"
326 "**\n"
327 "****************************************************************************/\n"
328 "\n"
329 "#ifndef FRAGMENTPROGRAMS_P_H\n"
330 "#define FRAGMENTPROGRAMS_P_H\n"
331 "\n"
332 "//\n"
333 "// W A R N I N G\n"
334 "// -------------\n"
335 "//\n"
336 "// This file is not part of the Qt API. It exists purely as an\n"
337 "// implementation detail. This header file may change from version to\n"
338 "// version without notice, or even be removed.\n"
339 "//\n"
340 "// We mean it.\n"
341 "//\n"
342 "\n";
343
344 writeVariablesEnum(out, "FragmentVariable", variables);
345 writeTypesEnum(out, "FragmentBrushType", brushes);
346 writeTypesEnum(out, "FragmentCompositionModeType", compositionModes);
347 writeTypesEnum(out, "FragmentMaskType", masks);
348
349 out << "static const unsigned int num_fragment_variables = " << variables.size() << ";\n\n";
350 out << "static const unsigned int num_fragment_brushes = " << brushes.size() << ";\n";
351 out << "static const unsigned int num_fragment_composition_modes = " << compositionModes.size() << ";\n";
352 out << "static const unsigned int num_fragment_masks = " << masks.size() << ";\n\n";
353
354 foreach (QStringPair mask, masks) {
355 const QString compiledSource = compiled[mask.first]["MASK__"];
356
357 out << "static const char *FragmentProgram_" << mask.first << " =\n"
358 << trimmed(compiledSource)
359 << '\n';
360 }
361
362 foreach (QStringPair brush, brushes) {
363 foreach (QStringPair mode, compositionModes) {
364 const QString compiledSource = compiled[brush.first][mode.first];
365
366 out << "static const char *FragmentProgram_" << brush.first << '_' << mode.first << " =\n"
367 << trimmed(compiledSource)
368 << '\n';
369 }
370 }
371
372 out << "static const char *mask_fragment_program_sources[num_fragment_masks] = {\n";
373 foreach (QStringPair mask, masks)
374 out << tab << "FragmentProgram_" << mask.first << ",\n";
375 out << "};\n\n";
376
377 out << "static const char *painter_fragment_program_sources[num_fragment_brushes][num_fragment_composition_modes] = {\n";
378 foreach (QStringPair brush, brushes) {
379 out << tab << "{\n";
380
381 foreach (QStringPair mode, compositionModes)
382 out << tab << tab << "FragmentProgram_" << brush.first << '_' << mode.first << ",\n";
383
384 out << tab << "},\n";
385 }
386 out << "};\n\n";
387
388 out << "static int painter_variable_locations[num_fragment_brushes][num_fragment_composition_modes][num_fragment_variables] = {\n";
389 foreach (QStringPair brush, brushes) {
390 out << tab << "{\n";
391
392 foreach (QStringPair mode, compositionModes) {
393 out << tab << tab << "{ ";
394
395 QList<int> locations = getLocations(variables, compiled[brush.first][mode.first]);
396
397 foreach (int location, locations)
398 out << location << ", ";
399
400 out << "},\n";
401 }
402
403 out << tab << "},\n";
404 }
405 out << "};\n\n";
406
407 out << "static int mask_variable_locations[num_fragment_masks][num_fragment_variables] = {\n";
408 foreach (QStringPair mask, masks) {
409 out << tab << "{ ";
410
411 QList<int> locations = getLocations(variables, compiled[mask.first]["MASK__"]);
412
413 foreach (int location, locations)
414 out << location << ", ";
415
416 out << "},\n";
417 }
418 out << "};\n\n";
419 out << "#endif\n";
420}
421
422QList<QString> getVariables(QString program)
423{
424 QList<QString> result;
425
426 QTextStream in(&program);
427 while (!in.atEnd()) {
428 QString line = in.readLine();
429
430 if (line.startsWith("uniform")) {
431 QString word = getWord(line, 3);
432 result << word.left(word.size() - 1);
433 } else if (line.startsWith("#include")) {
434 QString file = getWord(line, 2);
435 result << getVariables(readSourceFile(file.mid(1, file.size() - 2)));
436 }
437 }
438
439 return result;
440}
441
442int main()
443{
444 QList<QStringPair> brushes = readConf(QLatin1String("brushes.conf"));
445 QList<QStringPair> compositionModes = readConf(QLatin1String("composition_modes.conf"));
446 QList<QStringPair> masks = readConf(QLatin1String("masks.conf"));
447
448 QString painterSource = readSourceFile("painter.glsl");
449 QString painterNoMaskSource = readSourceFile("painter_nomask.glsl");
450 QString fastPainterSource = readSourceFile("fast_painter.glsl");
451 QString brushPainterSource = readSourceFile("brush_painter.glsl");
452
453 QSet<QString> variables;
454
455 QList<QStringPair> programs[3] = { brushes, compositionModes, masks };
456
457 for (int i = 0; i < 3; ++i)
458 foreach (QStringPair value, programs[i])
459 variables += QSet<QString>::fromList(getVariables(value.second));
460
461 variables += QSet<QString>::fromList(getVariables(painterSource));
462 variables += QSet<QString>::fromList(getVariables(fastPainterSource));
463
464 QMap<QString, QMap<QString, QString> > compiled;
465
466 foreach (QStringPair brush, brushes) {
467 foreach (QStringPair mode, compositionModes) {
468 QString combinedSource = brush.second + mode.second + painterSource;
469 compiled[brush.first][mode.first] = compileSource(combinedSource);
470
471 combinedSource = brush.second + mode.second + painterNoMaskSource;
472 compiled[brush.first][mode.first + "_NOMASK"] = compileSource(combinedSource);
473 }
474
475 QString fastSource = brush.second + fastPainterSource;
476 QString brushSource = brush.second + brushPainterSource;
477
478 compiled[brush.first]["COMPOSITION_MODE_BLEND_MODE_MASK"] = compileSource(fastSource);
479 compiled[brush.first]["COMPOSITION_MODE_BLEND_MODE_NOMASK"] = compileSource(brushSource);
480 }
481
482 QList<QStringPair> temp;
483
484 foreach (QStringPair mode, compositionModes)
485 temp << QStringPair(mode.first + "_NOMASK", mode.second);
486
487 compositionModes += temp;
488
489 compositionModes << QStringPair("COMPOSITION_MODE_BLEND_MODE_MASK", "")
490 << QStringPair("COMPOSITION_MODE_BLEND_MODE_NOMASK", "");
491
492 foreach (QStringPair mask, masks)
493 compiled[mask.first]["MASK__"] = compileSource(mask.second);
494
495 writeIncludeFile(variables, brushes, compositionModes, masks, compiled);
496
497 return 0;
498}
499
500QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.