Qt 4.8
qglengineshadermanager_p.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 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 //
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 separate 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 
232 
234 
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;
256 static const GLuint QT_PMV_MATRIX_1_ATTR = 3;
257 static const GLuint QT_PMV_MATRIX_2_ATTR = 4;
258 static const GLuint QT_PMV_MATRIX_3_ATTR = 5;
259 
261 
263 {
264  Q_GADGET
265 public:
266 
267  enum SnippetName {
271 
272  // UntransformedPositionVertexShader must be first in the list:
286 
287  // MainFragmentShader_CMO must be first in the list:
297 
298  // ImageSrcFragmentShader must be first in the list::
311 
312  // NoMaskFragmentShader must be first in the list:
318 
319  // NoCompositionModeFragmentShader must be first in the list:
332 
333  TotalSnippetCount, InvalidSnippetName
334  };
335 #if defined (QT_DEBUG)
337  static QByteArray snippetNameStr(SnippetName snippetName);
338 #endif
339 
340 /*
341  // These allow the ShaderName enum to be used as a cache key
342  const int mainVertexOffset = 0;
343  const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader;
344  const int mainFragOffset = (1<<6) - MainFragmentShader_CMO;
345  const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader;
346  const int maskOffset = (1<<14) - NoMaskShader;
347  const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
348 */
349 
350  QGLEngineSharedShaders(const QGLContext *context);
351  ~QGLEngineSharedShaders();
352 
353  QGLShaderProgram *simpleProgram() { return simpleShaderProg; }
354  QGLShaderProgram *blitProgram() { return blitShaderProg; }
355  // Compile the program if it's not already in the cache, return the item in the cache.
356  QGLEngineShaderProg *findProgramInCache(const QGLEngineShaderProg &prog);
357  // Compile the custom shader if it's not already in the cache, return the item in the cache.
358 
359  static QGLEngineSharedShaders *shadersForContext(const QGLContext *context);
360 
361  // Ideally, this would be static and cleanup all programs in all contexts which
362  // contain the custom code. Currently it is just a hint and we rely on deleted
363  // custom shaders being cleaned up by being kicked out of the cache when it's
364  // full.
365  void cleanupCustomStage(QGLCustomShaderStage* stage);
366 
367 private:
373 
374  static const char* qShaderSnippets[TotalSnippetCount];
375 };
376 
377 
379 {
380 public:
382 
384  if (program)
385  delete program;
386  }
387 
394 
395  QByteArray customStageSource; //TODO: Decent cache key for custom stages
397 
399 
403 
404  bool operator==(const QGLEngineShaderProg& other) {
405  // We don't care about the program
406  return ( mainVertexShader == other.mainVertexShader &&
407  positionVertexShader == other.positionVertexShader &&
408  mainFragShader == other.mainFragShader &&
409  srcPixelFragShader == other.srcPixelFragShader &&
410  maskFragShader == other.maskFragShader &&
411  compositionFragShader == other.compositionFragShader &&
412  customStageSource == other.customStageSource
413  );
414  }
415 };
416 
418 {
419  Q_OBJECT
420 public:
423 
424  enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask};
426  ImageSrc = Qt::TexturePattern+1,
427  NonPremultipliedImageSrc = Qt::TexturePattern+2,
428  PatternSrc = Qt::TexturePattern+3,
429  TextureSrcWithPattern = Qt::TexturePattern+4
430  };
431 
432  enum Uniform {
451  NumUniforms
452  };
453 
454  enum OpacityMode {
457  AttributeOpacity
458  };
459 
460  // There are optimizations we can do, depending on the brush transform:
461  // 1) May not have to apply perspective-correction
462  // 2) Can use lower precision for matrix
463  void optimiseForBrushTransform(QTransform::TransformationType transformType);
464  void setSrcPixelType(Qt::BrushStyle);
465  void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
466  void setOpacityMode(OpacityMode);
467  void setMaskType(MaskType);
468  void setCompositionMode(QPainter::CompositionMode);
469  void setCustomStage(QGLCustomShaderStage* stage);
470  void removeCustomStage();
471 
472  GLuint getUniformLocation(Uniform id);
473 
474  void setDirty(); // someone has manually changed the current shader program
475  bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
476 
477  void useSimpleProgram();
478  void useBlitProgram();
479  void setHasComplexGeometry(bool hasComplexGeometry)
480  {
481  complexGeometry = hasComplexGeometry;
482  shaderProgNeedsChanging = true;
483  }
484  bool hasComplexGeometry() const
485  {
486  return complexGeometry;
487  }
488 
489  QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
490  QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
491  QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
492 
494 
495 private:
499 
500  // Current state variables which influence the choice of shader:
507 
509 };
510 
512 
514 
515 #endif //QGLENGINE_SHADER_MANAGER_H
QGLSharedResourceGuard ctxGuard
BrushStyle
Definition: qnamespace.h:1162
static const GLuint QT_PMV_MATRIX_3_ATTR
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define QT_MODULE(x)
Definition: qglobal.h:2783
QGLEngineSharedShaders::SnippetName mainVertexShader
CompositionMode
Defines the modes supported for digital image compositing.
Definition: qpainter.h:138
#define QT_BEGIN_HEADER
Definition: qglobal.h:136
QGLCustomShaderStage * customSrcStage
QGLEngineSharedShaders::SnippetName mainFragShader
#define Q_OPENGL_EXPORT
Definition: qglobal.h:1455
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QGLShaderProgram * blitProgram()
QGLEngineSharedShaders::SnippetName maskFragShader
QGLEngineSharedShaders::SnippetName positionVertexShader
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
QGLShaderProgram * simpleShaderProg
static const GLuint QT_OPACITY_ATTR
#define Q_ENUMS(x)
Definition: qobjectdefs.h:84
QGLEngineShaderProg * currentShaderProg
TransformationType
Definition: qtransform.h:68
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QGLContext class encapsulates an OpenGL rendering context.
Definition: qgl.h:310
QPainter::CompositionMode compositionMode
static const GLuint QT_PMV_MATRIX_2_ATTR
QList< QGLEngineShaderProg * > cachedPrograms
QGLShaderProgram * simpleProgram()
QGLEngineSharedShaders::SnippetName compositionFragShader
bool operator==(const QGLEngineShaderProg &other)
#define Q_OBJECT
Definition: qobjectdefs.h:157
void setHasComplexGeometry(bool hasComplexGeometry)
#define Q_GADGET
Definition: qobjectdefs.h:173
static const GLuint QT_PMV_MATRIX_1_ATTR
static const GLuint QT_TEXTURE_COORDS_ATTR
QGLEngineSharedShaders::SnippetName srcPixelFragShader
static const GLuint QT_VERTEX_COORDS_ATTR
QGLEngineSharedShaders * sharedShaders
#define class
#define QT_END_HEADER
Definition: qglobal.h:137
The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
The QList class is a template class that provides lists.
Definition: qdatastream.h:62