/**************************************************************************** ** ** Copyright (C) 2018 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of Qt 3D Studio. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef Q3DSIMAGEMANAGERER_P_H #define Q3DSIMAGEMANAGERER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "q3dsruntimeglobal_p.h" #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class Q3DSProfiler; namespace Qt3DCore { class QEntity; } class ReloadableTexture { public: ReloadableTexture(Qt3DCore::QEntity *parent, bool generateIBL, const QByteArray &id, const QString &profileInfo, Q3DSProfiler *profiler) : m_parent(parent), m_id(id), m_profileInfo(profileInfo), m_generateIBL(generateIBL), m_profiler(profiler) { } void setSource(const QUrl &source); template void onLoad(Caller caller, Params... params) { m_loadFunc = [this, caller, params...]() { caller(m_texture, params...); }; // onLoad call might provide new parameters when called after loading so call it now if (m_loaded) m_loadFunc(); else triggerLoading(); } template void onUnload(Caller caller, Params... params) { m_unloadFunc = [this, caller, params...]() { caller(m_texture, params...); }; triggerLoading(); } void reload(); void unload(); QUrl source() const { return m_source; } void loaded(Qt3DRender::QAbstractTexture *texture); bool wasLoaded() const { return m_loaded; } Qt3DRender::QAbstractTexture *texture() { return m_texture; } QString info() { return m_profileInfo; } Q3DSProfiler *profiler() { return m_profiler; } private: void triggerLoading(); Qt3DCore::QEntity *m_parent = nullptr; Qt3DRender::QAbstractTexture *m_texture = nullptr; QByteArray m_id; QString m_profileInfo; QUrl m_source; bool m_generateIBL = false; bool m_loaded = false; Q3DSProfiler *m_profiler = nullptr; std::function m_loadFunc = nullptr; std::function m_unloadFunc = nullptr; }; typedef QSharedPointer ReloadableTexturePtr; class Q3DSImageManager { public: enum ImageFlag { GenerateMipMapsForIBL = 0x01 }; Q_DECLARE_FLAGS(ImageFlags, ImageFlag) Q3DSImageManager(); static Q3DSImageManager &instance(); void invalidate(); Qt3DRender::QAbstractTexture *newTextureForImage(Qt3DCore::QEntity *parent, ImageFlags flags, const QByteArray &id, Q3DSProfiler *profiler = nullptr, const QString &profilerInfo = {}); ReloadableTexturePtr newReloadableTextureForImage(Qt3DCore::QEntity *parent, ImageFlags flags, const QByteArray &id, Q3DSProfiler *profiler = nullptr, const char *profName = nullptr, ...); void setSource(Qt3DRender::QAbstractTexture *tex, const QImage &image); QSize size(Qt3DRender::QAbstractTexture *tex) const; Qt3DRender::QAbstractTexture::TextureFormat format(Qt3DRender::QAbstractTexture *tex) const; bool wasCached(Qt3DRender::QAbstractTexture *tex) const; qint64 ioTimeMsecs() const { return m_ioTime; } qint64 iblTimeMsecs() const { return m_iblTime; } void finishAsyncLoad(bool wait = true); void beginImageLoad(const QSet &imageSet); void beginUnload(const QSet &imageSet); bool inResourceSet(const QUrl &url) const; private: void loadImageData(const QUrl &source, bool async = true); void setSource(Qt3DRender::QAbstractTexture *tex, const QUrl &source); void textureLoaded(Qt3DRender::QAbstractTexture *tex, const QUrl &source); QVector load(const QUrl &source); int blockSizeForFormat(QOpenGLTexture::TextureFormat format); QByteArray generateIblMip(int w, int h, int prevW, int prevH, QOpenGLTexture::TextureFormat format, int blockSize, const QByteArray &prevLevelData); QVector generateIblForImageData( QVector result); struct TextureInfo { ImageFlags flags; QUrl source; QSize size; Qt3DRender::QAbstractTexture::TextureFormat format = Qt3DRender::QAbstractTexture::NoFormat; bool wasCached = false; }; struct LoadImageDataAsync { QFuture future; QString source; bool preferKtx = false; bool done = false; }; QVector m_reloadableTextures; QSet m_resourceSet; QHash m_metadata; QHash > m_cache; QHash m_loadImageDataAsync; QHash *> m_pendingSetSource; QThreadPool m_threadPool; static QMutex s_loadMutex; qint64 m_ioTime = 0; qint64 m_iblTime = 0; QMutex m_finishAsyncLoadLock; friend ReloadableTexture; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Q3DSImageManager::ImageFlags) QT_END_NAMESPACE #endif // Q3DSIMAGEMANAGERER_P_H