From 1075dca1b50926f52daddf099b5f5a9fbb5da6c7 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 22 Aug 2014 16:52:05 +0200 Subject: [PATCH] Added an example that shows how to consume texture providers from C++. And how to use use two textures in the same material. Change-Id: Idcc618ed359422c2a104eeed105b7c4f5086ee4e Reviewed-by: Laszlo Agocs --- examples/quick/scenegraph/scenegraph.pro | 3 +- .../doc/images/twotextureproviders-example.jpg | Bin 0 -> 44785 bytes .../doc/src/twotextureproviders.qdoc | 36 +++ .../quick/scenegraph/twotextureproviders/main.cpp | 59 +++++ .../quick/scenegraph/twotextureproviders/main.qml | 146 +++++++++++ .../twotextureproviders/twotextureproviders.pro | 12 + .../twotextureproviders/twotextureproviders.qrc | 5 + .../scenegraph/twotextureproviders/xorblender.cpp | 272 +++++++++++++++++++++ .../scenegraph/twotextureproviders/xorblender.h | 76 ++++++ src/quick/scenegraph/util/qsgtextureprovider.cpp | 2 + 10 files changed, 610 insertions(+), 1 deletion(-) create mode 100644 examples/quick/scenegraph/twotextureproviders/doc/images/twotextureproviders-example.jpg create mode 100644 examples/quick/scenegraph/twotextureproviders/doc/src/twotextureproviders.qdoc create mode 100644 examples/quick/scenegraph/twotextureproviders/main.cpp create mode 100644 examples/quick/scenegraph/twotextureproviders/main.qml create mode 100644 examples/quick/scenegraph/twotextureproviders/twotextureproviders.pro create mode 100644 examples/quick/scenegraph/twotextureproviders/twotextureproviders.qrc create mode 100644 examples/quick/scenegraph/twotextureproviders/xorblender.cpp create mode 100644 examples/quick/scenegraph/twotextureproviders/xorblender.h diff --git a/examples/quick/scenegraph/scenegraph.pro b/examples/quick/scenegraph/scenegraph.pro index 85ae259..1e7e743 100644 --- a/examples/quick/scenegraph/scenegraph.pro +++ b/examples/quick/scenegraph/scenegraph.pro @@ -6,4 +6,5 @@ SUBDIRS += \ simplematerial \ textureinsgnode \ textureinthread \ - threadedanimation + threadedanimation \ + twotextureproviders diff --git a/examples/quick/scenegraph/twotextureproviders/doc/images/twotextureproviders-example.jpg b/examples/quick/scenegraph/twotextureproviders/doc/images/twotextureproviders-example.jpg new file mode 100644 index 0000000000000000000000000000000000000000..331233fa323f1b7080f3a17218574ee5a4b38fc6 GIT binary patch literal 44785 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 literal 0 HcmV?d00001 diff --git a/examples/quick/scenegraph/twotextureproviders/doc/src/twotextureproviders.qdoc b/examples/quick/scenegraph/twotextureproviders/doc/src/twotextureproviders.qdoc new file mode 100644 index 0000000..3283bcf --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/doc/src/twotextureproviders.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Gunnar Sletta +** 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/twotextureproviders + \title Scene Graph - Two Texture Providers + \ingroup qtquickexamples + + \brief Shows how to combine two textures from two texture providers in a custom scene graph node. + + \image twotextureproviders-example.jpg + */ diff --git a/examples/quick/scenegraph/twotextureproviders/main.cpp b/examples/quick/scenegraph/twotextureproviders/main.cpp new file mode 100644 index 0000000..49edd8b --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Gunnar Sletta +** 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 + +#include + +#include "xorblender.h" + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + qmlRegisterType("SceneGraphRendering", 1, 0, "XorBlender"); + + QQuickView view; + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:///scenegraph/twotextureproviders/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/examples/quick/scenegraph/twotextureproviders/main.qml b/examples/quick/scenegraph/twotextureproviders/main.qml new file mode 100644 index 0000000..c842cad --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/main.qml @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Gunnar Sletta +** 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.2 +import SceneGraphRendering 1.0 + +Item { + id: root + + // The checkers background + ShaderEffect { + anchors.fill: parent + + property real tileSize: 16 + property color color1: Qt.rgba(0.9, 0.9, 0.9, 1); + property color color2: Qt.rgba(0.8, 0.8, 0.8, 1); + + property size pixelSize: Qt.size(width / tileSize, height / tileSize); + + fragmentShader: + " + uniform lowp vec4 color1; + uniform lowp vec4 color2; + uniform highp vec2 pixelSize; + varying highp vec2 qt_TexCoord0; + void main() { + highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize)); + if (tc.x != tc.y) + gl_FragColor = color1; + else + gl_FragColor = color2; + } + " + } + + width: 320 + height: 480 + + Item { + id: box + width: root.width * 0.9 + height: width + + Rectangle { + anchors.centerIn: parent + width: parent.width * 0.9 + height: parent.width * 0.4 + radius: width * 0.1; + gradient: Gradient { + GradientStop { position: 0; color: Qt.hsla(0.6, 0.9, 0.9, 1); } + GradientStop { position: 1; color: Qt.hsla(0.6, 0.6, 0.3, 1); } + } + RotationAnimator on rotation { from: 0; to: 360; duration: 10000; loops: Animation.Infinite } + } + + visible: false + layer.enabled: true + } + + Item { + id: text + width: box.width + height: width + Text { + anchors.centerIn: parent + color: "black" // Qt.hsla(0.8, 0.8, 0.8); + text: "Qt\nQuick" + + horizontalAlignment: Text.AlignHCenter + + font.bold: true + font.pixelSize: text.width * 0.25 + RotationAnimator on rotation { from: 360; to: 0; duration: 9000; loops: Animation.Infinite } + } + visible: false + layer.enabled: true + } + + XorBlender { + anchors.horizontalCenter: parent.horizontalCenter + y: root.height * 0.05; + width: box.width + height: box.height + source1: box + source2: text + } + + Rectangle { + id: labelFrame + anchors.margins: -10 + radius: 10 + color: "white" + border.color: "black" + opacity: 0.8 + anchors.fill: description + } + + Text { + id: description + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 20 + wrapMode: Text.WordWrap + text: "This example creates two animated items and sets 'layer.enabled: true' on both of them. " + + "This turns the items into texture providers and we can access their texture from C++ in a custom material. " + + "The XorBlender is a custom C++ item which uses performs an Xor blend between them." + } +} diff --git a/examples/quick/scenegraph/twotextureproviders/twotextureproviders.pro b/examples/quick/scenegraph/twotextureproviders/twotextureproviders.pro new file mode 100644 index 0000000..7b7c093 --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/twotextureproviders.pro @@ -0,0 +1,12 @@ +QT += qml quick + +HEADERS += xorblender.h +SOURCES += xorblender.cpp main.cpp + +RESOURCES += twotextureproviders.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/twotextureproviders +INSTALLS += target + +OTHER_FILES += \ + main.qml diff --git a/examples/quick/scenegraph/twotextureproviders/twotextureproviders.qrc b/examples/quick/scenegraph/twotextureproviders/twotextureproviders.qrc new file mode 100644 index 0000000..1424333 --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/twotextureproviders.qrc @@ -0,0 +1,5 @@ + + + main.qml + + diff --git a/examples/quick/scenegraph/twotextureproviders/xorblender.cpp b/examples/quick/scenegraph/twotextureproviders/xorblender.cpp new file mode 100644 index 0000000..c46a99e --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/xorblender.cpp @@ -0,0 +1,272 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Gunnar Sletta +** 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 "xorblender.h" + +#include + +#include +#include + +#include +#include +#include +#include + +/* This example could just as well have been implemented all in QML using + * a ShaderEffect, and for 90% of all usecases, using a ShaderEffect will + * be sufficient. This example exists to illustrate how to consume + * texture providers from C++ and how to use multiple texture sources in + * a custom material. + */ + +struct XorBlendState { + QSGTexture *texture1; + QSGTexture *texture2; +}; + +class XorBlendShader : public QSGSimpleMaterialShader +{ + QSG_DECLARE_SIMPLE_SHADER(XorBlendShader, XorBlendState) +public: + + const char *vertexShader() const { + return + "attribute highp vec4 aVertex; \n" + "attribute highp vec2 aTexCoord; \n" + "uniform highp mat4 qt_Matrix; \n" + "varying highp vec2 vTexCoord; \n" + "void main() { \n" + " gl_Position = qt_Matrix * aVertex; \n" + " vTexCoord = aTexCoord; \n" + "}"; + } + + const char *fragmentShader() const { + return + "uniform lowp float qt_Opacity; \n" + "uniform lowp sampler2D uSource1; \n" + "uniform lowp sampler2D uSource2; \n" + "varying highp vec2 vTexCoord; \n" + "void main() { \n" + " lowp vec4 p1 = texture2D(uSource1, vTexCoord); \n" + " lowp vec4 p2 = texture2D(uSource2, vTexCoord); \n" + " gl_FragColor = (p1 * (1.0 - p2.a) + p2 * (1.0 - p1.a)) * qt_Opacity; \n" + "}"; + } + + QList attributes() const { + return QList() << "aVertex" << "aTexCoord"; + } + + void updateState(const XorBlendState *state, const XorBlendState *) { + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + // We bind the textures in inverse order so that we leave the updateState + // function with GL_TEXTURE0 as the active texture unit. This is maintain + // the "contract" that updateState should not mess up the GL state beyond + // what is needed for this material. + f->glActiveTexture(GL_TEXTURE1); + state->texture2->bind(); + f->glActiveTexture(GL_TEXTURE0); + state->texture1->bind(); + } + + void resolveUniforms() { + // The texture units never change, only the texturess we bind to them so + // we set these once and for all here. + program()->setUniformValue("uSource1", 0); // GL_TEXTURE0 + program()->setUniformValue("uSource2", 1); // GL_TEXTURE1 + } +}; + +/* The rendering is split into two nodes. The top-most node is not actually + * rendering anything, but is responsible for managing the texture providers. + * The XorNode also has a geometry node internally which it uses to render + * the texture providers using the XorBlendShader when all providers and + * textures are all present. + * + * The texture providers are updated solely on the render thread (when rendering + * is happening on a separate thread). This is why we are using preprocess + * and direct signals between the the texture providers and the node rather + * than updating state in updatePaintNode. + */ +class XorNode : public QObject, public QSGNode +{ + Q_OBJECT +public: + XorNode(QSGTextureProvider *p1, QSGTextureProvider *p2) + : m_provider1(p1) + , m_provider2(p2) + { + setFlag(QSGNode::UsePreprocess, true); + + // Set up material so it is all set for later.. + m_material = XorBlendShader::createMaterial(); + m_material->state()->texture1 = 0; + m_material->state()->texture2 = 0; + m_material->setFlag(QSGMaterial::Blending); + m_node.setMaterial(m_material); + m_node.setFlag(QSGNode::OwnsMaterial); + + // Set up geometry, actual vertices will be initialized in updatePaintNode + m_node.setGeometry(new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)); + m_node.setFlag(QSGNode::OwnsGeometry); + + // If this node is used as in a shader effect source, we need to propegate + // changes that will occur in this node outwards. + connect(m_provider1, SIGNAL(textureChanged()), this, SLOT(textureChange()), Qt::DirectConnection); + connect(m_provider2, SIGNAL(textureChanged()), this, SLOT(textureChange()), Qt::DirectConnection); + } + + void preprocess() { + XorBlendState *state = m_material->state(); + // Update the textures from the providers, calling into QSGDynamicTexture if required + if (m_provider1) { + state->texture1 = m_provider1->texture(); + if (QSGDynamicTexture *dt1 = qobject_cast(state->texture1)) + dt1->updateTexture(); + } + if (m_provider2) { + state->texture2 = m_provider2->texture(); + if (QSGDynamicTexture *dt2 = qobject_cast(state->texture2)) + dt2->updateTexture(); + } + + // Remove node from the scene graph if it is there and either texture is missing... + if (m_node.parent() && (!state->texture1 || !state->texture2)) + removeChildNode(&m_node); + + // Add it if it is not already there and both textures are present.. + else if (!m_node.parent() && state->texture1 && state->texture2) + appendChildNode(&m_node); + } + + void setRect(const QRectF &rect) { + // Update geometry if it has changed and mark the change in the scene graph. + if (m_rect != rect) { + m_rect = rect; + QSGGeometry::updateTexturedRectGeometry(m_node.geometry(), m_rect, QRectF(0, 0, 1, 1)); + m_node.markDirty(QSGNode::DirtyGeometry); + } + } + +public slots: + void textureChange() { + // When our sources change, we will look different, so signal the change to the + // scene graph. + markDirty(QSGNode::DirtyMaterial); + } + +private: + QRectF m_rect; + QSGSimpleMaterial *m_material; + QSGGeometryNode m_node; + QPointer m_provider1; + QPointer m_provider2; +}; + +XorBlender::XorBlender(QQuickItem *parent) + : QQuickItem(parent) + , m_source1(0) + , m_source2(0) + , m_source1Changed(false) + , m_source2Changed(false) +{ + setFlag(ItemHasContents, true); +} + +void XorBlender::setSource1(QQuickItem *i) +{ + if (i == m_source1) + return; + m_source1 = i; + emit source1Changed(m_source1); + m_source1Changed = true; + update(); +} + +void XorBlender::setSource2(QQuickItem *i) +{ + if (i == m_source2) + return; + m_source2 = i; + emit source2Changed(m_source2); + m_source2Changed = true; + update(); +} + +QSGNode *XorBlender::updatePaintNode(QSGNode *old, UpdatePaintNodeData *) +{ + // Check if our input is valid and abort if not, deleting the old node. + bool abort = false; + if (!m_source1 || !m_source1->isTextureProvider()) { + qDebug() << "source1 is missing or not a texture provider"; + abort = true; + } + if (!m_source2 || !m_source2->isTextureProvider()) { + qDebug() << "source2 is missing or not a texture provider"; + abort = true; + } + if (abort) { + delete old; + return 0; + } + + XorNode *node = static_cast(old); + + // If the sources have changed, recreate the nodes + if (m_source1Changed || m_source2Changed) { + delete node; + node = 0; + m_source1Changed = false; + m_source2Changed = false; + } + + // Create a new XorNode for us to render with. + if (!node) + node = new XorNode(m_source1->textureProvider(), m_source2->textureProvider()); + + // Update the geometry of the node to match the new bounding rect + node->setRect(boundingRect()); + + return node; +} + +#include "xorblender.moc" diff --git a/examples/quick/scenegraph/twotextureproviders/xorblender.h b/examples/quick/scenegraph/twotextureproviders/xorblender.h new file mode 100644 index 0000000..d82352d --- /dev/null +++ b/examples/quick/scenegraph/twotextureproviders/xorblender.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Gunnar Sletta +** 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 XORBLENDER_H +#define XORBLENDER_H + +#include + +class XorBlender : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QQuickItem *source1 READ source1 WRITE setSource1 NOTIFY source1Changed) + Q_PROPERTY(QQuickItem *source2 READ source2 WRITE setSource2 NOTIFY source2Changed) + +public: + explicit XorBlender(QQuickItem *parent = 0); + + QQuickItem *source1() const { return m_source1; } + QQuickItem *source2() const { return m_source2; } + + void setSource1(QQuickItem *i); + void setSource2(QQuickItem *i); + +protected: + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); + +signals: + void source1Changed(QQuickItem *item); + void source2Changed(QQuickItem *item); + +private: + QQuickItem *m_source1; + QQuickItem *m_source2; + + bool m_source1Changed; + bool m_source2Changed; +}; + +#endif // XORBLENDER_H diff --git a/src/quick/scenegraph/util/qsgtextureprovider.cpp b/src/quick/scenegraph/util/qsgtextureprovider.cpp index 05bc75d..4a43f71 100644 --- a/src/quick/scenegraph/util/qsgtextureprovider.cpp +++ b/src/quick/scenegraph/util/qsgtextureprovider.cpp @@ -40,6 +40,8 @@ QT_BEGIN_NAMESPACE \brief The QSGTextureProvider class encapsulates texture based entities in QML. The QSGTextureProvider lives primarily in the scene graph rendering thread. + + \sa {Scene Graph - Two Texture Providers} */ -- 2.7.4