~saviq/ubuntu/saucy/qtdeclarative-opensource-src/add-qtquick-delegate-range

« back to all changes in this revision

Viewing changes to src/quick/scenegraph/coreapi/qsgmaterial.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 14:17:19 UTC
  • Revision ID: package-import@ubuntu.com-20130205141719-qqeyml8wslpyez52
Tags: upstream-5.0.1
ImportĀ upstreamĀ versionĀ 5.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtQml 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
#include "qsgmaterial.h"
 
43
#include "qsgrenderer_p.h"
 
44
 
 
45
QT_BEGIN_NAMESPACE
 
46
 
 
47
 
 
48
/*!
 
49
    \class QSGMaterialShader
 
50
    \brief The QSGMaterialShader class represents an OpenGL shader program
 
51
    in the renderer.
 
52
    \inmodule QtQuick
 
53
 
 
54
    The QSGMaterialShader API is very low-level. A more convenient API, which
 
55
    provides almost all the same features, is available through
 
56
    QSGSimpleMaterialShader.
 
57
 
 
58
    The QSGMaterial and QSGMaterialShader form a tight relationship. For one
 
59
    scene graph (including nested graphs), there is one unique QSGMaterialShader
 
60
    instance which encapsulates the QOpenGLShaderProgram the scene graph uses
 
61
    to render that material, such as a shader to flat coloring of geometry.
 
62
    Each QSGGeometryNode can have a unique QSGMaterial containing the
 
63
    how the shader should be configured when drawing that node, such as
 
64
    the actual color used to render the geometry.
 
65
 
 
66
    An instance of QSGMaterialShader is never created explicitly by the user,
 
67
    it will be created on demand by the scene graph through
 
68
    QSGMaterial::createShader(). The scene graph will make sure that there
 
69
    is only one instance of each shader implementation through a scene graph.
 
70
 
 
71
    The source code returned from vertexShader() is used to control what the
 
72
    material does with the vertiex data that comes in from the geometry.
 
73
    The source code returned from the fragmentShader() is used to control
 
74
    what how the material should fill each individual pixel in the geometry.
 
75
    The vertex and fragment source code is queried once during initialization,
 
76
    changing what is returned from these functions later will not have
 
77
    any effect.
 
78
 
 
79
    The activate() function is called by the scene graph when a shader is
 
80
    is starting to be used. The deactivate function is called by the scene
 
81
    graph when the shader is no longer going to be used. While active,
 
82
    the scene graph may make one or more calls to updateState() which
 
83
    will update the state of the shader for each individual geometry to
 
84
    render.
 
85
 
 
86
    The attributeNames() returns the name of the attributes used in the
 
87
    vertexShader(). These are used in the default implementation of
 
88
    activate() and deactivate() to decide whice vertex registers are enabled.
 
89
 
 
90
    The initialize() function is called during program creation to allow
 
91
    subclasses to prepare for use, such as resolve uniform names in the
 
92
    vertexShader() and fragmentShader().
 
93
 
 
94
    A minimal example:
 
95
    \code
 
96
        class Shader : public QSGMaterialShader
 
97
        {
 
98
        public:
 
99
            const char *vertexShader() const {
 
100
                return
 
101
                "attribute highp vec4 vertex;          \n"
 
102
                "uniform highp mat4 matrix;            \n"
 
103
                "void main() {                         \n"
 
104
                "    gl_Position = matrix * vertex;    \n"
 
105
                "}";
 
106
            }
 
107
 
 
108
            const char *fragmentShader() const {
 
109
                return
 
110
                "uniform lowp float opacity;                            \n"
 
111
                "void main() {                                          \n"
 
112
                        "    gl_FragColor = vec4(1, 0, 0, 1) * opacity; \n"
 
113
                "}";
 
114
            }
 
115
 
 
116
            char const *const *attributeNames() const
 
117
            {
 
118
                static char const *const names[] = { "vertex", 0 };
 
119
                return names;
 
120
            }
 
121
 
 
122
            void initialize()
 
123
            {
 
124
                QSGMaterialShader::initialize();
 
125
                m_id_matrix = program()->uniformLocation("matrix");
 
126
                m_id_opacity = program()->uniformLocation("opacity");
 
127
            }
 
128
 
 
129
            void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
 
130
            {
 
131
                Q_ASSERT(program()->isLinked());
 
132
                if (state.isMatrixDirty())
 
133
                    program()->setUniformValue(m_id_matrix, state.combinedMatrix());
 
134
                if (state.isOpacityDirty())
 
135
                    program()->setUniformValue(m_id_opacity, state.opacity());
 
136
            }
 
137
 
 
138
        private:
 
139
            int m_id_matrix;
 
140
            int m_id_opacity;
 
141
        };
 
142
    \endcode
 
143
 
 
144
    \warning Instances of QSGMaterialShader belongs to the Scene Graph rendering
 
145
    thread, and cannot be used from the GUI thread.
 
146
 
 
147
 */
 
