aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qquickshadereffect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qquickshadereffect.cpp')
-rw-r--r--src/declarative/items/qquickshadereffect.cpp763
1 files changed, 0 insertions, 763 deletions
diff --git a/src/declarative/items/qquickshadereffect.cpp b/src/declarative/items/qquickshadereffect.cpp
deleted file mode 100644
index bdef980440..0000000000
--- a/src/declarative/items/qquickshadereffect.cpp
+++ /dev/null
@@ -1,763 +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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <private/qquickshadereffect_p.h>
-#include <private/qquickshadereffectnode_p.h>
-
-#include "qsgmaterial.h"
-#include "qquickitem_p.h"
-
-#include <private/qsgcontext_p.h>
-#include <private/qsgtextureprovider_p.h>
-#include "qquickcanvas.h"
-
-#include "qquickimage_p.h"
-#include "qquickshadereffectsource_p.h"
-
-#include <QtCore/qsignalmapper.h>
-#include <QtGui/qopenglframebufferobject.h>
-
-QT_BEGIN_NAMESPACE
-
-static const char qt_default_vertex_code[] =
- "uniform highp mat4 qt_Matrix; \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_Matrix * qt_Vertex; \n"
- "}";
-
-static const char qt_default_fragment_code[] =
- "varying highp vec2 qt_TexCoord0; \n"
- "uniform sampler2D source; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
- "}";
-
-static const char qt_position_attribute_name[] = "qt_Vertex";
-static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
-
-const char *qtPositionAttributeName()
-{
- return qt_position_attribute_name;
-}
-
-const char *qtTexCoordAttributeName()
-{
- return qt_texcoord_attribute_name;
-}
-
-/*!
- \qmlclass ShaderEffect QQuickShaderEffect
- \inqmlmodule QtQuick 2
- \ingroup qml-basic-visual-elements
- \brief The ShaderEffect element applies custom shaders to a rectangle.
- \inherits Item
-
- The ShaderEffect element applies a custom OpenGL
- \l{vertexShader}{vertex} and \l{fragmentShader}{fragment} shader to a
- rectangle. It allows you to write effects such as drop shadow, blur,
- colorize and page curl directly in QML.
-
- There are two types of input to the \l vertexShader:
- uniform variables and attributes. Some are predefined:
- \list
- \o uniform mat4 qt_Matrix - combined transformation
- matrix, the product of the matrices from the root item to this
- ShaderEffect, and an orthogonal projection.
- \o uniform float qt_Opacity - combined opacity, the product of the
- opacities from the root item to this ShaderEffect.
- \o attribute vec4 qt_Vertex - vertex position, the top-left vertex has
- position (0, 0), the bottom-right (\l{Item::width}{width},
- \l{Item::height}{height}).
- \o attribute vec2 qt_MultiTexCoord0 - texture coordinate, the top-left
- coordinate is (0, 0), the bottom-right (1, 1).
- \endlist
-
- In addition, any property that can be mapped to an OpenGL Shading Language
- (GLSL) type is available as a uniform variable. The following list shows
- how properties are mapped to GLSL uniform variables:
- \list
- \o bool, int, qreal -> bool, int, float - If the type in the shader is not
- the same as in QML, the value is converted automatically.
- \o QColor -> vec4 - When colors are passed to the shader, they are first
- premultiplied. Thus Qt.rgba(0.2, 0.6, 1.0, 0.5) becomes
- vec4(0.1, 0.3, 0.5, 0.5) in the shader, for example.
- \o QRect, QRectF -> vec4 - Qt.rect(x, y, w, h) becomes vec4(x, y, w, h) in
- the shader.
- \o QPoint, QPointF, QSize, QSizeF -> vec2
- \o QVector3D -> vec3
- \o QTransform -> mat4
- \o \l Image, \l ShaderEffectSource -> sampler2D - Origin is in the top-left
- corner, and the color values are premultiplied.
- \endlist
-
- The output from the \l fragmentShader should be premultiplied. If
- \l blending is enabled, source-over blending is used. However, additive
- blending can be achieved by outputting zero in the alpha channel.
-
- \row
- \o \image declarative-shadereffectitem.png
- \o \qml
- import QtQuick 2.0
-
- Rectangle {
- width: 200; height: 100
- Row {
- Image { id: img; sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
- ShaderEffect {
- width: 100; height: 100
- property variant src: img
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 coord;
- void main() {
- coord = qt_MultiTexCoord0;
- gl_Position = qt_Matrix * qt_Vertex;
- }"
- fragmentShader: "
- varying highp vec2 coord;
- uniform sampler2D src;
- uniform lowp float qt_Opacity;
- void main() {
- lowp vec4 tex = texture2D(src, coord);
- gl_FragColor = vec4(vec3(dot(tex.rgb, vec3(0.344, 0.5, 0.156))), tex.a) * qt_Opacity;
- }"
- }
- }
- }
- \endqml
- \endrow
-
- By default, the ShaderEffect consists of four vertices, one for each
- corner. For non-linear vertex transformations, like page curl, you can
- specify a fine grid of vertices by specifying a \l mesh resolution.
-
- \note Scene Graph textures have origin in the top-left corner rather than
- bottom-left which is common in OpenGL.
-*/
-
-QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
- : QQuickItem(parent)
- , m_meshResolution(1, 1)
- , m_mesh(0)
- , m_cullMode(NoCulling)
- , m_blending(true)
- , m_dirtyData(true)
- , m_programDirty(true)
- , m_dirtyMesh(true)
- , m_dirtyGeometry(true)
-{
- setFlag(QQuickItem::ItemHasContents);
-}
-
-QQuickShaderEffect::~QQuickShaderEffect()
-{
- reset();
-}
-
-void QQuickShaderEffect::componentComplete()
-{
- updateProperties();
- QQuickItem::componentComplete();
-}
-
-/*!
- \qmlproperty string QtQuick2::ShaderEffect::fragmentShader
-
- This property holds the fragment shader's GLSL source code.
- The default shader passes the texture coordinate along to the fragment
- shader as "varying highp vec2 qt_TexCoord0".
-*/
-
-void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
-{
- if (m_source.fragmentCode.constData() == code.constData())
- return;
- m_source.fragmentCode = code;
- if (isComponentComplete()) {
- reset();
- updateProperties();
- update();
- }
- emit fragmentShaderChanged();
-}
-
-/*!
- \qmlproperty string QtQuick2::ShaderEffect::vertexShader
-
- This property holds the vertex shader's GLSL source code.
- The default shader expects the texture coordinate to be passed from the
- vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a
- sampler2D named "source".
-*/
-
-void QQuickShaderEffect::setVertexShader(const QByteArray &code)
-{
- if (m_source.vertexCode.constData() == code.constData())
- return;
- m_source.vertexCode = code;
- if (isComponentComplete()) {
- reset();
- updateProperties();
- update();
- }
- emit vertexShaderChanged();
-}
-
-/*!
- \qmlproperty bool QtQuick2::ShaderEffect::blending
-
- If this property is true, the output from the \l fragmentShader is blended
- with the background using source-over blend mode. If false, the background
- is disregarded. Blending decreases the performance, so you should set this
- property to false when blending is not needed. The default value is true.
-*/
-
-void QQuickShaderEffect::setBlending(bool enable)
-{
- if (blending() == enable)
- return;
-
- m_blending = enable;
- update();
-
- emit blendingChanged();
-}
-
-/*!
- \qmlproperty variant QtQuick2::ShaderEffect::mesh
-
- This property defines the mesh used to draw the ShaderEffect. It can hold
- any mesh object deriving from \l QQuickShaderEffectMesh, such as \l GridMesh.
- If a size value is assigned to this property, the ShaderEffect implicitly
- uses a \l GridMesh with the value as
- \l{GridMesh::resolution}{mesh resolution}. By default, this property is
- the size 1x1.
-
- \sa GridMesh
-*/
-
-QVariant QQuickShaderEffect::mesh() const
-{
- return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
- : qVariantFromValue(m_meshResolution);
-}
-
-void QQuickShaderEffect::setMesh(const QVariant &mesh)
-{
- QQuickShaderEffectMesh *newMesh = qobject_cast<QQuickShaderEffectMesh *>(qVariantValue<QObject *>(mesh));
- if (newMesh && newMesh == m_mesh)
- return;
- if (m_mesh)
- disconnect(m_mesh, SIGNAL(geometryChanged()), this, 0);
- m_mesh = newMesh;
- if (m_mesh) {
- connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
- } else {
- if (qVariantCanConvert<QSize>(mesh)) {
- m_meshResolution = mesh.toSize();
- } else {
- QList<QByteArray> res = mesh.toByteArray().split('x');
- bool ok = res.size() == 2;
- if (ok) {
- int w = res.at(0).toInt(&ok);
- if (ok) {
- int h = res.at(1).toInt(&ok);
- if (ok)
- m_meshResolution = QSize(w, h);
- }
- }
- if (!ok)
- qWarning("ShaderEffect: mesh property must be size or object deriving from QQuickShaderEffectMesh.");
- }
- m_defaultMesh.setResolution(m_meshResolution);
- }
-
- m_dirtyMesh = true;
- update();
- emit meshChanged();
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::ShaderEffect::cullMode
-
- This property defines which sides of the element should be visible.
-
- \list
- \o ShaderEffect.NoCulling - Both sides are visible
- \o ShaderEffect.BackFaceCulling - only front side is visible
- \o ShaderEffect.FrontFaceCulling - only back side is visible
- \endlist
-
- The default is NoCulling.
-*/
-
-void QQuickShaderEffect::setCullMode(CullMode face)
-{
- if (face == m_cullMode)
- return;
- m_cullMode = face;
- update();
- emit cullModeChanged();
-}
-
-void QQuickShaderEffect::changeSource(int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
- QVariant v = property(m_sources.at(index).name.constData());
- setSource(v, index);
-}
-
-void QQuickShaderEffect::updateData()
-{
- m_dirtyData = true;
- update();
-}
-
-void QQuickShaderEffect::updateGeometry()
-{
- m_dirtyGeometry = true;
- update();
-}
-
-void QQuickShaderEffect::setSource(const QVariant &var, int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
-
- SourceData &source = m_sources[index];
-
- source.sourceObject = 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);
- QQuickItem *item = qobject_cast<QQuickItem *>(obj);
- if (!item || !item->isTextureProvider()) {
- qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
- source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
- return;
- }
-
- source.sourceObject = item;
-
-
- // TODO: Find better solution.
- // '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 (item && item->parentItem() == 0) {
- item->setParentItem(this);
- item->setVisible(false);
- }
-}
-
-void QQuickShaderEffect::disconnectPropertySignals()
-{
- disconnect(this, 0, this, SLOT(updateData()));
- 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 QQuickShaderEffect::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("QQuickShaderEffect: property '%s' does not have notification method!", it->constData());
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().signature());
- connect(this, signalName, this, SLOT(updateData()));
- } else {
- qWarning("QQuickShaderEffect: '%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("QQuickShaderEffect: '%s' does not have a matching source!", source.name.constData());
- }
- }
-}
-
-void QQuickShaderEffect::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;
- QQuickItem *item = qobject_cast<QQuickItem *>(source.sourceObject);
- if (item && item->parentItem() == this)
- item->setParentItem(0);
- }
- m_sources.clear();
-
- m_programDirty = true;
- m_dirtyMesh = true;
-}
-
-void QQuickShaderEffect::updateProperties()
-{
- if (m_source.vertexCode.isEmpty()) {
- m_source.attributeNames.append(QByteArray(qt_position_attribute_name));
- m_source.attributeNames.append(QByteArray(qt_texcoord_attribute_name));
- m_source.respectsMatrix = true;
- } else {
- lookThroughShaderCode(m_source.vertexCode);
- }
- if (m_source.fragmentCode.isEmpty()) {
- m_source.respectsOpacity = true;
- QByteArray name("source");
- m_source.uniformNames.insert(name);
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.sourceObject = 0;
- m_sources.append(d);
- } else {
- lookThroughShaderCode(m_source.fragmentCode);
- }
-
- if (!m_mesh && !m_source.attributeNames.contains(qt_position_attribute_name))
- qWarning("QQuickShaderEffect: Missing reference to \'%s\'.", qt_position_attribute_name);
- if (!m_mesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
- qWarning("QQuickShaderEffect: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
- if (!m_source.respectsMatrix)
- qWarning("QQuickShaderEffect: Missing reference to \'qt_Matrix\'.");
- if (!m_source.respectsOpacity)
- qWarning("QQuickShaderEffect: Missing reference to \'qt_Opacity\'.");
-
- for (int i = 0; i < m_sources.size(); ++i) {
- QVariant v = property(m_sources.at(i).name);
- setSource(v, i);
- }
-
- connectPropertySignals();
-}
-
-namespace {
-
- enum VariableQualifier {
- AttributeQualifier,
- UniformQualifier
- };
-
- inline bool qt_isalpha(char c)
- {
- char ch = c | 0x20;
- return (ch >= 'a' && ch <= 'z') || c == '_';
- }
-
- inline bool qt_isalnum(char c)
- {
- return qt_isalpha(c) || (c >= '0' && c <= '9');
- }
-
- inline bool qt_isspace(char c)
- {
- return c == ' ' || (c >= 0x09 && c <= 0x0d);
- }
-
- // Returns -1 if not found, returns index to first character after the name if found.
- int qt_search_for_variable(const char *s, int length, int index, VariableQualifier &decl,
- int &typeIndex, int &typeLength,
- int &nameIndex, int &nameLength)
- {
- enum Identifier {
- QualifierIdentifier, // Base state
- PrecisionIdentifier,
- TypeIdentifier,
- NameIdentifier
- };
- Identifier expected = QualifierIdentifier;
- bool compilerDirectiveExpected = index == 0;
-
- while (index < length) {
- // Skip whitespace.
- while (qt_isspace(s[index])) {
- compilerDirectiveExpected |= s[index] == '\n';
- ++index;
- }
-
- if (qt_isalpha(s[index])) {
- // Read identifier.
- int idIndex = index;
- ++index;
- while (qt_isalnum(s[index]))
- ++index;
- int idLength = index - idIndex;
-
- const int attrLen = sizeof("attribute") - 1;
- const int uniLen = sizeof("uniform") - 1;
- const int loLen = sizeof("lowp") - 1;
- const int medLen = sizeof("mediump") - 1;
- const int hiLen = sizeof("highp") - 1;
-
- switch (expected) {
- case QualifierIdentifier:
- if (idLength == attrLen && qstrncmp("attribute", s + idIndex, attrLen) == 0) {
- decl = AttributeQualifier;
- expected = PrecisionIdentifier;
- } else if (idLength == uniLen && qstrncmp("uniform", s + idIndex, uniLen) == 0) {
- decl = UniformQualifier;
- expected = PrecisionIdentifier;
- }
- break;
- case PrecisionIdentifier:
- if ((idLength == loLen && qstrncmp("lowp", s + idIndex, loLen) == 0)
- || (idLength == medLen && qstrncmp("mediump", s + idIndex, medLen) == 0)
- || (idLength == hiLen && qstrncmp("highp", s + idIndex, hiLen) == 0))
- {
- expected = TypeIdentifier;
- break;
- }
- // Fall through.
- case TypeIdentifier:
- typeIndex = idIndex;
- typeLength = idLength;
- expected = NameIdentifier;
- break;
- case NameIdentifier:
- nameIndex = idIndex;
- nameLength = idLength;
- return index; // Attribute or uniform declaration found. Return result.
- default:
- break;
- }
- } else if (s[index] == '#' && compilerDirectiveExpected) {
- // Skip compiler directives.
- ++index;
- while (index < length && (s[index] != '\n' || s[index - 1] == '\\'))
- ++index;
- } else if (s[index] == '/' && s[index + 1] == '/') {
- // Skip comments.
- index += 2;
- while (index < length && s[index] != '\n')
- ++index;
- } else if (s[index] == '/' && s[index + 1] == '*') {
- // Skip comments.
- index += 2;
- while (index < length && (s[index] != '*' || s[index + 1] != '/'))
- ++index;
- if (index < length)
- index += 2; // Skip star-slash.
- } else {
- expected = QualifierIdentifier;
- ++index;
- }
- compilerDirectiveExpected = false;
- }
- return -1;
- }
-}
-
-void QQuickShaderEffect::lookThroughShaderCode(const QByteArray &code)
-{
- int index = 0;
- int typeIndex, typeLength, nameIndex, nameLength;
- const char *s = code.constData();
- VariableQualifier decl;
- while ((index = qt_search_for_variable(s, code.size(), index, decl, typeIndex, typeLength,
- nameIndex, nameLength)) != -1)
- {
- if (decl == AttributeQualifier) {
- m_source.attributeNames.append(QByteArray(s + nameIndex, nameLength));
- } else {
- Q_ASSERT(decl == UniformQualifier);
-
- const int matLen = sizeof("qt_Matrix") - 1;
- const int opLen = sizeof("qt_Opacity") - 1;
- const int sampLen = sizeof("sampler2D") - 1;
-
- if (nameLength == matLen && qstrncmp("qt_Matrix", s + nameIndex, matLen) == 0) {
- m_source.respectsMatrix = true;
- } else if (nameLength == opLen && qstrncmp("qt_Opacity", s + nameIndex, opLen) == 0) {
- m_source.respectsOpacity = true;
- } else {
- QByteArray name(s + nameIndex, nameLength);
- m_source.uniformNames.insert(name);
- if (typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0) {
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.sourceObject = 0;
- m_sources.append(d);
- }
- }
- }
- }
-}
-
-void QQuickShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- m_dirtyGeometry = true;
- QQuickItem::geometryChanged(newGeometry, oldGeometry);
-}
-
-QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- QQuickShaderEffectNode *node = static_cast<QQuickShaderEffectNode *>(oldNode);
-
- // In the case of a bad vertex shader, don't try to create a node...
- if (m_source.attributeNames.isEmpty()) {
- if (node)
- delete node;
- return 0;
- }
-
- if (!node) {
- node = new QQuickShaderEffectNode;
- m_programDirty = true;
- m_dirtyData = true;
- m_dirtyGeometry = true;
- }
-
- QQuickShaderEffectMaterial *material = node->shaderMaterial();
-
- if (m_dirtyMesh) {
- node->setGeometry(0);
- m_dirtyMesh = false;
- m_dirtyGeometry = true;
- }
-
- if (m_dirtyGeometry) {
- node->setFlag(QSGNode::OwnsGeometry, false);
- QSGGeometry *geometry = node->geometry();
- QRectF rect(0, 0, width(), height());
- QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
-
- geometry = mesh->updateGeometry(geometry, m_source.attributeNames, rect);
- if (!geometry) {
- delete node;
- return 0;
- }
-
- node->setGeometry(geometry);
- node->setFlag(QSGNode::OwnsGeometry, true);
-
- m_dirtyGeometry = false;
- }
-
- if (m_programDirty) {
- QQuickShaderEffectProgram s = m_source;
- if (s.fragmentCode.isEmpty())
- s.fragmentCode = qt_default_fragment_code;
- if (s.vertexCode.isEmpty())
- s.vertexCode = qt_default_vertex_code;
- s.className = metaObject()->className();
-
- material->setProgramSource(s);
- node->markDirty(QSGNode::DirtyMaterial);
- m_programDirty = false;
- }
-
- // Update blending
- if (bool(material->flags() & QSGMaterial::Blending) != m_blending) {
- material->setFlag(QSGMaterial::Blending, m_blending);
- node->markDirty(QSGNode::DirtyMaterial);
- }
-
- if (int(material->cullMode()) != int(m_cullMode)) {
- material->setCullMode(QQuickShaderEffectMaterial::CullMode(m_cullMode));
- node->markDirty(QSGNode::DirtyMaterial);
- }
-
- if (m_dirtyData) {
- QVector<QPair<QByteArray, QVariant> > values;
- QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = material->textureProviders();
-
- 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) {
- QSGTextureProvider *t = oldTextures.at(i).second;
- if (t)
- disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- QSGTextureProvider *t = source.sourceObject ? source.sourceObject->textureProvider() : 0;
- textures.append(qMakePair(source.name, t));
- if (t)
- connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
- }
- material->setUniforms(values);
- material->setTextureProviders(textures);
- node->markDirty(QSGNode::DirtyMaterial);
- m_dirtyData = false;
- }
-
- return node;
-}
-
-QT_END_NAMESPACE