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