148
 
 
149
 
 
150
 
 
151
/*!
 
152
    Creates a new QSGMaterialShader.
 
153
 */
 
154
QSGMaterialShader::QSGMaterialShader()
 
155
{
 
156
}
 
157
 
 
158
/*!
 
159
    \fn QSGMaterialShader::~QSGMaterialShader()
 
160
    \internal
 
161
 */
 
162
 
 
163
/*!
 
164
    \fn char const *const *QSGMaterialShader::attributeNames() const
 
165
 
 
166
    Returns a zero-terminated array describing the names of the
 
167
    attributes used in the vertex shader.
 
168
 
 
169
    This function is called when the shader is compiled to specify
 
170
    which attributes exist. The order of the attribute names
 
171
    defines the attribute register position in the vertex shader.
 
172
 */
 
173
 
 
174
 
 
175
/*!
 
176
    \fn const char *QSGMaterialShader::vertexShader() const
 
177
 
 
178
    Called when the shader is being initialized to get the vertex
 
179
    shader source code.
 
180
 
 
181
    The contents returned from this function should never change.
 
182
*/
 
183
 
 
184
 
 
185
/*!
 
186
   \fn const char *QSGMaterialShader::fragmentShader() const
 
187
 
 
188
    Called when the shader is being initialized to get the fragment
 
189
    shader source code.
 
190
 
 
191
    The contents returned from this function should never change.
 
192
*/
 
193
 
 
194
 
 
195
/*!
 
196
    \fn QOpenGLShaderProgram *QSGMaterialShader::program()
 
197
 
 
198
    Returns the shader program used by this QSGMaterialShader.
 
199
 */
 
200
 
 
201
 
 
202
/*!
 
203
    \fn void QSGMaterialShader::initialize()
 
204
 
 
205
    Reimplement this function to do one-time initialization when the
 
206
    shader program is compiled. The OpenGL shader program is compiled
 
207
    and linked, but not bound, when this function is called.
 
208
 */
 
209
 
 
210
 
 
211
/*!
 
212
    This function is called by the scene graph to indicate that geometry is
 
213
    about to be rendered using this shader.
 
214
 
 
215
    State that is global for all uses of the shader, independent of the geometry
 
216
    that is being drawn, can be setup in this function.
 
217
 
 
218
    If reimplemented, make sure to either call the base class implementation to
 
219
    enable the vertex attribute registers.
 
220
 */
 
221
 
 
222
void QSGMaterialShader::activate()
 
223
{
 
224
    Q_ASSERT(program()->isLinked());
 
225
 
 
226
    program()->bind();
 
227
    char const *const *attr = attributeNames();
 
228
    for (int i = 0; attr[i]; ++i) {
 
229
        if (*attr[i])
 
230
            program()->enableAttributeArray(i);
 
231
    }
 
232
}
 
233
 
 
234
 
 
235
 
 
236
/*!
 
237
    This function is called by the scene graph to indicate that geometry will
 
238
    no longer to be rendered using this shader.
 
239
 
 
240
    If reimplemented, make sure to either call the base class implementation to
 
241
    disable the vertex attribute registers.
 
242
 */
 
243
 
 
244
void QSGMaterialShader::deactivate()
 
245
{
 
246
    char const *const *attr = attributeNames();
 
247
    for (int i = 0; attr[i]; ++i) {
 
248
        if (*attr[i])
 
249
            program()->disableAttributeArray(i);
 
250
    }
 
251
}
 
252
 
 
253
 
 
254
 
 
255
/*!
 
256
    This function is called by the scene graph before geometry is rendered
 
257
    to make sure the shader is in the right state.
 
258
 
 
259
    The current rendering \a state is passed from the scene graph. If the state
 
260
    indicates that any state is dirty, the updateState implementation must
 
261
    update accordingly for the geometry to render correctly.
 
262
 
 
263
    The subclass specific state, such as the color of a flat color material, should
 
264
    be extracted from \a newMaterial to update the color uniforms accordingly.
 
265
 
 
266
    The \a oldMaterial can be used to minimze state changes when updating
 
267
    material states. The \a oldMaterial is 0 if this shader was just activated.
 
268
 
 
269
    \sa activate(), deactivate()
 
270
 */
 
