diff options
Diffstat (limited to 'examples/quick/scenegraph')
31 files changed, 1405 insertions, 82 deletions
diff --git a/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc b/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc index d98407b6c1..e3cef52bf7 100644 --- a/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc +++ b/examples/quick/scenegraph/customgeometry/doc/src/customgeometry.qdoc @@ -41,7 +41,7 @@ \section1 BezierCurve Declaration - \snippet quick/scenegraph/customgeometry/beziercurve.h 1 + \snippet scenegraph/customgeometry/beziercurve.h 1 The item declaration subclasses the QQuickItem class and adds five properties. One for each of the four control points in the bezier @@ -52,7 +52,7 @@ signals for each of them so changes will be picked up the QML engine and used accordingly. - \snippet quick/scenegraph/customgeometry/beziercurve.h 2 + \snippet scenegraph/customgeometry/beziercurve.h 2 The synchronization point between the QML scene and the rendering scene graph is the virtual function \l @@ -67,7 +67,7 @@ \section1 BezierCurve Implementation - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 1 + \snippet scenegraph/customgeometry/beziercurve.cpp 1 The BezierCurve constructor sets up default values for the control points and the number of segments. The bezier curve @@ -80,7 +80,7 @@ QQuickItem::updatePaintNode() when it is time for the QML scene to be synchronized with the rendering scene graph. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 2 + \snippet scenegraph/customgeometry/beziercurve.cpp 2 The BezierCurve class has no data members that need to be cleaned up so the destructor does nothing. It is worth mentioning that the @@ -89,7 +89,7 @@ QSGNode references in the QQuickItem class nor try to clean them up explicitly. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 3 + \snippet scenegraph/customgeometry/beziercurve.cpp 3 The setter function for the p1 property checks if the value is unchanged and exits early if this is the case. Then it updates the @@ -103,7 +103,7 @@ The other property setters are equivalent, and are omitted from this example. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 4 + \snippet scenegraph/customgeometry/beziercurve.cpp 4 The updatePaintNode() function is the primary integration point for synchronizing the state of the QML scene with the rendering @@ -113,7 +113,7 @@ our QSGGeometryNode which we will fill with geometry and a material. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 5 + \snippet scenegraph/customgeometry/beziercurve.cpp 5 We then create the geometry and add it to the node. The first argument to the QSGGeometry constructor is a definition of the @@ -135,7 +135,7 @@ geometry a member of a QSGGeometryNode subclass, in which case, we would not have set the QSGGeometryNode::OwnsGeometry flag. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 6 + \snippet scenegraph/customgeometry/beziercurve.cpp 6 The scene graph API provides a few commonly used used material implementations. In this example we use the QSGFlatColorMaterial @@ -143,7 +143,7 @@ color. Again we pass the ownership of the material to the node, so it can be cleaned up by the scene graph. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 7 + \snippet scenegraph/customgeometry/beziercurve.cpp 7 In the case where the QML item has changed and we only want to modify the existing node's geometry, we cast the \c oldNode to a @@ -151,7 +151,7 @@ segment count has changed, we call QSGGeometry::allocate() to make sure it has the right number of vertices. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 8 + \snippet scenegraph/customgeometry/beziercurve.cpp 8 To fill the geometry, we first extract the vertex array from it. Since we are using one of the default attribute sets, we can @@ -159,14 +159,14 @@ Then we go through each segment and calculate its position and write that value to the vertex. - \snippet quick/scenegraph/customgeometry/beziercurve.cpp 9 + \snippet scenegraph/customgeometry/beziercurve.cpp 9 In the end of the function, we return the node so the scene graph can render it. \section1 Application Entry-Point - \snippet quick/scenegraph/customgeometry/main.cpp 1 + \snippet scenegraph/customgeometry/main.cpp 1 The application is a straightforward QML application, with a QGuiApplication and a QQuickView that we pass a .qml file. To make @@ -183,24 +183,24 @@ \section1 Using the Item - \snippet quick/scenegraph/customgeometry/main.qml 1 + \snippet scenegraph/customgeometry/main.qml 1 Our .qml file imports the \c {QtQuick 2.0} module to get the standard types and also our own \c {CustomGeometry 1.0} module which contains our newly created BezierCurve objects. - \snippet quick/scenegraph/customgeometry/main.qml 2 + \snippet scenegraph/customgeometry/main.qml 2 Then we create the our root item and an instance of the BezierCurve which we anchor to fill the root. - \snippet quick/scenegraph/customgeometry/main.qml 3 + \snippet scenegraph/customgeometry/main.qml 3 To make the example a bit more interesting we add an animation to change the two control points in the curve. The end points stay unchanged. - \snippet quick/scenegraph/customgeometry/main.qml 4 + \snippet scenegraph/customgeometry/main.qml 4 Finally we overlay a short text outlining what the example shows. diff --git a/examples/quick/scenegraph/graph/doc/images/graph-example.jpg b/examples/quick/scenegraph/graph/doc/images/graph-example.jpg Binary files differnew file mode 100644 index 0000000000..74975ee7c4 --- /dev/null +++ b/examples/quick/scenegraph/graph/doc/images/graph-example.jpg diff --git a/examples/quick/scenegraph/graph/doc/src/graph.qdoc b/examples/quick/scenegraph/graph/doc/src/graph.qdoc new file mode 100644 index 0000000000..d5a07cdc48 --- /dev/null +++ b/examples/quick/scenegraph/graph/doc/src/graph.qdoc @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example scenegraph/graph + \title Scene Graph - Graph + \ingroup qtquickexamples + + \brief Demonstrates how one can combine custom materials and geometries + under a single QQuickItem. + + \image graph-example.jpg + + */ diff --git a/examples/quick/scenegraph/graph/graph.cpp b/examples/quick/scenegraph/graph/graph.cpp new file mode 100644 index 0000000000..ad75307e57 --- /dev/null +++ b/examples/quick/scenegraph/graph/graph.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graph.h" + +#include "noisynode.h" +#include "gridnode.h" +#include "linenode.h" + +Graph::Graph() + : m_samplesChanged(false) + , m_geometryChanged(false) +{ + setFlag(ItemHasContents, true); +} + + +void Graph::appendSample(qreal value) +{ + m_samples << value; + m_samplesChanged = true; + update(); +} + + +void Graph::removeFirstSample() +{ + m_samples.removeFirst(); + m_samplesChanged = true; + update(); +} + +void Graph::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + m_geometryChanged = true; + update(); + QQuickItem::geometryChanged(newGeometry, oldGeometry); +} + + +class GraphNode : public QSGNode +{ +public: + NoisyNode *background; + GridNode *grid; + LineNode *line; + LineNode *shadow; +}; + + +QSGNode *Graph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + GraphNode *n= static_cast<GraphNode *>(oldNode); + + QRectF rect = boundingRect(); + + if (rect.isEmpty()) { + delete n; + return 0; + } + + if (!n) { + n = new GraphNode(); + + n->background = new NoisyNode(window()); + n->grid = new GridNode(); + n->line = new LineNode(10, 0.5, QColor("steelblue")); + n->shadow = new LineNode(20, 0.2, QColor::fromRgbF(0.2, 0.2, 0.2, 0.4)); + + n->appendChildNode(n->background); + n->appendChildNode(n->grid); + n->appendChildNode(n->shadow); + n->appendChildNode(n->line); + } + + if (m_geometryChanged) { + n->background->setRect(rect); + n->grid->setRect(rect); + } + + if (m_geometryChanged || m_samplesChanged) { + n->line->updateGeometry(rect, m_samples); + // We don't need to calculate the geometry twice, so just steal it from the other one... + n->shadow->setGeometry(n->line->geometry()); + } + + m_geometryChanged = false; + m_samplesChanged = false; + + return n; +} diff --git a/examples/quick/scenegraph/graph/graph.h b/examples/quick/scenegraph/graph/graph.h new file mode 100644 index 0000000000..28d14f166a --- /dev/null +++ b/examples/quick/scenegraph/graph/graph.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRAPH_H +#define GRAPH_H + +#include <QQuickItem> + +class Graph : public QQuickItem +{ + Q_OBJECT +public: + Graph(); + +protected: + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + +public slots: + void appendSample(qreal value); + void removeFirstSample(); + +private: + QList<qreal> m_samples; + + bool m_samplesChanged; + bool m_geometryChanged; +}; + +#endif // GRAPH_H diff --git a/examples/quick/scenegraph/graph/graph.pro b/examples/quick/scenegraph/graph/graph.pro new file mode 100644 index 0000000000..5991f799dc --- /dev/null +++ b/examples/quick/scenegraph/graph/graph.pro @@ -0,0 +1,34 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-06-11T13:13:18 +# +#------------------------------------------------- + +QT += core gui quick + +TARGET = graph + +TEMPLATE = app + +SOURCES += main.cpp \ + graph.cpp \ + noisynode.cpp \ + gridnode.cpp \ + linenode.cpp + +HEADERS += \ + graph.h \ + noisynode.h \ + gridnode.h \ + linenode.h + +RESOURCES += \ + graph.qrc + +OTHER_FILES += \ + main.qml \ + shaders/noisy.vsh \ + shaders/noisy.fsh \ + shaders/line.fsh \ + shaders/line.vsh + diff --git a/examples/quick/scenegraph/graph/graph.qrc b/examples/quick/scenegraph/graph/graph.qrc new file mode 100644 index 0000000000..2adaeac751 --- /dev/null +++ b/examples/quick/scenegraph/graph/graph.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/scenegraph/graph"> + <file>main.qml</file> + <file>shaders/noisy.vsh</file> + <file>shaders/noisy.fsh</file> + <file>shaders/line.vsh</file> + <file>shaders/line.fsh</file> + </qresource> +</RCC> diff --git a/examples/quick/scenegraph/graph/gridnode.cpp b/examples/quick/scenegraph/graph/gridnode.cpp new file mode 100644 index 0000000000..2b5e8cac16 --- /dev/null +++ b/examples/quick/scenegraph/graph/gridnode.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gridnode.h" + +#include "qmath.h" + +#define GRID_SIZE 32 + +GridNode::GridNode() + : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 0) +{ + setGeometry(&m_geometry); + m_geometry.setDrawingMode(GL_LINES); + + setMaterial(&m_material); + m_material.setColor(Qt::gray); +} + +/* + * The function hardcodes a fixed set of grid lines and scales + * those to the bounding rect. + */ +void GridNode::setRect(const QRectF &rect) +{ + int vCount = int((rect.width() - 1) / GRID_SIZE); + int hCount = int((rect.height() - 1) / GRID_SIZE); + + int lineCount = vCount + hCount; + + QSGGeometry *g = geometry(); + + g->allocate(lineCount * 2); + + float x = rect.x(); + float y = rect.y(); + float w = rect.width(); + float h = rect.height(); + + QSGGeometry::Point2D *v = g->vertexDataAsPoint2D(); + + // Then write the vertical lines + for (int i=0; i<vCount; ++i) { + float dx = (i + 1) * GRID_SIZE; + v[i*2].set(dx, y); + v[i*2+1].set(dx, y + h); + } + v += vCount * 2; + // Then write the horizontal lines + for (int i=0; i<hCount; ++i) { + float dy = (i + 1) * GRID_SIZE; + v[i*2].set(x, dy); + v[i*2+1].set(x + w, dy); + } + + // Tell the scenegraph we updated the geometry.. + markDirty(QSGNode::DirtyGeometry); +} diff --git a/examples/quick/scenegraph/graph/gridnode.h b/examples/quick/scenegraph/graph/gridnode.h new file mode 100644 index 0000000000..8581a993ae --- /dev/null +++ b/examples/quick/scenegraph/graph/gridnode.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRIDNODE_H +#define GRIDNODE_H + +#include <QtQuick/QSGGeometryNode> +#include <QtQuick/QSGFlatColorMaterial> + +class GridNode : public QSGGeometryNode +{ +public: + GridNode(); + + void setRect(const QRectF &rect); + +private: + QSGFlatColorMaterial m_material; + QSGGeometry m_geometry; +}; + +#endif // GRIDNODE_H diff --git a/examples/quick/scenegraph/graph/linenode.cpp b/examples/quick/scenegraph/graph/linenode.cpp new file mode 100644 index 0000000000..0d1229cf1d --- /dev/null +++ b/examples/quick/scenegraph/graph/linenode.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "linenode.h" + +#include <QtCore/QResource> + +#include <QtGui/QColor> + +#include <QtQuick/QSGSimpleMaterial> + +struct LineMaterial +{ + QColor color; + float spread; + float size; +}; + +class LineShader : public QSGSimpleMaterialShader<LineMaterial> +{ + QSG_DECLARE_SIMPLE_SHADER(LineShader, LineMaterial) + +public: + const char *vertexShader() const { + QResource r(":/scenegraph/graph/shaders/line.vsh"); + Q_ASSERT(r.isValid()); + return (const char *) r.data(); + } + + const char *fragmentShader() const { + QResource r(":/scenegraph/graph/shaders/line.fsh"); + Q_ASSERT(r.isValid()); + return (const char *) r.data(); + } + + QList<QByteArray> attributes() const { return QList<QByteArray>() << "pos" << "t"; } + + void updateState(const LineMaterial *m, const LineMaterial *) { + program()->setUniformValue(id_color, m->color); + program()->setUniformValue(id_spread, m->spread); + program()->setUniformValue(id_size, m->size); + } + + void resolveUniforms() { + id_spread = program()->uniformLocation("spread"); + id_size = program()->uniformLocation("size"); + id_color = program()->uniformLocation("color"); + } + +private: + int id_color; + int id_spread; + int id_size; +}; + +struct LineVertex { + float x; + float y; + float t; + inline void set(float xx, float yy, float tt) { x = xx; y = yy; t = tt; } +}; + +static const QSGGeometry::AttributeSet &attributes() +{ + static QSGGeometry::Attribute attr[] = { + QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), + QSGGeometry::Attribute::create(1, 1, GL_FLOAT) + }; + static QSGGeometry::AttributeSet set = { 2, 3 * sizeof(float), attr }; + return set; +} + +LineNode::LineNode(float size, float spread, const QColor &color) + : m_geometry(attributes(), 0) +{ + setGeometry(&m_geometry); + m_geometry.setDrawingMode(GL_TRIANGLE_STRIP); + + QSGSimpleMaterial<LineMaterial> *m = LineShader::createMaterial(); + m->state()->color = color; + m->state()->size = size; + m->state()->spread = spread; + m->setFlag(QSGMaterial::Blending); + setMaterial(m); + setFlag(OwnsMaterial); +} + +/* + * Assumes that samples have values in the range of 0 to 1 and scales them to + * the height of bounds. The samples are stretched out horizontally along the + * width of the bounds. + * + * The position of each pair of points is identical, but we use the third value + * "t" to shift the point up or down and to add antialiasing. + */ +void LineNode::updateGeometry(const QRectF &bounds, const QList<qreal> &samples) +{ + m_geometry.allocate(samples.size() * 2); + + float x = bounds.x(); + float y = bounds.y(); + float w = bounds.width(); + float h = bounds.height(); + + float dx = w / (samples.size() - 1); + + LineVertex *v = (LineVertex *) m_geometry.vertexData(); + for (int i=0; i<samples.size(); ++i) { + v[i*2+0].set(x + dx * i, y + samples.at(i) * h, 0); + v[i*2+1].set(x + dx * i, y + samples.at(i) * h, 1); + } + + markDirty(QSGNode::DirtyGeometry); +} diff --git a/examples/quick/scenegraph/graph/linenode.h b/examples/quick/scenegraph/graph/linenode.h new file mode 100644 index 0000000000..192bedbefc --- /dev/null +++ b/examples/quick/scenegraph/graph/linenode.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LINENODE_H +#define LINENODE_H + +#include <QSGGeometryNode> + +class LineNode : public QSGGeometryNode +{ +public: + LineNode(float size, float spread, const QColor &color); + + void updateGeometry(const QRectF &bounds, const QList<qreal> &samples); + +private: + QSGGeometry m_geometry; + +}; + +#endif // LINENODE_H diff --git a/examples/quick/scenegraph/graph/main.cpp b/examples/quick/scenegraph/graph/main.cpp new file mode 100644 index 0000000000..ed54ae59b1 --- /dev/null +++ b/examples/quick/scenegraph/graph/main.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QQuickView> + +#include "graph.h" +#include <QtQml/QQmlContext> + +int main(int argc, char *argv[]) +{ + QGuiApplication a(argc, argv); + + qmlRegisterType<Graph>("Graph", 1, 0, "Graph"); + + QQuickView view; + view.resize(800, 400); + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:///scenegraph/graph/main.qml")); + view.show(); + + return a.exec(); +} diff --git a/examples/quick/scenegraph/graph/main.qml b/examples/quick/scenegraph/graph/main.qml new file mode 100644 index 0000000000..ad952bcf1a --- /dev/null +++ b/examples/quick/scenegraph/graph/main.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +import Graph 1.0 + +Item { + width: 800 + height: 400 + + Graph { + id: graph + anchors.fill: parent + anchors.margins: 100 + + function newSample(i) { + return (Math.sin(i / 100.0 * Math.PI * 2) + 1) * 0.4 + Math.random() * 0.05; + } + + Component.onCompleted: { + for (var i=0; i<100; ++i) + appendSample(newSample(i)); + } + + property int offset: 100; + } + + Timer { + id: timer + interval: 500 + repeat: true + running: true + onTriggered: { + graph.removeFirstSample(); + graph.appendSample(graph.newSample(++graph.offset)); + } + + } + + Rectangle { + anchors.fill: graph + color: "transparent" + border.color: "black" + border.width: 2 + } + +} diff --git a/examples/quick/scenegraph/graph/noisynode.cpp b/examples/quick/scenegraph/graph/noisynode.cpp new file mode 100644 index 0000000000..1fc87a2b97 --- /dev/null +++ b/examples/quick/scenegraph/graph/noisynode.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "noisynode.h" + +#include <QtCore/QResource> + +#include <QtQuick/QSGSimpleMaterialShader> +#include <QtQuick/QSGTexture> +#include <QtQuick/QQuickWindow> + +#define NOISE_SIZE 64 + +struct NoisyMaterial +{ + ~NoisyMaterial() { + delete texture; + } + + QColor color; + QSGTexture *texture; +}; + +class NoisyShader : public QSGSimpleMaterialShader<NoisyMaterial> +{ + QSG_DECLARE_SIMPLE_SHADER(NoisyShader, NoisyMaterial) + +public: + const char *vertexShader() const { + QResource r(":/scenegraph/graph/shaders/noisy.vsh"); + Q_ASSERT(r.isValid()); + return (const char *) r.data(); + } + + const char *fragmentShader() const { + QResource r(":/scenegraph/graph/shaders/noisy.fsh"); + Q_ASSERT(r.isValid()); + return (const char *) r.data(); + } + + QList<QByteArray> attributes() const { return QList<QByteArray>() << "aVertex" << "aTexCoord"; } + + void updateState(const NoisyMaterial *m, const NoisyMaterial *) { + + // Set the color + program()->setUniformValue(id_color, m->color); + + // Bind the texture and set program to use texture unit 0 (the default) + m->texture->bind(); + + // Then set the texture size so we can adjust the texture coordinates accordingly in the + // vertex shader.. + QSize s = m->texture->textureSize(); + program()->setUniformValue(id_textureSize, QSizeF(1.0 / s.width(), 1.0 / s.height())); + } + + void resolveUniforms() { + id_texture = program()->uniformLocation("texture"); + id_textureSize = program()->uniformLocation("textureSize"); + id_color = program()->uniformLocation("color"); + + // We will only use texture unit 0, so set it only once. + program()->setUniformValue(id_texture, 0); + } + +private: + int id_color; + int id_texture; + int id_textureSize; +}; + +NoisyNode::NoisyNode(QQuickWindow *window) +{ + // Make some noise... + QImage image(NOISE_SIZE, NOISE_SIZE, QImage::Format_RGB32); + uint *data = (uint *) image.bits(); + for (int i=0; i<NOISE_SIZE * NOISE_SIZE; ++i) { + uint g = rand() & 0xff; + data[i] = 0xff000000 | (g << 16) | (g << 8) | g; + } + + QSGTexture *t = window->createTextureFromImage(image); + t->setFiltering(QSGTexture::Nearest); + t->setHorizontalWrapMode(QSGTexture::Repeat); + t->setVerticalWrapMode(QSGTexture::Repeat); + + QSGSimpleMaterial<NoisyMaterial> *m = NoisyShader::createMaterial(); + m->state()->texture = t; + m->state()->color = QColor::fromRgbF(0.95, 0.95, 0.97); + m->setFlag(QSGMaterial::Blending); + + setMaterial(m); + setFlag(OwnsMaterial, true); + + QSGGeometry *g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); + QSGGeometry::updateTexturedRectGeometry(g, QRect(), QRect()); + setGeometry(g); + setFlag(OwnsGeometry, true); +} + +void NoisyNode::setRect(const QRectF &bounds) +{ + QSGGeometry::updateTexturedRectGeometry(geometry(), bounds, QRectF(0, 0, 1, 1)); + markDirty(QSGNode::DirtyGeometry); +} diff --git a/examples/quick/scenegraph/graph/noisynode.h b/examples/quick/scenegraph/graph/noisynode.h new file mode 100644 index 0000000000..b5a291330f --- /dev/null +++ b/examples/quick/scenegraph/graph/noisynode.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NOISYNODE_H +#define NOISYNODE_H + +#include <QSGGeometryNode> + +class QQuickWindow; + +class NoisyNode : public QSGGeometryNode +{ +public: + NoisyNode(QQuickWindow *window); + + void setRect(const QRectF &bounds); +}; + +#endif // NOISYNODE_H diff --git a/examples/quick/scenegraph/graph/shaders/line.fsh b/examples/quick/scenegraph/graph/shaders/line.fsh new file mode 100644 index 0000000000..b07558c2ab --- /dev/null +++ b/examples/quick/scenegraph/graph/shaders/line.fsh @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +uniform lowp vec4 color; +uniform lowp float qt_Opacity; +uniform lowp float spread; + +varying lowp float vT; + +#define PI 3.14159265359 + +void main(void) +{ + lowp float tt = smoothstep(spread, 1.0, sin(vT * PI)); + + gl_FragColor = color * qt_Opacity * tt; +} diff --git a/examples/quick/scenegraph/graph/shaders/line.vsh b/examples/quick/scenegraph/graph/shaders/line.vsh new file mode 100644 index 0000000000..84353b852c --- /dev/null +++ b/examples/quick/scenegraph/graph/shaders/line.vsh @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +attribute highp vec4 pos; +attribute highp float t; + +uniform lowp float size; +uniform highp mat4 qt_Matrix; + +varying lowp float vT; + +void main(void) +{ + vec4 adjustedPos = pos; + adjustedPos.y += (t * size); + gl_Position = qt_Matrix * adjustedPos; + + vT = t; +} diff --git a/examples/quick/scenegraph/graph/shaders/noisy.fsh b/examples/quick/scenegraph/graph/shaders/noisy.fsh new file mode 100644 index 0000000000..227c2b5974 --- /dev/null +++ b/examples/quick/scenegraph/graph/shaders/noisy.fsh @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +uniform sampler2D texture; +uniform lowp float qt_Opacity; +uniform lowp vec4 color; + +varying highp vec2 vTexCoord; +varying lowp vec2 vShadeCoord; + +#define PI 3.14159265359 + +void main() +{ + lowp float shade = texture2D(texture, vTexCoord).r * 0.05 - length(vec2(0.5, 0.4) - vShadeCoord) * 0.3; + lowp vec4 c = vec4(color.xyz + shade, color.w); + gl_FragColor = c * qt_Opacity; +} diff --git a/examples/quick/scenegraph/graph/shaders/noisy.vsh b/examples/quick/scenegraph/graph/shaders/noisy.vsh new file mode 100644 index 0000000000..ce648e51b9 --- /dev/null +++ b/examples/quick/scenegraph/graph/shaders/noisy.vsh @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +attribute highp vec4 aVertex; +attribute highp vec2 aTexCoord; + +uniform highp mat4 qt_Matrix; +uniform highp vec2 textureSize; + +varying highp vec2 vTexCoord; +varying lowp vec2 vShadeCoord; + +void main() { + gl_Position = qt_Matrix * aVertex; + vTexCoord = aVertex.xy * textureSize; + vShadeCoord = aTexCoord; +} diff --git a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc index 4bf5444d79..1f87412aa4 100644 --- a/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc +++ b/examples/quick/scenegraph/openglunderqml/doc/src/openglunderqml.qdoc @@ -50,7 +50,7 @@ in the QML file and this value is used by the OpenGL shader program that draws the squircles. - \snippet quick/scenegraph/openglunderqml/squircle.h 1 + \snippet scenegraph/openglunderqml/squircle.h 1 First of all, we need a QObject with a slot to connect the signals to. We subclass QQuickItem in order to use the \l @@ -73,13 +73,13 @@ Lets move on to the implementation. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 7 + \snippet scenegraph/openglunderqml/squircle.cpp 7 The constructor of the \c Squircle class simply initializes the values. The shader program will be initialized during rendering later. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 8 + \snippet scenegraph/openglunderqml/squircle.cpp 8 The property setter checks that the value has indeed changed before updating its internal variable. It then calls \l @@ -88,13 +88,13 @@ initialization, before the object has been entered into the scene and before it has a window. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 1 - \snippet quick/scenegraph/openglunderqml/squircle.cpp 2 + \snippet scenegraph/openglunderqml/squircle.cpp 1 + \snippet scenegraph/openglunderqml/squircle.cpp 2 For our paint function to be called, we need to connect to the window's signals. When Squircle object is populated into the - scene, the itemChange function is called with the change type \c - ItemSceneChange. We connect \l QQuickWindow::beforeRendering() to + scene, the windowChanged signal is emitted. In our handler, + we connect \l QQuickWindow::beforeRendering() to \c paint() to do the rendering, and \l QQuickWindow::beforeSynchronizing() to \c sync() to copy the state of the \c t property for the upcoming frame. @@ -106,14 +106,14 @@ slots are invoked on the wrong thread with no OpenGL context present. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 3 + \snippet scenegraph/openglunderqml/squircle.cpp 3 The default behavior of the scene graph is to clear the framebuffer before rendering. Since we render before the scene graph, we need to turn this clearing off. This means that we need to clear ourselves in the \c paint() function. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 4 + \snippet scenegraph/openglunderqml/squircle.cpp 4 The first thing we do in the \c paint() function is to initialize the shader program. By initializing the shader program @@ -126,18 +126,18 @@ all rendering related operations must happen on the rendering thread. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 5 + \snippet scenegraph/openglunderqml/squircle.cpp 5 We use the shader program to draw the squircle. At the end of the \c paint function we release the program and disable the attributes we used so that the OpenGL context is in a "clean" state for the scene graph to pick it up. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 6 + \snippet scenegraph/openglunderqml/squircle.cpp 6 In the \c cleanup() function we delete the program. - \snippet quick/scenegraph/openglunderqml/squircle.cpp 9 + \snippet scenegraph/openglunderqml/squircle.cpp 9 We use the \c sync() function to copy the state of the object in the GUI thread into the rendering thread. @@ -146,20 +146,20 @@ thread is blocked, so it is safe to simply copy the value without any additional protection. - \snippet quick/scenegraph/openglunderqml/main.cpp 1 + \snippet scenegraph/openglunderqml/main.cpp 1 The application's \c main() function instantiates a QQuickView and launches the \c main.qml file. The only thing worth noting is that we export the \c Squircle class to QML using the \l qmlRegisterType() macro. - \snippet quick/scenegraph/openglunderqml/main.qml 1 + \snippet scenegraph/openglunderqml/main.qml 1 We import the Squircle QML type with the name we registered in the \c main() function. We then instantiate it and create a running - NumberAnimation on the its \c t property. + NumberAnimation on its \c t property. - \snippet quick/scenegraph/openglunderqml/main.qml 2 + \snippet scenegraph/openglunderqml/main.qml 2 Then we overlay a short descriptive text, so that it is clearly visible that we are in fact rendering OpenGL under our Qt Quick diff --git a/examples/quick/scenegraph/openglunderqml/squircle.cpp b/examples/quick/scenegraph/openglunderqml/squircle.cpp index 84509fb615..8ceb9c5f9e 100644 --- a/examples/quick/scenegraph/openglunderqml/squircle.cpp +++ b/examples/quick/scenegraph/openglunderqml/squircle.cpp @@ -51,6 +51,7 @@ Squircle::Squircle() , m_t(0) , m_thread_t(0) { + connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); } //! [7] @@ -66,17 +67,11 @@ void Squircle::setT(qreal t) } //! [8] - //! [1] -void Squircle::itemChange(ItemChange change, const ItemChangeData &) +void Squircle::handleWindowChanged(QQuickWindow *win) { - // The ItemSceneChange event is sent when we are first attached to a window. - if (change == ItemSceneChange) { - QQuickWindow *win = window(); - if (!win) - return; + if (win) { //! [1] - // Connect the beforeRendering signal to our paint function. // Since this call is executed on the rendering thread it must be // a Qt::DirectConnection diff --git a/examples/quick/scenegraph/openglunderqml/squircle.h b/examples/quick/scenegraph/openglunderqml/squircle.h index e292ca325f..449e02bbf1 100644 --- a/examples/quick/scenegraph/openglunderqml/squircle.h +++ b/examples/quick/scenegraph/openglunderqml/squircle.h @@ -61,14 +61,14 @@ public: signals: void tChanged(); -protected: - void itemChange(ItemChange change, const ItemChangeData &); - public slots: void paint(); void cleanup(); void sync(); +private slots: + void handleWindowChanged(QQuickWindow *win); + private: QOpenGLShaderProgram *m_program; diff --git a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc index 1529649798..5d83b9fa5f 100644 --- a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc +++ b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc @@ -47,7 +47,7 @@ material state is what we assign to each individual node, in this case to give them different colors. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 1 + \snippet scenegraph/simplematerial/simplematerial.cpp 1 The first thing we do when creating custom materials with the simplified scheme is to create a state class. In this case the @@ -55,7 +55,7 @@ compare function which the scene graph can use to reorder the node rendering. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 2 + \snippet scenegraph/simplematerial/simplematerial.cpp 2 Next we define the material shader, by subclassing a template instantiation of \l QSGSimpleMaterialShader with our \c State. @@ -74,21 +74,21 @@ classes. Using the same \c State class in multiple shaders will will lead to undefined behavior. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 3 + \snippet scenegraph/simplematerial/simplematerial.cpp 3 Next comes the declaration of the shader source code, where we define a vertex and fragment shader. The simple material assumes the presence of \c qt_Matrix in the vertex shader and \c qt_Opacity in the fragment shader. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 4 + \snippet scenegraph/simplematerial/simplematerial.cpp 4 We reimplement the \c attributes function to return the name of the \c aVertex and \c aTexCoord attribute names. These attributes will be mapped to attribute indices 0 and 1 in the node's geometry. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 6 + \snippet scenegraph/simplematerial/simplematerial.cpp 6 Uniforms can be accessed either by name or by index, where index is faster than name, so we reimplement the \c resolveUniforms() @@ -96,7 +96,7 @@ to worry about resolving \c qt_Opacity or \c qt_Matrix as these are handled by the baseclass. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 5 + \snippet scenegraph/simplematerial/simplematerial.cpp 5 The \c updateState() function is called once for every unique state and we use it to update the shader program with the current @@ -105,7 +105,7 @@ usecase, where all the colors are different, the updateState will be called once for every node. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 7 + \snippet scenegraph/simplematerial/simplematerial.cpp 7 The \c ColorNode class is supposed to draw something, so it needs to be a subclass of \l QSGGeometryNode. @@ -129,12 +129,12 @@ Finally, we tell the node to take ownership of the material, so we do not have to explicitly memorymanage it. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 8 + \snippet scenegraph/simplematerial/simplematerial.cpp 8 Since the Item is providing its own graphics to the scene graph, we set the flag \l QQuickItem::ItemHasContents. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 9 + \snippet scenegraph/simplematerial/simplematerial.cpp 9 Whenever the Item has changed graphically, the \l QQuickItem::updatePaintNode() function is called. @@ -157,23 +157,23 @@ state. Finally, we notify the scene graph that the node has undergone changes to its geometry and material. - \snippet quick/scenegraph/simplematerial/simplematerial.cpp 11 + \snippet scenegraph/simplematerial/simplematerial.cpp 11 The \c main() function of the application adds the custom QML type using \l qmlRegisterType() and opens up a \l QQuickView with our QML file. - \snippet quick/scenegraph/simplematerial/main.qml 1 + \snippet scenegraph/simplematerial/main.qml 1 In the QML file, we import our custom type so we can instantiate it. - \snippet quick/scenegraph/simplematerial/main.qml 2 + \snippet scenegraph/simplematerial/main.qml 2 Then we create a column of three instances of our custom item, each with a different color. - \snippet quick/scenegraph/simplematerial/main.qml 3 + \snippet scenegraph/simplematerial/main.qml 3 And finally we overlay a short descriptive text. diff --git a/examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc b/examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc index b24b0bd97b..0917604a35 100644 --- a/examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc +++ b/examples/quick/scenegraph/textureinsgnode/doc/src/textureinsgnode.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example quick/scenegraph/textureinsgnode + \example scenegraph/textureinsgnode \title Scene Graph - Rendering FBOs \ingroup qtquickexamples diff --git a/examples/quick/scenegraph/textureinthread/doc/src/textureinthread.qdoc b/examples/quick/scenegraph/textureinthread/doc/src/textureinthread.qdoc index 476605b268..6f4a2514f0 100644 --- a/examples/quick/scenegraph/textureinthread/doc/src/textureinthread.qdoc +++ b/examples/quick/scenegraph/textureinthread/doc/src/textureinthread.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example quick/scenegraph/textureinthread + \example scenegraph/textureinthread \title Scene Graph - Rendering FBOs in a thread \ingroup qtquickexamples diff --git a/examples/quick/scenegraph/textureinthread/error.qml b/examples/quick/scenegraph/textureinthread/error.qml new file mode 100644 index 0000000000..1dbd576ef7 --- /dev/null +++ b/examples/quick/scenegraph/textureinthread/error.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +Text { + width: 400 + height: 100 + text: 'Platform does not support threaded OpenGL needed by this example.' + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter +} diff --git a/examples/quick/scenegraph/textureinthread/main.cpp b/examples/quick/scenegraph/textureinthread/main.cpp index e415d254a1..801f1891b9 100644 --- a/examples/quick/scenegraph/textureinthread/main.cpp +++ b/examples/quick/scenegraph/textureinthread/main.cpp @@ -38,8 +38,13 @@ ** ****************************************************************************/ +#include <QtCore/QThread> + #include <QGuiApplication> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/qpa/qplatformintegration.h> + #include <QtQuick/QQuickView> #include "threadrenderer.h" @@ -48,12 +53,39 @@ int main(int argc, char **argv) { QGuiApplication app(argc, argv); + if (!QGuiApplicationPrivate::platform_integration->hasCapability(QPlatformIntegration::ThreadedOpenGL)) { + QQuickView view; + view.setSource(QUrl("qrc:///scenegraph/textureinthread/error.qml")); + view.show(); + return app.exec(); + } + qmlRegisterType<ThreadRenderer>("SceneGraphRendering", 1, 0, "Renderer"); + int execReturn = 0; + + { + QQuickView view; + + // Rendering in a thread introduces a slightly more complicated cleanup + // so we ensure that no cleanup of graphics resources happen until the + // application is shutting down. + view.setPersistentOpenGLContext(true); + view.setPersistentSceneGraph(true); + + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:///scenegraph/textureinthread/main.qml")); + view.show(); + + execReturn = app.exec(); + } - QQuickView view; - view.setResizeMode(QQuickView::SizeRootObjectToView); - view.setSource(QUrl("qrc:///scenegraph/textureinsgnode/main.qml")); - view.show(); + // As the render threads make use of our QGuiApplication object + // to clean up gracefully, wait for them to finish before + // QGuiApp is taken off the heap. + foreach (QThread *t, ThreadRenderer::threads) { + t->wait(); + delete t; + } - return app.exec(); + return execReturn; } diff --git a/examples/quick/scenegraph/textureinthread/textureinthread.pro b/examples/quick/scenegraph/textureinthread/textureinthread.pro index b48c2a1863..7f5fbb76e9 100644 --- a/examples/quick/scenegraph/textureinthread/textureinthread.pro +++ b/examples/quick/scenegraph/textureinthread/textureinthread.pro @@ -1,5 +1,8 @@ QT += quick +# To make threaded gl check... +QT += core-private gui-private + HEADERS += threadrenderer.h SOURCES += threadrenderer.cpp main.cpp @@ -13,4 +16,5 @@ target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/textureinthread INSTALLS += target OTHER_FILES += \ - main.qml + main.qml \ + error.qml diff --git a/examples/quick/scenegraph/textureinthread/textureinthread.qrc b/examples/quick/scenegraph/textureinthread/textureinthread.qrc index 9ecf0ada1c..66eb53b736 100644 --- a/examples/quick/scenegraph/textureinthread/textureinthread.qrc +++ b/examples/quick/scenegraph/textureinthread/textureinthread.qrc @@ -1,5 +1,6 @@ <RCC> - <qresource prefix="/scenegraph/textureinsgnode"> + <qresource prefix="/scenegraph/textureinthread"> <file>main.qml</file> + <file>error.qml</file> </qresource> </RCC> diff --git a/examples/quick/scenegraph/textureinthread/threadrenderer.cpp b/examples/quick/scenegraph/textureinthread/threadrenderer.cpp index 90b6b49880..7de1d294ba 100644 --- a/examples/quick/scenegraph/textureinthread/threadrenderer.cpp +++ b/examples/quick/scenegraph/textureinthread/threadrenderer.cpp @@ -46,10 +46,13 @@ #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLFramebufferObject> +#include <QtGui/QGuiApplication> +#include <QtGui/QOffscreenSurface> #include <QtQuick/QQuickWindow> #include <qsgsimpletexturenode.h> +QList<QThread *> ThreadRenderer::threads; /* * The render thread shares a context with the scene graph and will @@ -60,37 +63,39 @@ class RenderThread : public QThread { Q_OBJECT public: - RenderThread(const QSize &size) + RenderThread(const QSize &size, QOpenGLContext *context) : m_renderFbo(0) , m_displayFbo(0) , m_logoRenderer(0) + , m_fakeSurface(0) , m_size(size) { - // Since we're using queued connections, we need affinity to the rendering thread. - moveToThread(this); + ThreadRenderer::threads << this; // Set up the QOpenGLContext to use for rendering in this thread. It is sharing // memory space with the GL context of the scene graph. This constructor is called // during updatePaintNode, so we are currently on the scene graph thread with the // scene graph's OpenGL context current. - QOpenGLContext *current = QOpenGLContext::currentContext(); m_context = new QOpenGLContext(); - m_context->setShareContext(current); - m_context->setFormat(current->format()); - m_context->create(); + m_context->setShareContext(context); + m_context->setFormat(context->format()); m_context->moveToThread(this); - // We need a non-visible surface to make current... - m_fakeSurface = new QWindow(); - m_fakeSurface->setGeometry(0, 0, 64, 64); - m_fakeSurface->setSurfaceType(QWindow::OpenGLSurface); - m_fakeSurface->setFormat(current->format()); + // We need a non-visible surface to make current in the other thread + // and QWindows must be created and managed on the GUI thread. + m_fakeSurface = new QOffscreenSurface(); + m_fakeSurface->setFormat(context->format()); m_fakeSurface->create(); } + void setSurface(QOffscreenSurface *surface) { m_fakeSurface = surface; } + public slots: void renderNext() { + if (!m_context->isValid()) + m_context->create(); + m_context->makeCurrent(m_fakeSurface); if (!m_renderFbo) { @@ -119,6 +124,23 @@ public slots: emit textureReady(m_displayFbo->texture(), m_size); } + void shutDown() + { + m_context->makeCurrent(m_fakeSurface); + delete m_renderFbo; + delete m_displayFbo; + delete m_logoRenderer; + m_context->doneCurrent(); + delete m_context; + + // schedule this to be deleted only after we're done cleaning up + m_fakeSurface->deleteLater(); + + // Stop event processing, move the thread to GUI and make sure it is deleted. + exit(); + moveToThread(QGuiApplication::instance()->thread()); + } + signals: void textureReady(int id, const QSize &size); @@ -128,7 +150,7 @@ private: LogoRenderer *m_logoRenderer; - QWindow *m_fakeSurface; + QOffscreenSurface *m_fakeSurface; QOpenGLContext *m_context; QSize m_size; }; @@ -209,19 +231,35 @@ private: ThreadRenderer::ThreadRenderer() + : m_renderThread(0) { setFlag(ItemHasContents, true); + polish(); } +void ThreadRenderer::updatePolish() +{ + if (!window() || !window()->openglContext()) + return; + m_renderThread = new RenderThread(QSize(512, 512), window()->openglContext()); + m_renderThread->moveToThread(m_renderThread); + m_renderThread->start(); + connect(window(), SIGNAL(sceneGraphInvalidated()), m_renderThread, SLOT(shutDown()), Qt::QueuedConnection); +} QSGNode *ThreadRenderer::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { + if (!m_renderThread) { + polish(); + update(); + return 0; + } + TextureNode *node = static_cast<TextureNode *>(oldNode); if (!node) { node = new TextureNode(window()); - m_renderThread = new RenderThread(QSize(512, 512)); /* Set up connections to get the production of FBO textures in sync with vsync on the * rendering thread. @@ -242,9 +280,6 @@ QSGNode *ThreadRenderer::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * connect(window(), SIGNAL(beforeRendering()), node, SLOT(prepareNode()), Qt::DirectConnection); connect(node, SIGNAL(textureInUse()), m_renderThread, SLOT(renderNext()), Qt::QueuedConnection); - // Start the render thread and enter let it process events. - m_renderThread->start(); - // Get the production of FBO textures started.. QMetaObject::invokeMethod(m_renderThread, "renderNext", Qt::QueuedConnection); } diff --git a/examples/quick/scenegraph/textureinthread/threadrenderer.h b/examples/quick/scenegraph/textureinthread/threadrenderer.h index f12e6404e5..8c68e27d92 100644 --- a/examples/quick/scenegraph/textureinthread/threadrenderer.h +++ b/examples/quick/scenegraph/textureinthread/threadrenderer.h @@ -52,9 +52,15 @@ class ThreadRenderer : public QQuickItem public: ThreadRenderer(); + static QList<QThread *> threads; + +public slots: + void updatePolish(); + protected: QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + private: RenderThread *m_renderThread; }; |