author | Eckhart Koeppen <eckhart.koppen@nokia.com> |
Thu, 08 Apr 2010 14:19:33 +0300 | |
branch | RCL_3 |
changeset 8 | 3f74d0d4af4c |
parent 5 | d3bac044e0f0 |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the QtOpenGL module of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
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 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
38 |
** $QT_END_LICENSE$ |
|
39 |
** |
|
40 |
****************************************************************************/ |
|
41 |
||
42 |
// |
|
43 |
// W A R N I N G |
|
44 |
// ------------- |
|
45 |
// |
|
46 |
// This file is not part of the Qt API. It exists purely as an |
|
47 |
// implementation detail. This header file may change from version to |
|
48 |
// version without notice, or even be removed. |
|
49 |
// |
|
50 |
// We mean it. |
|
51 |
// |
|
52 |
||
53 |
/* |
|
54 |
VERTEX SHADERS |
|
55 |
============== |
|
56 |
||
57 |
Vertex shaders are specified as multiple (partial) shaders. On desktop, |
|
58 |
this works fine. On ES, QGLShader & QGLShaderProgram will make partial |
|
59 |
shaders work by concatenating the source in each QGLShader and compiling |
|
60 |
it as a single shader. This is abstracted nicely by QGLShaderProgram and |
|
61 |
the GL2 engine doesn't need to worry about it. |
|
62 |
||
63 |
Generally, there's two vertex shader objects. The position shaders are |
|
64 |
the ones which set gl_Position. There's also two "main" vertex shaders, |
|
65 |
one which just calls the position shader and another which also passes |
|
66 |
through some texture coordinates from a vertex attribute array to a |
|
67 |
varying. These texture coordinates are used for mask position in text |
|
68 |
rendering and for the source coordinates in drawImage/drawPixmap. There's |
|
69 |
also a "Simple" vertex shader for rendering a solid colour (used to render |
|
70 |
into the stencil buffer where the actual colour value is discarded). |
|
71 |
||
72 |
The position shaders for brushes look scary. This is because many of the |
|
73 |
calculations which logically belong in the fragment shader have been moved |
|
74 |
into the vertex shader to improve performance. This is why the position |
|
75 |
calculation is in a seperate shader. Not only does it calculate the |
|
76 |
position, but it also calculates some data to be passed to the fragment |
|
77 |
shader as a varying. It is optimal to move as much of the calculation as |
|
78 |
possible into the vertex shader as this is executed less often. |
|
79 |
||
80 |
The varyings passed to the fragment shaders are interpolated (which is |
|
81 |
cheap). Unfortunately, GL will apply perspective correction to the |
|
82 |
interpolation calusing errors. To get around this, the vertex shader must |
|
83 |
apply perspective correction itself and set the w-value of gl_Position to |
|
84 |
zero. That way, GL will be tricked into thinking it doesn't need to apply a |
|
85 |
perspective correction and use linear interpolation instead (which is what |
|
86 |
we want). Of course, if the brush transform is affeine, no perspective |
|
87 |
correction is needed and a simpler vertex shader can be used instead. |
|
88 |
||
89 |
So there are the following "main" vertex shaders: |
|
90 |
qglslMainVertexShader |
|
91 |
qglslMainWithTexCoordsVertexShader |
|
92 |
||
93 |
And the the following position vertex shaders: |
|
94 |
qglslPositionOnlyVertexShader |
|
95 |
qglslPositionWithTextureBrushVertexShader |
|
96 |
qglslPositionWithPatternBrushVertexShader |
|
97 |
qglslPositionWithLinearGradientBrushVertexShader |
|
98 |
qglslPositionWithRadialGradientBrushVertexShader |
|
99 |
qglslPositionWithConicalGradientBrushVertexShader |
|
100 |
qglslAffinePositionWithTextureBrushVertexShader |
|
101 |
qglslAffinePositionWithPatternBrushVertexShader |
|
102 |
qglslAffinePositionWithLinearGradientBrushVertexShader |
|
103 |
qglslAffinePositionWithRadialGradientBrushVertexShader |
|
104 |
qglslAffinePositionWithConicalGradientBrushVertexShader |
|
105 |
||
106 |
Leading to 23 possible vertex shaders |
|
107 |
||
108 |
||
109 |
FRAGMENT SHADERS |
|
110 |
================ |
|
111 |
||
112 |
Fragment shaders are also specified as multiple (partial) shaders. The |
|
113 |
different fragment shaders represent the different stages in Qt's fragment |
|
114 |
pipeline. There are 1-3 stages in this pipeline: First stage is to get the |
|
115 |
fragment's colour value. The next stage is to get the fragment's mask value |
|
116 |
(coverage value for anti-aliasing) and the final stage is to blend the |
|
117 |
incoming fragment with the background (for composition modes not supported |
|
118 |
by GL). |
|
119 |
||
120 |
Of these, the first stage will always be present. If Qt doesn't need to |
|
121 |
apply anti-aliasing (because it's off or handled by multisampling) then |
|
122 |
the coverage value doesn't need to be applied. (Note: There are two types |
|
123 |
of mask, one for regular anti-aliasing and one for sub-pixel anti- |
|
124 |
aliasing.) If the composition mode is one which GL supports natively then |
|
125 |
the blending stage doesn't need to be applied. |
|
126 |
||
127 |
As eash stage can have multiple implementations, they are abstracted as |
|
128 |
GLSL function calls with the following signatures: |
|
129 |
||
130 |
Brushes & image drawing are implementations of "qcolorp vec4 srcPixel()": |
|
131 |
qglslImageSrcFragShader |
|
132 |
qglslImageSrcWithPatternFragShader |
|
133 |
qglslNonPremultipliedImageSrcFragShader |
|
134 |
qglslSolidBrushSrcFragShader |
|
135 |
qglslTextureBrushSrcFragShader |
|
136 |
qglslTextureBrushWithPatternFragShader |
|
137 |
qglslPatternBrushSrcFragShader |
|
138 |
qglslLinearGradientBrushSrcFragShader |
|
139 |
qglslRadialGradientBrushSrcFragShader |
|
140 |
qglslConicalGradientBrushSrcFragShader |
|
141 |
NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied |
|
142 |
||
143 |
Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)": |
|
144 |
qglslMaskFragmentShader |
|
145 |
qglslRgbMaskFragmentShaderPass1 |
|
146 |
qglslRgbMaskFragmentShaderPass2 |
|
147 |
qglslRgbMaskWithGammaFragmentShader |
|
148 |
||
149 |
Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)": |
|
150 |
qglslColorBurnCompositionModeFragmentShader |
|
151 |
qglslColorDodgeCompositionModeFragmentShader |
|
152 |
qglslDarkenCompositionModeFragmentShader |
|
153 |
qglslDifferenceCompositionModeFragmentShader |
|
154 |
qglslExclusionCompositionModeFragmentShader |
|
155 |
qglslHardLightCompositionModeFragmentShader |
|
156 |
qglslLightenCompositionModeFragmentShader |
|
157 |
qglslMultiplyCompositionModeFragmentShader |
|
158 |
qglslOverlayCompositionModeFragmentShader |
|
159 |
qglslScreenCompositionModeFragmentShader |
|
160 |
qglslSoftLightCompositionModeFragmentShader |
|
161 |
||
162 |
||
163 |
Note: In the future, some GLSL compilers will support an extension allowing |
|
164 |
a new 'color' precision specifier. To support this, qcolorp is used for |
|
165 |
all color components so it can be defined to colorp or lowp depending upon |
|
166 |
the implementation. |
|
167 |
||
168 |
So there are differnt frament shader main functions, depending on the |
|
169 |
number & type of pipelines the fragment needs to go through. |
|
170 |
||
171 |
The choice of which main() fragment shader string to use depends on: |
|
172 |
- Use of global opacity |
|
173 |
- Brush style (some brushes apply opacity themselves) |
|
174 |
- Use & type of mask (TODO: Need to support high quality anti-aliasing & text) |
|
175 |
- Use of non-GL Composition mode |
|
176 |
||
177 |
Leading to the following fragment shader main functions: |
|
178 |
gl_FragColor = compose(applyMask(srcPixel()*globalOpacity)); |
|
179 |
gl_FragColor = compose(applyMask(srcPixel())); |
|
180 |
gl_FragColor = applyMask(srcPixel()*globalOpacity); |
|
181 |
gl_FragColor = applyMask(srcPixel()); |
|
182 |
gl_FragColor = compose(srcPixel()*globalOpacity); |
|
183 |
gl_FragColor = compose(srcPixel()); |
|
184 |
gl_FragColor = srcPixel()*globalOpacity; |
|
185 |
gl_FragColor = srcPixel(); |
|
186 |
||
187 |
Called: |
|
188 |
qglslMainFragmentShader_CMO |
|
189 |
qglslMainFragmentShader_CM |
|
190 |
qglslMainFragmentShader_MO |
|
191 |
qglslMainFragmentShader_M |
|
192 |
qglslMainFragmentShader_CO |
|
193 |
qglslMainFragmentShader_C |
|
194 |
qglslMainFragmentShader_O |
|
195 |
qglslMainFragmentShader |
|
196 |
||
197 |
Where: |
|
198 |
M = Mask |
|
199 |
C = Composition |
|
200 |
O = Global Opacity |
|
201 |
||
202 |
||
203 |
CUSTOM SHADER CODE |
|
204 |
================== |
|
205 |
||
206 |
The use of custom shader code is supported by the engine for drawImage and |
|
207 |
drawPixmap calls. This is implemented via hooks in the fragment pipeline. |
|
208 |
||
209 |
The custom shader is passed to the engine as a partial fragment shader |
|
210 |
(QGLCustomShaderStage). The shader will implement a pre-defined method name |
|
211 |
which Qt's fragment pipeline will call: |
|
212 |
||
213 |
lowp vec4 customShader(lowp sampler2d imageTexture, highp vec2 textureCoords) |
|
214 |
||
215 |
The provided src and srcCoords parameters can be used to sample from the |
|
216 |
source image. |
|
217 |
||
218 |
Transformations, clipping, opacity, and composition modes set using QPainter |
|
219 |
will be respected when using the custom shader hook. |
|
220 |
*/ |
|
221 |
||
222 |
#ifndef QGLENGINE_SHADER_MANAGER_H |
|
223 |
#define QGLENGINE_SHADER_MANAGER_H |
|
224 |
||
225 |
#include <QGLShader> |
|
226 |
#include <QGLShaderProgram> |
|
227 |
#include <QPainter> |
|
228 |
#include <private/qgl_p.h> |
|
229 |
#include <private/qglcustomshaderstage_p.h> |
|
230 |
||
231 |
QT_BEGIN_HEADER |
|
232 |
||
233 |
QT_BEGIN_NAMESPACE |
|
234 |
||
235 |
QT_MODULE(OpenGL) |
|
236 |
||
237 |
||
238 |
/* |
|
239 |
struct QGLEngineCachedShaderProg |
|
240 |
{ |
|
241 |
QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain, |
|
242 |
QGLEngineShaderManager::ShaderName vertexPosition, |
|
243 |
QGLEngineShaderManager::ShaderName fragMain, |
|
244 |
QGLEngineShaderManager::ShaderName pixelSrc, |
|
245 |
QGLEngineShaderManager::ShaderName mask, |
|
246 |
QGLEngineShaderManager::ShaderName composition); |
|
247 |
||
248 |
int cacheKey; |
|
249 |
QGLShaderProgram* program; |
|
250 |
} |
|
251 |
*/ |
|
252 |
||
253 |
static const GLuint QT_VERTEX_COORDS_ATTR = 0; |
|
254 |
static const GLuint QT_TEXTURE_COORDS_ATTR = 1; |
|
255 |
static const GLuint QT_OPACITY_ATTR = 2; |
|
5
d3bac044e0f0
Revision: 201007
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
4
diff
changeset
|
256 |
static const GLuint QT_PMV_MATRIX_1_ATTR = 3; |
d3bac044e0f0
Revision: 201007
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
4
diff
changeset
|
257 |
static const GLuint QT_PMV_MATRIX_2_ATTR = 4; |
d3bac044e0f0
Revision: 201007
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
4
diff
changeset
|
258 |
static const GLuint QT_PMV_MATRIX_3_ATTR = 5; |
0 | 259 |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
260 |
class QGLEngineShaderProg; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
261 |
|
0 | 262 |
class QGLEngineSharedShaders : public QObject |
263 |
{ |
|
264 |
Q_OBJECT |
|
265 |
public: |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
266 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
267 |
enum SnippetName { |
0 | 268 |
MainVertexShader, |
269 |
MainWithTexCoordsVertexShader, |
|
270 |
MainWithTexCoordsAndOpacityVertexShader, |
|
271 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
272 |
// UntransformedPositionVertexShader must be first in the list: |
0 | 273 |
UntransformedPositionVertexShader, |
274 |
PositionOnlyVertexShader, |
|
275 |
PositionWithPatternBrushVertexShader, |
|
276 |
PositionWithLinearGradientBrushVertexShader, |
|
277 |
PositionWithConicalGradientBrushVertexShader, |
|
278 |
PositionWithRadialGradientBrushVertexShader, |
|
279 |
PositionWithTextureBrushVertexShader, |
|
280 |
AffinePositionWithPatternBrushVertexShader, |
|
281 |
AffinePositionWithLinearGradientBrushVertexShader, |
|
282 |
AffinePositionWithConicalGradientBrushVertexShader, |
|
283 |
AffinePositionWithRadialGradientBrushVertexShader, |
|
284 |
AffinePositionWithTextureBrushVertexShader, |
|
285 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
286 |
// MainFragmentShader_CMO must be first in the list: |
0 | 287 |
MainFragmentShader_CMO, |
288 |
MainFragmentShader_CM, |
|
289 |
MainFragmentShader_MO, |
|
290 |
MainFragmentShader_M, |
|
291 |
MainFragmentShader_CO, |
|
292 |
MainFragmentShader_C, |
|
293 |
MainFragmentShader_O, |
|
294 |
MainFragmentShader, |
|
295 |
MainFragmentShader_ImageArrays, |
|
296 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
297 |
// ImageSrcFragmentShader must be first in the list:: |
0 | 298 |
ImageSrcFragmentShader, |
299 |
ImageSrcWithPatternFragmentShader, |
|
300 |
NonPremultipliedImageSrcFragmentShader, |
|
301 |
CustomImageSrcFragmentShader, |
|
302 |
SolidBrushSrcFragmentShader, |
|
303 |
TextureBrushSrcFragmentShader, |
|
304 |
TextureBrushSrcWithPatternFragmentShader, |
|
305 |
PatternBrushSrcFragmentShader, |
|
306 |
LinearGradientBrushSrcFragmentShader, |
|
307 |
RadialGradientBrushSrcFragmentShader, |
|
308 |
ConicalGradientBrushSrcFragmentShader, |
|
309 |
ShockingPinkSrcFragmentShader, |
|
310 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
311 |
// NoMaskFragmentShader must be first in the list: |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
312 |
NoMaskFragmentShader, |
0 | 313 |
MaskFragmentShader, |
314 |
RgbMaskFragmentShaderPass1, |
|
315 |
RgbMaskFragmentShaderPass2, |
|
316 |
RgbMaskWithGammaFragmentShader, |
|
317 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
318 |
// NoCompositionModeFragmentShader must be first in the list: |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
319 |
NoCompositionModeFragmentShader, |
0 | 320 |
MultiplyCompositionModeFragmentShader, |
321 |
ScreenCompositionModeFragmentShader, |
|
322 |
OverlayCompositionModeFragmentShader, |
|
323 |
DarkenCompositionModeFragmentShader, |
|
324 |
LightenCompositionModeFragmentShader, |
|
325 |
ColorDodgeCompositionModeFragmentShader, |
|
326 |
ColorBurnCompositionModeFragmentShader, |
|
327 |
HardLightCompositionModeFragmentShader, |
|
328 |
SoftLightCompositionModeFragmentShader, |
|
329 |
DifferenceCompositionModeFragmentShader, |
|
330 |
ExclusionCompositionModeFragmentShader, |
|
331 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
332 |
TotalSnippetCount, InvalidSnippetName |
0 | 333 |
}; |
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
334 |
#if defined (QT_DEBUG) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
335 |
Q_ENUMS(SnippetName) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
336 |
static QByteArray snippetNameStr(SnippetName snippetName); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
337 |
#endif |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
338 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
339 |
/* |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
340 |
// These allow the ShaderName enum to be used as a cache key |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
341 |
const int mainVertexOffset = 0; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
342 |
const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
343 |
const int mainFragOffset = (1<<6) - MainFragmentShader_CMO; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
344 |
const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
345 |
const int maskOffset = (1<<14) - NoMaskShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
346 |
const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
347 |
*/ |
0 | 348 |
|
349 |
QGLEngineSharedShaders(const QGLContext *context); |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
350 |
~QGLEngineSharedShaders(); |
0 | 351 |
|
352 |
QGLShaderProgram *simpleProgram() { return simpleShaderProg; } |
|
353 |
QGLShaderProgram *blitProgram() { return blitShaderProg; } |
|
354 |
// Compile the program if it's not already in the cache, return the item in the cache. |
|
355 |
QGLEngineShaderProg *findProgramInCache(const QGLEngineShaderProg &prog); |
|
356 |
// Compile the custom shader if it's not already in the cache, return the item in the cache. |
|
357 |
||
358 |
static QGLEngineSharedShaders *shadersForContext(const QGLContext *context); |
|
359 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
360 |
// Ideally, this would be static and cleanup all programs in all contexts which |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
361 |
// contain the custom code. Currently it is just a hint and we rely on deleted |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
362 |
// custom shaders being cleaned up by being kicked out of the cache when it's |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
363 |
// full. |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
364 |
void cleanupCustomStage(QGLCustomShaderStage* stage); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
365 |
|
0 | 366 |
signals: |
367 |
void shaderProgNeedsChanging(); |
|
368 |
||
369 |
private: |
|
370 |
QGLSharedResourceGuard ctxGuard; |
|
371 |
QGLShaderProgram *blitShaderProg; |
|
372 |
QGLShaderProgram *simpleShaderProg; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
373 |
QList<QGLEngineShaderProg*> cachedPrograms; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
374 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
375 |
static const char* qShaderSnippets[TotalSnippetCount]; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
376 |
}; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
377 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
378 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
379 |
class QGLEngineShaderProg |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
380 |
{ |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
381 |
public: |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
382 |
QGLEngineShaderProg() : program(0) {} |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
383 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
384 |
~QGLEngineShaderProg() { |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
385 |
if (program) |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
386 |
delete program; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
387 |
} |
0 | 388 |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
389 |
QGLEngineSharedShaders::SnippetName mainVertexShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
390 |
QGLEngineSharedShaders::SnippetName positionVertexShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
391 |
QGLEngineSharedShaders::SnippetName mainFragShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
392 |
QGLEngineSharedShaders::SnippetName srcPixelFragShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
393 |
QGLEngineSharedShaders::SnippetName maskFragShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
394 |
QGLEngineSharedShaders::SnippetName compositionFragShader; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
395 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
396 |
QByteArray customStageSource; //TODO: Decent cache key for custom stages |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
397 |
QGLShaderProgram* program; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
398 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
399 |
QVector<uint> uniformLocations; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
400 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
401 |
bool useTextureCoords; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
402 |
bool useOpacityAttribute; |
5
d3bac044e0f0
Revision: 201007
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
4
diff
changeset
|
403 |
bool usePmvMatrix; |
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
404 |
|
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
405 |
bool operator==(const QGLEngineShaderProg& other) { |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
406 |
// We don't care about the program |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
407 |
return ( mainVertexShader == other.mainVertexShader && |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
408 |
positionVertexShader == other.positionVertexShader && |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
409 |
mainFragShader == other.mainFragShader && |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
410 |
srcPixelFragShader == other.srcPixelFragShader && |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
411 |
maskFragShader == other.maskFragShader && |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
412 |
compositionFragShader == other.compositionFragShader && |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
413 |
customStageSource == other.customStageSource |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
414 |
); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
415 |
} |
0 | 416 |
}; |
417 |
||
418 |
class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject |
|
419 |
{ |
|
420 |
Q_OBJECT |
|
421 |
public: |
|
422 |
QGLEngineShaderManager(QGLContext* context); |
|
423 |
~QGLEngineShaderManager(); |
|
424 |
||
425 |
enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask}; |
|
426 |
enum PixelSrcType { |
|
427 |
ImageSrc = Qt::TexturePattern+1, |
|
428 |
NonPremultipliedImageSrc = Qt::TexturePattern+2, |
|
429 |
PatternSrc = Qt::TexturePattern+3, |
|
430 |
TextureSrcWithPattern = Qt::TexturePattern+4 |
|
431 |
}; |
|
432 |
||
433 |
enum Uniform { |
|
434 |
ImageTexture, |
|
435 |
PatternColor, |
|
436 |
GlobalOpacity, |
|
437 |
Depth, |
|
438 |
MaskTexture, |
|
439 |
FragmentColor, |
|
440 |
LinearData, |
|
441 |
Angle, |
|
442 |
HalfViewportSize, |
|
443 |
Fmp, |
|
444 |
Fmp2MRadius2, |
|
445 |
Inverse2Fmp2MRadius2, |
|
446 |
InvertedTextureSize, |
|
447 |
BrushTransform, |
|
448 |
BrushTexture, |
|
449 |
NumUniforms |
|
450 |
}; |
|
451 |
||
452 |
enum OpacityMode { |
|
453 |
NoOpacity, |
|
454 |
UniformOpacity, |
|
455 |
AttributeOpacity |
|
456 |
}; |
|
457 |
||
458 |
// There are optimisations we can do, depending on the brush transform: |
|
459 |
// 1) May not have to apply perspective-correction |
|
460 |
// 2) Can use lower precision for matrix |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
461 |
void optimiseForBrushTransform(QTransform::TransformationType transformType); |
0 | 462 |
void setSrcPixelType(Qt::BrushStyle); |
463 |
void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images |
|
464 |
void setOpacityMode(OpacityMode); |
|
465 |
void setMaskType(MaskType); |
|
466 |
void setCompositionMode(QPainter::CompositionMode); |
|
467 |
void setCustomStage(QGLCustomShaderStage* stage); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
468 |
void removeCustomStage(); |
0 | 469 |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
470 |
GLuint getUniformLocation(Uniform id); |
0 | 471 |
|
472 |
void setDirty(); // someone has manually changed the current shader program |
|
473 |
bool useCorrectShaderProg(); // returns true if the shader program needed to be changed |
|
474 |
||
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
475 |
void useSimpleProgram(); |
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
476 |
void useBlitProgram(); |
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
477 |
|
0 | 478 |
QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen |
479 |
QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers |
|
480 |
QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer |
|
481 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
482 |
QGLEngineSharedShaders* sharedShaders; |
0 | 483 |
|
484 |
private slots: |
|
485 |
void shaderProgNeedsChangingSlot() { shaderProgNeedsChanging = true; } |
|
486 |
||
487 |
private: |
|
488 |
QGLContext* ctx; |
|
489 |
bool shaderProgNeedsChanging; |
|
490 |
||
491 |
// Current state variables which influence the choice of shader: |
|
492 |
QTransform brushTransform; |
|
493 |
int srcPixelType; |
|
494 |
OpacityMode opacityMode; |
|
495 |
MaskType maskType; |
|
496 |
QPainter::CompositionMode compositionMode; |
|
497 |
QGLCustomShaderStage* customSrcStage; |
|
498 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
499 |
QGLEngineShaderProg* currentShaderProg; |
0 | 500 |
}; |
501 |
||
502 |
QT_END_NAMESPACE |
|
503 |
||
504 |
QT_END_HEADER |
|
505 |
||
506 |
#endif //QGLENGINE_SHADER_MANAGER_H |