271
 
 
272
void QSGMaterialShader::updateState(const RenderState & /* state */, QSGMaterial * /* newMaterial */, QSGMaterial * /* oldMaterial */)
 
273
{
 
274
}
 
275
 
 
276
 
 
277
 
 
278
/*!
 
279
    This function is called when the shader is initialized to compile the
 
280
    actual QOpenGLShaderProgram. Do not call it explicitly.
 
281
 
 
282
    The default implementation will extract the vertexShader() and
 
283
    fragmentShader() and bind the names returned from attributeNames()
 
284
    to consecutive vertex attribute registers starting at 0.
 
285
 */
 
286
 
 
287
void QSGMaterialShader::compile()
 
288
{
 
289
    Q_ASSERT_X(!m_program.isLinked(), "QSGSMaterialShader::compile()", "Compile called multiple times!");
 
290
 
 
291
    program()->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader());
 
292
    program()->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader());
 
293
 
 
294
    char const *const *attr = attributeNames();
 
295
#ifndef QT_NO_DEBUG
 
296
    int maxVertexAttribs = 0;
 
297
    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
 
298
    for (int i = 0; attr[i]; ++i) {
 
299
        if (i >= maxVertexAttribs) {
 
300
            qFatal("List of attribute names is either too long or not null-terminated.\n"
 
301
                   "Maximum number of attributes on this hardware is %i.\n"
 
302
                   "Vertex shader:\n%s\n"
 
303
                   "Fragment shader:\n%s\n",
 
304
                   maxVertexAttribs, vertexShader(), fragmentShader());
 
305
        }
 
306
        if (*attr[i])
 
307
            program()->bindAttributeLocation(attr[i], i);
 
308
    }
 
309
#else
 
310
    for (int i = 0; attr[i]; ++i) {
 
311
        if (*attr[i])
 
312
            program()->bindAttributeLocation(attr[i], i);
 
313
    }
 
314
#endif
 
315
 
 
316
    if (!program()->link()) {
 
317
        qWarning("QSGMaterialShader: Shader compilation failed:");
 
318
        qWarning() << program()->log();
 
319
    }
 
320
}
 
321
 
 
322
 
 
323
 
 
324
/*!
 
325
    \class QSGMaterialShader::RenderState
 
326
    \brief The QSGMaterialShader::RenderState encapsulates the current rendering state
 
327
    during a call to QSGMaterialShader::updateState().
 
328
 
 
329
    The render state contains a number of accessors that the shader needs to respect
 
330
    in order to conform to the current state of the scene graph.
 
331
 
 
332
    The instance is only valid inside a call to QSGMaterialShader::updateState() and
 
333
    should not be used outisde this function.
 
334
 */
 
335
 
 
336
 
 
337
 
 
338
/*!
 
339
    \enum QSGMaterialShader::RenderState::DirtyState
 
340
 
 
341
    \value DirtyMatrix Used to indicate that the matrix has changed and must be updated.
 
342
 
 
343
    \value DirtyOpacity Used to indicate that the opacity has changed and must be updated.
 
344
 */
 
345
 
 
346
 
 
347
 
 
348
/*!
 
349
    \fn bool QSGMaterialShader::RenderState::isMatrixDirty() const
 
350
 
 
351
    Returns \c true if the dirtyStates() contain the dirty matrix state,
 
352
    otherwise returns \c false.
 
353
 */
 
354
 
 
355
 
 
356
 
 
357
/*!
 
358
    \fn bool QSGMaterialShader::RenderState::isOpacityDirty() const
 
359
 
 
360
    Returns \c true if the dirtyStates() contains the dirty opacity state,
 
361
    otherwise returns \c false.
 
362
 */
 
363
 
 
364
 
 
365
 
 
366
/*!
 
367
    \fn QSGMaterialShader::RenderState::DirtyStates QSGMaterialShader::RenderState::dirtyStates() const
 
368
 
 
369
    Returns which rendering states that have changed and needs to be updated
 
370
    for geometry rendered with this material to conform to the current
 
371
    rendering state.
 
372
 */
 
373
 
 
374
 
 
375
 
 
376
/*!
 
377
    Returns the accumulated opacity to be used for rendering.
 
378
 */
 
379
 
 
380
float QSGMaterialShader::RenderState::opacity() const
 
381
{
 
382
    Q_ASSERT(m_data);
 
383
    return static_cast<const QSGRenderer *>(m_data)->currentOpacity();
 
384
}
 
