~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/opengl/gl2paintengineex/qglengineshadermanager_p.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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