diff options
author | Jonas Karlsson <jonas.karlsson@qt.io> | 2020-06-23 13:25:39 +0200 |
---|---|---|
committer | Jonas Karlsson <jonas.karlsson@qt.io> | 2020-06-29 15:24:12 +0200 |
commit | bd1c28a82c2ff955e0d154fac2e2df8d5a110dd7 (patch) | |
tree | 499f56b6a1d39f7ceb202b53a3f8a4d0bd530eb9 /src/quick/items/qquickshadereffect.cpp | |
parent | a059aa2e2812fab98dc11da73a6241ba6937dce1 (diff) |
Reimplement UniformAnimator for ShaderEffect
Fixes: QTBUG-83976
Change-Id: I307e96be0d3d2edeb8d9065d100c1ef38c8824c7
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/quick/items/qquickshadereffect.cpp')
-rw-r--r-- | src/quick/items/qquickshadereffect.cpp | 94 |
1 files changed, 81 insertions, 13 deletions
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index bc4cfad87b..df900d1f5e 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -435,6 +435,8 @@ public: void handleComponentComplete(); void handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value); void maybeUpdateShaders(); + bool updateUniformValue(const QByteArray &name, const QVariant &value, + QSGShaderEffectNode *node); private slots: void propertyChanged(int mappedId); @@ -458,6 +460,7 @@ private: void disconnectSignals(Shader shaderType); void clearMappers(Shader shaderType); bool sourceIsUnique(QQuickItem *source, Shader typeToSkip, int indexToSkip) const; + std::optional<int> findMappedShaderVariableId(const QByteArray &name) const; QQuickShaderEffect *m_item; const QMetaObject *m_itemMetaObject = nullptr; @@ -747,6 +750,15 @@ QString QQuickShaderEffect::parseLog() // for OpenGL-based autotests return m_impl->parseLog(); } +bool QQuickShaderEffect::updateUniformValue(const QByteArray &name, const QVariant &value) +{ + auto node = static_cast<QSGShaderEffectNode *>(QQuickItemPrivate::get(this)->paintNode); + if (!node) + return false; + + return m_impl->updateUniformValue(name, value, node); +} + void QQuickShaderEffectPrivate::updatePolish() { Q_Q(QQuickShaderEffect); @@ -755,6 +767,21 @@ void QQuickShaderEffectPrivate::updatePolish() q->m_impl->maybeUpdateShaders(); } +constexpr int indexToMappedId(const int shaderType, const int idx) +{ + return idx | (shaderType << 16); +} + +constexpr int mappedIdToIndex(const int mappedId) +{ + return mappedId & 0xFFFF; +} + +constexpr int mappedIdToShaderType(const int mappedId) +{ + return mappedId >> 16; +} + QQuickShaderEffectImpl::QQuickShaderEffectImpl(QQuickShaderEffect *item) : QObject(item) , m_item(item) @@ -916,16 +943,10 @@ QQuickShaderEffect::Status QQuickShaderEffectImpl::status() const void QQuickShaderEffectImpl::handleEvent(QEvent *event) { if (event->type() == QEvent::DynamicPropertyChange) { - QDynamicPropertyChangeEvent *e = static_cast<QDynamicPropertyChangeEvent *>(event); - for (int shaderType = 0; shaderType < NShader; ++shaderType) { - const auto &vars(m_shaders[shaderType].shaderInfo.variables); - for (int idx = 0; idx < vars.count(); ++idx) { - if (vars[idx].name == e->propertyName()) { - propertyChanged((shaderType << 16) | idx); - break; - } - } - } + const auto propertyName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); + const auto mappedId = findMappedShaderVariableId(propertyName); + if (mappedId) + propertyChanged(*mappedId); } } @@ -1026,6 +1047,40 @@ void QQuickShaderEffectImpl::maybeUpdateShaders() } } +bool QQuickShaderEffectImpl::updateUniformValue(const QByteArray &name, const QVariant &value, + QSGShaderEffectNode *node) +{ + const auto mappedId = findMappedShaderVariableId(name); + if (!mappedId) + return false; + + const Shader type = Shader(mappedIdToShaderType(*mappedId)); + const int idx = mappedIdToIndex(*mappedId); + + // Update value + m_shaders[type].varData[idx].value = value; + + // Insert dirty uniform + QSet<int> dirtyConstants[NShader]; + dirtyConstants[type].insert(idx); + + // Sync material change + QSGShaderEffectNode::SyncData sd; + sd.dirty = QSGShaderEffectNode::DirtyShaderConstant; + sd.cullMode = QSGShaderEffectNode::CullMode(m_cullMode); + sd.blending = m_blending; + sd.vertex.shader = &m_shaders[Vertex]; + sd.vertex.dirtyConstants = &dirtyConstants[Vertex]; + sd.vertex.dirtyTextures = {}; + sd.fragment.shader = &m_shaders[Fragment]; + sd.fragment.dirtyConstants = &dirtyConstants[Fragment]; + sd.fragment.dirtyTextures = {}; + + node->syncMaterial(&sd); + + return true; +} + void QQuickShaderEffectImpl::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) { // Move the window ref. @@ -1290,7 +1345,7 @@ void QQuickShaderEffectImpl::updateShaderVars(Shader shaderType) } else { auto *&mapper = m_mappers[shaderType][i]; if (!mapper) { - const int mappedId = i | (shaderType << 16); + const int mappedId = indexToMappedId(shaderType, i); mapper = new QtPrivate::EffectSlotMapper([this, mappedId](){ this->propertyChanged(mappedId); }); @@ -1339,10 +1394,23 @@ bool QQuickShaderEffectImpl::sourceIsUnique(QQuickItem *source, Shader typeToSki return true; } +std::optional<int> QQuickShaderEffectImpl::findMappedShaderVariableId(const QByteArray &name) const +{ + for (int shaderType = 0; shaderType < NShader; ++shaderType) { + const auto &vars = m_shaders[shaderType].shaderInfo.variables; + for (int idx = 0; idx < vars.count(); ++idx) { + if (vars[idx].name == name) + return indexToMappedId(shaderType, idx); + } + } + + return {}; +} + void QQuickShaderEffectImpl::propertyChanged(int mappedId) { - const Shader type = Shader(mappedId >> 16); - const int idx = mappedId & 0xFFFF; + const Shader type = Shader(mappedIdToShaderType(mappedId)); + const int idx = mappedIdToIndex(mappedId); const auto &v(m_shaders[type].shaderInfo.variables[idx]); auto &vd(m_shaders[type].varData[idx]); |