385
 
 
386
/*!
 
387
    Returns the modelview determinant to be used for rendering.
 
388
 */
 
389
 
 
390
float QSGMaterialShader::RenderState::determinant() const
 
391
{
 
392
    Q_ASSERT(m_data);
 
393
    return static_cast<const QSGRenderer *>(m_data)->determinant();
 
394
}
 
395
 
 
396
/*!
 
397
    Returns the matrix combined of modelview matrix and project matrix.
 
398
 */
 
399
 
 
400
QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const
 
401
{
 
402
    Q_ASSERT(m_data);
 
403
    return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix();
 
404
}
 
405
 
 
406
 
 
407
 
 
408
/*!
 
409
    Returns the model view matrix.
 
410
 
 
411
    If the material has the RequiresFullMatrix flag
 
412
    set, this is guaranteed to be the complete transform
 
413
    matrix calculated from the scenegraph.
 
414
 
 
415
    However, if this flag is not set, the renderer may
 
416
    choose to alter this matrix. For example, it may
 
417
    pre-transform vertices on the CPU and set this matrix
 
418
    to identity.
 
419
 
 
420
    In a situation such as the above, it is still possible
 
421
    to retrieve the actual matrix determinant by setting
 
422
    the RequiresDeterminant flag in the material and
 
423
    calling the determinant() accessor.
 
424
 */
 
425
 
 
426
QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const
 
427
{
 
428
    Q_ASSERT(m_data);
 
429
    return static_cast<const QSGRenderer *>(m_data)->currentModelViewMatrix();
 
430
}
 
431
 
 
432
 
 
433
 
 
434
/*!
 
435
    Returns the viewport rect of the surface being rendered to.
 
436
 */
 
437
 
 
438
QRect QSGMaterialShader::RenderState::viewportRect() const
 
439
{
 
440
    Q_ASSERT(m_data);
 
441
    return static_cast<const QSGRenderer *>(m_data)->viewportRect();
 
442
}
 
443
 
 
444
 
 
445
 
 
446
/*!
 
447
    Returns the device rect of the surface being rendered to
 
448
 */
 
449
 
 
450
QRect QSGMaterialShader::RenderState::deviceRect() const
 
451
{
 
452
    Q_ASSERT(m_data);
 
453
    return static_cast<const QSGRenderer *>(m_data)->deviceRect();
 
454
}
 
455
 
 
456
 
 
457
 
 
458
/*!
 
459
    Returns the QOpenGLContext that is being used for rendering
 
460
 */
 
461
 
 
462
QOpenGLContext *QSGMaterialShader::RenderState::context() const
 
463
{
 
464
    return static_cast<const QSGRenderer *>(m_data)->glContext();
 
465
}
 
466
 
 
467
 
 
468
#ifndef QT_NO_DEBUG
 
469
static int qt_material_count = 0;
 
470
 
 
471
static void qt_print_material_count()
 
472
{
 
473
    qDebug("Number of leaked materials: %i", qt_material_count);
 
474
    qt_material_count = -1;
 
475
}
 
476
#endif
 
477
 
 
478
/*!
 
479
    \class QSGMaterialType
 
480
    \brief The QSGMaterialType class is used as a unique type token in combination with QSGMaterial.
 
481
    \inmodule QtQuick
 
482
 
 
483
    It serves no purpose outside the QSGMaterial::type() function.
 
484
 */
 
485
 
 
486
/*!
 
487
    \class QSGMaterial
 
488
    \brief The QSGMaterial class encapsulates rendering state for a shader program.
 
489
    \inmodule QtQuick
 
490
 
 
491
    The QSGMaterial API is very low-level. A more convenient API, which
 
492
    provides almost all the same features, is available through
 
493
    QSGSimpleMaterialShader.
 
494
 
 
495
    The QSGMaterial and QSGMaterialShader subclasses form a tight relationship. For
 
496
    one scene graph (including nested graphs), there is one unique QSGMaterialShader
 
497
    instance which encapsulates the QOpenGLShaderProgram the scene graph uses
 
498
    to render that material, such as a shader to flat coloring of geometry.
 
499
    Each QSGGeometryNode can have a unique QSGMaterial containing the
 
500
    how the shader should be configured when drawing that node, such as
 
501
    the actual color to used to render the geometry.
 
502
 
 
503
    The QSGMaterial has two virtual functions that both need to be implemented.
 
504
    The function type() should return a unique instance for all instances of a
 
505
    specific subclass. The createShader() function should return a new instance
 
506
    of QSGMaterialShader, specific to the subclass of QSGMaterial.
 
507
 
 
508
    A minimal QSGMaterial implementation could look like this:
 
509
    \code
 
510
        class Material : public QSGMaterial
 
511
        {
 
512
        public:
 
513
            QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
 
514
            QSGMaterialShader *createShader() const { return new Shader; }
 
515
        };
 
516
    \endcode
 
517
 
 
518
    \warning Instances of QSGMaterial belongs to the Scene Graph rendering thread,
 
519
    and cannot be used from the GUI thread.
 
520
 */
 
