aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickshadereffectnode.cpp
diff options
context:
space:
mode:
authorKim Motoyoshi Kalland <kim.kalland@nokia.com>2012-03-21 14:21:51 +0100
committerQt by Nokia <qt-info@nokia.com>2012-04-04 03:29:45 +0200
commitc71c8c4619594a276d69378bbd77da5117afd566 (patch)
tree9b8ac6fb0db75abb747de6ec2a74e754770f4820 /src/quick/items/qquickshadereffectnode.cpp
parent2c741bc8af46aa26ec9a61bc996bb0de2e409943 (diff)
Fixed crash when using 'var' property in ShaderEffect.
Also made CustomParticle and ShaderEffect share some code. Task-number: QTBUG-23924 Change-Id: I975f71f031b379cf5e29302a9c931e4ead5437ea Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
Diffstat (limited to 'src/quick/items/qquickshadereffectnode.cpp')
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp209
1 files changed, 96 insertions, 113 deletions
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index be1fb29904..a3cadb97a2 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -60,7 +60,6 @@ protected:
friend class QQuickShaderEffectNode;
virtual void compile();
- virtual void initialize();
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
@@ -70,17 +69,15 @@ protected:
QString m_log;
bool m_compiled;
- QVector<int> m_uniformLocs;
- int m_opacityLoc;
- int m_matrixLoc;
- uint m_textureIndicesSet;
+ QVector<int> m_uniformLocs[QQuickShaderEffectMaterialKey::ShaderTypeCount];
+ uint m_initialized : 1;
};
QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes)
: m_key(key)
, m_attributes(attributes)
, m_compiled(false)
- , m_textureIndicesSet(false)
+ , m_initialized(false)
{
for (int i = 0; i < attributes.count(); ++i)
m_attributeNames.append(attributes.at(i).constData());
@@ -104,24 +101,25 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
: QQuickShaderEffect::Error);
}
- if (!m_textureIndicesSet) {
- for (int i = 0; i < material->m_textures.size(); ++i)
- program()->setUniformValue(material->m_textures.at(i).first.constData(), i);
- m_textureIndicesSet = true;
- }
+ if (!m_initialized) {
+ for (int i = 0; i < material->textureProviders.size(); ++i)
+ program()->setUniformValue(material->textureProviders.at(i).first.constData(), i);
- if (m_uniformLocs.size() != material->m_uniformValues.size()) {
- m_uniformLocs.reserve(material->m_uniformValues.size());
- for (int i = 0; i < material->m_uniformValues.size(); ++i) {
- const QByteArray &name = material->m_uniformValues.at(i).first;
- m_uniformLocs.append(program()->uniformLocation(name.constData()));
+ for (int shaderType = 0; shaderType < QQuickShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
+ Q_ASSERT(m_uniformLocs[shaderType].isEmpty());
+ m_uniformLocs[shaderType].reserve(material->uniforms[shaderType].size());
+ for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
+ const QByteArray &name = material->uniforms[shaderType].at(i).name;
+ m_uniformLocs[shaderType].append(program()->uniformLocation(name.constData()));
+ }
}
+ m_initialized = true;
}
QOpenGLFunctions *functions = state.context()->functions();
- for (int i = material->m_textures.size() - 1; i >= 0; --i) {
+ for (int i = material->textureProviders.size() - 1; i >= 0; --i) {
functions->glActiveTexture(GL_TEXTURE0 + i);
- if (QSGTextureProvider *provider = material->m_textures.at(i).second) {
+ if (QSGTextureProvider *provider = material->textureProviders.at(i).second) {
if (QSGTexture *texture = provider->texture()) {
texture->bind();
continue;
@@ -131,57 +129,67 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
glBindTexture(GL_TEXTURE_2D, 0);
}
- if (material->m_source.respectsOpacity)
- program()->setUniformValue(m_opacityLoc, state.opacity());
-
- for (int i = 0; i < material->m_uniformValues.count(); ++i) {
- const QVariant &v = material->m_uniformValues.at(i).second;
-
- switch (v.type()) {
- case QMetaType::QColor:
- program()->setUniformValue(m_uniformLocs.at(i), qt_premultiply_color(qvariant_cast<QColor>(v)));
- break;
- case QMetaType::Float:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<float>(v));
- break;
- case QMetaType::Double:
- program()->setUniformValue(m_uniformLocs.at(i), (float) qvariant_cast<double>(v));
- break;
- case QMetaType::QTransform:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QTransform>(v));
- break;
- case QMetaType::Int:
- program()->setUniformValue(m_uniformLocs.at(i), v.toInt());
- break;
- case QMetaType::Bool:
- program()->setUniformValue(m_uniformLocs.at(i), GLint(v.toBool()));
- break;
- case QMetaType::QSize:
- case QMetaType::QSizeF:
- program()->setUniformValue(m_uniformLocs.at(i), v.toSizeF());
- break;
- case QMetaType::QPoint:
- case QMetaType::QPointF:
- program()->setUniformValue(m_uniformLocs.at(i), v.toPointF());
- break;
- case QMetaType::QRect:
- case QMetaType::QRectF:
- {
- QRectF r = v.toRectF();
- program()->setUniformValue(m_uniformLocs.at(i), r.x(), r.y(), r.width(), r.height());
+ for (int shaderType = 0; shaderType < QQuickShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
+ const QQuickShaderEffectMaterial::UniformData &d = material->uniforms[shaderType].at(i);
+ int loc = m_uniformLocs[shaderType].at(i);
+
+ if (d.specialType == QQuickShaderEffectMaterial::UniformData::Opacity) {
+ program()->setUniformValue(loc, state.opacity());
+ } if (d.specialType == QQuickShaderEffectMaterial::UniformData::Matrix) {
+ if (state.isMatrixDirty())
+ program()->setUniformValue(loc, state.combinedMatrix());
+ } else {
+ switch (d.value.type()) {
+ case QMetaType::QColor:
+ program()->setUniformValue(loc, qt_premultiply_color(qvariant_cast<QColor>(d.value)));
+ break;
+ case QMetaType::Float:
+ program()->setUniformValue(loc, qvariant_cast<float>(d.value));
+ break;
+ case QMetaType::Double:
+ program()->setUniformValue(loc, (float) qvariant_cast<double>(d.value));
+ break;
+ case QMetaType::QTransform:
+ program()->setUniformValue(loc, qvariant_cast<QTransform>(d.value));
+ break;
+ case QMetaType::Int:
+ program()->setUniformValue(loc, d.value.toInt());
+ break;
+ case QMetaType::Bool:
+ program()->setUniformValue(loc, GLint(d.value.toBool()));
+ break;
+ case QMetaType::QSize:
+ case QMetaType::QSizeF:
+ program()->setUniformValue(loc, d.value.toSizeF());
+ break;
+ case QMetaType::QPoint:
+ case QMetaType::QPointF:
+ program()->setUniformValue(loc, d.value.toPointF());
+ break;
+ case QMetaType::QRect:
+ case QMetaType::QRectF:
+ {
+ QRectF r = d.value.toRectF();
+ program()->setUniformValue(loc, r.x(), r.y(), r.width(), r.height());
+ }
+ break;
+ case QMetaType::QVector3D:
+ program()->setUniformValue(loc, qvariant_cast<QVector3D>(d.value));
+ break;
+ case QMetaType::QVector4D:
+ program()->setUniformValue(loc, qvariant_cast<QVector4D>(d.value));
+ break;
+ default:
+ break;
+ }
}
- break;
- case QMetaType::QVector3D:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QVector3D>(v));
- break;
- default:
- break;
}
}
const QQuickShaderEffectMaterial *oldMaterial = static_cast<const QQuickShaderEffectMaterial *>(oldEffect);
- if (oldEffect == 0 || material->cullMode() != oldMaterial->cullMode()) {
- switch (material->cullMode()) {
+ if (oldEffect == 0 || material->cullMode != oldMaterial->cullMode) {
+ switch (material->cullMode) {
case QQuickShaderEffectMaterial::FrontFaceCulling:
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
@@ -195,9 +203,6 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
break;
}
}
-
- if ((state.isMatrixDirty()) && material->m_source.respectsMatrix)
- program()->setUniformValue(m_matrixLoc, state.combinedMatrix());
}
char const *const *QQuickCustomMaterialShader::attributeNames() const
@@ -277,38 +282,42 @@ void QQuickCustomMaterialShader::compile()
}
}
-void QQuickCustomMaterialShader::initialize()
-{
- m_opacityLoc = program()->uniformLocation("qt_Opacity");
- m_matrixLoc = program()->uniformLocation("qt_Matrix");
-}
-
const char *QQuickCustomMaterialShader::vertexShader() const
{
- return m_key.vertexCode.constData();
+ return m_key.sourceCode[QQuickShaderEffectMaterialKey::VertexShader].constData();
}
const char *QQuickCustomMaterialShader::fragmentShader() const
{
- return m_key.fragmentCode.constData();
+ return m_key.sourceCode[QQuickShaderEffectMaterialKey::FragmentShader].constData();
}
bool QQuickShaderEffectMaterialKey::operator == (const QQuickShaderEffectMaterialKey &other) const
{
- return vertexCode == other.vertexCode && fragmentCode == other.fragmentCode && className == other.className;
+ if (className != other.className)
+ return false;
+ for (int shaderType = 0; shaderType < ShaderTypeCount; ++shaderType) {
+ if (sourceCode[shaderType] != other.sourceCode[shaderType])
+ return false;
+ }
+ return true;
}
uint qHash(const QQuickShaderEffectMaterialKey &key)
{
- return qHash(qMakePair(qMakePair(key.vertexCode, key.fragmentCode), key.className));
+ uint hash = qHash((void *)key.className);
+ typedef QQuickShaderEffectMaterialKey Key;
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
+ hash = hash * 31337 + qHash(key.sourceCode[shaderType]);
+ return hash;
}
QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > QQuickShaderEffectMaterial::materialMap;
QQuickShaderEffectMaterial::QQuickShaderEffectMaterial(QQuickShaderEffectNode *node)
- : m_cullMode(NoCulling)
+ : cullMode(NoCulling)
, m_node(node)
, m_emittedLogChanged(false)
{
@@ -322,7 +331,7 @@ QSGMaterialType *QQuickShaderEffectMaterial::type() const
QSGMaterialShader *QQuickShaderEffectMaterial::createShader() const
{
- return new QQuickCustomMaterialShader(m_source, m_source.attributeNames);
+ return new QQuickCustomMaterialShader(m_source, attributes);
}
int QQuickShaderEffectMaterial::compare(const QSGMaterial *other) const
@@ -330,17 +339,7 @@ int QQuickShaderEffectMaterial::compare(const QSGMaterial *other) const
return this - static_cast<const QQuickShaderEffectMaterial *>(other);
}
-void QQuickShaderEffectMaterial::setCullMode(QQuickShaderEffectMaterial::CullMode face)
-{
- m_cullMode = face;
-}
-
-QQuickShaderEffectMaterial::CullMode QQuickShaderEffectMaterial::cullMode() const
-{
- return m_cullMode;
-}
-
-void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectProgram &source)
+void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectMaterialKey &source)
{
m_source = source;
m_emittedLogChanged = false;
@@ -351,25 +350,10 @@ void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectProgra
}
}
-void QQuickShaderEffectMaterial::setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues)
-{
- m_uniformValues = uniformValues;
-}
-
-void QQuickShaderEffectMaterial::setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures)
-{
- m_textures = textures;
-}
-
-const QVector<QPair<QByteArray, QSGTextureProvider *> > &QQuickShaderEffectMaterial::textureProviders() const
-{
- return m_textures;
-}
-
void QQuickShaderEffectMaterial::updateTextures() const
{
- for (int i = 0; i < m_textures.size(); ++i) {
- if (QSGTextureProvider *provider = m_textures.at(i).second) {
+ for (int i = 0; i < textureProviders.size(); ++i) {
+ if (QSGTextureProvider *provider = textureProviders.at(i).second) {
if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
texture->updateTexture();
}
@@ -378,18 +362,16 @@ void QQuickShaderEffectMaterial::updateTextures() const
void QQuickShaderEffectMaterial::invalidateTextureProvider(QSGTextureProvider *provider)
{
- for (int i = 0; i < m_textures.size(); ++i) {
- if (provider == m_textures.at(i).second)
- m_textures[i].second = 0;
+ for (int i = 0; i < textureProviders.size(); ++i) {
+ if (provider == textureProviders.at(i).second)
+ textureProviders[i].second = 0;
}
}
QQuickShaderEffectNode::QQuickShaderEffectNode()
- : m_material(this)
{
QSGNode::setFlag(UsePreprocess, true);
- setMaterial(&m_material);
#ifdef QML_RUNTIME_TESTING
description = QLatin1String("shadereffect");
@@ -407,7 +389,8 @@ void QQuickShaderEffectNode::markDirtyTexture()
void QQuickShaderEffectNode::textureProviderDestroyed(QObject *object)
{
- m_material.invalidateTextureProvider(static_cast<QSGTextureProvider *>(object));
+ Q_ASSERT(material());
+ static_cast<QQuickShaderEffectMaterial *>(material())->invalidateTextureProvider(static_cast<QSGTextureProvider *>(object));
}
void QQuickShaderEffectNode::preprocess()