diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-06-23 10:37:03 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-07-05 08:00:21 +0000 |
commit | 8c745d808527684836d04da9014ee33c7cf8b6f1 (patch) | |
tree | 7f1ab16a2639f91afe153e1d897ed36ac091d446 /src | |
parent | 5b470b6b6ad07975f9f9a56425a09b4827e87650 (diff) |
QtQuick: clean up shader effect property connections
- Don't use a signal mapper, but handle the mapping using a custom slot
object and a lambda to do the dispatching ourselves.
- Don't do meta-calls by property name, but by index.
- Cache the meta-object.
- Resolve the property indices by using the QML property cache.
For a shader with 6 property connections, the time spent goes from 320k
instructions to 80k instructions (valgrind on x86_64).
Task-number: QTBUG-53901
Change-Id: I2809198cf62f9716b3683798222203fc3e97fbb3
Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/particles/qquickcustomparticle.cpp | 17 | ||||
-rw-r--r-- | src/particles/qquickcustomparticle_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/ftw/qhashedstring_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmldata_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 12 | ||||
-rw-r--r-- | src/quick/items/qquickopenglshadereffect.cpp | 126 | ||||
-rw-r--r-- | src/quick/items/qquickopenglshadereffect_p.h | 26 | ||||
-rw-r--r-- | src/quick/items/qquickopenglshadereffectnode_p.h | 10 |
8 files changed, 139 insertions, 62 deletions
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index a89b0d6a3b..8ee431aeb2 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -94,7 +94,8 @@ struct PlainVertices { QQuickCustomParticle::QQuickCustomParticle(QQuickItem* parent) : QQuickParticlePainter(parent) - , m_common(this) + , m_common(this, [this](int mappedId){this->propertyChanged(mappedId);}) + , m_myMetaObject(nullptr) , m_dirtyUniforms(true) , m_dirtyUniformValues(true) , m_dirtyTextureProviders(true) @@ -114,7 +115,10 @@ QQuickCustomParticle::~QQuickCustomParticle() void QQuickCustomParticle::componentComplete() { - m_common.updateShader(this, Key::FragmentShader); + if (!m_myMetaObject) + m_myMetaObject = metaObject(); + + m_common.updateShader(this, m_myMetaObject, Key::FragmentShader); updateVertexShader(); reset(); QQuickParticlePainter::componentComplete(); @@ -138,7 +142,7 @@ void QQuickCustomParticle::setFragmentShader(const QByteArray &code) m_common.source.sourceCode[Key::FragmentShader] = code; m_dirtyProgram = true; if (isComponentComplete()) { - m_common.updateShader(this, Key::FragmentShader); + m_common.updateShader(this, m_myMetaObject, Key::FragmentShader); reset(); } emit fragmentShaderChanged(); @@ -202,7 +206,6 @@ void QQuickCustomParticle::setVertexShader(const QByteArray &code) void QQuickCustomParticle::updateVertexShader() { m_common.disconnectPropertySignals(this, Key::VertexShader); - qDeleteAll(m_common.signalMappers[Key::VertexShader]); m_common.uniformData[Key::VertexShader].clear(); m_common.signalMappers[Key::VertexShader].clear(); m_common.attributes.clear(); @@ -225,9 +228,9 @@ void QQuickCustomParticle::updateVertexShader() const QByteArray &code = m_common.source.sourceCode[Key::VertexShader]; if (!code.isEmpty()) - m_common.lookThroughShaderCode(this, Key::VertexShader, code); + m_common.lookThroughShaderCode(this, m_myMetaObject, Key::VertexShader, code); - m_common.connectPropertySignals(this, Key::VertexShader); + m_common.connectPropertySignals(this, m_myMetaObject, Key::VertexShader); } void QQuickCustomParticle::reset() @@ -392,7 +395,7 @@ void QQuickCustomParticle::sourceDestroyed(QObject *object) void QQuickCustomParticle::propertyChanged(int mappedId) { bool textureProviderChanged; - m_common.propertyChanged(this, mappedId, &textureProviderChanged); + m_common.propertyChanged(this, m_myMetaObject, mappedId, &textureProviderChanged); m_dirtyTextureProviders |= textureProviderChanged; m_dirtyUniformValues = true; update(); diff --git a/src/particles/qquickcustomparticle_p.h b/src/particles/qquickcustomparticle_p.h index d9690aa96a..e9d68cbe5c 100644 --- a/src/particles/qquickcustomparticle_p.h +++ b/src/particles/qquickcustomparticle_p.h @@ -99,9 +99,10 @@ protected: private Q_SLOTS: void sourceDestroyed(QObject *object); - void propertyChanged(int mappedId); private: + void propertyChanged(int mappedId); + typedef QQuickOpenGLShaderEffectMaterialKey Key; typedef QQuickOpenGLShaderEffectMaterial::UniformData UniformData; @@ -109,6 +110,7 @@ private: void updateVertexShader(); QQuickOpenGLShaderEffectCommon m_common; + const QMetaObject *m_myMetaObject; QHash<int, QQuickOpenGLShaderEffectNode*> m_nodes; qreal m_lastTime; diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index 6ff3e4a11b..03361f47f7 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE // #define QSTRINGHASH_LINK_DEBUG class QHashedStringRef; -class Q_AUTOTEST_EXPORT QHashedString : public QString +class Q_QML_PRIVATE_EXPORT QHashedString : public QString { public: inline QHashedString(); @@ -94,7 +94,7 @@ private: }; class QHashedCStringRef; -class Q_AUTOTEST_EXPORT QHashedStringRef +class Q_QML_PRIVATE_EXPORT QHashedStringRef { public: inline QHashedStringRef(); diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index 94a3b0f198..a9f2acdb06 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -229,7 +229,7 @@ public: static inline void flushPendingBinding(QObject *, int coreIndex); - static void ensurePropertyCache(QJSEngine *engine, QObject *object); + static QQmlPropertyCache *ensurePropertyCache(QJSEngine *engine, QObject *object); private: // For attachedProperties diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 6cd32852e1..f7191feec5 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1805,14 +1805,16 @@ void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex) QQmlData_setBit(this, obj, coreIndex * 2 + 1); } -void QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object) +QQmlPropertyCache *QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object) { Q_ASSERT(engine); QQmlData *ddata = QQmlData::get(object, /*create*/true); - if (ddata->propertyCache) - return; - ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object); - if (ddata->propertyCache) ddata->propertyCache->addref(); + if (!ddata->propertyCache) { + ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object); + if (ddata->propertyCache) + ddata->propertyCache->addref(); + } + return ddata->propertyCache; } void QQmlEnginePrivate::sendQuit() diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp index b77a7830ff..3f057ecd64 100644 --- a/src/quick/items/qquickopenglshadereffect.cpp +++ b/src/quick/items/qquickopenglshadereffect.cpp @@ -179,12 +179,40 @@ namespace { } } +namespace QtPrivate { +class MappedSlotObject: public QtPrivate::QSlotObjectBase +{ +public: + typedef std::function<void()> PropChangedFunc; + explicit MappedSlotObject(PropChangedFunc func) + : QSlotObjectBase(&impl), _signalIndex(-1), func(func) + {} -QQuickOpenGLShaderEffectCommon::~QQuickOpenGLShaderEffectCommon() -{ - for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) - qDeleteAll(signalMappers[shaderType]); + void setSignalIndex(int idx) { _signalIndex = idx; } + int signalIndex() const { return _signalIndex; } + +private: + int _signalIndex; + PropChangedFunc func; + + static void impl(int which, QSlotObjectBase *this_, QObject *, void **a, bool *ret) + { + auto thiz = static_cast<MappedSlotObject*>(this_); + switch (which) { + case Destroy: + delete thiz; + break; + case Call: + thiz->func(); + break; + case Compare: + *ret = thiz == reinterpret_cast<MappedSlotObject *>(a[0]); + break; + case NumOperations: ; + } + } +}; } void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType) @@ -193,9 +221,9 @@ void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item, if (signalMappers[shaderType].at(i) == 0) continue; const UniformData &d = uniformData[shaderType].at(i); - QSignalMapper *mapper = signalMappers[shaderType].at(i); - QObject::disconnect(item, 0, mapper, SLOT(map())); - QObject::disconnect(mapper, SIGNAL(mapped(int)), host, SLOT(propertyChanged(int))); + auto mapper = signalMappers[shaderType].at(i); + void *a = mapper; + QObjectPrivate::disconnect(item, mapper->signalIndex(), &a); if (d.specialType == UniformData::Sampler) { QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value)); if (source) { @@ -207,25 +235,30 @@ void QQuickOpenGLShaderEffectCommon::disconnectPropertySignals(QQuickItem *item, } } -void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item, Key::ShaderType shaderType) +void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item, + const QMetaObject *itemMetaObject, + Key::ShaderType shaderType) { + QQmlPropertyCache *propCache = QQmlData::ensurePropertyCache(qmlEngine(item), item); for (int i = 0; i < uniformData[shaderType].size(); ++i) { if (signalMappers[shaderType].at(i) == 0) continue; const UniformData &d = uniformData[shaderType].at(i); - int pi = item->metaObject()->indexOfProperty(d.name.constData()); - if (pi >= 0) { - QMetaProperty mp = item->metaObject()->property(pi); - if (!mp.hasNotifySignal()) + QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr); + if (pd && !pd->isFunction()) { + if (pd->notifyIndex == -1) { qWarning("QQuickOpenGLShaderEffect: property '%s' does not have notification method!", d.name.constData()); - const QByteArray signalName = '2' + mp.notifySignal().methodSignature(); - QSignalMapper *mapper = signalMappers[shaderType].at(i); - QObject::connect(item, signalName, mapper, SLOT(map())); - QObject::connect(mapper, SIGNAL(mapped(int)), host, SLOT(propertyChanged(int))); + } else { + auto *mapper = signalMappers[shaderType].at(i); + mapper->setSignalIndex(pd->notifyIndex); + Q_ASSERT(item->metaObject() == itemMetaObject); + QObjectPrivate::connectImpl(item, mapper->signalIndex(), item, nullptr, mapper, + Qt::AutoConnection, nullptr, itemMetaObject); + } } else { // If the source is set via a dynamic property, like the layer is, then we need this // check to disable the warning. - if (!item->property(d.name.constData()).isValid()) + if (!item->property(d.name).isValid()) qWarning("QQuickOpenGLShaderEffect: '%s' does not have a matching property!", d.name.constData()); } @@ -269,8 +302,12 @@ void QQuickOpenGLShaderEffectCommon::updateParseLog(bool ignoreAttributes) parseLog += QLatin1String("Warning: Shaders are missing reference to \'qt_Opacity\'.\n"); } -void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, Key::ShaderType shaderType, const QByteArray &code) +void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, + const QMetaObject *itemMetaObject, + Key::ShaderType shaderType, + const QByteArray &code) { + QQmlPropertyCache *propCache = QQmlData::ensurePropertyCache(qmlEngine(item), item); int index = 0; int typeIndex = -1; int typeLength = 0; @@ -293,7 +330,7 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, Key const int srLen = sizeof("qt_SubRect_") - 1; UniformData d; - QSignalMapper *mapper = 0; + QtPrivate::MappedSlotObject *mapper = nullptr; d.name = QByteArray(s + nameIndex, nameLength); if (nameLength == opLen && qstrncmp("qt_Opacity", s + nameIndex, opLen) == 0) { d.specialType = UniformData::Opacity; @@ -302,11 +339,17 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, Key } else if (nameLength > srLen && qstrncmp("qt_SubRect_", s + nameIndex, srLen) == 0) { d.specialType = UniformData::SubRect; } else { - mapper = new QSignalMapper; - mapper->setMapping(item, uniformData[shaderType].size() | (shaderType << 16)); - d.value = item->property(d.name.constData()); + if (QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr)) { + if (!pd->isFunction()) + d.propertyIndex = pd->coreIndex; + } + const int mappedId = uniformData[shaderType].size() | (shaderType << 16); + mapper = new QtPrivate::MappedSlotObject([this, mappedId](){ + this->mappedPropertyChanged(mappedId); + }); bool sampler = typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0; d.specialType = sampler ? UniformData::Sampler : UniformData::None; + d.setValueFromProperty(item, itemMetaObject); } uniformData[shaderType].append(d); signalMappers[shaderType].append(mapper); @@ -314,10 +357,11 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, Key } } -void QQuickOpenGLShaderEffectCommon::updateShader(QQuickItem *item, Key::ShaderType shaderType) +void QQuickOpenGLShaderEffectCommon::updateShader(QQuickItem *item, + const QMetaObject *itemMetaObject, + Key::ShaderType shaderType) { disconnectPropertySignals(item, shaderType); - qDeleteAll(signalMappers[shaderType]); uniformData[shaderType].clear(); signalMappers[shaderType].clear(); if (shaderType == Key::VertexShader) @@ -363,20 +407,20 @@ void QQuickOpenGLShaderEffectCommon::updateShader(QQuickItem *item, Key::ShaderT d.specialType = UniformData::Opacity; uniformData[Key::FragmentShader].append(d); signalMappers[Key::FragmentShader].append(0); - QSignalMapper *mapper = new QSignalMapper; - mapper->setMapping(item, 1 | (Key::FragmentShader << 16)); + const int mappedId = 1 | (Key::FragmentShader << 16); + auto mapper = new QtPrivate::MappedSlotObject([this, mappedId](){mappedPropertyChanged(mappedId);}); const char *sourceName = "source"; d.name = sourceName; - d.value = item->property(sourceName); + d.setValueFromProperty(item, itemMetaObject); d.specialType = UniformData::Sampler; uniformData[Key::FragmentShader].append(d); signalMappers[Key::FragmentShader].append(mapper); } } else { - lookThroughShaderCode(item, shaderType, code); + lookThroughShaderCode(item, itemMetaObject, shaderType, code); } - connectPropertySignals(item, shaderType); + connectPropertySignals(item, itemMetaObject, shaderType); } void QQuickOpenGLShaderEffectCommon::updateMaterial(QQuickOpenGLShaderEffectNode *node, @@ -507,8 +551,9 @@ static bool qquick_uniqueInUniformData(QQuickItem *source, const QVector<QQuickO return true; } -void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId, - bool *textureProviderChanged) +void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, + const QMetaObject *itemMetaObject, + int mappedId, bool *textureProviderChanged) { Key::ShaderType shaderType = Key::ShaderType(mappedId >> 16); int index = mappedId & 0xffff; @@ -527,7 +572,7 @@ void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, int mappe QObject::disconnect(source, SIGNAL(destroyed(QObject*)), host, SLOT(sourceDestroyed(QObject*))); } - d.value = item->property(d.name.constData()); + d.setValueFromProperty(item, itemMetaObject); source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value)); if (source) { @@ -542,7 +587,7 @@ void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, int mappe if (textureProviderChanged) *textureProviderChanged = true; } else { - d.value = item->property(d.name.constData()); + d.setValueFromProperty(item, itemMetaObject); if (textureProviderChanged) *textureProviderChanged = false; } @@ -551,11 +596,12 @@ void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, int mappe QQuickOpenGLShaderEffect::QQuickOpenGLShaderEffect(QQuickShaderEffect *item, QObject *parent) : QObject(parent) , m_item(item) + , m_itemMetaObject(nullptr) , m_meshResolution(1, 1) , m_mesh(0) , m_cullMode(QQuickShaderEffect::NoCulling) , m_status(QQuickShaderEffect::Uncompiled) - , m_common(this) + , m_common(this, [this](int mappedId){this->propertyChanged(mappedId);}) , m_blending(true) , m_dirtyUniforms(true) , m_dirtyUniformValues(true) @@ -708,7 +754,8 @@ void QQuickOpenGLShaderEffect::handleEvent(QEvent *event) for (int i = 0; i < m_common.uniformData[shaderType].size(); ++i) { if (m_common.uniformData[shaderType].at(i).name == e->propertyName()) { bool textureProviderChanged; - m_common.propertyChanged(m_item, (shaderType << 16) | i, &textureProviderChanged); + m_common.propertyChanged(m_item, m_itemMetaObject, + (shaderType << 16) | i, &textureProviderChanged); m_dirtyTextureProviders |= textureProviderChanged; m_dirtyUniformValues = true; m_item->update(); @@ -746,7 +793,7 @@ void QQuickOpenGLShaderEffect::sourceDestroyed(QObject *object) void QQuickOpenGLShaderEffect::propertyChanged(int mappedId) { bool textureProviderChanged; - m_common.propertyChanged(m_item, mappedId, &textureProviderChanged); + m_common.propertyChanged(m_item, m_itemMetaObject, mappedId, &textureProviderChanged); m_dirtyTextureProviders |= textureProviderChanged; m_dirtyUniformValues = true; m_item->update(); @@ -880,6 +927,9 @@ QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuic void QQuickOpenGLShaderEffect::maybeUpdateShaders(bool force) { + if (!m_itemMetaObject) + m_itemMetaObject = m_item->metaObject(); + // Defer processing if a window is not yet associated with the item. This // is because the actual scenegraph backend is not known so conditions // based on GraphicsInfo.shaderType and similar evaluate to wrong results. @@ -890,12 +940,12 @@ void QQuickOpenGLShaderEffect::maybeUpdateShaders(bool force) if (m_vertNeedsUpdate) { m_vertNeedsUpdate = false; - m_common.updateShader(m_item, Key::VertexShader); + m_common.updateShader(m_item, m_itemMetaObject, Key::VertexShader); } if (m_fragNeedsUpdate) { m_fragNeedsUpdate = false; - m_common.updateShader(m_item, Key::FragmentShader); + m_common.updateShader(m_item, m_itemMetaObject, Key::FragmentShader); } } diff --git a/src/quick/items/qquickopenglshadereffect_p.h b/src/quick/items/qquickopenglshadereffect_p.h index 062eedd744..44b60c97d9 100644 --- a/src/quick/items/qquickopenglshadereffect_p.h +++ b/src/quick/items/qquickopenglshadereffect_p.h @@ -61,6 +61,7 @@ #include "qquickshadereffectmesh_p.h" #include <QtCore/qpointer.h> +#include <functional> QT_BEGIN_NAMESPACE @@ -69,32 +70,39 @@ class QSignalMapper; class QFileSelector; class QQuickOpenGLCustomMaterialShader; +namespace QtPrivate { +class MappedSlotObject; +} + // Common class for QQuickOpenGLShaderEffect and QQuickCustomParticle. struct Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffectCommon { typedef QQuickOpenGLShaderEffectMaterialKey Key; typedef QQuickOpenGLShaderEffectMaterial::UniformData UniformData; - QQuickOpenGLShaderEffectCommon(QObject *host) : host(host), fileSelector(nullptr) { } - ~QQuickOpenGLShaderEffectCommon(); + QQuickOpenGLShaderEffectCommon(QObject *host, std::function<void(int)> mappedPropertyChanged) + : host(host), mappedPropertyChanged(mappedPropertyChanged), fileSelector(nullptr) + { } + void disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType); - void connectPropertySignals(QQuickItem *item, Key::ShaderType shaderType); + void connectPropertySignals(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType); void updateParseLog(bool ignoreAttributes); - void lookThroughShaderCode(QQuickItem *item, Key::ShaderType shaderType, const QByteArray &code); - void updateShader(QQuickItem *item, Key::ShaderType shaderType); + void lookThroughShaderCode(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType, const QByteArray &code); + void updateShader(QQuickItem *item, const QMetaObject *itemMetaObject, Key::ShaderType shaderType); void updateMaterial(QQuickOpenGLShaderEffectNode *node, QQuickOpenGLShaderEffectMaterial *material, bool updateUniforms, bool updateUniformValues, bool updateTextureProviders); void updateWindow(QQuickWindow *window); // Called by slots in QQuickOpenGLShaderEffect: void sourceDestroyed(QObject *object); - void propertyChanged(QQuickItem *item, int mappedId, bool *textureProviderChanged); + void propertyChanged(QQuickItem *item, const QMetaObject *itemMetaObject, int mappedId, bool *textureProviderChanged); QObject *host; + std::function<void(int)> mappedPropertyChanged; Key source; QVector<QByteArray> attributes; QVector<UniformData> uniformData[Key::ShaderTypeCount]; - QVector<QSignalMapper *> signalMappers[Key::ShaderTypeCount]; + QVector<QtPrivate::MappedSlotObject *> signalMappers[Key::ShaderTypeCount]; QString parseLog; QFileSelector *fileSelector; }; @@ -142,9 +150,10 @@ private Q_SLOTS: void updateGeometryIfAtlased(); void updateLogAndStatus(const QString &log, int status); void sourceDestroyed(QObject *object); - void propertyChanged(int mappedId); private: + void propertyChanged(int mappedId); + friend class QQuickCustomMaterialShader; friend class QQuickOpenGLShaderEffectNode; @@ -152,6 +161,7 @@ private: typedef QQuickOpenGLShaderEffectMaterial::UniformData UniformData; QQuickShaderEffect *m_item; + const QMetaObject *m_itemMetaObject; QSize m_meshResolution; QQuickShaderEffectMesh *m_mesh; QQuickGridMesh m_defaultMesh; diff --git a/src/quick/items/qquickopenglshadereffectnode_p.h b/src/quick/items/qquickopenglshadereffectnode_p.h index adf5ef730b..5abe3ae3d0 100644 --- a/src/quick/items/qquickopenglshadereffectnode_p.h +++ b/src/quick/items/qquickopenglshadereffectnode_p.h @@ -90,9 +90,19 @@ public: QByteArray name; QVariant value; + int propertyIndex = -1; SpecialType specialType; bool operator == (const UniformData &other) const; + + void setValueFromProperty(QObject *item, const QMetaObject *itemMetaObject) + { + if (propertyIndex == -1) { + value = item->property(name); + } else { + value = itemMetaObject->property(propertyIndex).read(item); + } + } }; explicit QQuickOpenGLShaderEffectMaterial(QQuickOpenGLShaderEffectNode *node = 0); |