1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsgmaterial.h"
41#include "qsgrenderer_p.h"
42
43QT_BEGIN_NAMESPACE
44
45#ifndef QT_NO_DEBUG
46bool qsg_material_failure = false;
47bool qsg_test_and_clear_material_failure()
48{
49 bool fail = qsg_material_failure;
50 qsg_material_failure = false;
51 return fail;
52}
53
54void qsg_set_material_failure()
55{
56 qsg_material_failure = true;
57}
58#endif
59
60#ifndef QT_NO_DEBUG
61static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty(varName: "QML_LEAK_CHECK");
62#endif
63
64/*!
65 \group qtquick-scenegraph-materials
66 \title Qt Quick Scene Graph Material Classes
67 \brief classes used to define materials in the Qt Quick Scene Graph.
68
69 This page lists the material classes in \l {Qt Quick}'s
70 \l {scene graph}{Qt Quick Scene Graph}.
71 */
72
73#ifndef QT_NO_DEBUG
74static int qt_material_count = 0;
75
76static void qt_print_material_count()
77{
78 qDebug(msg: "Number of leaked materials: %i", qt_material_count);
79 qt_material_count = -1;
80}
81#endif
82
83/*!
84 \class QSGMaterialType
85 \brief The QSGMaterialType class is used as a unique type token in combination with QSGMaterial.
86 \inmodule QtQuick
87 \ingroup qtquick-scenegraph-materials
88
89 It serves no purpose outside the QSGMaterial::type() function.
90
91 \note All classes with QSG prefix should be used solely on the scene graph's
92 rendering thread. See \l {Scene Graph and Rendering} for more information.
93 */
94
95/*!
96 \class QSGMaterial
97 \brief The QSGMaterial class encapsulates rendering state for a shader program.
98 \inmodule QtQuick
99 \ingroup qtquick-scenegraph-materials
100
101 The QSGMaterial, QSGMaterialShader and QSGMaterialRhiShader subclasses
102 form a tight relationship. For one scene graph (including nested graphs),
103 there is one unique QSGMaterialShader or QSGMaterialRhiShader instance
104 which encapsulates the shaders the scene graph uses to render that
105 material, such as a shader to flat coloring of geometry. Each
106 QSGGeometryNode can have a unique QSGMaterial containing the how the shader
107 should be configured when drawing that node, such as the actual color to
108 used to render the geometry.
109
110 QSGMaterial has two virtual functions that both need to be implemented. The
111 function type() should return a unique instance for all instances of a
112 specific subclass. The createShader() function should return a new instance
113 of QSGMaterialShader or QSGMaterialRhiShader, specific to that subclass of
114 QSGMaterial.
115
116 A minimal QSGMaterial implementation could look like this:
117 \code
118 class Material : public QSGMaterial
119 {
120 public:
121 QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
122 QSGMaterialShader *createShader() const { return new Shader; }
123 };
124 \endcode
125
126 This is suitable only for the OpenGL-based, traditional renderer of the
127 scene graph. When using the new, graphics API abstracted renderer,
128 materials must create QSGMaterialRhiShader instances instead, or in
129 addition:
130 \code
131 class Material : public QSGMaterial
132 {
133 public:
134 Material() { setFlag(SupportsRhiShader, true); }
135 QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
136 QSGMaterialShader *createShader() {
137 if (flags().testFlag(RhiShaderWanted)) {
138 return new RhiShader;
139 } else {
140 // this is optional, relevant for materials that intend to be usable with the legacy OpenGL renderer as well
141 return new Shader;
142 }
143 }
144 };
145 \endcode
146
147 \note All classes with QSG prefix should be used solely on the scene graph's
148 rendering thread. See \l {Scene Graph and Rendering} for more information.
149 */
150
151/*!
152 \internal
153 */
154
155QSGMaterial::QSGMaterial()
156{
157 Q_UNUSED(m_reserved);
158#ifndef QT_NO_DEBUG
159 if (qsg_leak_check) {
160 ++qt_material_count;
161 static bool atexit_registered = false;
162 if (!atexit_registered) {
163 atexit(func: qt_print_material_count);
164 atexit_registered = true;
165 }
166 }
167#endif
168}
169
170
171/*!
172 \internal
173 */
174
175QSGMaterial::~QSGMaterial()
176{
177#ifndef QT_NO_DEBUG
178 if (qsg_leak_check) {
179 --qt_material_count;
180 if (qt_material_count < 0)
181 qDebug(msg: "Material destroyed after qt_print_material_count() was called.");
182 }
183#endif
184}
185
186
187
188/*!
189 \enum QSGMaterial::Flag
190
191 \value Blending Set this flag to true if the material requires GL_BLEND to be
192 enabled during rendering.
193
194 \value RequiresDeterminant Set this flag to true if the material relies on
195 the determinant of the matrix of the geometry nodes for rendering.
196
197 \value RequiresFullMatrixExceptTranslate Set this flag to true if the material
198 relies on the full matrix of the geometry nodes for rendering, except the translation part.
199
200 \value RequiresFullMatrix Set this flag to true if the material relies on
201 the full matrix of the geometry nodes for rendering.
202
203 \value CustomCompileStep Starting with Qt 5.2, the scene graph will not always call
204 QSGMaterialShader::compile() when its shader program is compiled and linked.
205 Set this flag to enforce that the function is called.
206
207 \value SupportsRhiShader Starting with Qt 5.14, the scene graph supports
208 QSGMaterialRhiShader as an alternative to the OpenGL-specific
209 QSGMaterialShader. Set this flag to indicate createShader() is capable of
210 returning QSGMaterialRhiShader instances when the RhiShaderWanted flag is
211 set.
212
213 \value RhiShaderWanted This flag is set by the scene graph, not by the
214 QSGMaterial. When set, and that can only happen when SupportsRhiShader was
215 set by the material, it indicates that createShader() must return a
216 QSGMaterialRhiShader instance instead of QSGMaterialShader.
217 */
218
219/*!
220 \fn QSGMaterial::Flags QSGMaterial::flags() const
221
222 Returns the material's flags.
223 */
224
225
226
227/*!
228 Sets the flags \a flags on this material if \a on is true;
229 otherwise clears the attribute.
230*/
231
232void QSGMaterial::setFlag(Flags flags, bool on)
233{
234 if (on)
235 m_flags |= flags;
236 else
237 m_flags &= ~flags;
238}
239
240
241
242/*!
243 Compares this material to \a other and returns 0 if they are equal; -1 if
244 this material should sort before \a other and 1 if \a other should sort
245 before.
246
247 The scene graph can reorder geometry nodes to minimize state changes.
248 The compare function is called during the sorting process so that
249 the materials can be sorted to minimize state changes in each
250 call to QSGMaterialShader::updateState().
251
252 The this pointer and \a other is guaranteed to have the same type().
253 */
254
255int QSGMaterial::compare(const QSGMaterial *other) const
256{
257 Q_ASSERT(other && type() == other->type());
258 return qint64(this) - qint64(other);
259}
260
261
262
263/*!
264 \fn QSGMaterialType QSGMaterial::type() const
265
266 This function is called by the scene graph to return a unique instance
267 per subclass.
268 */
269
270
271
272/*!
273 \fn QSGMaterialShader *QSGMaterial::createShader() const
274
275 This function returns a new instance of a the QSGMaterialShader
276 implementatation used to render geometry for a specific implementation
277 of QSGMaterial.
278
279 The function will be called only once for each material type that
280 exists in the scene graph and will be cached internally.
281
282 When the QSGMaterial reports SupportsRhiShader in flags(), the scene graph
283 may request a QSGMaterialRhiShader instead of QSGMaterialShader. This is
284 indicated by having the RhiShaderWanted flag set. In this case the return
285 value must be a QSGRhiMaterialShader subclass.
286*/
287
288QT_END_NAMESPACE
289

source code of qtdeclarative/src/quick/scenegraph/coreapi/qsgmaterial.cpp