aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2016-06-23 10:37:03 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2016-07-05 08:00:21 +0000
commit8c745d808527684836d04da9014ee33c7cf8b6f1 (patch)
tree7f1ab16a2639f91afe153e1d897ed36ac091d446 /src
parent5b470b6b6ad07975f9f9a56425a09b4827e87650 (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.cpp17
-rw-r--r--src/particles/qquickcustomparticle_p.h4
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h4
-rw-r--r--src/qml/qml/qqmldata_p.h2
-rw-r--r--src/qml/qml/qqmlengine.cpp12
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp126
-rw-r--r--src/quick/items/qquickopenglshadereffect_p.h26
-rw-r--r--src/quick/items/qquickopenglshadereffectnode_p.h10
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);