src/opengl/gl2paintengineex/qglengineshadermanager_p.h
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     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 struct QGLEngineShaderProg
       
   238 {
       
   239     QGLShader*          mainVertexShader;
       
   240     QGLShader*          positionVertexShader;
       
   241     QGLShader*          mainFragShader;
       
   242     QGLShader*          srcPixelFragShader;
       
   243     QGLShader*          maskFragShader;        // Can be null for no mask
       
   244     QGLShader*          compositionFragShader; // Can be null for GL-handled mode
       
   245     QGLShaderProgram*   program;
       
   246 
       
   247     QVector<uint> uniformLocations;
       
   248 
       
   249     bool                useTextureCoords;
       
   250     bool                useOpacityAttribute;
       
   251 
       
   252     bool operator==(const QGLEngineShaderProg& other) {
       
   253         // We don't care about the program
       
   254         return ( mainVertexShader      == other.mainVertexShader &&
       
   255                  positionVertexShader  == other.positionVertexShader &&
       
   256                  mainFragShader        == other.mainFragShader &&
       
   257                  srcPixelFragShader    == other.srcPixelFragShader &&
       
   258                  maskFragShader        == other.maskFragShader &&
       
   259                  compositionFragShader == other.compositionFragShader
       
   260                );
       
   261     }
       
   262 };
       
   263 
       
   264 /*
       
   265 struct QGLEngineCachedShaderProg
       
   266 {
       
   267     QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain,
       
   268                               QGLEngineShaderManager::ShaderName vertexPosition,
       
   269                               QGLEngineShaderManager::ShaderName fragMain,
       
   270                               QGLEngineShaderManager::ShaderName pixelSrc,
       
   271                               QGLEngineShaderManager::ShaderName mask,
       
   272                               QGLEngineShaderManager::ShaderName composition);
       
   273 
       
   274     int cacheKey;
       
   275     QGLShaderProgram* program;
       
   276 }
       
   277 */
       
   278 
       
   279 static const GLuint QT_VERTEX_COORDS_ATTR  = 0;
       
   280 static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
       
   281 static const GLuint QT_OPACITY_ATTR = 2;
       
   282 
       
   283 class QGLEngineSharedShaders : public QObject
       
   284 {
       
   285     Q_OBJECT
       
   286 public:
       
   287     enum ShaderName {
       
   288         MainVertexShader,
       
   289         MainWithTexCoordsVertexShader,
       
   290         MainWithTexCoordsAndOpacityVertexShader,
       
   291 
       
   292         UntransformedPositionVertexShader,
       
   293         PositionOnlyVertexShader,
       
   294         PositionWithPatternBrushVertexShader,
       
   295         PositionWithLinearGradientBrushVertexShader,
       
   296         PositionWithConicalGradientBrushVertexShader,
       
   297         PositionWithRadialGradientBrushVertexShader,
       
   298         PositionWithTextureBrushVertexShader,
       
   299         AffinePositionWithPatternBrushVertexShader,
       
   300         AffinePositionWithLinearGradientBrushVertexShader,
       
   301         AffinePositionWithConicalGradientBrushVertexShader,
       
   302         AffinePositionWithRadialGradientBrushVertexShader,
       
   303         AffinePositionWithTextureBrushVertexShader,
       
   304 
       
   305         MainFragmentShader_CMO,
       
   306         MainFragmentShader_CM,
       
   307         MainFragmentShader_MO,
       
   308         MainFragmentShader_M,
       
   309         MainFragmentShader_CO,
       
   310         MainFragmentShader_C,
       
   311         MainFragmentShader_O,
       
   312         MainFragmentShader,
       
   313         MainFragmentShader_ImageArrays,
       
   314 
       
   315         ImageSrcFragmentShader,
       
   316         ImageSrcWithPatternFragmentShader,
       
   317         NonPremultipliedImageSrcFragmentShader,
       
   318         CustomImageSrcFragmentShader,
       
   319         SolidBrushSrcFragmentShader,
       
   320         TextureBrushSrcFragmentShader,
       
   321         TextureBrushSrcWithPatternFragmentShader,
       
   322         PatternBrushSrcFragmentShader,
       
   323         LinearGradientBrushSrcFragmentShader,
       
   324         RadialGradientBrushSrcFragmentShader,
       
   325         ConicalGradientBrushSrcFragmentShader,
       
   326         ShockingPinkSrcFragmentShader,
       
   327 
       
   328         MaskFragmentShader,
       
   329         RgbMaskFragmentShaderPass1,
       
   330         RgbMaskFragmentShaderPass2,
       
   331         RgbMaskWithGammaFragmentShader,
       
   332 
       
   333         MultiplyCompositionModeFragmentShader,
       
   334         ScreenCompositionModeFragmentShader,
       
   335         OverlayCompositionModeFragmentShader,
       
   336         DarkenCompositionModeFragmentShader,
       
   337         LightenCompositionModeFragmentShader,
       
   338         ColorDodgeCompositionModeFragmentShader,
       
   339         ColorBurnCompositionModeFragmentShader,
       
   340         HardLightCompositionModeFragmentShader,
       
   341         SoftLightCompositionModeFragmentShader,
       
   342         DifferenceCompositionModeFragmentShader,
       
   343         ExclusionCompositionModeFragmentShader,
       
   344 
       
   345         TotalShaderCount, InvalidShaderName
       
   346     };
       
   347 
       
   348     QGLEngineSharedShaders(const QGLContext *context);
       
   349 
       
   350     QGLShader *compileNamedShader(ShaderName name, QGLShader::ShaderType type);
       
   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     QGLShader *compileCustomShader(QGLCustomShaderStage *stage, QGLShader::ShaderType type);
       
   358 
       
   359     static QGLEngineSharedShaders *shadersForContext(const QGLContext *context);
       
   360 
       
   361 signals:
       
   362     void shaderProgNeedsChanging();
       
   363 
       
   364 private slots:
       
   365     void shaderDestroyed(QObject *shader);
       
   366 
       
   367 private:
       
   368     QGLSharedResourceGuard ctxGuard;
       
   369     QGLShaderProgram *blitShaderProg;
       
   370     QGLShaderProgram *simpleShaderProg;
       
   371     QList<QGLEngineShaderProg> cachedPrograms;
       
   372     QCache<QByteArray, QGLShader> customShaderCache;
       
   373     QGLShader* compiledShaders[TotalShaderCount];
       
   374 
       
   375     static const char* qglEngineShaderSourceCode[TotalShaderCount];
       
   376 };
       
   377 
       
   378 class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject
       
   379 {
       
   380     Q_OBJECT
       
   381 public:
       
   382     QGLEngineShaderManager(QGLContext* context);
       
   383     ~QGLEngineShaderManager();
       
   384 
       
   385     enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask};
       
   386     enum PixelSrcType {
       
   387         ImageSrc = Qt::TexturePattern+1,
       
   388         NonPremultipliedImageSrc = Qt::TexturePattern+2,
       
   389         PatternSrc = Qt::TexturePattern+3,
       
   390         TextureSrcWithPattern = Qt::TexturePattern+4
       
   391     };
       
   392 
       
   393     enum Uniform {
       
   394         ImageTexture,
       
   395         PatternColor,
       
   396         GlobalOpacity,
       
   397         Depth,
       
   398         PmvMatrix,
       
   399         MaskTexture,
       
   400         FragmentColor,
       
   401         LinearData,
       
   402         Angle,
       
   403         HalfViewportSize,
       
   404         Fmp,
       
   405         Fmp2MRadius2,
       
   406         Inverse2Fmp2MRadius2,
       
   407         InvertedTextureSize,
       
   408         BrushTransform,
       
   409         BrushTexture,
       
   410         NumUniforms
       
   411     };
       
   412 
       
   413     enum OpacityMode {
       
   414         NoOpacity,
       
   415         UniformOpacity,
       
   416         AttributeOpacity
       
   417     };
       
   418 
       
   419     // There are optimisations we can do, depending on the brush transform:
       
   420     //    1) May not have to apply perspective-correction
       
   421     //    2) Can use lower precision for matrix
       
   422     void optimiseForBrushTransform(const QTransform &transform);
       
   423     void setSrcPixelType(Qt::BrushStyle);
       
   424     void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
       
   425     void setOpacityMode(OpacityMode);
       
   426     void setMaskType(MaskType);
       
   427     void setCompositionMode(QPainter::CompositionMode);
       
   428     void setCustomStage(QGLCustomShaderStage* stage);
       
   429     void removeCustomStage(QGLCustomShaderStage* stage);
       
   430 
       
   431     uint getUniformLocation(Uniform id);
       
   432 
       
   433     void setDirty(); // someone has manually changed the current shader program
       
   434     bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
       
   435 
       
   436     QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
       
   437     QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
       
   438     QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
       
   439 
       
   440 /*
       
   441     // These allow the ShaderName enum to be used as a cache key
       
   442     const int mainVertexOffset = 0;
       
   443     const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader;
       
   444     const int mainFragOffset = (1<<6) - MainFragmentShader_CMO;
       
   445     const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader;
       
   446     const int maskOffset = (1<<14) - NoMaskShader;
       
   447     const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
       
   448 */
       
   449 
       
   450 #if defined (QT_DEBUG)
       
   451     Q_ENUMS(ShaderName)
       
   452 #endif
       
   453 
       
   454 private slots:
       
   455     void shaderProgNeedsChangingSlot() { shaderProgNeedsChanging = true; }
       
   456 
       
   457 private:
       
   458     QGLContext*     ctx;
       
   459     bool            shaderProgNeedsChanging;
       
   460 
       
   461     // Current state variables which influence the choice of shader:
       
   462     QTransform                  brushTransform;
       
   463     int                         srcPixelType;
       
   464     OpacityMode                 opacityMode;
       
   465     MaskType                    maskType;
       
   466     QPainter::CompositionMode   compositionMode;
       
   467     QGLCustomShaderStage*       customSrcStage;
       
   468 
       
   469     QGLEngineShaderProg*  currentShaderProg;
       
   470     QGLEngineSharedShaders *sharedShaders;
       
   471     QGLShader *customShader;
       
   472 };
       
   473 
       
   474 QT_END_NAMESPACE
       
   475 
       
   476 QT_END_HEADER
       
   477 
       
   478 #endif //QGLENGINE_SHADER_MANAGER_H