521
 
 
522
/*!
 
523
    \internal
 
524
 */
 
525
 
 
526
QSGMaterial::QSGMaterial()
 
527
    : m_flags(0)
 
528
{
 
529
#ifndef QT_NO_DEBUG
 
530
    ++qt_material_count;
 
531
    static bool atexit_registered = false;
 
532
    if (!atexit_registered) {
 
533
        atexit(qt_print_material_count);
 
534
        atexit_registered = true;
 
535
    }
 
536
#endif
 
537
}
 
538
 
 
539
 
 
540
/*!
 
541
    \internal
 
542
 */
 
543
 
 
544
QSGMaterial::~QSGMaterial()
 
545
{
 
546
#ifndef QT_NO_DEBUG
 
547
    --qt_material_count;
 
548
    if (qt_material_count < 0)
 
549
        qDebug("Material destroyed after qt_print_material_count() was called.");
 
550
#endif
 
551
}
 
552
 
 
553
 
 
554
 
 
555
/*!
 
556
    \enum QSGMaterial::Flag
 
557
 
 
558
    \value Blending Set this flag to true if the material requires GL_BLEND to be
 
559
    enabled during rendering.
 
560
 
 
561
    \value RequiresDeterminant Set this flag to true if the material relies on
 
562
    the determinant of the matrix of the geometry nodes for rendering.
 
563
 
 
564
    \value RequiresFullMatrixExceptTranslate Set this flag to true if the material
 
565
    relies on the full matrix of the geometry nodes for rendering, except the translation part.
 
566
 
 
567
    \value RequiresFullMatrix Set this flag to true if the material relies on
 
568
    the full matrix of the geometry nodes for rendering.
 
569
 */
 
570
 
 
571
/*!
 
572
    \fn QSGMaterial::Flags QSGMaterial::flags() const
 
573
 
 
574
    Returns the material's flags.
 
575
 */
 
576
 
 
577
 
 
578
 
 
579
/*!
 
580
    Sets the flags \a flags on this material if \a on is true;
 
581
    otherwise clears the attribute.
 
582
*/
 
583
 
 
584
void QSGMaterial::setFlag(Flags flags, bool on)
 
585
{
 
586
    if (on)
 
587
        m_flags |= flags;
 
588
    else
 
589
        m_flags &= ~flags;
 
590
}
 
591
 
 
592
 
 
593
 
 
594
/*!
 
595
    Compares this material to \a other and returns 0 if they are equal; -1 if
 
596
    this material should sort before \a other and 1 if \a other should sort
 
597
    before.
 
598
 
 
599
    The scene graph can reorder geometry nodes to minimize state changes.
 
600
    The compare function is called during the sorting process so that
 
601
    the materials can be sorted to minimize state changes in each
 
602
    call to QSGMaterialShader::updateState().
 
603
 
 
604
    The this pointer and \a other is guaranteed to have the same type().
 
605
 */
 
606
 
 
607
int QSGMaterial::compare(const QSGMaterial *other) const
 
608
{
 
609
    Q_ASSERT(other && type() == other->type());
 
610
    return qint64(this) - qint64(other);
 
611
}
 
612
 
 
613
 
 
614
 
 
615
/*!
 
616
    \fn QSGMaterialType QSGMaterial::type() const
 
617
 
 
618
    This function is called by the scene graph to return a unique instance
 
619
    per subclass.
 
620
 */
 
621
 
 
622
 
 
623
 
 
624
/*!
 
625
    \fn QSGMaterialShader *QSGMaterial::createShader() const
 
626
 
 
627
    This function returns a new instance of a the QSGMaterialShader
 
628
    implementatation used to render geometry for a specific implementation
 
629
    of QSGMaterial.
 
630
 
 
631
    The function will be called only once for each material type that
 
632
    exists in the scene graph and will be cached internally.
 
633
*/
 
634
 
 
635
 
 
636
QT_END_NAMESPACE