summaryrefslogtreecommitdiffstats
path: root/src/imports/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'src/imports/shaders')
-rw-r--r--src/imports/shaders/glfunctions.h75
-rw-r--r--src/imports/shaders/qmldir2
-rw-r--r--src/imports/shaders/qmlshadersplugin_plugin.cpp55
-rw-r--r--src/imports/shaders/qmlshadersplugin_plugin.h56
-rw-r--r--src/imports/shaders/scenegraph/qsggeometry.cpp194
-rw-r--r--src/imports/shaders/scenegraph/qsggeometry.h234
-rw-r--r--src/imports/shaders/shadereffect.cpp196
-rw-r--r--src/imports/shaders/shadereffect.h81
-rw-r--r--src/imports/shaders/shadereffectbuffer.cpp52
-rw-r--r--src/imports/shaders/shadereffectbuffer.h62
-rw-r--r--src/imports/shaders/shadereffectitem.cpp955
-rw-r--r--src/imports/shaders/shadereffectitem.h154
-rw-r--r--src/imports/shaders/shadereffectsource.cpp451
-rw-r--r--src/imports/shaders/shadereffectsource.h159
-rw-r--r--src/imports/shaders/shaders.pro38
15 files changed, 2764 insertions, 0 deletions
diff --git a/src/imports/shaders/glfunctions.h b/src/imports/shaders/glfunctions.h
new file mode 100644
index 00000000..214143a5
--- /dev/null
+++ b/src/imports/shaders/glfunctions.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef GLFUNCTIONS_H
+#define GLFUNCTIONS_H
+
+#ifndef QT_OPENGL_ES
+
+#ifndef Q_WS_MAC
+# ifndef APIENTRYP
+# ifdef APIENTRY
+# define APIENTRYP APIENTRY *
+# else
+# define APIENTRY
+# define APIENTRYP *
+# endif
+# endif
+#else
+# define APIENTRY
+# define APIENTRYP *
+#endif
+
+#define GL_TEXTURE0 0x84C0
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_BGRA 0x80E1
+
+typedef void (APIENTRYP type_glActiveTexture)(GLenum texture);
+typedef void (APIENTRYP type_glGenerateMipmap)(GLenum target);
+typedef void (APIENTRYP type_glVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+
+#define glActiveTexture ((type_glActiveTexture)QGLContext::currentContext()->getProcAddress(QLatin1String("glActiveTexture")))
+#define glGenerateMipmap ((type_glGenerateMipmap)QGLContext::currentContext()->getProcAddress(QLatin1String("glGenerateMipmap")))
+#define glVertexAttribPointer ((type_glVertexAttribPointer)QGLContext::currentContext()->getProcAddress(QLatin1String("glVertexAttribPointer")))
+
+#endif
+
+#endif // GLFUNCTIONS_H
diff --git a/src/imports/shaders/qmldir b/src/imports/shaders/qmldir
new file mode 100644
index 00000000..b2a9de21
--- /dev/null
+++ b/src/imports/shaders/qmldir
@@ -0,0 +1,2 @@
+plugin qmlshadersplugin
+
diff --git a/src/imports/shaders/qmlshadersplugin_plugin.cpp b/src/imports/shaders/qmlshadersplugin_plugin.cpp
new file mode 100644
index 00000000..613e1834
--- /dev/null
+++ b/src/imports/shaders/qmlshadersplugin_plugin.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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 "qmlshadersplugin_plugin.h"
+#include "shadereffectitem.h"
+#include "shadereffectsource.h"
+
+#include <QtDeclarative/qdeclarative.h>
+
+void qmlshaderspluginPlugin::registerTypes(const char *uri)
+{
+ qmlRegisterType<ShaderEffectItem>(uri, 1, 0, "ShaderEffectItem");
+ qmlRegisterType<ShaderEffectSource>(uri, 1, 0, "ShaderEffectSource");
+}
+
+Q_EXPORT_PLUGIN2(qmlshadersplugin, qmlshaderspluginPlugin)
+
diff --git a/src/imports/shaders/qmlshadersplugin_plugin.h b/src/imports/shaders/qmlshadersplugin_plugin.h
new file mode 100644
index 00000000..d1f7746c
--- /dev/null
+++ b/src/imports/shaders/qmlshadersplugin_plugin.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef QMLSHADERSPLUGIN_PLUGIN_H
+#define QMLSHADERSPLUGIN_PLUGIN_H
+
+#include <QtDeclarative/QDeclarativeExtensionPlugin>
+
+class qmlshaderspluginPlugin : public QDeclarativeExtensionPlugin
+{
+ Q_OBJECT
+
+public:
+ void registerTypes(const char *uri);
+};
+
+#endif // QMLSHADERSPLUGIN_PLUGIN_H
+
diff --git a/src/imports/shaders/scenegraph/qsggeometry.cpp b/src/imports/shaders/scenegraph/qsggeometry.cpp
new file mode 100644
index 00000000..371b6e88
--- /dev/null
+++ b/src/imports/shaders/scenegraph/qsggeometry.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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 "qsggeometry.h"
+
+QT_BEGIN_NAMESPACE
+
+
+const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D()
+{
+ static Attribute data[] = {
+ { 0, 2, GL_FLOAT }
+ };
+ static AttributeSet attrs = { 1, sizeof(float) * 2, data };
+ return attrs;
+}
+
+
+const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D()
+{
+ static Attribute data[] = {
+ { 0, 2, GL_FLOAT },
+ { 1, 2, GL_FLOAT }
+ };
+ static AttributeSet attrs = { 2, sizeof(float) * 4, data };
+ return attrs;
+}
+
+
+const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D()
+{
+ static Attribute data[] = {
+ { 0, 2, GL_FLOAT },
+ { 1, 4, GL_UNSIGNED_BYTE }
+ };
+ static AttributeSet attrs = { 2, 2 * sizeof(float) + 4 * sizeof(char), data };
+ return attrs;
+}
+
+
+
+QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
+ int vertexCount,
+ int indexCount,
+ int indexType)
+ : m_drawing_mode(GL_TRIANGLE_STRIP)
+ , m_vertex_count(0)
+ , m_index_count(0)
+ , m_index_type(indexType)
+ , m_attributes(attributes)
+ , m_data(0)
+ , m_index_data_offset(-1)
+ , m_owns_data(false)
+{
+ Q_ASSERT(m_attributes.count > 0);
+ Q_ASSERT(m_attributes.stride > 0);
+
+ // Because allocate reads m_vertex_count, m_index_count and m_owns_data, these
+ // need to be set before calling allocate...
+ allocate(vertexCount, indexCount);
+}
+
+QSGGeometry::~QSGGeometry()
+{
+ if (m_owns_data)
+ qFree(m_data);
+}
+
+void *QSGGeometry::indexData()
+{
+ return m_index_data_offset < 0
+ ? 0
+ : ((char *) m_data + m_index_data_offset);
+}
+
+const void *QSGGeometry::indexData() const
+{
+ return m_index_data_offset < 0
+ ? 0
+ : ((char *) m_data + m_index_data_offset);
+}
+
+void QSGGeometry::setDrawingMode(GLenum mode)
+{
+ m_drawing_mode = mode;
+}
+
+void QSGGeometry::allocate(int vertexCount, int indexCount)
+{
+ if (vertexCount == m_vertex_count && indexCount == m_index_count)
+ return;
+
+ m_vertex_count = vertexCount;
+ m_index_count = indexCount;
+
+ bool canUsePrealloc = m_index_count <= 0;
+ int vertexByteSize = m_attributes.stride * m_vertex_count;
+
+ if (m_owns_data)
+ qFree(m_data);
+
+ if (canUsePrealloc && vertexByteSize <= (int) sizeof(m_prealloc)) {
+ m_data = (void *) &m_prealloc[0];
+ m_index_data_offset = -1;
+ m_owns_data = false;
+ } else {
+ Q_ASSERT(m_index_type == GL_UNSIGNED_INT || m_index_type == GL_UNSIGNED_SHORT);
+ int indexByteSize = indexCount * (m_index_type == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32));
+ m_data = (void *) qMalloc(vertexByteSize + indexByteSize);
+ m_index_data_offset = vertexByteSize;
+ m_owns_data = true;
+ }
+
+}
+
+void QSGGeometry::updateRectGeometry(QSGGeometry *g, const QRectF &rect)
+{
+ Point2D *v = g->vertexDataAsPoint2D();
+ v[0].x = rect.left();
+ v[0].y = rect.top();
+
+ v[1].x = rect.right();
+ v[1].y = rect.top();
+
+ v[2].x = rect.left();
+ v[2].y = rect.bottom();
+
+ v[3].x = rect.right();
+ v[3].y = rect.bottom();
+}
+
+void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
+{
+ TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
+ v[0].x = rect.left();
+ v[0].y = rect.top();
+ v[0].tx = textureRect.left();
+ v[0].ty = textureRect.top();
+
+ v[1].x = rect.right();
+ v[1].y = rect.top();
+ v[1].tx = textureRect.right();
+ v[1].ty = textureRect.top();
+
+ v[2].x = rect.left();
+ v[2].y = rect.bottom();
+ v[2].tx = textureRect.left();
+ v[2].ty = textureRect.bottom();
+
+ v[3].x = rect.right();
+ v[3].y = rect.bottom();
+ v[3].tx = textureRect.right();
+ v[3].ty = textureRect.bottom();
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/shaders/scenegraph/qsggeometry.h b/src/imports/shaders/scenegraph/qsggeometry.h
new file mode 100644
index 00000000..9596898b
--- /dev/null
+++ b/src/imports/shaders/scenegraph/qsggeometry.h
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef QSGGEOMETRY_H
+#define QSGGEOMETRY_H
+
+#include <QtOpenGL/qgl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QSGGeometry
+{
+public:
+ struct Attribute
+ {
+ int position;
+ int tupleSize;
+ int type;
+ };
+
+ struct AttributeSet {
+ int count;
+ int stride;
+ const Attribute *attributes;
+ };
+
+ struct Point2D { float x, y; };
+ struct TexturedPoint2D { float x, y; float tx, ty; };
+ struct ColoredPoint2D { float x, y; unsigned char r, g, b, a; };
+
+ static const AttributeSet &defaultAttributes_Point2D();
+ static const AttributeSet &defaultAttributes_TexturedPoint2D();
+ static const AttributeSet &defaultAttributes_ColoredPoint2D();
+
+ QSGGeometry(const QSGGeometry::AttributeSet &attribs,
+ int vertexCount,
+ int indexCount = 0,
+ int indexType = GL_UNSIGNED_SHORT);
+ ~QSGGeometry();
+
+ void setDrawingMode(GLenum mode);
+ inline GLenum drawingMode() const { return m_drawing_mode; }
+
+ void allocate(int vertexCount, int indexCount = 0);
+
+ int vertexCount() const { return m_vertex_count; }
+
+ void *vertexData() { return m_data; }
+ inline Point2D *vertexDataAsPoint2D();
+ inline TexturedPoint2D *vertexDataAsTexturedPoint2D();
+ inline ColoredPoint2D *vertexDataAsColoredPoint2D();
+
+ inline const void *vertexData() const { return m_data; }
+ inline const Point2D *vertexDataAsPoint2D() const;
+ inline const TexturedPoint2D *vertexDataAsTexturedPoint2D() const;
+ inline const ColoredPoint2D *vertexDataAsColoredPoint2D() const;
+
+ inline int indexType() const { return m_index_type; }
+
+ int indexCount() const { return m_index_count; }
+
+ void *indexData();
+ inline uint *indexDataAsUInt();
+ inline quint16 *indexDataAsUShort();
+
+ const void *indexData() const;
+ inline const uint *indexDataAsUInt() const;
+ inline const quint16 *indexDataAsUShort() const;
+
+ inline int attributeCount() const { return m_attributes.count; }
+ inline const Attribute *attributes() const { return m_attributes.attributes; }
+ inline int stride() const { return m_attributes.stride; }
+
+ static void updateRectGeometry(QSGGeometry *g, const QRectF &rect);
+ static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect);
+
+private:
+ int m_drawing_mode;
+ int m_vertex_count;
+ int m_index_count;
+ int m_index_type;
+ const AttributeSet &m_attributes;
+ void *m_data;
+ int m_index_data_offset;
+
+ void *m_reserved_pointer;
+
+ uint m_owns_data : 1;
+ uint m_reserved_bits : 31;
+
+ float m_prealloc[16];
+};
+
+inline uint *QSGGeometry::indexDataAsUInt()
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
+ return (uint *) indexData();
+}
+
+inline quint16 *QSGGeometry::indexDataAsUShort()
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
+ return (quint16 *) indexData();
+}
+
+inline const uint *QSGGeometry::indexDataAsUInt() const
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
+ return (uint *) indexData();
+}
+
+inline const quint16 *QSGGeometry::indexDataAsUShort() const
+{
+ Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
+ return (quint16 *) indexData();
+}
+
+inline QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D()
+{
+ Q_ASSERT(m_attributes.count == 1);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ return (Point2D *) m_data;
+}
+
+inline QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D()
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
+ return (TexturedPoint2D *) m_data;
+}
+
+inline QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D()
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
+ return (ColoredPoint2D *) m_data;
+}
+
+inline const QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() const
+{
+ Q_ASSERT(m_attributes.count == 1);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ return (const Point2D *) m_data;
+}
+
+inline const QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() const
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
+ return (const TexturedPoint2D *) m_data;
+}
+
+inline const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() const
+{
+ Q_ASSERT(m_attributes.count == 2);
+ Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
+ Q_ASSERT(m_attributes.attributes[0].position == 0);
+ Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
+ Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
+ Q_ASSERT(m_attributes.attributes[1].position == 1);
+ Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
+ Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
+ return (const ColoredPoint2D *) m_data;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGGEOMETRY_H
diff --git a/src/imports/shaders/shadereffect.cpp b/src/imports/shaders/shadereffect.cpp
new file mode 100644
index 00000000..97649eb6
--- /dev/null
+++ b/src/imports/shaders/shadereffect.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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 "shadereffect.h"
+#include "shadereffectbuffer.h"
+#include "shadereffectsource.h"
+
+#include <QDeclarativeItem>
+#include <QPainter>
+#include <QtOpenGL>
+
+static QTransform savedWorldTransform;
+
+ShaderEffect::ShaderEffect(QObject *parent)
+ : QGraphicsEffect(parent)
+ , m_changed(true)
+{
+}
+
+ShaderEffect::~ShaderEffect()
+{
+}
+
+void ShaderEffect::prepareBufferedDraw(QPainter *painter)
+{
+#ifndef QT_NO_DYNAMIC_CAST
+ // This workaround needed because QGraphicsEffect seems to always utilize default painters worldtransform
+ // instead of the active painters worldtransform.
+ const ShaderEffectBuffer *effectBuffer = dynamic_cast<ShaderEffectBuffer*> (painter->device());
+ if (effectBuffer) {
+ savedWorldTransform = painter->worldTransform() * savedWorldTransform;
+ painter->setWorldTransform(savedWorldTransform);
+ } else {
+ savedWorldTransform = painter->worldTransform();
+ }
+#else
+ Q_UNUSED(painter);
+#endif
+}
+
+void ShaderEffect::draw (QPainter *painter)
+{
+ const QGLContext *context = QGLContext::currentContext();
+
+ prepareBufferedDraw(painter);
+
+ if (context) {
+ updateRenderTargets();
+ }
+
+ if (!context || m_renderTargets.count() == 0 || !hideOriginal())
+ drawSource(painter);
+}
+
+void ShaderEffect::updateRenderTargets()
+{
+ if (!m_changed)
+ return;
+
+ m_changed = false;
+
+ int count = m_renderTargets.count();
+ for (int i = 0; i < count; i++) {
+ if (m_renderTargets[i]->isLive() || m_renderTargets[i]->isDirtyTexture()) {
+ m_renderTargets[i]->updateBackbuffer();
+ ShaderEffectBuffer* target = m_renderTargets[i]->fbo();
+ if (target && target->isValid() && target->width() > 0 && target->height() > 0) {
+ QPainter p(target);
+ p.setCompositionMode(QPainter::CompositionMode_Clear);
+ p.fillRect(QRect(QPoint(0, 0), target->size()), Qt::transparent);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+ QRectF sourceRect = m_renderTargets[i]->sourceRect();
+ QSize textureSize = m_renderTargets[i]->textureSize();
+
+ qreal yflip = m_renderTargets[i]->isMirrored() ? -1.0 : 1.0; // flip y to match scenegraph, it also flips texturecoordinates
+ qreal xscale = 1.0;
+ qreal yscale = 1.0 * yflip;
+
+ qreal leftMargin = 0.0;
+ qreal rightMargin = 0.0;
+ qreal topMargin = 0.0;
+ qreal bottomMargin = 0.0;
+
+ qreal width = m_renderTargets[i]->sourceItem()->width();
+ qreal height = m_renderTargets[i]->sourceItem()->height();
+
+ if (!sourceRect.isEmpty()) {
+ leftMargin = -sourceRect.left();
+ rightMargin = sourceRect.right() - width;
+ topMargin = -sourceRect.top();
+ bottomMargin = sourceRect.bottom() - height;
+ }
+
+ if ((width + leftMargin + rightMargin) > 0 && (height + topMargin + bottomMargin) > 0) {
+ if (!textureSize.isEmpty()) {
+ qreal textureWidth = textureSize.width();
+ qreal textureHeight = textureSize.height();
+
+ xscale = width / (width + leftMargin + rightMargin);
+ yscale = height / (height + topMargin + bottomMargin);
+
+ p.translate(textureWidth / 2, textureHeight / 2);
+ p.scale(xscale, yscale * yflip);
+ p.translate(-textureWidth / 2, -textureHeight / 2);
+ p.scale(textureWidth / width, textureHeight / height);
+ } else {
+ xscale = width / (width + leftMargin + rightMargin);
+ yscale = height / (height + topMargin + bottomMargin);
+
+ p.translate(width / 2, height / 2);
+ p.scale(xscale, yscale * yflip);
+ p.translate(-width / 2, -height / 2);
+ }
+ }
+
+ drawSource(&p);
+ p.end();
+ m_renderTargets[i]->markSceneGraphDirty();
+ }
+ }
+ }
+}
+
+void ShaderEffect::sourceChanged (ChangeFlags flags)
+{
+ Q_UNUSED(flags);
+ m_changed = true;
+}
+
+void ShaderEffect::addRenderTarget(ShaderEffectSource *target)
+{
+ if (!m_renderTargets.contains(target))
+ m_renderTargets.append(target);
+}
+
+void ShaderEffect::removeRenderTarget(ShaderEffectSource *target)
+{
+ int index = m_renderTargets.indexOf(target);
+ if (index >= 0)
+ m_renderTargets.remove(index);
+ else
+ qWarning() << "ShaderEffect::removeRenderTarget - did not find target.";
+}
+
+bool ShaderEffect::hideOriginal() const
+{
+ if (m_renderTargets.count() == 0)
+ return false;
+
+ // Just like scenegraph version, if there is even one source that says "hide original" we hide it.
+ int count = m_renderTargets.count();
+ for (int i = 0; i < count; i++) {
+ if (m_renderTargets[i]->hideSource())
+ return true;
+ }
+ return false;
+}
diff --git a/src/imports/shaders/shadereffect.h b/src/imports/shaders/shadereffect.h
new file mode 100644
index 00000000..ac61d2ea
--- /dev/null
+++ b/src/imports/shaders/shadereffect.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef SHADEREFFECT_H
+#define SHADEREFFECT_H
+
+#include <QGraphicsEffect>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class ShaderEffectSource;
+
+class ShaderEffect : public QGraphicsEffect
+{
+ Q_OBJECT
+
+public:
+ ShaderEffect(QObject *parent = 0);
+ ~ShaderEffect();
+ void addRenderTarget(ShaderEffectSource *target);
+ void removeRenderTarget(ShaderEffectSource *target);
+
+protected:
+ virtual void draw (QPainter *painter);
+ virtual void sourceChanged (ChangeFlags flags);
+
+private:
+ void prepareBufferedDraw(QPainter *painter);
+ void updateRenderTargets();
+ bool hideOriginal() const;
+
+public:
+ QVector<ShaderEffectSource*> m_renderTargets;
+ bool m_changed : 1;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // SHADEREFFECT_H
diff --git a/src/imports/shaders/shadereffectbuffer.cpp b/src/imports/shaders/shadereffectbuffer.cpp
new file mode 100644
index 00000000..415f9272
--- /dev/null
+++ b/src/imports/shaders/shadereffectbuffer.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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 "shadereffectbuffer.h"
+
+ShaderEffectBuffer::ShaderEffectBuffer(const QSize & size, const QGLFramebufferObjectFormat & format)
+ : QGLFramebufferObject(size, format)
+{
+}
+
+ShaderEffectBuffer::~ShaderEffectBuffer()
+{
+}
+
diff --git a/src/imports/shaders/shadereffectbuffer.h b/src/imports/shaders/shadereffectbuffer.h
new file mode 100644
index 00000000..274a81ac
--- /dev/null
+++ b/src/imports/shaders/shadereffectbuffer.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef SHADEREFFECTBUFFER_H
+#define SHADEREFFECTBUFFER_H
+
+#include <QtOpenGL>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class ShaderEffectBuffer : public QGLFramebufferObject
+{
+public:
+ ShaderEffectBuffer(const QSize &size, const QGLFramebufferObjectFormat &format);
+ ~ShaderEffectBuffer();
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // SHADEREFFECTBUFFER_H
diff --git a/src/imports/shaders/shadereffectitem.cpp b/src/imports/shaders/shadereffectitem.cpp
new file mode 100644
index 00000000..3259c850
--- /dev/null
+++ b/src/imports/shaders/shadereffectitem.cpp
@@ -0,0 +1,955 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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 "shadereffectitem.h"
+#include "shadereffect.h"
+#include "glfunctions.h"
+
+#include <QPainter>
+#include <QtOpenGL>
+
+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(void)\n"
+ "{\n"
+ "qt_TexCoord0 = qt_MultiTexCoord0;\n"
+ "gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;\n"
+ "}\n";
+
+static const char qt_default_fragment_code[] =
+ "varying highp vec2 qt_TexCoord0;\n"
+ "uniform lowp sampler2D source;\n"
+ "void main(void)\n"
+ "{\n"
+ "gl_FragColor = texture2D(source, qt_TexCoord0.st);\n"
+ "}\n";
+
+static const char qt_postion_attribute_name[] = "qt_Vertex";
+static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
+static const char qt_emptyAttributeName[] = "";
+
+
+/*!
+ \qmlclass ShaderEffectItem ShaderEffectItem
+ \ingroup qml-shader-elements
+ \brief The ShaderEffectItem object alters the output of given item with OpenGL shaders.
+ \inherits Item
+
+ ShaderEffectItem is available in the \bold{Qt.labs.shaders 1.0} module.
+ \e {Elements in the Qt.labs module are not guaranteed to remain compatible
+ in future versions.}
+
+ This element provides preliminary support for embedding OpenGL shader code into QML,
+ and may be heavily changed or removed in later versions.
+
+ Requirement for the use of shaders is that the application is either using
+ Qt OpenGL graphicssystem or is using OpenGL by setting QGLWidget as the viewport to QDeclarativeView (depending on which one is the recommened way in the targeted platform).
+
+ ShaderEffectItem internal behaviour is such that during the paint event it first renders its
+ ShaderEffectSource items into a OpenGL framebuffer object which can be used as a texture. If the ShaderEffectSource is defined to be an image,
+ it is directly uploaded as a texture. The texture(s) containing the source pixelcontent are then bound to graphics
+ pipeline texture units. Finally a textured mesh is passed to the vertex- and fragmentshaders which
+ then produce the final output for the ShaderEffectItem. It is possible to alter the mesh structure by defining
+ the amount vertices it contains, but currently it is not possible to import complex 3D-models to be used as the mesh.
+
+ It is possible to define one or more ShaderEffectItems to be a ShaderEffectSource for other ShaderEffectItems, but ShaderEffectItem
+ should never be declared as a child element of its source item(s) because it would cause circular loop in the painting.
+
+ A standard set of vertex attributes are provided for the shaders:
+
+ \list
+ \o qt_Vertex - The primary position of the vertex.
+ \o qt_MultiTexCoord0 - The texture co-ordinate at each vertex for texture unit 0.
+ \endlist
+
+ Additionally following uniforms are available for shaders:
+
+ \list
+ \o qt_Opacity - Effective opacity of the item.
+ \o qt_ModelViewProjectionMatrix - current 4x4 transformation matrix of the item.
+ \endlist
+
+ Furthermore, it is possible to utilize automatic QML propertybinding into vertex- and fragment shader
+ uniforms. Conversions are done according to the table below:
+
+ \table
+ \header
+ \o QML property
+ \o GLSL uniform
+ \row
+ \o property double foo: 1.0
+ \o uniform highp float foo
+ \row
+ \o property real foo: 1.0
+ \o uniform highp float foo
+ \row
+ \o property bool foo: true
+ \o uniform bool foo
+ \row
+ \o property int foo: 1
+ \o uniform int foo
+ \row
+ \o property variant foo: Qt.point(1,1)
+ \o uniform highp vec2 foo
+ \row
+ \o property variant foo: Qt.size(1, 1)
+ \o uniform highp vec2 foo
+ \row
+ \o property variant foo: Qt.rect(1, 1, 2, 2)
+ \o uniform highp vec4 foo
+ \row
+ \o property color foo: "#00000000"
+ \o uniform lowp vec4 foo
+ \row
+ \o property variant foo: Qt.vector3d(1.0, 2.0, 0.0)
+ \o uniform highp vec3 foo
+ \row
+ \o property variant foo: ShaderEffectSource { SourceItem: bar }
+ \o uniform lowp sampler2D foo
+ \endtable
+ \note
+ The uniform precision definitions in the above table are not strict, it is possible to choose the uniform
+ precision based on what is the most suitable for the shader code for that particular uniform.
+
+
+ The below example uses fragment shader to create simple wiggly effect to a text label.
+ Automatic property binding takes care of binding the properties to the uniforms if their
+ names are identical. ShaderEffectSource referring to textLabel is bound to sampler2D uniform inside the fragment
+ shader code.
+
+ \qml
+import QtQuick 1.0
+import Qt.labs.shaders 1.0
+
+Rectangle {
+ width: 300
+ height: 300
+ color: "black"
+
+ Text {
+ id: textLabel
+ text: "Hello World"
+ anchors.centerIn: parent
+ font.pixelSize: 32
+ color: "white"
+
+ }
+
+ ShaderEffectItem {
+ property variant source: ShaderEffectSource { sourceItem: textLabel; hideSource: true }
+ property real wiggleAmount: 0.005
+ anchors.fill: textLabel
+
+ fragmentShader: "
+ varying highp vec2 qt_TexCoord0;
+ uniform sampler2D source;
+ uniform highp float wiggleAmount;
+ void main(void)
+ {
+ highp vec2 wiggledTexCoord = qt_TexCoord0;
+ wiggledTexCoord.s += sin(4.0 * 3.141592653589 * wiggledTexCoord.t) * wiggleAmount;
+ gl_FragColor = texture2D(source, wiggledTexCoord.st);
+ }
+ "
+ }
+}
+ \endqml
+ \image shaderexample.png
+
+*/
+
+#ifdef Q_OS_SYMBIAN
+#define OBSERVE_GL_CONTEXT_LOSS 1
+#endif
+
+ShaderEffectItem::ShaderEffectItem(QDeclarativeItem *parent)
+ : QDeclarativeItem(parent)
+ , m_program(0)
+ , m_meshResolution(1, 1)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+ , m_blending(true)
+ , m_program_dirty(true)
+ , m_active(true)
+ , m_respectsMatrix(false)
+ , m_respectsOpacity(false)
+ , m_checkedViewportUpdateMode(false)
+ , m_checkedOpenGL(false)
+ , m_checkedShaderPrograms(false)
+ , m_hasShaderPrograms(false)
+ , m_mirrored(false)
+ , m_defaultVertexShader(true)
+ , m_contextObserver(0)
+{
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+ connect(this, SIGNAL(visibleChanged()), this, SLOT(handleVisibilityChange()));
+ m_active = isVisible();
+
+#ifndef OBSERVE_GL_CONTEXT_LOSS
+ m_program = new QGLShaderProgram(this);
+#endif
+}
+
+ShaderEffectItem::~ShaderEffectItem()
+{
+ reset();
+ delete m_contextObserver;
+}
+
+
+/*!
+ \qmlproperty string ShaderEffectItem::fragmentShader
+ This property holds the OpenGL fragment shader code.
+
+ The default fragment shader is following:
+
+ \code
+ varying highp vec2 qt_TexCoord0;
+ uniform sampler2D source;
+ void main(void)
+ {
+ gl_FragColor = texture2D(source, qt_TexCoord0.st);
+ }
+ \endcode
+
+*/
+
+void ShaderEffectItem::setFragmentShader(const QString &code)
+{
+ if (m_fragment_code.constData() == code.constData())
+ return;
+
+ m_fragment_code = code;
+ if (isComponentComplete()) {
+ reset();
+ updateProperties();
+ }
+ emit fragmentShaderChanged();
+}
+
+/*!
+ \qmlproperty string ShaderEffectItem::vertexShader
+ This property holds the OpenGL vertex shader code.
+
+ The default vertex shader is following:
+
+ \code
+ uniform highp mat4 qt_ModelViewProjectionMatrix;
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec2 qt_MultiTexCoord0;
+ varying highp vec2 qt_TexCoord0;
+ void main(void)
+ {
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
+ }
+ \endcode
+
+*/
+
+void ShaderEffectItem::setVertexShader(const QString &code)
+{
+ if (m_vertex_code.constData() == code.constData())
+ return;
+
+ m_vertex_code = code;
+ m_defaultVertexShader = false;
+ if (isComponentComplete()) {
+ reset();
+ updateProperties();
+ }
+ emit vertexShaderChanged();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectItem::blending
+ This property defines whether item is drawn using blending.
+
+ If true, the RGBA pixel output from the fragment shader is blended with
+ the pixel RGBA-values already in the framebuffer.
+
+ If false, fragment shader output is written to framebuffer as such.
+
+ Usually drawing without blending is slightly faster, thus disabling blending
+ might be a good choice when item is used as a background element.
+
+ \note
+ By default the pixel data in textures is stored in 32-bit premultiplied alpha format.
+ This should be taken into account when blending or reading the pixel values
+ in the fragment shader code.
+
+ The default value is true.
+*/
+
+void ShaderEffectItem::setBlending(bool enable)
+{
+ if (m_blending == enable)
+ return;
+
+ m_blending = enable;
+ m_changed = true;
+ emit blendingChanged();
+}
+
+
+/*!
+ \qmlproperty QSize ShaderEffectItem::meshResolution
+ This property defines to how many triangles the item is divided into before its
+ vertices are passed to the vertex shader.
+
+ Triangles are defined as triangle strips and the amount of triangles can be controlled
+ separately for x and y-axis.
+
+ The default value is QSize(1,1).
+*/
+
+void ShaderEffectItem::setMeshResolution(const QSize &size)
+{
+ if (size == m_meshResolution)
+ return;
+
+ m_meshResolution = size;
+ emit meshResolutionChanged();
+ updateGeometry();
+}
+
+void ShaderEffectItem::componentComplete()
+{
+ updateProperties();
+ QDeclarativeItem::componentComplete();
+}
+
+void ShaderEffectItem::checkViewportUpdateMode()
+{
+ if (!m_checkedViewportUpdateMode) {
+ QGraphicsScene *s = scene();
+ if (s){
+ QList<QGraphicsView*> views = s->views();
+ for (int i = 0; i < views.count(); i++) {
+ if (views[i]->viewportUpdateMode() != QGraphicsView::FullViewportUpdate) {
+ qWarning() << "ShaderEffectItem::checkViewportUpdateMode - consider setting QGraphicsView::FullViewportUpdate mode with OpenGL!";
+ }
+ }
+ }
+ m_checkedViewportUpdateMode = true;
+ }
+}
+
+void ShaderEffectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (!m_active) return;
+
+ const QGLContext *context = QGLContext::currentContext();
+
+ if (context) {
+ if (!m_checkedShaderPrograms) {
+ m_hasShaderPrograms = QGLShaderProgram::hasOpenGLShaderPrograms(context);
+ m_checkedShaderPrograms = true;
+
+ if (!m_hasShaderPrograms)
+ qWarning() << "ShaderEffectItem::paint - Shader programs are not supported";
+ }
+
+ if ( !m_hasShaderPrograms )
+ return;
+
+ checkViewportUpdateMode();
+ painter->save();
+ painter->beginNativePainting();
+ QMatrix4x4 combinedMatrix = QMatrix4x4(painter->transform());
+ renderEffect(painter, combinedMatrix);
+ painter->endNativePainting();
+ painter->restore();
+ } else {
+ if (!m_checkedOpenGL) {
+ qWarning() << "ShaderEffectItem::paint - OpenGL not available";
+ m_checkedOpenGL = true;
+ }
+ }
+}
+
+void ShaderEffectItem::renderEffect(QPainter *painter, const QMatrix4x4 &matrix)
+{
+ if (!painter || !painter->device())
+ return;
+
+#ifdef OBSERVE_GL_CONTEXT_LOSS
+ QGLContext *context = const_cast <QGLContext*> (QGLContext::currentContext());
+ if (!m_program || !m_contextObserver || !m_contextObserver->isValid()) {
+ // Context has changed, re-create QGLShaderProgram
+ if (context) {
+ delete m_program;
+ m_program = 0;
+
+ delete m_contextObserver;
+ m_contextObserver = 0;
+
+ m_program = new QGLShaderProgram(this);
+ m_contextObserver = new QGLFramebufferObject(QSize(2,2));
+
+ if (!m_contextObserver || !m_program) {
+ delete m_program;
+ m_program = 0;
+ delete m_contextObserver;
+ m_contextObserver = 0;
+ qWarning() << "ShaderEffectItem::renderEffect - Creating QGLShaderProgram or QGLFrameBufferObject failed!";
+ }
+ }
+ }
+#endif
+
+ if (!m_program)
+ return;
+
+ if (!m_program->isLinked() || m_program_dirty)
+ updateShaderProgram();
+
+ m_program->bind();
+
+ QMatrix4x4 combinedMatrix;
+ combinedMatrix.scale(2.0 / painter->device()->width(), -2.0 / painter->device()->height(), 1.0);
+ combinedMatrix.translate(-painter->device()->width() / 2.0, -painter->device()->height() / 2.0 );
+ combinedMatrix *= matrix;
+ updateEffectState(combinedMatrix);
+
+ for (int i = 0; i < m_attributeNames.size(); ++i) {
+ m_program->enableAttributeArray(m_geometry.attributes()[i].position);
+ }
+
+ bindGeometry();
+
+ // Optimization, disable depth test when we know we don't need it.
+ if (m_defaultVertexShader) {
+ glDepthMask(false);
+ glDisable(GL_DEPTH_TEST);
+ } else {
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_GREATER);
+ glDepthMask(true);
+#if defined(QT_OPENGL_ES)
+ glClearDepthf(0);
+#else
+ glClearDepth(0);
+#endif
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ if (m_blending){
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glDisable(GL_BLEND);
+ }
+
+ if (m_geometry.indexCount())
+ glDrawElements(m_geometry.drawingMode(), m_geometry.indexCount(), m_geometry.indexType(), m_geometry.indexData());
+ else
+ glDrawArrays(m_geometry.drawingMode(), 0, m_geometry.vertexCount());
+
+ glDepthMask(false);
+ glDisable(GL_DEPTH_TEST);
+
+ for (int i = 0; i < m_attributeNames.size(); ++i)
+ m_program->disableAttributeArray(m_geometry.attributes()[i].position);
+}
+
+void ShaderEffectItem::updateEffectState(const QMatrix4x4 &matrix)
+{
+ if (!m_program)
+ return;
+
+ for (int i = m_sources.size() - 1; i >= 0; --i) {
+ const ShaderEffectItem::SourceData &source = m_sources.at(i);
+ if (!source.source)
+ continue;
+
+ glActiveTexture(GL_TEXTURE0 + i);
+ source.source->bind();
+ }
+
+ if (m_respectsOpacity)
+ m_program->setUniformValue("qt_Opacity", static_cast<float> (effectiveOpacity()));
+
+ if (m_respectsMatrix){
+ m_program->setUniformValue("qt_ModelViewProjectionMatrix", matrix);
+ }
+
+ QSet<QByteArray>::const_iterator it;
+ for (it = m_uniformNames.begin(); it != m_uniformNames.end(); ++it) {
+ const QByteArray &name = *it;
+ QVariant v = property(name.constData());
+
+ switch (v.type()) {
+ case QVariant::Color:
+ m_program->setUniformValue(name.constData(), qvariant_cast<QColor>(v));
+ break;
+ case QVariant::Double:
+ m_program->setUniformValue(name.constData(), (float) qvariant_cast<double>(v));
+ break;
+ case QVariant::Transform:
+ m_program->setUniformValue(name.constData(), qvariant_cast<QTransform>(v));
+ break;
+ case QVariant::Int:
+ m_program->setUniformValue(name.constData(), GLint(v.toInt()));
+ break;
+ case QVariant::Bool:
+ m_program->setUniformValue(name.constData(), GLint(v.toBool()));
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ m_program->setUniformValue(name.constData(), v.toSizeF());
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ m_program->setUniformValue(name.constData(), v.toPointF());
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ QRectF r = v.toRectF();
+ m_program->setUniformValue(name.constData(), r.x(), r.y(), r.width(), r.height());
+ }
+ break;
+ case QVariant::Vector3D:
+ m_program->setUniformValue(name.constData(), qvariant_cast<QVector3D>(v));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static inline int size_of_type(GLenum type)
+{
+ static int sizes[] = {
+ sizeof(char),
+ sizeof(unsigned char),
+ sizeof(short),
+ sizeof(unsigned short),
+ sizeof(int),
+ sizeof(unsigned int),
+ sizeof(float),
+ 2,
+ 3,
+ 4,
+ sizeof(double)
+ };
+ return sizes[type - GL_BYTE];
+}
+
+void ShaderEffectItem::bindGeometry()
+{
+ if (!m_program)
+ return;
+
+ char const *const *attrNames = m_attributeNames.constData();
+ int offset = 0;
+ for (int j = 0; j < m_attributeNames.size(); ++j) {
+ if (!*attrNames[j])
+ continue;
+ Q_ASSERT_X(j < m_geometry.attributeCount(), "ShaderEffectItem::bindGeometry()", "Geometry lacks attribute required by material");
+ const QSGGeometry::Attribute &a = m_geometry.attributes()[j];
+ Q_ASSERT_X(j == a.position, "ShaderEffectItem::bindGeometry()", "Geometry does not have continuous attribute positions");
+#if defined(QT_OPENGL_ES_2)
+ GLboolean normalize = a.type != GL_FLOAT;
+#else
+ GLboolean normalize = a.type != GL_FLOAT && a.type != GL_DOUBLE;
+#endif
+ if (normalize)
+ qWarning() << "ShaderEffectItem::bindGeometry() - non supported attribute type!";
+
+ m_program->setAttributeArray(a.position, (GLfloat*) (((char*) m_geometry.vertexData()) + offset), a.tupleSize, m_geometry.stride());
+ //glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, m_geometry.stride(), (char *) m_geometry.vertexData() + offset);
+ offset += a.tupleSize * size_of_type(a.type);
+ }
+}
+
+void ShaderEffectItem::updateGeometry()
+{
+ QRectF srcRect(0, 1, 1, -1);
+
+ if (m_mirrored)
+ srcRect = QRectF(0, 0, 1, 1);
+
+ QRectF dstRect = QRectF(0,0, width(), height());
+
+ int vmesh = m_meshResolution.height();
+ int hmesh = m_meshResolution.width();
+
+ QSGGeometry *g = &m_geometry;
+ if (vmesh == 1 && hmesh == 1) {
+ if (g->vertexCount() != 4)
+ g->allocate(4);
+ QSGGeometry::updateTexturedRectGeometry(g, dstRect, srcRect);
+ return;
+ }
+
+ g->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2));
+
+ QSGGeometry::TexturedPoint2D *vdata = g->vertexDataAsTexturedPoint2D();
+
+ for (int iy = 0; iy <= vmesh; ++iy) {
+ float fy = iy / float(vmesh);
+ float y = float(dstRect.top()) + fy * float(dstRect.height());
+ float ty = float(srcRect.top()) + fy * float(srcRect.height());
+ for (int ix = 0; ix <= hmesh; ++ix) {
+ float fx = ix / float(hmesh);
+ vdata->x = float(dstRect.left()) + fx * float(dstRect.width());
+ vdata->y = y;
+ vdata->tx = float(srcRect.left()) + fx * float(srcRect.width());
+ vdata->ty = ty;
+ ++vdata;
+ }
+ }
+
+ quint16 *indices = (quint16 *)g->indexDataAsUShort();
+ int i = 0;
+ for (int iy = 0; iy < vmesh; ++iy) {
+ *(indices++) = i + hmesh + 1;
+ for (int ix = 0; ix <= hmesh; ++ix, ++i) {
+ *(indices++) = i + hmesh + 1;
+ *(indices++) = i;
+ }
+ *(indices++) = i - 1;
+ }
+}
+
+void ShaderEffectItem::setActive(bool enable)
+{
+ if (m_active == enable)
+ return;
+
+ if (m_active) {
+ for (int i = 0; i < m_sources.size(); ++i) {
+ ShaderEffectSource *source = m_sources.at(i).source;
+ if (!source)
+ continue;
+ disconnect(source, SIGNAL(repaintRequired()), this, SLOT(markDirty()));
+ source->derefFromEffectItem();
+ }
+ }
+
+ m_active = enable;
+
+ if (m_active) {
+ for (int i = 0; i < m_sources.size(); ++i) {
+ ShaderEffectSource *source = m_sources.at(i).source;
+ if (!source)
+ continue;
+ source->refFromEffectItem();
+ connect(source, SIGNAL(repaintRequired()), this, SLOT(markDirty()));
+ }
+ }
+
+ // QGLShaderProgram is deleted when not active (to minimize GPU memory usage).
+#ifdef OBSERVE_GL_CONTEXT_LOSS
+ if (!m_active && m_program) {
+ delete m_program;
+ m_program = 0;
+ delete m_contextObserver;
+ m_contextObserver = 0;
+ }
+#endif
+
+ emit activeChanged();
+ markDirty();
+}
+
+void ShaderEffectItem::preprocess()
+{
+ for (int i = 0; i < m_sources.size(); ++i) {
+ ShaderEffectSource *source = m_sources.at(i).source;
+ if (source)
+ source->updateBackbuffer();
+ }
+}
+
+void ShaderEffectItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ if (newGeometry.size() != oldGeometry.size())
+ updateGeometry();
+ QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+}
+
+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() {
+ 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);
+
+ source.source = qobject_cast<ShaderEffectSource *>(obj);
+ source.item = qobject_cast<QDeclarativeItem *>(obj);
+
+ if (!source.item)
+ qWarning("Could not assign property '%s', did not implement QDeclarativeItem.", source.name.constData());
+
+ if (!source.source)
+ qWarning("Could not assign property '%s', did not implement ShaderEffectSource.", source.name.constData());
+
+ // 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);
+ // Unlike in scenegraph, we cannot set item invisible here because qgraphicsview would optimize it away.
+ }
+
+ // Unlike in scenegraph, ref counting is used to optimize memory consumption. Sources themself may free fbos when not referenced.
+ if (m_active && source.source) {
+ source.source->refFromEffectItem();
+ connect(source.source, SIGNAL(repaintRequired()), this, SLOT(markDirty()));
+ }
+}
+
+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_uniformNames.begin(); it != m_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();
+
+ if (m_program)
+ m_program->removeAllShaders();
+
+ m_attributeNames.clear();
+ m_uniformNames.clear();
+ for (int i = 0; i < m_sources.size(); ++i) {
+ const SourceData &source = m_sources.at(i);
+ if (m_active && source.source)
+ source.source->derefFromEffectItem();
+ delete source.mapper;
+ }
+
+ m_sources.clear();
+ m_program_dirty = true;
+}
+
+void ShaderEffectItem::updateProperties()
+{
+ QString vertexCode = m_vertex_code;
+ QString fragmentCode = m_fragment_code;
+
+ if (vertexCode.isEmpty())
+ vertexCode = qt_default_vertex_code;
+
+ if (fragmentCode.isEmpty())
+ fragmentCode = qt_default_fragment_code;
+
+ lookThroughShaderCode(vertexCode);
+ lookThroughShaderCode(fragmentCode);
+
+ if (!m_attributeNames.contains(qt_postion_attribute_name))
+ qWarning("ShaderEffectItem: Missing reference to \'%s\'.", qt_postion_attribute_name);
+ if (!m_attributeNames.contains(qt_texcoord_attribute_name))
+ qWarning("ShaderEffectItem: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
+ if (!m_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); // Property exists.
+ }
+
+ connectPropertySignals();
+}
+
+void ShaderEffectItem::updateShaderProgram()
+{
+ if (!m_program)
+ return;
+
+ QString vertexCode = m_vertex_code;
+ QString fragmentCode = m_fragment_code;
+
+ if (vertexCode.isEmpty())
+ vertexCode = QString::fromLatin1(qt_default_vertex_code);
+
+ if (fragmentCode.isEmpty())
+ fragmentCode = QString::fromLatin1(qt_default_fragment_code);
+
+ m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexCode);
+ m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentCode);
+
+ for (int i = 0; i < m_attributeNames.size(); ++i) {
+ m_program->bindAttributeLocation(m_attributeNames.at(i), m_geometry.attributes()[i].position);
+ }
+
+ if (!m_program->link()) {
+ qWarning("ShaderEffectItem: Shader compilation failed:");
+ qWarning() << m_program->log();
+ }
+
+ if (!m_attributeNames.contains(qt_postion_attribute_name))
+ qWarning("ShaderEffectItem: Missing reference to \'qt_Vertex\'.");
+ if (!m_attributeNames.contains(qt_texcoord_attribute_name))
+ qWarning("ShaderEffectItem: Missing reference to \'qt_MultiTexCoord0\'.");
+ if (!m_respectsMatrix)
+ qWarning("ShaderEffectItem: Missing reference to \'qt_ModelViewProjectionMatrix\'.");
+
+ if (m_program->isLinked()) {
+ m_program->bind();
+ for (int i = 0; i < m_sources.size(); ++i)
+ m_program->setUniformValue(m_sources.at(i).name.constData(), (GLint) i);
+ }
+
+ m_program_dirty = false;
+}
+
+void ShaderEffectItem::lookThroughShaderCode(const QString &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());
+ QString wideCode = code;
+
+ 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_attributeNames.insert(0, qt_postion_attribute_name);
+ } else if (name == "qt_MultiTexCoord0") {
+ if (m_attributeNames.at(0) == 0) {
+ m_attributeNames.insert(0, qt_emptyAttributeName);
+ }
+ m_attributeNames.insert(1, qt_texcoord_attribute_name);
+ } else {
+ // TODO: Support user defined attributes.
+ qWarning("ShaderEffectItem: Attribute \'%s\' not recognized.", name.constData());
+ }
+ } else {
+ Q_ASSERT(decl == "uniform");
+
+ if (name == "qt_ModelViewProjectionMatrix") {
+ m_respectsMatrix = true;
+ } else if (name == "qt_Opacity") {
+ m_respectsOpacity = true;
+ } else {
+ m_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);
+ }
+ }
+ }
+ }
+}
+
+void ShaderEffectItem::handleVisibilityChange()
+{
+ setActive(isVisible());
+}
diff --git a/src/imports/shaders/shadereffectitem.h b/src/imports/shaders/shadereffectitem.h
new file mode 100644
index 00000000..a5581b44
--- /dev/null
+++ b/src/imports/shaders/shadereffectitem.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef SHADEREFFECTITEM_H
+#define SHADEREFFECTITEM_H
+
+#include <QDeclarativeItem>
+#include <QtOpenGL>
+#include "shadereffectsource.h"
+#include "scenegraph/qsggeometry.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class ShaderEffectItem : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+ Q_PROPERTY(QString fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
+ Q_PROPERTY(QString vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
+ Q_PROPERTY(bool blending READ blending WRITE setBlending NOTIFY blendingChanged)
+ Q_PROPERTY(QSize meshResolution READ meshResolution WRITE setMeshResolution NOTIFY meshResolutionChanged)
+
+public:
+ ShaderEffectItem(QDeclarativeItem* parent = 0);
+ ~ShaderEffectItem();
+
+ virtual void componentComplete();
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ QString fragmentShader() const { return m_fragment_code; }
+ void setFragmentShader(const QString &code);
+
+ QString vertexShader() const { return m_vertex_code; }
+ void setVertexShader(const QString &code);
+
+ bool blending() const { return m_blending; }
+ void setBlending(bool enable);
+
+ QSize meshResolution() const { return m_meshResolution; }
+ void setMeshResolution(const QSize &size);
+
+ void preprocess();
+
+Q_SIGNALS:
+ void fragmentShaderChanged();
+ void vertexShaderChanged();
+ void blendingChanged();
+ void activeChanged();
+ void meshResolutionChanged();
+
+protected:
+ virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+
+private Q_SLOTS:
+ void changeSource(int index);
+ void handleVisibilityChange();
+ void markDirty();
+
+private:
+ void checkViewportUpdateMode();
+ void renderEffect(QPainter *painter, const QMatrix4x4 &matrix);
+ void updateEffectState(const QMatrix4x4 &matrix);
+ void updateGeometry();
+ void bindGeometry();
+ void setSource(const QVariant &var, int index);
+ void disconnectPropertySignals();
+ void connectPropertySignals();
+ void reset();
+ void updateProperties();
+ void updateShaderProgram();
+ void lookThroughShaderCode(const QString &code);
+ bool active() const { return m_active; }
+ void setActive(bool enable);
+
+private:
+ QString m_fragment_code;
+ QString m_vertex_code;
+ QGLShaderProgram* m_program;
+ QVector<const char *> m_attributeNames;
+ QSet<QByteArray> m_uniformNames;
+ QSize m_meshResolution;
+ QSGGeometry m_geometry;
+
+ struct SourceData
+ {
+ QSignalMapper *mapper;
+ QPointer<ShaderEffectSource> source;
+ QPointer<QDeclarativeItem> item;
+ QByteArray name;
+ };
+
+ QVector<SourceData> m_sources;
+
+ bool m_changed : 1;
+ bool m_blending : 1;
+ bool m_program_dirty : 1;
+ bool m_active : 1;
+ bool m_respectsMatrix : 1;
+ bool m_respectsOpacity : 1;
+ bool m_checkedViewportUpdateMode : 1;
+ bool m_checkedOpenGL : 1;
+ bool m_checkedShaderPrograms : 1;
+ bool m_hasShaderPrograms : 1;
+ bool m_mirrored : 1;
+ bool m_defaultVertexShader : 1;
+
+ QGLFramebufferObject* m_contextObserver;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+#endif // SHADEREFFECTITEM_H
diff --git a/src/imports/shaders/shadereffectsource.cpp b/src/imports/shaders/shadereffectsource.cpp
new file mode 100644
index 00000000..aa434e1c
--- /dev/null
+++ b/src/imports/shaders/shadereffectsource.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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 "shadereffectsource.h"
+#include "shadereffectbuffer.h"
+#include "shadereffect.h"
+#include "glfunctions.h"
+
+#include <QtOpenGL>
+
+/*!
+ \qmlclass ShaderEffectSource ShaderEffectSource
+ \ingroup qml-shader-elements
+ \brief The ShaderEffectSource object encapsulates the source content for the ShaderEffectItem.
+
+ ShaderEffectSource is available in the \bold{Qt.labs.shaders 1.0} module.
+ \e {Elements in the Qt.labs module are not guaranteed to remain compatible
+ in future versions.}
+
+ This element provides preliminary support for OpenGL shaders in QML,
+ and may be heavily changed or removed in later versions.
+
+ Requirement for the ability to use of shaders is that the application is either using
+ opengl graphicssystem or has set QGLWidget as the viewport to QDeclarativeView (recommended way).
+
+ ShaderEffectSource object encapsulates the source content so that it can be utilized in ShaderEffectItem.
+ Source content can be a live QML object tree, or a snapshot of QML object tree.
+
+*/
+
+ShaderEffectSource::ShaderEffectSource(QDeclarativeItem *parent)
+ : QDeclarativeItem(parent)
+ , m_sourceItem(0)
+ , m_wrapMode(ClampToEdge)
+ , m_sourceRect(0, 0, 0, 0)
+ , m_textureSize(0, 0)
+ , m_format(RGBA)
+ , m_size(0, 0)
+ , m_fbo(0)
+ , m_multisampledFbo(0)
+ , m_refs(0)
+ , m_dirtyTexture(true)
+ , m_dirtySceneGraph(true)
+ , m_multisamplingSupported(false)
+ , m_checkedForMultisamplingSupport(false)
+ , m_live(true)
+ , m_hideSource(false)
+ , m_mirrored(false)
+{
+}
+
+ShaderEffectSource::~ShaderEffectSource()
+{
+ if (m_refs && m_sourceItem)
+ detachSourceItem();
+
+ delete m_fbo;
+ delete m_multisampledFbo;
+}
+
+/*!
+ \qmlproperty Item ShaderEffectSource::sourceItem
+ This property holds the Item which is used as the source for the shader effect.
+ If the item has children, those are included as well.
+
+ \note When source item content is passed to the ShaderEffectItem(s), it is always clipped to the boundingrect of the
+ sourceItem regardless of its clipping property.
+*/
+
+void ShaderEffectSource::setSourceItem(QDeclarativeItem *item)
+{
+ if (item == m_sourceItem)
+ return;
+
+ if (m_sourceItem) {
+ disconnect(m_sourceItem, SIGNAL(widthChanged()), this, SLOT(markSourceSizeDirty()));
+ disconnect(m_sourceItem, SIGNAL(heightChanged()), this, SLOT(markSourceSizeDirty()));
+
+ if (m_refs)
+ detachSourceItem();
+ }
+
+ m_sourceItem = item;
+
+ if (m_sourceItem) {
+
+ // Must have some item as parent
+ if (m_sourceItem->parentItem() == 0)
+ m_sourceItem->setParentItem(this);
+
+ if (m_refs)
+ attachSourceItem();
+
+ connect(m_sourceItem, SIGNAL(widthChanged()), this, SLOT(markSourceSizeDirty()));
+ connect(m_sourceItem, SIGNAL(heightChanged()), this, SLOT(markSourceSizeDirty()));
+ }
+
+ updateSizeAndTexture();
+ emit sourceItemChanged();
+ emit repaintRequired();
+}
+
+/*!
+ \qmlproperty QRectF ShaderEffectSource::sourceRect
+ This property can be used to specify margins for the source content.
+
+ If other value than Qt.rect(0,0,0,0) is assigned to this property, it is interpreted as
+ specifying a relative source rectangle for the source content.
+
+ For example, setting Qt.rect(-10.0, -10.0, 120.0, 120.0) for a source that has width and height
+ of 100 pixels would produce 10 pixels margins to each side of the source.
+
+ Margins are useful when the original content is wanted to be spread outside the original source area,
+ like when creating a dropshadow with the shader or in other similar effects.
+
+ The default value is Qt.rect(0,0,0,0).
+*/
+
+void ShaderEffectSource::setSourceRect(const QRectF &rect)
+{
+ if (rect == m_sourceRect)
+ return;
+ m_sourceRect = rect;
+ updateSizeAndTexture();
+ emit sourceRectChanged();
+ emit repaintRequired();
+
+ m_dirtyTexture = true;
+ markSourceItemDirty();
+}
+
+/*!
+ \qmlproperty QSize ShaderEffectSource::textureSize
+ This property holds the size for the texture containing the source content.
+
+ If value QSize(0,0) is assigned to this property, texture is resized
+ according to the source size. Otherwise source content is scaled to
+ the given size.
+
+ The default value is QSize(0,0).
+*/
+
+void ShaderEffectSource::setTextureSize(const QSize &size)
+{
+ if (size == m_textureSize)
+ return;
+
+ m_textureSize = size;
+ updateSizeAndTexture();
+ emit textureSizeChanged();
+ emit repaintRequired();
+
+ m_dirtyTexture = true;
+ markSourceItemDirty();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectSource::live
+ This property holds the optimization flag to define whether the source item content is changing or
+ static.
+
+ If value true is assigned to this property, source item content is re-rendered into a
+ texture for every frame. Setting the value to false improves the performance as it skips
+ rendering the source item (and its chidleren) and instead immediately passes the previously
+ rendered and cached texture to the shaders.
+
+ The default value is true.
+*/
+
+void ShaderEffectSource::setLive(bool s)
+{
+ if (s == m_live)
+ return;
+
+ m_live = s;
+
+ emit liveChanged();
+ emit repaintRequired();
+}
+
+/*!
+ \qmlproperty bool ShaderEffectSource::hideSource
+ This property holds the flag to define whether the original source item is
+ hidden when the effect item is drawn.
+
+ The default value is false.
+*/
+
+void ShaderEffectSource::setHideSource(bool hide)
+{
+ if (hide == m_hideSource)
+ return;
+
+ m_hideSource = hide;
+
+ emit hideSourceChanged();
+ emit repaintRequired();
+}
+
+/*!
+ \qmlproperty enumeration ShaderEffectSource::wrapMode
+
+ This property defines the wrap parameter for the source after it has been mapped as a texture.
+
+ \list
+ \o ShaderEffectSource.ClampToEdge - Causes texturecoordinates to be clamped to the range [ 1/2*N , 1 - 1/2*N ], where N is the texture width.
+ \o ShaderEffectSource.RepeatHorizontally - Causes the integer part of the horizontal texturecoordinate to be ignored; the GL uses only the fractional part, thereby creating a horizontal repeating pattern.
+ \o ShaderEffectSource.RepeatVertically - Causes the integer part of the vertical texturecoordinate to be ignored; the GL uses only the fractional part, thereby creating a vertical repeating pattern.
+ \o ShaderEffectSource.Repeat - Causes the integer part of both the horizontal and vertical texturecoordinates to be ignored; the GL uses only the fractional part, thereby creating a repeating pattern.
+ \endlist
+
+ The default value is ClampToEdge.
+
+*/
+
+void ShaderEffectSource::setWrapMode(WrapMode mode)
+{
+ if (mode == m_wrapMode)
+ return;
+
+ m_wrapMode = mode;
+ emit wrapModeChanged();
+
+ m_dirtyTexture = true;
+ markSourceItemDirty();
+}
+
+/*!
+ \qmlmethod ShaderEffectSource::grab()
+
+ Repaints the source item content into the texture.
+
+ This method is useful when ShaderEffectSource::live has been set to false and
+ the changes in the source item content is desired to be made visible for the shaders.
+
+*/
+
+void ShaderEffectSource::grab()
+{
+ m_dirtyTexture = true;
+ emit repaintRequired();
+}
+
+void ShaderEffectSource::bind()
+{
+ GLint filtering = smooth() ? GL_LINEAR : GL_NEAREST;
+ GLuint hwrap = (m_wrapMode == Repeat || m_wrapMode == RepeatHorizontally) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+ GLuint vwrap = (m_wrapMode == Repeat || m_wrapMode == RepeatVertically) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+
+#if !defined(QT_OPENGL_ES_2)
+ glEnable(GL_TEXTURE_2D);
+#endif
+
+ if (m_fbo && m_fbo->isValid()) {
+ glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+ } else {
+ m_dirtyTexture = true;
+ emit repaintRequired();
+ markSourceItemDirty();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth() ? GL_LINEAR : GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, hwrap);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vwrap);
+}
+
+void ShaderEffectSource::refFromEffectItem()
+{
+ if (m_refs++ == 0) {
+ attachSourceItem();
+ emit activeChanged();
+ }
+}
+
+void ShaderEffectSource::derefFromEffectItem()
+{
+ if (--m_refs == 0) {
+ detachSourceItem();
+ emit activeChanged();
+ }
+ Q_ASSERT(m_refs >= 0);
+}
+
+void ShaderEffectSource::updateBackbuffer()
+{
+ if (!m_sourceItem || !QGLContext::currentContext())
+ return;
+
+ // Multisampling is not (for now) supported.
+ QSize size = QSize(m_sourceItem->width(), m_sourceItem->height());
+ if (!m_textureSize.isEmpty())
+ size = m_textureSize;
+
+ if (size.height() > 0 && size.width() > 0) {
+ QGLFramebufferObjectFormat format;
+ format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalTextureFormat(m_format);
+
+ if (!m_fbo) {
+ m_fbo = new ShaderEffectBuffer(size, format);
+ } else {
+ if (!m_fbo->isValid() || m_fbo->size() != size || m_fbo->format().internalTextureFormat() != GLenum(m_format)) {
+ delete m_fbo;
+ m_fbo = 0;
+ m_fbo = new ShaderEffectBuffer(size, format);
+ }
+ }
+ }
+
+ // Note that real update for the source content happens in shadereffect.cpp
+ m_dirtyTexture = false;
+}
+
+void ShaderEffectSource::markSceneGraphDirty()
+{
+ m_dirtySceneGraph = true;
+ emit repaintRequired();
+}
+
+void ShaderEffectSource::markSourceSizeDirty()
+{
+ Q_ASSERT(m_sourceItem);
+ if (m_textureSize.isEmpty())
+ updateSizeAndTexture();
+ if (m_refs)
+ emit repaintRequired();
+}
+
+void ShaderEffectSource::markSourceItemDirty()
+{
+ m_dirtyTexture = true;
+ if (m_sourceItem) {
+ ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect());
+ if (effect)
+ effect->m_changed = true;
+ }
+}
+
+void ShaderEffectSource::updateSizeAndTexture()
+{
+ if (m_sourceItem) {
+ QSize size = m_textureSize;
+ if (size.isEmpty())
+ size = QSize(m_sourceItem->width(), m_sourceItem->height());
+ if (size.width() < 1)
+ size.setWidth(1);
+ if (size.height() < 1)
+ size.setHeight(1);
+ if (m_fbo && (m_fbo->size() != size || !m_fbo->isValid())) {
+ delete m_fbo;
+ m_fbo = 0;
+ delete m_multisampledFbo;
+ m_fbo = m_multisampledFbo = 0;
+ }
+ if (m_size.width() != size.width()) {
+ m_size.setWidth(size.width());
+ emit widthChanged();
+ }
+ if (m_size.height() != size.height()) {
+ m_size.setHeight(size.height());
+ emit heightChanged();
+ }
+ m_dirtyTexture = true;
+ } else {
+ if (m_size.width() != 0) {
+ m_size.setWidth(0);
+ emit widthChanged();
+ }
+ if (m_size.height() != 0) {
+ m_size.setHeight(0);
+ emit heightChanged();
+ }
+ }
+}
+
+void ShaderEffectSource::attachSourceItem()
+{
+ if (!m_sourceItem)
+ return;
+
+ ShaderEffect *effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect());
+
+ if (!effect) {
+ effect = new ShaderEffect();
+ m_sourceItem->setGraphicsEffect(effect);
+ }
+
+ if (effect)
+ effect->addRenderTarget(this);
+
+ m_sourceItem->update();
+}
+
+void ShaderEffectSource::detachSourceItem()
+{
+ if (!m_sourceItem)
+ return;
+
+ ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect());
+
+ if (effect)
+ effect->removeRenderTarget(this);
+
+ delete m_fbo;
+ m_fbo = 0;
+
+ delete m_multisampledFbo;
+ m_multisampledFbo = 0;
+
+ m_dirtyTexture = true;
+}
diff --git a/src/imports/shaders/shadereffectsource.h b/src/imports/shaders/shadereffectsource.h
new file mode 100644
index 00000000..d7b44bcc
--- /dev/null
+++ b/src/imports/shaders/shadereffectsource.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QML Shaders plugin 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$
+**
+****************************************************************************/
+
+#ifndef SHADEREFFECTSOURCE_H
+#define SHADEREFFECTSOURCE_H
+
+#include <QDeclarativeItem>
+#include <QtOpenGL>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class ShaderEffectBuffer;
+
+class ShaderEffectSource : public QDeclarativeItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeItem *sourceItem READ sourceItem WRITE setSourceItem NOTIFY sourceItemChanged)
+ Q_PROPERTY(QRectF sourceRect READ sourceRect WRITE setSourceRect NOTIFY sourceRectChanged)
+ Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
+ Q_PROPERTY(bool live READ isLive WRITE setLive NOTIFY liveChanged)
+ Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
+ Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
+ Q_ENUMS(WrapMode)
+ Q_ENUMS(Format)
+
+public:
+ enum WrapMode {
+ ClampToEdge,
+ RepeatHorizontally,
+ RepeatVertically,
+ Repeat
+ };
+
+ enum Format {
+ Alpha = GL_ALPHA,
+ RGB = GL_RGB,
+ RGBA = GL_RGBA
+ };
+
+ ShaderEffectSource(QDeclarativeItem *parent = 0);
+ virtual ~ShaderEffectSource();
+
+ QDeclarativeItem *sourceItem() const { return m_sourceItem.data(); }
+ void setSourceItem(QDeclarativeItem *item);
+
+ QRectF sourceRect() const { return m_sourceRect; };
+ void setSourceRect(const QRectF &rect);
+
+ QSize textureSize() const { return m_textureSize; }
+ void setTextureSize(const QSize &size);
+
+ bool isLive() const { return m_live; }
+ void setLive(bool s);
+
+ bool hideSource() const { return m_hideSource; }
+ void setHideSource(bool hide);
+
+ WrapMode wrapMode() const { return m_wrapMode; };
+ void setWrapMode(WrapMode mode);
+
+ bool isActive() const { return m_refs; }
+ void bind();
+ void refFromEffectItem();
+ void derefFromEffectItem();
+ void updateBackbuffer();
+
+ ShaderEffectBuffer* fbo() { return m_fbo; }
+ bool isDirtyTexture() { return m_dirtyTexture; }
+ bool isMirrored() { return m_mirrored; }
+
+ Q_INVOKABLE void grab();
+
+Q_SIGNALS:
+ void sourceItemChanged();
+ void sourceRectChanged();
+ void textureSizeChanged();
+ void formatChanged();
+ void liveChanged();
+ void hideSourceChanged();
+ void activeChanged();
+ void repaintRequired();
+ void wrapModeChanged();
+
+public Q_SLOTS:
+ void markSceneGraphDirty();
+ void markSourceSizeDirty();
+ void markSourceItemDirty();
+
+private:
+ void updateSizeAndTexture();
+ void attachSourceItem();
+ void detachSourceItem();
+
+private:
+ QPointer<QDeclarativeItem> m_sourceItem;
+ WrapMode m_wrapMode;
+ QRectF m_sourceRect;
+ QSize m_textureSize;
+ Format m_format;
+ QSize m_size;
+
+ ShaderEffectBuffer *m_fbo;
+ ShaderEffectBuffer *m_multisampledFbo;
+ int m_refs;
+ bool m_dirtyTexture : 1;
+ bool m_dirtySceneGraph : 1;
+ bool m_multisamplingSupported : 1;
+ bool m_checkedForMultisamplingSupport : 1;
+ bool m_live : 1;
+ bool m_hideSource : 1;
+ bool m_mirrored : 1;
+};
+
+QT_END_HEADER
+
+QT_END_NAMESPACE
+
+
+#endif // SHADEREFFECTSOURCE_H
diff --git a/src/imports/shaders/shaders.pro b/src/imports/shaders/shaders.pro
new file mode 100644
index 00000000..51a9a918
--- /dev/null
+++ b/src/imports/shaders/shaders.pro
@@ -0,0 +1,38 @@
+TARGET = qmlshadersplugin
+TARGETPATH = Qt/labs/shaders
+include(../qimportbase.pri)
+
+QT += declarative opengl
+
+SOURCES += \
+ qmlshadersplugin_plugin.cpp \
+ shadereffect.cpp \
+ shadereffectitem.cpp \
+ shadereffectsource.cpp \
+ scenegraph/qsggeometry.cpp \
+ shadereffectbuffer.cpp
+
+HEADERS += \
+ qmlshadersplugin_plugin.h \
+ glfunctions.h \
+ shadereffect.h \
+ shadereffectitem.h \
+ shadereffectsource.h \
+ scenegraph/qsggeometry.h \
+ shadereffectbuffer.h
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH
+target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+qmldir.files += $$PWD/qmldir
+qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+symbian:{
+ TARGET.UID3 = 0x20034907
+ isEmpty(DESTDIR):importFiles.sources = qmlparticlesplugin$${QT_LIBINFIX}.dll qmldir
+ else:importFiles.sources = $$DESTDIR/qmlparticlesplugin$${QT_LIBINFIX}.dll qmldir
+ importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH
+ DEPLOYMENT += importFiles
+}
+
+INSTALLS += target qmldir