qgraphicsshadereffect.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtOpenGL module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qgraphicsshadereffect_p.h" -
43#include "qglshaderprogram.h" -
44#include "gl2paintengineex/qglcustomshaderstage_p.h" -
45#define QGL_HAVE_CUSTOM_SHADERS 1 -
46#include <QtGui/qpainter.h> -
47#include <QtWidgets/qgraphicsitem.h> -
48#include <private/qgraphicseffect_p.h> -
49 -
50QT_BEGIN_NAMESPACE -
51 -
52/*# -
53 \class QGraphicsShaderEffect -
54 \inmodule QtOpenGL -
55 \brief The QGraphicsShaderEffect class is the base class for creating -
56 custom GLSL shader effects in a QGraphicsScene. -
57 \since 4.6 -
58 \ingroup multimedia -
59 \ingroup graphicsview-api -
60 -
61 The specific effect is defined by a fragment of GLSL source code -
62 supplied to setPixelShaderFragment(). This source code must define a -
63 function with the signature -
64 \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)} -
65 that returns the source pixel value -
66 to use in the paint engine's shader program. The shader fragment -
67 is linked with the regular shader code used by the GL2 paint engine -
68 to construct a complete QGLShaderProgram. -
69 -
70 The following example shader converts the incoming pixmap to -
71 grayscale and then applies a colorize operation using the -
72 \c effectColor value: -
73 -
74 \code -
75 static char const colorizeShaderCode[] = -
76 "uniform lowp vec4 effectColor;\n" -
77 "lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {\n" -
78 " vec4 src = texture2D(imageTexture, textureCoords);\n" -
79 " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" -
80 " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" -
81 " return vec4(colorize.rgb, src.a);\n" -
82 "}"; -
83 \endcode -
84 -
85 To use this shader code, it is necessary to define a subclass -
86 of QGraphicsShaderEffect as follows: -
87 -
88 \code -
89 class ColorizeEffect : public QGraphicsShaderEffect -
90 { -
91 Q_OBJECT -
92 public: -
93 ColorizeEffect(QObject *parent = 0) -
94 : QGraphicsShaderEffect(parent), color(Qt::black) -
95 { -
96 setPixelShaderFragment(colorizeShaderCode); -
97 } -
98 -
99 QColor effectColor() const { return color; } -
100 void setEffectColor(const QColor& c) -
101 { -
102 color = c; -
103 setUniformsDirty(); -
104 } -
105 -
106 protected: -
107 void setUniforms(QGLShaderProgram *program) -
108 { -
109 program->setUniformValue("effectColor", color); -
110 } -
111 -
112 private: -
113 QColor color; -
114 }; -
115 \endcode -
116 -
117 The setUniforms() function is called when the effect is about -
118 to be used for drawing to give the subclass the opportunity to -
119 set effect-specific uniform variables. -
120 -
121 QGraphicsShaderEffect is only supported when the GL2 paint engine -
122 is in use. When any other paint engine is in use (GL1, raster, etc), -
123 the drawItem() method will draw its item argument directly with -
124 no effect applied. -
125 -
126 \sa QGraphicsEffect -
127*/ -
128 -
129static const char qglslDefaultImageFragmentShader[] = "\ -
130 lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { \ -
131 return texture2D(imageTexture, textureCoords); \ -
132 }\n"; -
133 -
134#ifdef QGL_HAVE_CUSTOM_SHADERS -
135 -
136class QGLCustomShaderEffectStage : public QGLCustomShaderStage -
137{ -
138public: -
139 QGLCustomShaderEffectStage -
140 (QGraphicsShaderEffect *e, const QByteArray& source) -
141 : QGLCustomShaderStage(), -
142 effect(e) -
143 { -
144 setSource(source);
never executed (the execution status of this line is deduced): setSource(source);
-
145 }
never executed: }
0
146 -
147 void setUniforms(QGLShaderProgram *program); -
148 -
149 QGraphicsShaderEffect *effect; -
150}; -
151 -
152void QGLCustomShaderEffectStage::setUniforms(QGLShaderProgram *program) -
153{ -
154 effect->setUniforms(program);
never executed (the execution status of this line is deduced): effect->setUniforms(program);
-
155}
never executed: }
0
156 -
157#endif -
158 -
159class QGraphicsShaderEffectPrivate : public QGraphicsEffectPrivate -
160{ -
161 Q_DECLARE_PUBLIC(QGraphicsShaderEffect) -
162public: -
163 QGraphicsShaderEffectPrivate() -
164 : pixelShaderFragment(qglslDefaultImageFragmentShader) -
165#ifdef QGL_HAVE_CUSTOM_SHADERS -
166 , customShaderStage(0) -
167#endif -
168 { -
169 }
never executed: }
0
170 -
171 QByteArray pixelShaderFragment; -
172#ifdef QGL_HAVE_CUSTOM_SHADERS -
173 QGLCustomShaderEffectStage *customShaderStage; -
174#endif -
175}; -
176 -
177/*# -
178 Constructs a shader effect and attaches it to \a parent. -
179*/ -
180QGraphicsShaderEffect::QGraphicsShaderEffect(QObject *parent) -
181 : QGraphicsEffect(*new QGraphicsShaderEffectPrivate(), parent) -
182{ -
183}
never executed: }
0
184 -
185/*# -
186 Destroys this shader effect. -
187*/ -
188QGraphicsShaderEffect::~QGraphicsShaderEffect() -
189{ -
190#ifdef QGL_HAVE_CUSTOM_SHADERS -
191 Q_D(QGraphicsShaderEffect);
never executed (the execution status of this line is deduced): QGraphicsShaderEffectPrivate * const d = d_func();
-
192 delete d->customShaderStage;
never executed (the execution status of this line is deduced): delete d->customShaderStage;
-
193#endif -
194}
never executed: }
0
195 -
196/*# -
197 Returns the source code for the pixel shader fragment for -
198 this shader effect. The default is a shader that copies -
199 its incoming pixmap directly to the output with no effect -
200 applied. -
201 -
202 \sa setPixelShaderFragment() -
203*/ -
204QByteArray QGraphicsShaderEffect::pixelShaderFragment() const -
205{ -
206 Q_D(const QGraphicsShaderEffect);
never executed (the execution status of this line is deduced): const QGraphicsShaderEffectPrivate * const d = d_func();
-
207 return d->pixelShaderFragment;
never executed: return d->pixelShaderFragment;
0
208} -
209 -
210/*# -
211 Sets the source code for the pixel shader fragment for -
212 this shader effect to \a code. -
213 -
214 The \a code must define a GLSL function with the signature -
215 \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)} -
216 that returns the source pixel value to use in the paint engine's -
217 shader program. The following is the default pixel shader fragment, -
218 which draws a pixmap with no effect applied: -
219 -
220 \code -
221 lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { -
222 return texture2D(imageTexture, textureCoords); -
223 } -
224 \endcode -
225 -
226 \sa pixelShaderFragment(), setUniforms() -
227*/ -
228void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code) -
229{ -
230 Q_D(QGraphicsShaderEffect);
never executed (the execution status of this line is deduced): QGraphicsShaderEffectPrivate * const d = d_func();
-
231 if (d->pixelShaderFragment != code) {
never evaluated: d->pixelShaderFragment != code
0
232 d->pixelShaderFragment = code;
never executed (the execution status of this line is deduced): d->pixelShaderFragment = code;
-
233#ifdef QGL_HAVE_CUSTOM_SHADERS -
234 delete d->customShaderStage;
never executed (the execution status of this line is deduced): delete d->customShaderStage;
-
235 d->customShaderStage = 0;
never executed (the execution status of this line is deduced): d->customShaderStage = 0;
-
236#endif -
237 }
never executed: }
0
238}
never executed: }
0
239 -
240/*# -
241 \reimp -
242*/ -
243void QGraphicsShaderEffect::draw(QPainter *painter) -
244{ -
245 Q_D(QGraphicsShaderEffect);
never executed (the execution status of this line is deduced): QGraphicsShaderEffectPrivate * const d = d_func();
-
246 -
247#ifdef QGL_HAVE_CUSTOM_SHADERS -
248 // Set the custom shader on the paint engine. The setOnPainter() -
249 // call may fail if the paint engine is not GL2. In that case, -
250 // we fall through to drawing the pixmap normally. -
251 if (!d->customShaderStage) {
never evaluated: !d->customShaderStage
0
252 d->customShaderStage = new QGLCustomShaderEffectStage
never executed (the execution status of this line is deduced): d->customShaderStage = new QGLCustomShaderEffectStage
-
253 (this, d->pixelShaderFragment);
never executed (the execution status of this line is deduced): (this, d->pixelShaderFragment);
-
254 }
never executed: }
0
255 bool usingShader = d->customShaderStage->setOnPainter(painter);
never executed (the execution status of this line is deduced): bool usingShader = d->customShaderStage->setOnPainter(painter);
-
256 -
257 QPoint offset;
never executed (the execution status of this line is deduced): QPoint offset;
-
258 if (sourceIsPixmap()) {
never evaluated: sourceIsPixmap()
0
259 // No point in drawing in device coordinates (pixmap will be scaled anyways). -
260 const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset);
never executed (the execution status of this line is deduced): const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset);
-
261 painter->drawPixmap(offset, pixmap);
never executed (the execution status of this line is deduced): painter->drawPixmap(offset, pixmap);
-
262 } else {
never executed: }
0
263 // Draw pixmap in device coordinates to avoid pixmap scaling. -
264 const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
never executed (the execution status of this line is deduced): const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
-
265 QTransform restoreTransform = painter->worldTransform();
never executed (the execution status of this line is deduced): QTransform restoreTransform = painter->worldTransform();
-
266 painter->setWorldTransform(QTransform());
never executed (the execution status of this line is deduced): painter->setWorldTransform(QTransform());
-
267 painter->drawPixmap(offset, pixmap);
never executed (the execution status of this line is deduced): painter->drawPixmap(offset, pixmap);
-
268 painter->setWorldTransform(restoreTransform);
never executed (the execution status of this line is deduced): painter->setWorldTransform(restoreTransform);
-
269 }
never executed: }
0
270 -
271 // Remove the custom shader to return to normal painting operations. -
272 if (usingShader)
never evaluated: usingShader
0
273 d->customShaderStage->removeFromPainter(painter);
never executed: d->customShaderStage->removeFromPainter(painter);
0
274#else -
275 drawSource(painter); -
276#endif -
277}
never executed: }
0
278 -
279/*# -
280 Sets the custom uniform variables on this shader effect to -
281 be dirty. The setUniforms() function will be called the next -
282 time the shader program corresponding to this effect is used. -
283 -
284 This function is typically called by subclasses when an -
285 effect-specific parameter is changed by the application. -
286 -
287 \sa setUniforms() -
288*/ -
289void QGraphicsShaderEffect::setUniformsDirty() -
290{ -
291#ifdef QGL_HAVE_CUSTOM_SHADERS -
292 Q_D(QGraphicsShaderEffect);
never executed (the execution status of this line is deduced): QGraphicsShaderEffectPrivate * const d = d_func();
-
293 if (d->customShaderStage)
never evaluated: d->customShaderStage
0
294 d->customShaderStage->setUniformsDirty();
never executed: d->customShaderStage->setUniformsDirty();
0
295#endif -
296}
never executed: }
0
297 -
298/*# -
299 Sets custom uniform variables on the current GL context when -
300 \a program is about to be used by the paint engine. -
301 -
302 This function should be overridden if the shader set with -
303 setPixelShaderFragment() has additional parameters beyond -
304 those that the paint engine normally sets itself. -
305 -
306 \sa setUniformsDirty() -
307*/ -
308void QGraphicsShaderEffect::setUniforms(QGLShaderProgram *program) -
309{ -
310 Q_UNUSED(program);
never executed (the execution status of this line is deduced): (void)program;;
-
311}
never executed: }
0
312 -
313QT_END_NAMESPACE -
314 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial