// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QT3DRENDER_RENDER_TEXTUREDATAMANAGER_H #define QT3DRENDER_RENDER_TEXTUREDATAMANAGER_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of other Qt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { /** * The texture data managers associates each texture data generator * with the data objects generated by them. That is, either * * QTextureImageDataGenerator -> QTextureImageData, or * QTextureGenerator -> QTextureData * * This way, texture classes only need to refer to the texture functors used. * Aspect jobs will make sure that at the start of each frame, all generators * registered with the GeneratorDataManagers have been executed. * * This guarantees that no texture data generator is executed twice. * * Each Generator is associated with a number of textures that reference it. * If the last texture disassociates from a generator, the QTextureData will * be deleted. */ template class GeneratorDataManager { public: GeneratorDataManager() {} /*! * If no data for the given generator exists, make sure that the * generators are executed the next frame. Reference generator by * given texture * * Returns true if the Entry for a given generator had to be created */ bool requestData(const GeneratorPtr &generator, ReferencedType r) { QMutexLocker lock(&m_mutex); Entry *entry = findEntry(generator); const bool needsToBeCreated = (entry == nullptr); if (needsToBeCreated) entry = createEntry(generator); Q_ASSERT(entry); if (!entry->referencingObjects.contains(r)) entry->referencingObjects.push_back(r); return needsToBeCreated; } /*! * Dereference given generator from texture. If no other textures still reference * the generator, the associated data will be deleted */ void releaseData(const GeneratorPtr &generator, ReferencedType r) { QMutexLocker lock(&m_mutex); const auto end = m_data.end(); for (auto it = m_data.begin(); it != end; ++it) { Entry &entry = *it; if (*entry.generator == *generator) { entry.referencingObjects.removeAll(r); // delete, if that was the last reference if (entry.referencingObjects.empty()) { m_data.erase(it); return; } } } } /*! * Return data associated with given generator, if existent */ DataPtr getData(const GeneratorPtr &generator) { QMutexLocker lock(&m_mutex); const Entry *entry = findEntry(generator); return entry ? entry->data : DataPtr(); } /*! * Returns all generators that were not yet executed */ QList pendingGenerators() { QMutexLocker lock(&m_mutex); QList ret; for (const Entry &entry : m_data) if (!entry.data && !ret.contains(entry.generator)) ret.push_back(entry.generator); return ret; } /*! * Assigns a piece of data to the generator that was used to * create it. */ void assignData(const GeneratorPtr &generator, const DataPtr &data) { QMutexLocker lock(&m_mutex); Entry *entry = findEntry(generator); if (!entry) { qWarning() << "[TextureDataManager] assignData() called with non-existent generator"; return; } entry->data = data; } bool contains(const GeneratorPtr &generator) { return findEntry(generator) != nullptr; } private: struct Entry { GeneratorPtr generator; QList referencingObjects; DataPtr data; }; /*! * Helper function: return entry for given generator if it exists, nullptr * otherwise. */ Entry* findEntry(const GeneratorPtr &generator) { for (int i = 0, sz = m_data.size(); i < sz; ++i) if (*m_data[i].generator == *generator) return &m_data[i]; return nullptr; } Entry *createEntry(const GeneratorPtr &generator) { Entry newEntry; newEntry.generator = generator; m_data.push_back(newEntry); return &m_data.back(); } QMutex m_mutex; QList m_data; }; class QT3DRENDERSHARED_PRIVATE_EXPORT TextureDataManager : public GeneratorDataManager { }; class QT3DRENDERSHARED_PRIVATE_EXPORT TextureImageDataManager : public GeneratorDataManager { }; } // namespace Render } // namespace Qt3DRender QT_END_NAMESPACE #endif // TEXTUREDATAMANAGER_H