source: trunk/src/opengl/gl2paintengineex/qglpexshadermanager.cpp@ 5

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

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

File size: 17.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
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 qt-sales@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qglpexshadermanager_p.h"
43
44#include "glgc_shader_source.h"
45
46QGLPEXShaderManager::QGLPEXShaderManager(const QGLContext* context)
47{
48 ctx = const_cast<QGLContext*>(context);
49
50 defaultVertexShader= new QGLShader(QGLShader::VertexShader, context);
51 defaultVertexShader->addSource(QLatin1String(qglslDefaultVertexShader));
52 if (!defaultVertexShader->compile())
53 qWarning() << "Default vertex shader failed to compile: " << defaultVertexShader->log();
54
55 noBrushShader = new QGLShader(QGLShader::FragmentShader, context);
56 noBrushShader->addSource(QLatin1String(qglslFragmentShaderMain));
57 noBrushShader->addSource(QLatin1String(qglslNoBrushFragmentShader));
58 if (!noBrushShader->compile())
59 qWarning() << "No brush shader failed to compile:" << noBrushShader->log();
60
61
62 // Create a program for noBrush:
63 QGLShaderProgram* noBrushProg = new QGLShaderProgram(ctx);
64 noBrushProg->addShader(defaultVertexShader);
65 noBrushProg->addShader(noBrushShader);
66 if (!noBrushProg->link())
67 qWarning() << "NoBrush shader program failed to link:" << noBrushProg->log();
68
69 // Add noBrush Program to cache:
70 QGLCachedShaderProg cachedProg;
71 cachedProg.vertexShader = defaultVertexShader;
72 cachedProg.brushShader = noBrushShader;
73 cachedProg.compositionShader = 0;
74 cachedProg.shader = noBrushProg;
75 cachedPrograms.append(cachedProg);
76
77
78 // Set state
79 useGlobalOpacity = true;
80 currentBrushStyle = Qt::NoBrush;
81 currentTransformType = FullTransform;
82 shaderProgNeedsChanging = false;
83 activeProgram = noBrushProg;
84
85 solidBrushShader = 0;
86
87 conicalBrushVertexShader = 0;
88 conicalBrushFragmentShader = 0;
89
90 radialBrushVertexShader = 0;
91 radialBrushFragmentShader = 0;
92
93 linearBrushVertexShader = 0;
94 linearBrushFragmentShader = 0;
95
96 patternBrushVertexShader = 0;
97 patternBrushFragmentShader = 0;
98
99 textureBrushFragmentShader = 0;
100 textureBrushVertexShader = 0;
101
102 simpleFragmentShader = 0;
103 simpleShaderProgram = 0;
104
105 imageVertexShader = 0;
106 imageFragmentShader = 0;
107 imageShaderProgram = 0;
108
109 textVertexShader = 0;
110 textFragmentShader = 0;
111 textShaderProgram = 0;
112}
113
114QGLPEXShaderManager::~QGLPEXShaderManager()
115{
116 delete defaultVertexShader;
117 delete imageVertexShader;
118 delete imageFragmentShader;
119 delete imageShaderProgram;
120 delete textVertexShader;
121 delete textFragmentShader;
122 delete textShaderProgram;
123 delete noBrushShader;
124 delete solidBrushShader;
125
126 delete conicalBrushVertexShader;
127 delete conicalBrushFragmentShader;
128
129 delete radialBrushVertexShader;
130 delete radialBrushFragmentShader;
131
132 delete linearBrushFragmentShader;
133 delete linearBrushVertexShader;
134
135 delete patternBrushFragmentShader;
136 delete patternBrushVertexShader;
137
138 delete textureBrushFragmentShader;
139 delete textureBrushVertexShader;
140
141 delete simpleFragmentShader;
142 delete simpleShaderProgram;
143}
144
145void QGLPEXShaderManager::setUseGlobalOpacity(bool value)
146{
147 if (value != useGlobalOpacity)
148 shaderProgNeedsChanging = true;
149
150 useGlobalOpacity = value;
151}
152
153void QGLPEXShaderManager::setBrushStyle(Qt::BrushStyle style)
154{
155 if (currentBrushStyle != style)
156 shaderProgNeedsChanging = true;
157
158 currentBrushStyle = style;
159}
160
161void QGLPEXShaderManager::setAffineOnlyBrushTransform(bool value)
162{
163 Q_UNUSED(value);
164 // TODO
165}
166
167bool QGLPEXShaderManager::useCorrectShaderProg()
168{
169 if (!shaderProgNeedsChanging) {
170 activeProgram->use();
171 return false;
172 }
173
174 const char* fragmentShaderMainSrc = qglslFragmentShaderMain;
175 QGLShader* vertexShader = defaultVertexShader;
176 QGLShader* fragmentShader = noBrushShader;
177
178 // Make sure we compile up the correct brush shader
179 switch (currentBrushStyle) {
180 case Qt::NoBrush:
181 break;
182 case Qt::SolidPattern:
183 if (!solidBrushShader) {
184 qDebug("Compiling qglslSolidBrushFragmentShader");
185 solidBrushShader = new QGLShader(QGLShader::FragmentShader, ctx);
186 solidBrushShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain));
187 solidBrushShader->addSource(QLatin1String(qglslSolidBrushFragmentShader));
188 if (!solidBrushShader->compile())
189 qWarning() << "qglslSolidBrush failed to compile:" << solidBrushShader->log();
190 }
191 fragmentShader = solidBrushShader;
192 break;
193 case Qt::TexturePattern:
194 if (!textureBrushVertexShader) {
195 qDebug("Compiling qglslTextureBrushVertexShader");
196 textureBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
197 textureBrushVertexShader->addSource(QLatin1String(qglslTextureBrushVertexShader));
198 if (!textureBrushVertexShader->compile()) {
199 qWarning() << "qglslTextureBrushVertexShader failed to compile: "
200 << textureBrushVertexShader->log();
201 }
202 }
203 vertexShader = textureBrushVertexShader;
204
205 if (!textureBrushFragmentShader) {
206 qDebug("Compiling qglslTextureBrushFragmentShader");
207 textureBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
208 textureBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
209 textureBrushFragmentShader->addSource(QLatin1String(qglslTextureBrushFragmentShader));
210 if (!textureBrushFragmentShader->compile()) {
211 qWarning() << "qglslTextureBrushFragmentShader failed to compile:"
212 << textureBrushFragmentShader->log();
213 }
214 }
215 fragmentShader = textureBrushFragmentShader;
216 break;
217 case Qt::LinearGradientPattern:
218 if (!linearBrushVertexShader) {
219 qDebug("Compiling qglslLinearGradientBrushVertexShader");
220 linearBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
221 linearBrushVertexShader->addSource(QLatin1String(qglslLinearGradientBrushVertexShader));
222 if (!linearBrushVertexShader->compile()) {
223 qWarning() << "qglslLinearGradientBrushVertexShader failed to compile: "
224 << linearBrushVertexShader->log();
225 }
226 }
227 vertexShader = linearBrushVertexShader;
228
229 if (!linearBrushFragmentShader) {
230 qDebug("Compiling qglslLinearGradientBrushFragmentShader");
231 linearBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
232 linearBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
233 linearBrushFragmentShader->addSource(QLatin1String(qglslLinearGradientBrushFragmentShader));
234 if (!linearBrushFragmentShader->compile()) {
235 qWarning() << "qglslLinearGradientBrushFragmentShader failed to compile:"
236 << linearBrushFragmentShader->log();
237 }
238 }
239 fragmentShader = linearBrushFragmentShader;
240 break;
241 case Qt::RadialGradientPattern:
242 if (!radialBrushVertexShader) {
243 qDebug("Compiling qglslRadialGradientBrushVertexShader");
244 radialBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
245 radialBrushVertexShader->addSource(QLatin1String(qglslRadialGradientBrushVertexShader));
246 if (!radialBrushVertexShader->compile()) {
247 qWarning() << "qglslRadialGradientBrushVertexShader failed to compile: "
248 << radialBrushVertexShader->log();
249 }
250 }
251 vertexShader = radialBrushVertexShader;
252
253 if (!radialBrushFragmentShader) {
254 qDebug("Compiling qglslRadialGradientBrushFragmentShader");
255 radialBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
256 radialBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
257 radialBrushFragmentShader->addSource(QLatin1String(qglslRadialGradientBrushFragmentShader));
258 if (!radialBrushFragmentShader->compile()) {
259 qWarning() << "qglslRadialGradientBrushFragmentShader failed to compile:"
260 << radialBrushFragmentShader->log();
261 }
262 }
263 fragmentShader = radialBrushFragmentShader;
264 break;
265 case Qt::ConicalGradientPattern:
266 // FIXME: We currently use the same vertex shader as radial brush
267 if (!conicalBrushVertexShader) {
268 qDebug("Compiling qglslConicalGradientBrushVertexShader");
269 conicalBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
270 conicalBrushVertexShader->addSource(QLatin1String(qglslConicalGradientBrushVertexShader));
271 if (!conicalBrushVertexShader->compile()) {
272 qWarning() << "qglslConicalGradientBrushVertexShader failed to compile: "
273 << conicalBrushVertexShader->log();
274 }
275 }
276 vertexShader = conicalBrushVertexShader;
277
278 if (!conicalBrushFragmentShader) {
279 qDebug("Compiling qglslConicalGradientBrushFragmentShader");
280 conicalBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
281 conicalBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
282 conicalBrushFragmentShader->addSource(QLatin1String(qglslConicalGradientBrushFragmentShader));
283 if (!conicalBrushFragmentShader->compile()) {
284 qWarning() << "qglslConicalGradientBrushFragmentShader failed to compile:"
285 << conicalBrushFragmentShader->log();
286 }
287 }
288 fragmentShader = conicalBrushFragmentShader;
289 break;
290 case Qt::Dense1Pattern:
291 case Qt::Dense2Pattern:
292 case Qt::Dense3Pattern:
293 case Qt::Dense4Pattern:
294 case Qt::Dense5Pattern:
295 case Qt::Dense6Pattern:
296 case Qt::Dense7Pattern:
297 case Qt::HorPattern:
298 case Qt::VerPattern:
299 case Qt::CrossPattern:
300 case Qt::BDiagPattern:
301 case Qt::FDiagPattern:
302 case Qt::DiagCrossPattern:
303 if (!patternBrushVertexShader) {
304 qDebug("Compiling qglslPatternBrushVertexShader");
305 patternBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
306 patternBrushVertexShader->addSource(QLatin1String(qglslPatternBrushVertexShader));
307 if (!patternBrushVertexShader->compile()) {
308 qWarning() << "qglslPatternBrushVertexShader failed to compile: "
309 << patternBrushVertexShader->log();
310 }
311 }
312 vertexShader = patternBrushVertexShader;
313
314 if (!patternBrushFragmentShader) {
315 qDebug("Compiling qglslPatternBrushFragmentShader");
316 patternBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
317 patternBrushFragmentShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain));
318 patternBrushFragmentShader->addSource(QLatin1String(qglslPatternBrushFragmentShader));
319 if (!patternBrushFragmentShader->compile()) {
320 qWarning() << "qglslPatternBrushFragmentShader failed to compile:"
321 << patternBrushFragmentShader->log();
322 }
323 }
324 fragmentShader = patternBrushFragmentShader;
325 break;
326 default:
327 qWarning("Unimplemented brush style (%d)", currentBrushStyle);
328 }
329
330 // Now newBrushShader is set correctly, check to see if we already have the program
331 // already linked and ready to go in the cache:
332 bool foundProgram = false;
333 foreach (QGLCachedShaderProg cachedProg, cachedPrograms) {
334 if ((cachedProg.vertexShader == vertexShader) &&
335 (cachedProg.brushShader == fragmentShader) &&
336 (cachedProg.compositionShader == 0) ) {
337
338 activeProgram = cachedProg.shader;
339 foundProgram = true;
340 break;
341 }
342 }
343
344 if (!foundProgram) {
345 qDebug() << "Linking shader program for " << currentBrushStyle;
346 // Required program not found - create it.
347 QGLShaderProgram* newProg = new QGLShaderProgram(ctx);
348
349 newProg->addShader(vertexShader);
350 newProg->addShader(fragmentShader);
351
352 if (!newProg->link())
353 qWarning() << "Shader program for " << currentBrushStyle << "failed to link:" << newProg->log();
354
355 QGLCachedShaderProg cachedProg;
356 cachedProg.vertexShader = vertexShader;
357 cachedProg.brushShader = fragmentShader;
358 cachedProg.compositionShader = 0;
359 cachedProg.shader = newProg;
360
361 cachedPrograms.append(cachedProg);
362 activeProgram = newProg;
363 }
364
365 activeProgram->use();
366 shaderProgNeedsChanging = false;
367 return true;
368}
369
370QGLShaderProgram* QGLPEXShaderManager::brushShader()
371{
372 return activeProgram;
373}
374
375// The only uniform the simple shader has is the PMV matrix
376QGLShaderProgram* QGLPEXShaderManager::simpleShader()
377{
378 if (!simpleShaderProgram) {
379 simpleShaderProgram = new QGLShaderProgram(ctx);
380
381 if (!simpleFragmentShader) {
382 simpleFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
383 simpleFragmentShader->addSource(QLatin1String(qglslSimpleFragmentShader));
384 if (!simpleFragmentShader->compile())
385 qWarning() << "qglslSimpleFragmentShader failed to compile:" << simpleFragmentShader->log();
386 }
387
388 simpleShaderProgram->addShader(defaultVertexShader);
389 simpleShaderProgram->addShader(simpleFragmentShader);
390 if (!simpleShaderProgram->link())
391 qWarning() << "Simple shader program failed to link:" << simpleShaderProgram->log();
392 }
393
394 return simpleShaderProgram;
395}
396
397QGLShaderProgram* QGLPEXShaderManager::imageShader()
398{
399 if (!imageShaderProgram) {
400 if (!imageVertexShader) {
401 imageVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
402 imageVertexShader->addSource(QLatin1String(qglslImageVertexShader));
403 if (!imageVertexShader->compile())
404 qWarning() << "Image/Pixmap vertex shader failed to compile:" << imageVertexShader->log();
405 }
406
407 if (!imageFragmentShader) {
408 imageFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
409 imageFragmentShader->addSource(QLatin1String(qglslImageFragmentShader));
410 if (!imageFragmentShader->compile())
411 qWarning() << "Image/Pixmap fragment shader failed to compile:" << imageFragmentShader->log();
412 }
413
414 imageShaderProgram = new QGLShaderProgram(ctx);
415 imageShaderProgram->addShader(imageVertexShader);
416 imageShaderProgram->addShader(imageFragmentShader);
417 if (!imageShaderProgram->link())
418 qWarning() << "Image/Pixmap shader program failed to link:" << imageShaderProgram->log();
419 }
420
421 return imageShaderProgram;
422}
423
424QGLShaderProgram* QGLPEXShaderManager::textShader()
425{
426 if (!textShaderProgram) {
427 if (!textVertexShader) {
428 textVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
429 textVertexShader->addSource(QLatin1String(qglslImageVertexShader));
430 if (!textVertexShader->compile())
431 qWarning() << "Text vertex shader failed to compile:" << textVertexShader->log();
432 }
433
434 if (!textFragmentShader) {
435 textFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
436 textFragmentShader->addSource(QLatin1String(qglslTextFragmentShader));
437 if (!textFragmentShader->compile())
438 qWarning() << "Text fragment shader failed to compile:" << textFragmentShader->log();
439 }
440
441 textShaderProgram = new QGLShaderProgram(ctx);
442 textShaderProgram->addShader(textVertexShader);
443 textShaderProgram->addShader(textFragmentShader);
444 if (!textShaderProgram->link())
445 qWarning() << "Text shader program failed to link:" << textShaderProgram->log();
446 }
447
448 return textShaderProgram;
449}
450
Note: See TracBrowser for help on using the repository browser.