1/****************************************************************************
2**
3** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D 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 "qtextureimage.h"
41#include "qtextureimage_p.h"
42#include "qtexture_p.h"
43#include "qabstracttextureimage_p.h"
44#include <Qt3DCore/qpropertyupdatedchange.h>
45#include <QtCore/QFileInfo>
46#include <QtCore/QDateTime>
47
48QT_BEGIN_NAMESPACE
49
50namespace Qt3DRender {
51
52/*!
53 \class Qt3DRender::QTextureImage
54 \inmodule Qt3DRender
55 \since 5.5
56 \brief Encapsulates the necessary information to create an OpenGL texture
57 image from an image source.
58
59 It contains the necessary information mipmap level, layer, cube face and
60 source URL to load at the proper place data into an OpenGL texture.
61 */
62
63/*!
64 \qmltype TextureImage
65 \instantiates Qt3DRender::QTextureImage
66 \inherits AbstractTextureImage
67 \inqmlmodule Qt3D.Render
68 \since 5.5
69 \brief Encapsulates the necessary information to create an OpenGL texture
70 image from an image source.
71*/
72
73/*!
74 \enum QTextureImage::Status
75
76 This enumeration specifies the status values for texture image loading.
77
78 \value None The texture image loading has not been started yet.
79 \value Loading The texture image loading has started, but not finised.
80 \value Ready The texture image loading has finished.
81 \value Error The texture image loading confronted an error.
82*/
83
84/*!
85 \qmlproperty enumeration TextureImage::status
86
87 This property holds the status of the texture image loading.
88
89 \list
90 \li TextureImage.None
91 \li TextureImage.Loading
92 \li TextureImage.Ready
93 \li TextureImage.Error
94 \endlist
95 \readonly
96*/
97
98/*!
99 \property Qt3DRender::QTextureImage::source
100
101 This property holds the source url from which data for the texture
102 image will be loaded.
103*/
104
105/*!
106 \property QTextureImage::status
107
108 This property holds the status of the texture image loading.
109
110 \list
111 \li TextureImage.None
112 \li TextureImage.Loading
113 \li TextureImage.Ready
114 \li TextureImage.Error
115 \endlist
116 \readonly
117*/
118
119/*!
120 Constructs a new Qt3DRender::QTextureImage instance with \a parent as parent.
121 */
122QTextureImage::QTextureImage(QNode *parent)
123 : QAbstractTextureImage(*new QTextureImagePrivate, parent)
124{
125}
126
127/*! \internal */
128QTextureImage::~QTextureImage()
129{
130}
131
132/*!
133 Returns the source url from which data for the texture image will be loaded.
134 */
135QUrl QTextureImage::source() const
136{
137 Q_D(const QTextureImage);
138 return d->m_source;
139}
140
141/*!
142 Returns the current status.
143 */
144QTextureImage::Status QTextureImage::status() const
145{
146 Q_D(const QTextureImage);
147 return d->m_status;
148}
149
150/*!
151 * Returns whether mirroring is enabled or not.
152 */
153bool QTextureImage::isMirrored() const
154{
155 Q_D(const QTextureImage);
156 return d->m_mirrored;
157}
158
159/*!
160 \qmlproperty url Qt3D.Render::TextureImage::source
161
162 This property holds the source url from which data for the texture
163 image will be loaded.
164*/
165
166/*!
167 Sets the source url of the texture image to \a source.
168 \note This internally triggers a call to update the data generator.
169 */
170void QTextureImage::setSource(const QUrl &source)
171{
172 Q_D(QTextureImage);
173 if (source != d->m_source) {
174 d->m_source = source;
175 const bool blocked = blockNotifications(block: true);
176 emit sourceChanged(source);
177 blockNotifications(block: blocked);
178 notifyDataGeneratorChanged();
179 }
180}
181
182/*!
183 \property Qt3DRender::QTextureImage::mirrored
184
185 This property specifies whether the image should be mirrored when loaded. This
186 is a convenience to avoid having to manipulate images to match the origin of
187 the texture coordinates used by the rendering API. By default this property
188 is set to true. This has no effect when using GPU compressed texture formats.
189
190 \warning This property results in a performance price payed at runtime when
191 loading uncompressed or CPU compressed image formats such as PNG. To avoid this
192 performance price it is better to set this property to false and load texture
193 assets that have been pre-mirrored.
194
195 \note OpenGL specifies the origin of texture coordinates from the lower left
196 hand corner whereas DirectX uses the the upper left hand corner.
197
198 \note When using cube map texture you'll probably want mirroring disabled as
199 the cube map sampler takes a direction rather than regular texture
200 coordinates.
201*/
202
203/*!
204 \qmlproperty bool Qt3DRender::QTextureImage::mirrored
205
206 This property specifies whether the image should be mirrored when loaded. This
207 is a convenience to avoid having to manipulate images to match the origin of
208 the texture coordinates used by the rendering API. By default this property
209 is set to true. This has no effect when using GPU compressed texture formats.
210
211 \warning This property results in a performance price payed at runtime when
212 loading uncompressed or CPU compressed image formats such as PNG. To avoid this
213 performance price it is better to set this property to false and load texture
214 assets that have been pre-mirrored.
215
216 \note OpenGL specifies the origin of texture coordinates from the lower left
217 hand corner whereas DirectX uses the the upper left hand corner.
218
219 \note When using cube map texture you'll probably want mirroring disabled as
220 the cube map sampler takes a direction rather than regular texture
221 coordinates.
222*/
223
224/*!
225 Sets mirroring to \a mirrored.
226 \note This internally triggers a call to update the data generator.
227 */
228void QTextureImage::setMirrored(bool mirrored)
229{
230 Q_D(QTextureImage);
231 if (mirrored != d->m_mirrored) {
232 d->m_mirrored = mirrored;
233 const bool blocked = blockNotifications(block: true);
234 emit mirroredChanged(mirrored);
235 blockNotifications(block: blocked);
236 notifyDataGeneratorChanged();
237 }
238}
239
240/*!
241 * Sets the status to \a status.
242 * \param status
243 */
244void QTextureImage::setStatus(Status status)
245{
246 Q_D(QTextureImage);
247 if (status != d->m_status) {
248 d->m_status = status;
249 emit statusChanged(status);
250 }
251}
252
253/*!
254 Returns the Qt3DRender::QTextureImageDataGeneratorPtr functor to be used by the
255 backend to load the texture image data into an OpenGL texture object.
256 */
257QTextureImageDataGeneratorPtr QTextureImage::dataGenerator() const
258{
259 return QTextureImageDataGeneratorPtr(new QImageTextureDataFunctor(source(), isMirrored()));
260}
261
262/*!
263 Sets the scene change event to \a change.
264 \param change
265 */
266void QTextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
267{
268 Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(src: change);
269
270 if (e->propertyName() == QByteArrayLiteral("status"))
271 setStatus(static_cast<QTextureImage::Status>(e->value().toInt()));
272}
273
274/*
275 The constructor creates a new QImageTextureDataFunctor::QImageTextureDataFunctor
276 instance with the specified \a url.
277 */
278QImageTextureDataFunctor::QImageTextureDataFunctor(const QUrl &url, bool mirrored)
279 : QTextureImageDataGenerator()
280 , m_url(url)
281 , m_status(QTextureImage::None)
282 , m_mirrored(mirrored)
283{
284 if (url.isLocalFile()) {
285 QFileInfo info(url.toLocalFile());
286 m_lastModified = info.lastModified();
287 }
288}
289
290QTextureImageDataPtr QImageTextureDataFunctor::operator ()()
291{
292 if (!m_url.isValid())
293 return QTextureImageDataPtr();
294
295 // We assume that a texture image is going to contain a single image data
296 // For compressed dds or ktx textures a warning should be issued if
297 // there are layers or 3D textures
298 if (!Qt3DCore::QDownloadHelperService::isLocal(url: m_url))
299 qWarning() << "QTextureImage only supports local url";
300
301 QTextureImageDataPtr data = TextureLoadingHelper::loadTextureData(source: m_url, allow3D: false, mirrored: m_mirrored);
302
303 // Data failed to load
304 // Still create an empty QTextureImage to avoid trying to reload it every frame
305 if (!data)
306 data = QTextureImageDataPtr::create();
307 return data;
308}
309
310bool QImageTextureDataFunctor::operator ==(const QTextureImageDataGenerator &other) const
311{
312 const QImageTextureDataFunctor *otherFunctor = functor_cast<QImageTextureDataFunctor>(other: &other);
313
314 // if its the same URL, but different modification times, its not the same image.
315 return (otherFunctor != nullptr &&
316 otherFunctor->m_url == m_url &&
317 otherFunctor->m_lastModified == m_lastModified &&
318 otherFunctor->m_mirrored == m_mirrored);
319}
320
321QUrl QImageTextureDataFunctor::url() const
322{
323 return m_url;
324}
325
326bool QImageTextureDataFunctor::isMirrored() const
327{
328 return m_mirrored;
329}
330
331} // namespace Qt3DRender
332
333QT_END_NAMESPACE
334
335

source code of qt3d/src/render/texture/qtextureimage.cpp