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 "qsgtexturematerial_p.h"
5#include <private/qsgtexture_p.h>
6#include <rhi/qrhi.h>
7
8QT_BEGIN_NAMESPACE
9
10inline static bool isPowerOfTwo(int x)
11{
12 // Assumption: x >= 1
13 return x == (x & -x);
14}
15
16QSGOpaqueTextureMaterialRhiShader::QSGOpaqueTextureMaterialRhiShader(int viewCount)
17{
18 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/opaquetexture.vert.qsb"), viewCount);
19 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/opaquetexture.frag.qsb"), viewCount);
20}
21
22bool QSGOpaqueTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *)
23{
24 bool changed = false;
25 QByteArray *buf = state.uniformData();
26 const int matrixCount = qMin(a: state.projectionMatrixCount(), b: newMaterial->viewCount());
27
28 for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
29 if (state.isMatrixDirty()) {
30 const QMatrix4x4 m = state.combinedMatrix(index: viewIndex);
31 memcpy(dest: buf->data() + 64 * viewIndex, src: m.constData(), n: 64);
32 changed = true;
33 }
34 }
35
36 return changed;
37}
38
39void QSGOpaqueTextureMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
40 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
41{
42 if (binding != 1)
43 return;
44
45#ifdef QT_NO_DEBUG
46 Q_UNUSED(oldMaterial);
47#endif
48 Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type());
49 QSGOpaqueTextureMaterial *tx = static_cast<QSGOpaqueTextureMaterial *>(newMaterial);
50 QSGTexture *t = tx->texture();
51 if (!t) {
52 *texture = nullptr;
53 return;
54 }
55
56 t->setFiltering(tx->filtering());
57 t->setMipmapFiltering(tx->mipmapFiltering());
58 t->setAnisotropyLevel(tx->anisotropyLevel());
59
60 t->setHorizontalWrapMode(tx->horizontalWrapMode());
61 t->setVerticalWrapMode(tx->verticalWrapMode());
62 if (!state.rhi()->isFeatureSupported(feature: QRhi::NPOTTextureRepeat)) {
63 QSize size = t->textureSize();
64 const bool isNpot = !isPowerOfTwo(x: size.width()) || !isPowerOfTwo(x: size.height());
65 if (isNpot) {
66 t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
67 t->setVerticalWrapMode(QSGTexture::ClampToEdge);
68 t->setMipmapFiltering(QSGTexture::None);
69 }
70 }
71
72 t->commitTextureOperations(rhi: state.rhi(), resourceUpdates: state.resourceUpdateBatch());
73 *texture = t;
74}
75
76
77/*!
78 \class QSGOpaqueTextureMaterial
79 \brief The QSGOpaqueTextureMaterial class provides a convenient way of
80 rendering textured geometry in the scene graph.
81 \inmodule QtQuick
82 \ingroup qtquick-scenegraph-materials
83
84 \warning This utility class is only functional when running with the
85 default backend of the Qt Quick scenegraph.
86
87 The opaque textured material will fill every pixel in a geometry with
88 the supplied texture. The material does not respect the opacity of the
89 QSGMaterialShader::RenderState, so opacity nodes in the parent chain
90 of nodes using this material, have no effect.
91
92 The geometry to be rendered with an opaque texture material requires
93 vertices in attribute location 0 and texture coordinates in attribute
94 location 1. The texture coordinate is a 2-dimensional floating-point
95 tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an
96 attribute set compatible with this material.
97
98 The texture to be rendered can be set using setTexture(). How the
99 texture should be rendered can be specified using setMipmapFiltering(),
100 setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode().
101 The rendering state is set on the texture instance just before it
102 is bound.
103
104 The opaque textured material respects the current matrix and the alpha
105 channel of the texture. It will disregard the accumulated opacity in
106 the scenegraph.
107
108 A texture material must have a texture set before it is used as
109 a material in the scene graph.
110 */
111
112
113
114/*!
115 Creates a new QSGOpaqueTextureMaterial.
116
117 The default mipmap filtering and filtering mode is set to
118 QSGTexture::Nearest. The default wrap modes is set to
119 \c QSGTexture::ClampToEdge.
120
121 */
122QSGOpaqueTextureMaterial::QSGOpaqueTextureMaterial()
123 : m_texture(nullptr)
124 , m_filtering(QSGTexture::Nearest)
125 , m_mipmap_filtering(QSGTexture::None)
126 , m_horizontal_wrap(QSGTexture::ClampToEdge)
127 , m_vertical_wrap(QSGTexture::ClampToEdge)
128 , m_anisotropy_level(QSGTexture::AnisotropyNone)
129{
130}
131
132
133/*!
134 \internal
135 */
136QSGMaterialType *QSGOpaqueTextureMaterial::type() const
137{
138 static QSGMaterialType type;
139 return &type;
140}
141
142/*!
143 \internal
144 */
145QSGMaterialShader *QSGOpaqueTextureMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
146{
147 Q_UNUSED(renderMode);
148 return new QSGOpaqueTextureMaterialRhiShader(viewCount());
149}
150
151
152/*!
153 \fn QSGTexture *QSGOpaqueTextureMaterial::texture() const
154
155 Returns this texture material's texture.
156 */
157
158
159
160/*!
161 Sets the texture of this material to \a texture.
162
163 The material does not take ownership of the texture.
164 */
165
166void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture)
167{
168 m_texture = texture;
169 setFlag(flags: Blending, on: m_texture ? m_texture->hasAlphaChannel() : false);
170}
171
172
173
174/*!
175 \fn void QSGOpaqueTextureMaterial::setMipmapFiltering(QSGTexture::Filtering filtering)
176
177 Sets the mipmap mode to \a filtering.
178
179 The mipmap filtering mode is set on the texture instance just before the
180 texture is bound for rendering.
181
182 If the texture does not have mipmapping support, enabling mipmapping has no
183 effect.
184 */
185
186
187
188/*!
189 \fn QSGTexture::Filtering QSGOpaqueTextureMaterial::mipmapFiltering() const
190
191 Returns this material's mipmap filtering mode.
192
193 The default mipmap mode is \c QSGTexture::Nearest.
194 */
195
196
197
198/*!
199 \fn void QSGOpaqueTextureMaterial::setFiltering(QSGTexture::Filtering filtering)
200
201 Sets the filtering to \a filtering.
202
203 The filtering mode is set on the texture instance just before the texture
204 is bound for rendering.
205 */
206
207
208
209/*!
210 \fn QSGTexture::Filtering QSGOpaqueTextureMaterial::filtering() const
211
212 Returns this material's filtering mode.
213
214 The default filtering is \c QSGTexture::Nearest.
215 */
216
217
218
219/*!
220 \fn void QSGOpaqueTextureMaterial::setHorizontalWrapMode(QSGTexture::WrapMode mode)
221
222 Sets the horizontal wrap mode to \a mode.
223
224 The horizontal wrap mode is set on the texture instance just before the texture
225 is bound for rendering.
226 */
227
228
229
230 /*!
231 \fn QSGTexture::WrapMode QSGOpaqueTextureMaterial::horizontalWrapMode() const
232
233 Returns this material's horizontal wrap mode.
234
235 The default horizontal wrap mode is \c QSGTexture::ClampToEdge.
236 */
237
238
239
240/*!
241 \fn void QSGOpaqueTextureMaterial::setVerticalWrapMode(QSGTexture::WrapMode mode)
242
243 Sets the vertical wrap mode to \a mode.
244
245 The vertical wrap mode is set on the texture instance just before the texture
246 is bound for rendering.
247 */
248
249
250
251 /*!
252 \fn QSGTexture::WrapMode QSGOpaqueTextureMaterial::verticalWrapMode() const
253
254 Returns this material's vertical wrap mode.
255
256 The default vertical wrap mode is \c QSGTexture::ClampToEdge.
257 */
258
259/*!
260 \fn void QSGOpaqueTextureMaterial::setAnisotropyLevel(QSGTexture::AnisotropyLevel level)
261
262 Sets this material's anistropy level to \a level.
263*/
264
265/*!
266 \fn QSGTexture::AnisotropyLevel QSGOpaqueTextureMaterial::anisotropyLevel() const
267
268 Returns this material's anistropy level.
269*/
270
271/*!
272 \internal
273 */
274
275int QSGOpaqueTextureMaterial::compare(const QSGMaterial *o) const
276{
277 Q_ASSERT(o && type() == o->type());
278 const QSGOpaqueTextureMaterial *other = static_cast<const QSGOpaqueTextureMaterial *>(o);
279 Q_ASSERT(m_texture);
280 Q_ASSERT(other->texture());
281 const qint64 diff = m_texture->comparisonKey() - other->texture()->comparisonKey();
282 if (diff != 0)
283 return diff < 0 ? -1 : 1;
284 return int(m_filtering) - int(other->m_filtering);
285}
286
287
288
289/*!
290 \class QSGTextureMaterial
291 \brief The QSGTextureMaterial class provides a convenient way of
292 rendering textured geometry in the scene graph.
293 \inmodule QtQuick
294 \ingroup qtquick-scenegraph-materials
295
296 \warning This utility class is only functional when running with the
297 default backend of the Qt Quick scenegraph.
298
299 The textured material will fill every pixel in a geometry with
300 the supplied texture.
301
302 The geometry to be rendered with a texture material requires
303 vertices in attribute location 0 and texture coordinates in attribute
304 location 1. The texture coordinate is a 2-dimensional floating-point
305 tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an
306 attribute set compatible with this material.
307
308 The texture to be rendered can be set using setTexture(). How the
309 texture should be rendered can be specified using setMipmapFiltering(),
310 setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode().
311 The rendering state is set on the texture instance just before it
312 is bound.
313
314 The textured material respects the current matrix and the alpha
315 channel of the texture. It will also respect the accumulated opacity
316 in the scenegraph.
317
318 A texture material must have a texture set before it is used as
319 a material in the scene graph.
320 */
321
322/*!
323 \internal
324 */
325
326QSGMaterialType *QSGTextureMaterial::type() const
327{
328 static QSGMaterialType type;
329 return &type;
330}
331
332/*!
333 \internal
334 */
335
336QSGMaterialShader *QSGTextureMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
337{
338 Q_UNUSED(renderMode);
339 return new QSGTextureMaterialRhiShader(viewCount());
340}
341
342
343QSGTextureMaterialRhiShader::QSGTextureMaterialRhiShader(int viewCount)
344 : QSGOpaqueTextureMaterialRhiShader(viewCount)
345{
346 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/texture.vert.qsb"), viewCount);
347 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/texture.frag.qsb"), viewCount);
348}
349
350bool QSGTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
351{
352 bool changed = false;
353 QByteArray *buf = state.uniformData();
354 const int shaderMatrixCount = newMaterial->viewCount();
355
356 if (state.isOpacityDirty()) {
357 const float opacity = state.opacity();
358 memcpy(dest: buf->data() + 64 * shaderMatrixCount, src: &opacity, n: 4);
359 changed = true;
360 }
361
362 changed |= QSGOpaqueTextureMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
363
364 return changed;
365}
366
367QT_END_NAMESPACE
368

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/quick/scenegraph/util/qsgtexturematerial.cpp