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 | |
43 | QT_BEGIN_NAMESPACE |
44 | |
45 | #ifndef QT_NO_DEBUG |
46 | bool qsg_material_failure = false; |
47 | bool qsg_test_and_clear_material_failure() |
48 | { |
49 | bool fail = qsg_material_failure; |
50 | qsg_material_failure = false; |
51 | return fail; |
52 | } |
53 | |
54 | void qsg_set_material_failure() |
55 | { |
56 | qsg_material_failure = true; |
57 | } |
58 | #endif |
59 | |
60 | #ifndef QT_NO_DEBUG |
61 | static 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 |
74 | static int qt_material_count = 0; |
75 | |
76 | static 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 | |
155 | QSGMaterial::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 | |
175 | QSGMaterial::~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 | |
232 | void 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 | |
255 | int 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 | |
288 | QT_END_NAMESPACE |
289 | |