doc: fix some more typos
[profile/ivi/qtdeclarative.git] / src / quick / scenegraph / coreapi / qsgmaterial.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
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