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

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