aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
authorJonas Karlsson <jonas.karlsson@qt.io>2020-06-23 13:25:39 +0200
committerJonas Karlsson <jonas.karlsson@qt.io>2020-06-29 15:24:12 +0200
commitbd1c28a82c2ff955e0d154fac2e2df8d5a110dd7 (patch)
tree499f56b6a1d39f7ceb202b53a3f8a4d0bd530eb9 /src/quick
parenta059aa2e2812fab98dc11da73a6241ba6937dce1 (diff)
Reimplement UniformAnimator for ShaderEffect
Fixes: QTBUG-83976 Change-Id: I307e96be0d3d2edeb8d9065d100c1ef38c8824c7 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/doc/snippets/qml/animators.qml82
-rw-r--r--src/quick/items/qquickshadereffect.cpp94
-rw-r--r--src/quick/items/qquickshadereffect_p.h2
-rw-r--r--src/quick/util/qquickanimator.cpp2
-rw-r--r--src/quick/util/qquickanimator_p.h4
-rw-r--r--src/quick/util/qquickanimatorjob.cpp77
-rw-r--r--src/quick/util/qquickanimatorjob_p.h14
7 files changed, 139 insertions, 136 deletions
diff --git a/src/quick/doc/snippets/qml/animators.qml b/src/quick/doc/snippets/qml/animators.qml
index 87684f2792..73c8097974 100644
--- a/src/quick/doc/snippets/qml/animators.qml
+++ b/src/quick/doc/snippets/qml/animators.qml
@@ -219,55 +219,39 @@ Rectangle {
}
}
//! [opacity target]
-//![shaderon]
-// Uniform animators are not yet ported to Qt 6
-//ShaderEffect {
-// width: 50
-// height: 50
-// property variant t;
-// UniformAnimator on t {
-// from: 0
-// to: 1
-// duration: 1000
-// }
-// fragmentShader:
-// "
-// uniform lowp float t;
-// varying highp vec2 qt_TexCoord0;
-// void main() {
-// lowp float c = qt_TexCoord0.y;
-// gl_FragColor = vec4(c * t, 0, 0, 1);
-// }
-// "
-//}
-//![shaderon]
-//![shader target]
-// Uniform animators are not yet ported to Qt 6
-//ShaderEffect {
-// id: shader
-// width: 50
-// height: 50
-// property variant t;
-// UniformAnimator {
-// target: shader
-// uniform: "t"
-// from: 0
-// to: 1
-// duration: 1000
-// running: true
-// }
-// fragmentShader:
-// "
-// uniform lowp float t;
-// varying highp vec2 qt_TexCoord0;
-// void main() {
-// lowp float c = qt_TexCoord0.y;
-// gl_FragColor = vec4(0, 0, c * t, 1);
-// }
-// "
-//}
-//![shader target]
-//![mixed]
+//! [shaderon]
+ShaderEffect {
+ width: 50
+ height: 50
+ property variant t;
+ UniformAnimator on t {
+ from: 0
+ to: 1
+ duration: 1000
+ }
+ fragmentShader: "qrc:shader.frag.qsb"
+}
+
+//! [shaderon]
+//! [shader target]
+ShaderEffect {
+ id: shader
+ width: 50
+ height: 50
+ property variant t;
+ UniformAnimator {
+ target: shader
+ uniform: "t"
+ from: 0
+ to: 1
+ duration: 1000
+ running: true
+ }
+ fragmentShader: "qrc:shader.frag.qsb"
+}
+
+//! [shader target]
+//! [mixed]
Rectangle {
id: mixBox
width: 50
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]);
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index f0abeb8cb7..184a69fdc7 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -119,6 +119,8 @@ public:
bool isComponentComplete() const;
QString parseLog();
+ bool updateUniformValue(const QByteArray &name, const QVariant &value);
+
Q_SIGNALS:
void fragmentShaderChanged();
void vertexShaderChanged();
diff --git a/src/quick/util/qquickanimator.cpp b/src/quick/util/qquickanimator.cpp
index 3a7c3ef808..f53f7e2f39 100644
--- a/src/quick/util/qquickanimator.cpp
+++ b/src/quick/util/qquickanimator.cpp
@@ -504,7 +504,6 @@ QQuickRotationAnimator::RotationDirection QQuickRotationAnimator::direction() co
return d->direction;
}
-#if 0 // QTBUG-83976
/*!
\qmltype UniformAnimator
\instantiates QQuickUniformAnimator
@@ -582,7 +581,6 @@ QQuickAnimatorJob *QQuickUniformAnimator::createJob() const
job->setUniform(u.toLatin1());
return job;
}
-#endif
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h
index a7c219ce1a..d34073c7ff 100644
--- a/src/quick/util/qquickanimator_p.h
+++ b/src/quick/util/qquickanimator_p.h
@@ -184,7 +184,6 @@ protected:
QString propertyName() const override { return QStringLiteral("rotation"); }
};
-#if 0 // QTBUG-83976
class QQuickUniformAnimatorPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimator : public QQuickAnimator
{
@@ -207,7 +206,6 @@ protected:
QQuickAnimatorJob *createJob() const override;
QString propertyName() const override;
};
-#endif
QT_END_NAMESPACE
@@ -217,7 +215,5 @@ QML_DECLARE_TYPE(QQuickYAnimator)
QML_DECLARE_TYPE(QQuickScaleAnimator)
QML_DECLARE_TYPE(QQuickRotationAnimator)
QML_DECLARE_TYPE(QQuickOpacityAnimator)
-#if 0 // QTBUG-83976
QML_DECLARE_TYPE(QQuickUniformAnimator)
-#endif
#endif // QQUICKANIMATOR_P_H
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index b46e2db258..1c2472dc49 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -43,12 +43,7 @@
#include "qquickanimator_p.h"
#include "qquickanimator_p_p.h"
#include <private/qquickitem_p.h>
-#if 0 // QTBUG-83976
-# include <private/qquickopenglshadereffectnode_p.h>
-# include <private/qquickopenglshadereffect_p.h>
-# include <private/qquickshadereffect_p.h>
-# include <QOpenGLContext>
-#endif
+#include <private/qquickshadereffect_p.h>
#include <private/qanimationgroupjob_p.h>
#include <qcoreapplication.h>
@@ -595,28 +590,31 @@ void QQuickOpacityAnimatorJob::updateCurrentTime(int time)
m_opacityNode->setOpacity(m_value);
}
-
-#if 0 // QTBUG-83976
QQuickUniformAnimatorJob::QQuickUniformAnimatorJob()
- : m_node(nullptr)
- , m_uniformIndex(-1)
- , m_uniformType(-1)
{
m_isUniform = true;
}
void QQuickUniformAnimatorJob::setTarget(QQuickItem *target)
{
- QQuickShaderEffect* effect = qobject_cast<QQuickShaderEffect*>(target);
- if (effect && effect->isOpenGLShaderEffect())
+ // Check target is of expected type
+ if (qobject_cast<QQuickShaderEffect *>(target) != nullptr)
m_target = target;
}
-void QQuickUniformAnimatorJob::invalidate()
+void QQuickUniformAnimatorJob::updateCurrentTime(int time)
+{
+ if (!m_effect)
+ return;
+
+ m_value = m_from + (m_to - m_from) * progress(time);
+ m_effect->updateUniformValue(m_uniform, m_value);
+}
+
+void QQuickUniformAnimatorJob::writeBack()
{
- m_node = nullptr;
- m_uniformIndex = -1;
- m_uniformType = -1;
+ if (m_target)
+ m_target->setProperty(m_uniform, value());
}
void QQuickUniformAnimatorJob::postSync()
@@ -626,52 +624,13 @@ void QQuickUniformAnimatorJob::postSync()
return;
}
- m_node = static_cast<QQuickOpenGLShaderEffectNode *>(QQuickItemPrivate::get(m_target)->paintNode);
-
- if (m_node && m_uniformIndex == -1 && m_uniformType == -1) {
- QQuickOpenGLShaderEffectMaterial *material =
- static_cast<QQuickOpenGLShaderEffectMaterial *>(m_node->material());
- bool found = false;
- for (int t=0; !found && t<QQuickOpenGLShaderEffectMaterialKey::ShaderTypeCount; ++t) {
- const QVector<QQuickOpenGLShaderEffectMaterial::UniformData> &uniforms = material->uniforms[t];
- for (int i=0; i<uniforms.size(); ++i) {
- if (uniforms.at(i).name == m_uniform) {
- m_uniformIndex = i;
- m_uniformType = t;
- found = true;
- break;
- }
- }
- }
- }
-
+ m_effect = qobject_cast<QQuickShaderEffect *>(m_target);
}
-void QQuickUniformAnimatorJob::updateCurrentTime(int time)
-{
- if (!m_controller)
- return;
-
- if (!m_node || m_uniformIndex == -1 || m_uniformType == -1)
- return;
-
- m_value = m_from + (m_to - m_from) * progress(time);
-
- QQuickOpenGLShaderEffectMaterial *material =
- static_cast<QQuickOpenGLShaderEffectMaterial *>(m_node->material());
- material->uniforms[m_uniformType][m_uniformIndex].value = m_value;
- // As we're not touching the nodes, we need to explicitly mark it dirty.
- // Otherwise, the renderer will abort repainting if this was the only
- // change in the graph currently rendering.
- m_node->markDirty(QSGNode::DirtyMaterial);
-}
-
-void QQuickUniformAnimatorJob::writeBack()
+void QQuickUniformAnimatorJob::invalidate()
{
- if (m_target)
- m_target->setProperty(m_uniform, value());
+ m_effect = nullptr;
}
-#endif
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index eaec1946ba..0ec1253118 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -69,7 +69,6 @@ class QQuickAbstractAnimation;
class QQuickAnimatorController;
class QQuickAnimatorProxyJobPrivate;
-class QQuickShaderEffectNode;
class QSGOpacityNode;
@@ -289,7 +288,9 @@ public:
private:
QSGOpacityNode *m_opacityNode;
};
-#if 0 // QTBUG-83976
+
+class QQuickShaderEffect;
+
class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimatorJob : public QQuickAnimatorJob
{
public:
@@ -300,21 +301,16 @@ public:
void setUniform(const QByteArray &uniform) { m_uniform = uniform; }
QByteArray uniform() const { return m_uniform; }
- void postSync() override;
-
void updateCurrentTime(int time) override;
void writeBack() override;
+ void postSync() override;
void invalidate() override;
private:
QByteArray m_uniform;
- QQuickOpenGLShaderEffectNode *m_node;
-
- int m_uniformIndex : 8;
- int m_uniformType : 8;
+ QQuickShaderEffect *m_effect = nullptr;
};
-#endif
QT_END_NAMESPACE