1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qsgmaterial.h" |
5 | #include "qsgrenderer_p.h" |
6 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | #ifndef QT_NO_DEBUG |
10 | bool qsg_material_failure = false; |
11 | bool qsg_test_and_clear_material_failure() |
12 | { |
13 | bool fail = qsg_material_failure; |
14 | qsg_material_failure = false; |
15 | return fail; |
16 | } |
17 | |
18 | void qsg_set_material_failure() |
19 | { |
20 | qsg_material_failure = true; |
21 | } |
22 | #endif |
23 | |
24 | /*! |
25 | \group qtquick-scenegraph-materials |
26 | \title Qt Quick Scene Graph Material Classes |
27 | \brief classes used to define materials in the Qt Quick Scene Graph. |
28 | |
29 | This page lists the material classes in \l {Qt Quick}'s |
30 | \l {scene graph}{Qt Quick Scene Graph}. |
31 | */ |
32 | |
33 | #ifndef QT_NO_DEBUG |
34 | static int qt_material_count = 0; |
35 | |
36 | static void qt_print_material_count() |
37 | { |
38 | qDebug(msg: "Number of leaked materials: %i" , qt_material_count); |
39 | qt_material_count = -1; |
40 | } |
41 | #endif |
42 | |
43 | /*! |
44 | \class QSGMaterialType |
45 | \brief The QSGMaterialType class is used as a unique type token in combination with QSGMaterial. |
46 | \inmodule QtQuick |
47 | \ingroup qtquick-scenegraph-materials |
48 | |
49 | It serves no purpose outside the QSGMaterial::type() function. |
50 | |
51 | \note All classes with QSG prefix should be used solely on the scene graph's |
52 | rendering thread. See \l {Scene Graph and Rendering} for more information. |
53 | */ |
54 | |
55 | /*! |
56 | \class QSGMaterial |
57 | \brief The QSGMaterial class encapsulates rendering state for a shader program. |
58 | \inmodule QtQuick |
59 | \ingroup qtquick-scenegraph-materials |
60 | |
61 | QSGMaterial and QSGMaterialShader subclasses form a tight relationship. For |
62 | one scene graph (including nested graphs), there is one unique |
63 | QSGMaterialShader instance which encapsulates the shaders the scene graph |
64 | uses to render that material, such as a shader to flat coloring of |
65 | geometry. Each QSGGeometryNode can have a unique QSGMaterial containing the |
66 | how the shader should be configured when drawing that node, such as the |
67 | actual color to used to render the geometry. |
68 | |
69 | QSGMaterial has two virtual functions that both need to be implemented. The |
70 | function type() should return a unique instance for all instances of a |
71 | specific subclass. The createShader() function should return a new instance |
72 | of QSGMaterialShader, specific to that subclass of QSGMaterial. |
73 | |
74 | A minimal QSGMaterial implementation could look like this: |
75 | \code |
76 | class Material : public QSGMaterial |
77 | { |
78 | public: |
79 | QSGMaterialType *type() const override { static QSGMaterialType type; return &type; } |
80 | QSGMaterialShader *createShader(QSGRendererInterface::RenderMode) const override { return new Shader; } |
81 | }; |
82 | \endcode |
83 | |
84 | See the \l{Scene Graph - Custom Material}{Custom Material example} for an introduction |
85 | on implementing a QQuickItem subclass backed by a QSGGeometryNode and a custom |
86 | material. |
87 | |
88 | \note createShader() is called only once per QSGMaterialType, to reduce |
89 | redundant work with shader preparation. If a QSGMaterial is backed by |
90 | multiple sets of vertex and fragment shader combinations, the implementation |
91 | of type() must return a different, unique QSGMaterialType pointer for each |
92 | combination of shaders. |
93 | |
94 | \note All classes with QSG prefix should be used solely on the scene graph's |
95 | rendering thread. See \l {Scene Graph and Rendering} for more information. |
96 | |
97 | \sa QSGMaterialShader, {Scene Graph - Custom Material}, {Scene Graph - Two Texture Providers}, {Scene Graph - Graph} |
98 | */ |
99 | |
100 | /*! |
101 | \internal |
102 | */ |
103 | |
104 | QSGMaterial::QSGMaterial() |
105 | { |
106 | Q_UNUSED(m_reserved); |
107 | #ifndef QT_NO_DEBUG |
108 | if (_q_sg_leak_check) { |
109 | ++qt_material_count; |
110 | static bool atexit_registered = false; |
111 | if (!atexit_registered) { |
112 | atexit(func: qt_print_material_count); |
113 | atexit_registered = true; |
114 | } |
115 | } |
116 | #endif |
117 | } |
118 | |
119 | |
120 | /*! |
121 | \internal |
122 | */ |
123 | |
124 | QSGMaterial::~QSGMaterial() |
125 | { |
126 | #ifndef QT_NO_DEBUG |
127 | if (_q_sg_leak_check) { |
128 | --qt_material_count; |
129 | if (qt_material_count < 0) |
130 | qDebug(msg: "Material destroyed after qt_print_material_count() was called." ); |
131 | } |
132 | #endif |
133 | } |
134 | |
135 | |
136 | |
137 | /*! |
138 | \enum QSGMaterial::Flag |
139 | |
140 | \value Blending Set this flag to true if the material requires blending to be |
141 | enabled during rendering. |
142 | |
143 | \value RequiresDeterminant Set this flag to true if the material relies on |
144 | the determinant of the matrix of the geometry nodes for rendering. |
145 | |
146 | \value RequiresFullMatrixExceptTranslate Set this flag to true if the material |
147 | relies on the full matrix of the geometry nodes for rendering, except the translation part. |
148 | |
149 | \value RequiresFullMatrix Set this flag to true if the material relies on |
150 | the full matrix of the geometry nodes for rendering. |
151 | |
152 | \value NoBatching Set this flag to true if the material uses shaders that are |
153 | incompatible with the \l{Qt Quick Scene Graph Default Renderer}{scene graph's batching |
154 | mechanism}. This is relevant in certain advanced usages, such as, directly |
155 | manipulating \c{gl_Position.z} in the vertex shader. Such solutions are often tied to |
156 | a specific scene structure, and are likely not safe to use with arbitrary contents in |
157 | a scene. Thus this flag should only be set after appropriate investigation, and will |
158 | never be needed for the vast majority of materials. Setting this flag can lead to |
159 | reduced performance due to having to issue more draw calls. This flag was introduced |
160 | in Qt 6.3. |
161 | |
162 | \value CustomCompileStep In Qt 6 this flag is identical to NoBatching. Prefer using |
163 | NoBatching instead. |
164 | */ |
165 | |
166 | /*! |
167 | \fn QSGMaterial::Flags QSGMaterial::flags() const |
168 | |
169 | Returns the material's flags. |
170 | */ |
171 | |
172 | |
173 | |
174 | /*! |
175 | Sets the flags \a flags on this material if \a on is true; |
176 | otherwise clears the attribute. |
177 | */ |
178 | |
179 | void QSGMaterial::setFlag(Flags flags, bool on) |
180 | { |
181 | if (on) |
182 | m_flags |= flags; |
183 | else |
184 | m_flags &= ~flags; |
185 | } |
186 | |
187 | |
188 | |
189 | /*! |
190 | Compares this material to \a other and returns 0 if they are equal; -1 if |
191 | this material should sort before \a other and 1 if \a other should sort |
192 | before. |
193 | |
194 | The scene graph can reorder geometry nodes to minimize state changes. |
195 | The compare function is called during the sorting process so that |
196 | the materials can be sorted to minimize state changes in each |
197 | call to QSGMaterialShader::updateState(). |
198 | |
199 | The this pointer and \a other is guaranteed to have the same type(). |
200 | */ |
201 | |
202 | int QSGMaterial::compare(const QSGMaterial *other) const |
203 | { |
204 | Q_ASSERT(other && type() == other->type()); |
205 | const qintptr diff = qintptr(this) - qintptr(other); |
206 | return diff < 0 ? -1 : (diff > 0 ? 1 : 0); |
207 | } |
208 | |
209 | |
210 | |
211 | /*! |
212 | \fn QSGMaterialType *QSGMaterial::type() const |
213 | |
214 | This function is called by the scene graph to query an identifier that is |
215 | unique to the QSGMaterialShader instantiated by createShader(). |
216 | |
217 | For many materials, the typical approach will be to return a pointer to a |
218 | static, and so globally available, QSGMaterialType instance. The |
219 | QSGMaterialType is an opaque object. Its purpose is only to serve as a |
220 | type-safe, simple way to generate unique material identifiers. |
221 | \code |
222 | QSGMaterialType *type() const override |
223 | { |
224 | static QSGMaterialType type; |
225 | return &type; |
226 | } |
227 | \endcode |
228 | */ |
229 | |
230 | |
231 | |
232 | /*! |
233 | \fn QSGMaterialShader *QSGMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const |
234 | |
235 | This function returns a new instance of a the QSGMaterialShader |
236 | implementation used to render geometry for a specific implementation |
237 | of QSGMaterial. |
238 | |
239 | The function will be called only once for each combination of material type and \a renderMode |
240 | and will be cached internally. |
241 | |
242 | For most materials, the \a renderMode can be ignored. A few materials may need |
243 | custom handling for specific render modes. For instance if the material implements |
244 | antialiasing in a way that needs to account for perspective transformations when |
245 | RenderMode3D is in use. |
246 | */ |
247 | |
248 | QT_END_NAMESPACE |
249 | |