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

Last change on this file since 82 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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