diff options
Diffstat (limited to 'src/declarative/items/shadereffectitem.cpp')
-rw-r--r-- | src/declarative/items/shadereffectitem.cpp | 397 |
1 files changed, 0 insertions, 397 deletions
diff --git a/src/declarative/items/shadereffectitem.cpp b/src/declarative/items/shadereffectitem.cpp deleted file mode 100644 index dc49395ec4..0000000000 --- a/src/declarative/items/shadereffectitem.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "shadereffectitem.h" -#include "shadereffectnode.h" - -#include "material.h" -#include "qsgitem_p.h" - -#include "qsgcontext.h" -#include "qsgtextureprovider.h" -#include "qsgcanvas.h" - -#include <QtCore/qsignalmapper.h> -#include <QtOpenGL/qglframebufferobject.h> - -QT_BEGIN_NAMESPACE - -static const char qt_default_vertex_code[] = - "uniform highp mat4 qt_ModelViewProjectionMatrix; \n" - "attribute highp vec4 qt_Vertex; \n" - "attribute highp vec2 qt_MultiTexCoord0; \n" - "varying highp vec2 qt_TexCoord0; \n" - "void main() { \n" - " qt_TexCoord0 = qt_MultiTexCoord0; \n" - " gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex; \n" - "}"; - -static const char qt_default_fragment_code[] = - "varying highp vec2 qt_TexCoord0; \n" - "uniform lowp sampler2D source; \n" - "void main() { \n" - " gl_FragColor = texture2D(source, qt_TexCoord0); \n" - "}"; - -static const char qt_postion_attribute_name[] = "qt_Vertex"; -static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0"; -static const char qt_emptyAttributeName[] = ""; - - -ShaderEffectItem::ShaderEffectItem(QSGItem *parent) - : QSGItem(parent) - , m_mesh_resolution(1, 1) - , m_blending(true) - , m_dirtyData(true) - , m_programDirty(true) -{ - setFlag(QSGItem::ItemHasContents); -} - -ShaderEffectItem::~ShaderEffectItem() -{ - reset(); -} - -void ShaderEffectItem::componentComplete() -{ - updateProperties(); - QSGItem::componentComplete(); -} - -void ShaderEffectItem::setFragmentShader(const QByteArray &code) -{ - if (m_source.fragmentCode.constData() == code.constData()) - return; - m_source.fragmentCode = code; - if (isComponentComplete()) { - reset(); - updateProperties(); - } - emit fragmentShaderChanged(); -} - -void ShaderEffectItem::setVertexShader(const QByteArray &code) -{ - if (m_source.vertexCode.constData() == code.constData()) - return; - m_source.vertexCode = code; - if (isComponentComplete()) { - reset(); - updateProperties(); - } - emit vertexShaderChanged(); -} - -void ShaderEffectItem::setBlending(bool enable) -{ - if (blending() == enable) - return; - - m_blending = enable; - update(); - - emit blendingChanged(); -} - -void ShaderEffectItem::setMeshResolution(const QSize &size) -{ - if (size == m_mesh_resolution) - return; - - m_mesh_resolution = size; - update(); -} - -void ShaderEffectItem::changeSource(int index) -{ - Q_ASSERT(index >= 0 && index < m_sources.size()); - QVariant v = property(m_sources.at(index).name.constData()); - setSource(v, index); -} - -void ShaderEffectItem::markDirty() -{ - m_dirtyData = true; - update(); -} - -void ShaderEffectItem::setSource(const QVariant &var, int index) -{ - Q_ASSERT(index >= 0 && index < m_sources.size()); - - SourceData &source = m_sources[index]; - - source.source = 0; - source.item = 0; - if (var.isNull()) { - return; - } else if (!qVariantCanConvert<QObject *>(var)) { - qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData()); - return; - } - - QObject *obj = qVariantValue<QObject *>(var); - - QSGTextureProviderInterface *int3rface = static_cast<QSGTextureProviderInterface *>(obj->qt_metacast("QSGTextureProviderInterface")); - if (int3rface) { - source.source = int3rface->textureProvider(); - } else { - qWarning("Could not assign property '%s', did not implement QSGTextureProviderInterface.", source.name.constData()); - } - - source.item = qobject_cast<QSGItem *>(obj); - - // TODO: Find better solution. - // 'source.item' needs a canvas to get a scenegraph node. - // The easiest way to make sure it gets a canvas is to - // make it a part of the same item tree as 'this'. - if (source.item && source.item->parentItem() == 0) { - source.item->setParentItem(this); - source.item->setVisible(false); - } -} - -void ShaderEffectItem::disconnectPropertySignals() -{ - disconnect(this, 0, this, SLOT(markDirty())); - for (int i = 0; i < m_sources.size(); ++i) { - SourceData &source = m_sources[i]; - disconnect(this, 0, source.mapper, 0); - disconnect(source.mapper, 0, this, 0); - } -} - -void ShaderEffectItem::connectPropertySignals() -{ - QSet<QByteArray>::const_iterator it; - for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) { - int pi = metaObject()->indexOfProperty(it->constData()); - if (pi >= 0) { - QMetaProperty mp = metaObject()->property(pi); - if (!mp.hasNotifySignal()) - qWarning("ShaderEffectItem: property '%s' does not have notification method!", it->constData()); - QByteArray signalName("2"); - signalName.append(mp.notifySignal().signature()); - connect(this, signalName, this, SLOT(markDirty())); - } else { - qWarning("ShaderEffectItem: '%s' does not have a matching property!", it->constData()); - } - } - for (int i = 0; i < m_sources.size(); ++i) { - SourceData &source = m_sources[i]; - int pi = metaObject()->indexOfProperty(source.name.constData()); - if (pi >= 0) { - QMetaProperty mp = metaObject()->property(pi); - QByteArray signalName("2"); - signalName.append(mp.notifySignal().signature()); - connect(this, signalName, source.mapper, SLOT(map())); - source.mapper->setMapping(this, i); - connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int))); - } else { - qWarning("ShaderEffectItem: '%s' does not have a matching source!", source.name.constData()); - } - } -} - -void ShaderEffectItem::reset() -{ - disconnectPropertySignals(); - - m_source.attributeNames.clear(); - m_source.uniformNames.clear(); - m_source.respectsOpacity = false; - m_source.respectsMatrix = false; - m_source.className = metaObject()->className(); - - for (int i = 0; i < m_sources.size(); ++i) { - const SourceData &source = m_sources.at(i); - delete source.mapper; - if (source.item && source.item->parentItem() == this) - source.item->setParentItem(0); - } - m_sources.clear(); - - m_programDirty = true; -} - -void ShaderEffectItem::updateProperties() -{ - QByteArray vertexCode = m_source.vertexCode; - QByteArray fragmentCode = m_source.fragmentCode; - if (vertexCode.isEmpty()) - vertexCode = qt_default_vertex_code; - if (fragmentCode.isEmpty()) - fragmentCode = qt_default_fragment_code; - - m_source.attributeNames.fill(0, 3); - lookThroughShaderCode(vertexCode); - lookThroughShaderCode(fragmentCode); - - if (!m_source.attributeNames.contains(qt_postion_attribute_name)) - qWarning("ShaderEffectItem: Missing reference to \'%s\'.", qt_postion_attribute_name); - if (!m_source.attributeNames.contains(qt_texcoord_attribute_name)) - qWarning("ShaderEffectItem: Missing reference to \'%s\'.", qt_texcoord_attribute_name); - if (!m_source.respectsMatrix) - qWarning("ShaderEffectItem: Missing reference to \'qt_ModelViewProjectionMatrix\'."); - - for (int i = 0; i < m_sources.size(); ++i) { - QVariant v = property(m_sources.at(i).name); - setSource(v, i); - } - - connectPropertySignals(); -} - -void ShaderEffectItem::lookThroughShaderCode(const QByteArray &code) -{ - // Regexp for matching attributes and uniforms. - // In human readable form: attribute|uniform [lowp|mediump|highp] <type> <name> - static QRegExp re(QLatin1String("\\b(attribute|uniform)\\b\\s*\\b(?:lowp|mediump|highp)?\\b\\s*\\b(\\w+)\\b\\s*\\b(\\w+)")); - Q_ASSERT(re.isValid()); - - int pos = -1; - - QString wideCode = QString::fromLatin1(code.constData(), code.size()); - - while ((pos = re.indexIn(wideCode, pos + 1)) != -1) { - QByteArray decl = re.cap(1).toLatin1(); // uniform or attribute - QByteArray type = re.cap(2).toLatin1(); // type - QByteArray name = re.cap(3).toLatin1(); // variable name - - if (decl == "attribute") { - if (name == qt_postion_attribute_name) { - m_source.attributeNames[0] = qt_postion_attribute_name; - } else if (name == "qt_MultiTexCoord0") { - m_source.attributeNames[1] = qt_texcoord_attribute_name; - if (m_source.attributeNames.at(0) == 0) - m_source.attributeNames[0] = qt_emptyAttributeName; - } else { - // TODO: Support user defined attributes. - qWarning("ShaderEffectItem: Attribute \'%s\' not recognized.", name.constData()); - } - } else { - Q_ASSERT(decl == "uniform"); - - if (name == "qt_ModelViewProjectionMatrix") { - m_source.respectsMatrix = true; - } else if (name == "qt_Opacity") { - m_source.respectsOpacity = true; - } else { - m_source.uniformNames.insert(name); - if (type == "sampler2D") { - SourceData d; - d.mapper = new QSignalMapper; - d.source = 0; - d.name = name; - d.item = 0; - m_sources.append(d); - } - } - } - } -} - -Node *ShaderEffectItem::updatePaintNode(Node *oldNode, UpdatePaintNodeData *) -{ - ShaderEffectNode *node = static_cast<ShaderEffectNode *>(oldNode); - if (!node) { - node = new ShaderEffectNode; - node->setMaterial(&m_material); - m_programDirty = true; - m_dirtyData = true; - } - - if (m_programDirty) { - ShaderEffectProgram s = m_source; - if (s.fragmentCode.isEmpty()) - s.fragmentCode = qt_default_fragment_code; - if (s.vertexCode.isEmpty()) - s.vertexCode = qt_default_vertex_code; - - m_material.setProgramSource(s); - node->markDirty(Node::DirtyMaterial); - m_programDirty = false; - } - - // Update blending - if (bool(m_material.flags() & AbstractMaterial::Blending) != m_blending) { - m_material.setFlag(AbstractMaterial::Blending, m_blending); - node->markDirty(Node::DirtyMaterial); - } - - if (node->resolution() != m_mesh_resolution) - node->setResolution(m_mesh_resolution); - - node->setRect(QRectF(0, 0, width(), height())); - - if (m_dirtyData) { - QVector<QPair<QByteArray, QVariant> > values; - QVector<QPair<QByteArray, QPointer<QSGTextureProvider> > > textures; - const QVector<QPair<QByteArray, QPointer<QSGTextureProvider> > > &oldTextures = m_material.textures(); - - for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin(); - it != m_source.uniformNames.end(); ++it) { - values.append(qMakePair(*it, property(*it))); - } - for (int i = 0; i < oldTextures.size(); ++i) { - QPointer<QSGTextureProvider> oldSource = oldTextures.at(i).second; - if (oldSource) - disconnect(oldSource, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture())); - } - for (int i = 0; i < m_sources.size(); ++i) { - const SourceData &source = m_sources.at(i); - textures.append(qMakePair(source.name, source.source)); - if (source.source) - connect(source.source, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture())); - } - m_material.setUniforms(values); - m_material.setTextures(textures); - node->markDirty(Node::DirtyMaterial); - m_dirtyData = false; - } - - node->update(); - - return node; -} - -QT_END_NAMESPACE |