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
5#include "qsgsimpletexturenode.h"
6#include <private/qsgnode_p.h>
7
8QT_BEGIN_NAMESPACE
9
10class QSGSimpleTextureNodePrivate : public QSGGeometryNodePrivate
11{
12public:
13 QSGSimpleTextureNodePrivate()
14 : texCoordMode(QSGSimpleTextureNode::NoTransform)
15 , isAtlasTexture(false)
16 , ownsTexture(false)
17 {}
18
19 QRectF sourceRect;
20 QSGSimpleTextureNode::TextureCoordinatesTransformMode texCoordMode;
21 uint isAtlasTexture : 1;
22 uint ownsTexture : 1;
23};
24
25static void qsgsimpletexturenode_update(QSGGeometry *g,
26 QSGTexture *texture,
27 const QRectF &rect,
28 QRectF sourceRect,
29 QSGSimpleTextureNode::TextureCoordinatesTransformMode texCoordMode)
30{
31 if (!texture)
32 return;
33
34 if (!sourceRect.width() || !sourceRect.height()) {
35 QSize ts = texture->textureSize();
36 sourceRect = QRectF(0, 0, ts.width(), ts.height());
37 }
38
39 // Maybe transform the texture coordinates
40 if (texCoordMode.testFlag(flag: QSGSimpleTextureNode::MirrorHorizontally)) {
41 float tmp = sourceRect.left();
42 sourceRect.setLeft(sourceRect.right());
43 sourceRect.setRight(tmp);
44 }
45 if (texCoordMode.testFlag(flag: QSGSimpleTextureNode::MirrorVertically)) {
46 float tmp = sourceRect.top();
47 sourceRect.setTop(sourceRect.bottom());
48 sourceRect.setBottom(tmp);
49 }
50
51 QSGGeometry::updateTexturedRectGeometry(g, rect, sourceRect: texture->convertToNormalizedSourceRect(rect: sourceRect));
52}
53
54/*!
55 \class QSGSimpleTextureNode
56 \brief The QSGSimpleTextureNode class is provided for convenience to easily draw
57 textured content using the QML scene graph.
58
59 \inmodule QtQuick
60
61 \warning The simple texture node class must have a texture before being
62 added to the scene graph to be rendered.
63
64 \warning This utility class is only functional when running with the default
65 or software backends of the Qt Quick scenegraph. As an alternative, prefer
66 using QSGImageNode via QQuickWindow::createImageNode(). However, this
67 standalone class is still useful when used via subclassing and the
68 application knows that no special scenegraph backends will be involved.
69*/
70
71/*!
72 Constructs a new simple texture node
73 */
74QSGSimpleTextureNode::QSGSimpleTextureNode()
75 : QSGGeometryNode(*new QSGSimpleTextureNodePrivate)
76 , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
77{
78 setGeometry(&m_geometry);
79 setMaterial(&m_material);
80 setOpaqueMaterial(&m_opaque_material);
81 m_material.setMipmapFiltering(QSGTexture::None);
82 m_opaque_material.setMipmapFiltering(QSGTexture::None);
83#ifdef QSG_RUNTIME_DESCRIPTION
84 qsgnode_set_description(node: this, description: QLatin1String("simpletexture"));
85#endif
86}
87
88/*!
89 Destroys the texture node
90 */
91QSGSimpleTextureNode::~QSGSimpleTextureNode()
92{
93 Q_D(QSGSimpleTextureNode);
94 if (d->ownsTexture)
95 delete m_material.texture();
96}
97
98/*!
99 Sets the filtering to be used for this texture node to \a filtering.
100
101 For smooth scaling, use QSGTexture::Linear; for normal scaling, use
102 QSGTexture::Nearest.
103 */
104void QSGSimpleTextureNode::setFiltering(QSGTexture::Filtering filtering)
105{
106 if (m_material.filtering() == filtering)
107 return;
108
109 m_material.setFiltering(filtering);
110 m_opaque_material.setFiltering(filtering);
111 markDirty(bits: DirtyMaterial);
112}
113
114
115/*!
116 Returns the filtering currently set on this texture node
117 */
118QSGTexture::Filtering QSGSimpleTextureNode::filtering() const
119{
120 return m_material.filtering();
121}
122
123
124/*!
125 Sets the target rect of this texture node to \a r.
126 */
127void QSGSimpleTextureNode::setRect(const QRectF &r)
128{
129 if (m_rect == r)
130 return;
131 m_rect = r;
132 Q_D(QSGSimpleTextureNode);
133 qsgsimpletexturenode_update(g: &m_geometry, texture: texture(), rect: m_rect, sourceRect: d->sourceRect, texCoordMode: d->texCoordMode);
134 markDirty(bits: DirtyGeometry);
135}
136
137/*!
138 \fn void QSGSimpleTextureNode::setRect(qreal x, qreal y, qreal w, qreal h)
139 \overload
140
141 Sets the rectangle of this texture node to begin at (\a x, \a y) and have
142 width \a w and height \a h.
143 */
144
145/*!
146 Returns the target rect of this texture node.
147 */
148QRectF QSGSimpleTextureNode::rect() const
149{
150 return m_rect;
151}
152
153/*!
154 Sets the source rect of this texture node to \a r.
155
156 \since 5.5
157 */
158void QSGSimpleTextureNode::setSourceRect(const QRectF &r)
159{
160 Q_D(QSGSimpleTextureNode);
161 if (d->sourceRect == r)
162 return;
163 d->sourceRect = r;
164 qsgsimpletexturenode_update(g: &m_geometry, texture: texture(), rect: m_rect, sourceRect: d->sourceRect, texCoordMode: d->texCoordMode);
165 markDirty(bits: DirtyGeometry);
166}
167
168/*!
169 \fn void QSGSimpleTextureNode::setSourceRect(qreal x, qreal y, qreal w, qreal h)
170 \overload
171 \since 5.5
172
173 Sets the rectangle of this texture node to show its texture from (\a x, \a y) and
174 have width \a w and height \a h relatively to the QSGTexture::textureSize.
175 */
176
177/*!
178 Returns the source rect of this texture node.
179
180 \since 5.5
181 */
182QRectF QSGSimpleTextureNode::sourceRect() const
183{
184 Q_D(const QSGSimpleTextureNode);
185 return d->sourceRect;
186}
187
188/*!
189 Sets the texture of this texture node to \a texture.
190
191 Use setOwnsTexture() to set whether the node should take
192 ownership of the texture. By default, the node does not
193 take ownership.
194
195 \warning A texture node must have a texture before being added
196 to the scenegraph to be rendered.
197 */
198void QSGSimpleTextureNode::setTexture(QSGTexture *texture)
199{
200 Q_ASSERT(texture);
201 Q_D(QSGSimpleTextureNode);
202 if (d->ownsTexture)
203 delete m_material.texture();
204 m_material.setTexture(texture);
205 m_opaque_material.setTexture(texture);
206 qsgsimpletexturenode_update(g: &m_geometry, texture, rect: m_rect, sourceRect: d->sourceRect, texCoordMode: d->texCoordMode);
207
208 DirtyState dirty = DirtyMaterial;
209 // It would be tempting to skip the extra bit here and instead use
210 // m_material.texture to get the old state, but that texture could
211 // have been deleted in the mean time.
212 bool wasAtlas = d->isAtlasTexture;
213 d->isAtlasTexture = texture->isAtlasTexture();
214 if (wasAtlas || d->isAtlasTexture)
215 dirty |= DirtyGeometry;
216 markDirty(bits: dirty);
217}
218
219
220
221/*!
222 Returns the texture for this texture node
223 */
224QSGTexture *QSGSimpleTextureNode::texture() const
225{
226 return m_material.texture();
227}
228
229/*!
230 \enum QSGSimpleTextureNode::TextureCoordinatesTransformFlag
231
232 The TextureCoordinatesTransformFlag enum is used to specify the
233 mode used to generate texture coordinates for a textured quad.
234
235 \value NoTransform Texture coordinates are oriented with window coordinates
236 i.e. with origin at top-left.
237
238 \value MirrorHorizontally Texture coordinates are inverted in the horizontal axis with
239 respect to window coordinates
240
241 \value MirrorVertically Texture coordinates are inverted in the vertical axis with
242 respect to window coordinates
243 */
244
245/*!
246 Sets the method used to generate texture coordinates to \a mode. This can be used to obtain
247 correct orientation of the texture. This is commonly needed when using a third party OpenGL
248 library to render to texture as OpenGL has an inverted y-axis relative to Qt Quick.
249
250 \sa textureCoordinatesTransform()
251 */
252void QSGSimpleTextureNode::setTextureCoordinatesTransform(QSGSimpleTextureNode::TextureCoordinatesTransformMode mode)
253{
254 Q_D(QSGSimpleTextureNode);
255 if (d->texCoordMode == mode)
256 return;
257 d->texCoordMode = mode;
258 qsgsimpletexturenode_update(g: &m_geometry, texture: texture(), rect: m_rect, sourceRect: d->sourceRect, texCoordMode: d->texCoordMode);
259 markDirty(bits: DirtyGeometry | DirtyMaterial);
260}
261
262/*!
263 Returns the mode used to generate texture coordinates for this node.
264
265 \sa setTextureCoordinatesTransform()
266 */
267QSGSimpleTextureNode::TextureCoordinatesTransformMode QSGSimpleTextureNode::textureCoordinatesTransform() const
268{
269 Q_D(const QSGSimpleTextureNode);
270 return d->texCoordMode;
271}
272
273/*!
274 Sets whether the node takes ownership of the texture to \a owns.
275
276 By default, the node does not take ownership of the texture.
277
278 \sa setTexture()
279
280 \since 5.4
281 */
282void QSGSimpleTextureNode::setOwnsTexture(bool owns)
283{
284 Q_D(QSGSimpleTextureNode);
285 d->ownsTexture = owns;
286}
287
288/*!
289 Returns \c true if the node takes ownership of the texture; otherwise returns \c false.
290
291 \since 5.4
292 */
293bool QSGSimpleTextureNode::ownsTexture() const
294{
295 Q_D(const QSGSimpleTextureNode);
296 return d->ownsTexture;
297}
298
299QT_END_NAMESPACE
300

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