aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/quick/scenegraph/scenegraph.pro1
-rw-r--r--examples/quick/scenegraph/sgengine/face-smile.pngbin0 -> 15408 bytes
-rw-r--r--examples/quick/scenegraph/sgengine/main.cpp52
-rw-r--r--examples/quick/scenegraph/sgengine/sgengine.pro11
-rw-r--r--examples/quick/scenegraph/sgengine/sgengine.qrc5
-rw-r--r--examples/quick/scenegraph/sgengine/window.cpp241
-rw-r--r--examples/quick/scenegraph/sgengine/window.h85
-rw-r--r--src/quick/items/qquickwindow.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp318
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer.h103
-rw-r--r--src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h77
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.h5
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp96
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h65
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp22
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h3
-rw-r--r--src/quick/scenegraph/scenegraph.pri6
-rw-r--r--src/quick/scenegraph/util/qsgengine.cpp204
-rw-r--r--src/quick/scenegraph/util/qsgengine.h80
-rw-r--r--src/quick/scenegraph/util/qsgengine_p.h66
20 files changed, 1304 insertions, 140 deletions
diff --git a/examples/quick/scenegraph/scenegraph.pro b/examples/quick/scenegraph/scenegraph.pro
index 4354954445..85ae25907a 100644
--- a/examples/quick/scenegraph/scenegraph.pro
+++ b/examples/quick/scenegraph/scenegraph.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
SUBDIRS += \
customgeometry \
openglunderqml \
+ sgengine \
simplematerial \
textureinsgnode \
textureinthread \
diff --git a/examples/quick/scenegraph/sgengine/face-smile.png b/examples/quick/scenegraph/sgengine/face-smile.png
new file mode 100644
index 0000000000..3d66d72578
--- /dev/null
+++ b/examples/quick/scenegraph/sgengine/face-smile.png
Binary files differ
diff --git a/examples/quick/scenegraph/sgengine/main.cpp b/examples/quick/scenegraph/sgengine/main.cpp
new file mode 100644
index 0000000000..9a9450710b
--- /dev/null
+++ b/examples/quick/scenegraph/sgengine/main.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "window.h"
+#include <QGuiApplication>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ Window window;
+ window.show();
+
+ return app.exec();
+}
diff --git a/examples/quick/scenegraph/sgengine/sgengine.pro b/examples/quick/scenegraph/sgengine/sgengine.pro
new file mode 100644
index 0000000000..c6507a4982
--- /dev/null
+++ b/examples/quick/scenegraph/sgengine/sgengine.pro
@@ -0,0 +1,11 @@
+QT += quick
+
+HEADERS += window.h
+SOURCES += window.cpp main.cpp
+RESOURCES += \
+ sgengine.qrc \
+ ../../shared/shared.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/scenegraph/sgengine
+INSTALLS += target
diff --git a/examples/quick/scenegraph/sgengine/sgengine.qrc b/examples/quick/scenegraph/sgengine/sgengine.qrc
new file mode 100644
index 0000000000..5d55bcfb6f
--- /dev/null
+++ b/examples/quick/scenegraph/sgengine/sgengine.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/scenegraph/sgengine">
+ <file>face-smile.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/scenegraph/sgengine/window.cpp b/examples/quick/scenegraph/sgengine/window.cpp
new file mode 100644
index 0000000000..9af4029165
--- /dev/null
+++ b/examples/quick/scenegraph/sgengine/window.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "window.h"
+
+#include <QOpenGLContext>
+#include <QSGAbstractRenderer>
+#include <QSGEngine>
+#include <QSGSimpleTextureNode>
+#include <QSGTransformNode>
+#include <QScreen>
+#include <QVariantAnimation>
+
+class Item {
+public:
+ Item(QSGNode *parentNode, QSGTexture *texture, const QPointF &fromPos, const QPointF &toPos) {
+ textureNode = new QSGSimpleTextureNode;
+ textureNode->setRect(QRect(QPoint(), texture->textureSize()));
+ textureNode->setTexture(texture);
+
+ transformNode = new QSGTransformNode;
+ transformNode->setFlag(QSGNode::OwnedByParent, false);
+ transformNode->appendChildNode(textureNode);
+ parentNode->appendChildNode(transformNode);
+
+ int duration = qrand() / float(RAND_MAX) * 400 + 800;
+ rotAnimation.setStartValue(qrand() / float(RAND_MAX) * 720 - 180);
+ rotAnimation.setEndValue(qrand() / float(RAND_MAX) * 720 - 180);
+ rotAnimation.setDuration(duration);
+ rotAnimation.start();
+
+ posAnimation.setStartValue(fromPos);
+ posAnimation.setEndValue(toPos);
+ posAnimation.setDuration(duration);
+ posAnimation.start();
+ }
+
+ ~Item() {
+ delete transformNode;
+ }
+
+ bool isDone() const { return posAnimation.state() != QAbstractAnimation::Running; }
+
+ void sync() {
+ QPointF currentPos = posAnimation.currentValue().toPointF();
+ QPointF center = textureNode->rect().center();
+ QMatrix4x4 m;
+ m.translate(currentPos.x(), currentPos.y());
+ m.translate(center.x(), center.y());
+ m.rotate(rotAnimation.currentValue().toFloat(), 0, 0, 1);
+ m.translate(-center.x(), -center.y());
+ transformNode->setMatrix(m);
+ }
+
+private:
+ QSGTransformNode *transformNode;
+ QSGSimpleTextureNode *textureNode;
+ QVariantAnimation posAnimation;
+ QVariantAnimation rotAnimation;
+};
+
+Window::Window()
+ : m_initialized(false)
+ , m_context(new QOpenGLContext)
+ , m_sgEngine(new QSGEngine)
+ , m_sgRootNode(new QSGRootNode)
+{
+ setSurfaceType(QWindow::OpenGLSurface);
+ QRect g(0, 0, 640, 480);
+ g.moveCenter(screen()->geometry().center());
+ setGeometry(g);
+ setTitle(QStringLiteral("Click me!"));
+
+ QSurfaceFormat format;
+ format.setDepthBufferSize(16);
+ setFormat(format);
+ m_context->setFormat(format);
+ m_context->create();
+
+ m_animationDriver.install();
+ connect(&m_animationDriver, &QAnimationDriver::started, this, &Window::update);
+}
+
+Window::~Window()
+{
+}
+
+void Window::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == m_updateTimer.timerId()) {
+ m_updateTimer.stop();
+
+ if (!m_context->makeCurrent(this))
+ return;
+
+ if (!m_initialized)
+ initialize();
+
+ sync();
+ render();
+
+ if (m_animationDriver.isRunning()) {
+ m_animationDriver.advance();
+ update();
+ }
+ } else
+ QWindow::timerEvent(e);
+}
+
+void Window::exposeEvent(QExposeEvent *)
+{
+ if (isExposed())
+ update();
+ else
+ invalidate();
+}
+
+void Window::mousePressEvent(QMouseEvent *)
+{
+ addItems();
+}
+
+void Window::keyPressEvent(QKeyEvent *)
+{
+ addItems();
+}
+
+void Window::addItems()
+{
+ if (!m_initialized)
+ return;
+
+ QSGTexture *textures[] = { m_smileTexture.data(), m_qtTexture.data() };
+ for (int i = 0; i < 50; ++i) {
+ QSGTexture *tex = textures[i%2];
+ QPointF fromPos(-tex->textureSize().width(), qrand() / float(RAND_MAX) * (height() - tex->textureSize().height()));
+ QPointF toPos(width(), qrand() / float(RAND_MAX) * height() * 1.5 - height() * 0.25);
+ m_items.append(QSharedPointer<Item>(new Item(m_sgRootNode.data(), tex, fromPos, toPos)));
+ }
+ update();
+}
+
+void Window::update()
+{
+ if (!m_updateTimer.isActive())
+ m_updateTimer.start(0, this);
+}
+
+void Window::sync()
+{
+ QList<QSharedPointer<Item> > validItems;
+ foreach (QSharedPointer<Item> item, m_items) {
+ if (!item->isDone()) {
+ validItems.append(item);
+ item->sync();
+ }
+ }
+ m_items.swap(validItems);
+}
+
+void Window::render()
+{
+ m_sgRenderer->setDeviceRect(size());
+ m_sgRenderer->setViewportRect(size());
+ m_sgRenderer->setProjectionMatrixToRect(QRectF(QPointF(), size()));
+ m_sgRenderer->renderScene();
+
+ m_context->swapBuffers(this);
+}
+
+void Window::initialize()
+{
+ m_sgEngine->initialize(m_context.data());
+ m_sgRenderer.reset(m_sgEngine->createRenderer());
+ m_sgRenderer->setRootNode(m_sgRootNode.data());
+ m_sgRenderer->setClearColor(QColor(32, 32, 32));
+
+ // With QSGEngine::createTextureFromId
+ GLuint glTexture;
+ glGenTextures(1, &glTexture);
+ glBindTexture(GL_TEXTURE_2D, glTexture);
+ QImage smile = QImage(":/scenegraph/sgengine/face-smile.png").scaled(48, 48, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ smile = smile.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ Q_ASSERT(!smile.isNull());
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smile.width(), smile.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, smile.constBits());
+ m_smileTexture.reset(m_sgEngine->createTextureFromId(glTexture, smile.size(), QFlag(QSGEngine::TextureOwnsGLTexture | QSGEngine::TextureHasAlphaChannel)));
+
+ // With QSGEngine::createTextureFromImage
+ QImage qtLogo = QImage(":/shared/images/qt-logo.png").scaled(48, 48, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ Q_ASSERT(!qtLogo.isNull());
+ m_qtTexture.reset(m_sgEngine->createTextureFromImage(qtLogo));
+ m_initialized = true;
+}
+
+void Window::invalidate()
+{
+ m_updateTimer.stop();
+ m_items.clear();
+ m_smileTexture.reset();
+ m_qtTexture.reset();
+ m_sgRenderer.reset();
+ m_sgEngine->invalidate();
+ m_initialized = false;
+}
diff --git a/examples/quick/scenegraph/sgengine/window.h b/examples/quick/scenegraph/sgengine/window.h
new file mode 100644
index 0000000000..2b239ea430
--- /dev/null
+++ b/examples/quick/scenegraph/sgengine/window.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 <QWindow>
+
+#include <QAnimationDriver>
+#include <QBasicTimer>
+#include <QSharedPointer>
+
+class Item;
+QT_FORWARD_DECLARE_CLASS(QSGAbstractRenderer)
+QT_FORWARD_DECLARE_CLASS(QSGEngine)
+QT_FORWARD_DECLARE_CLASS(QSGRootNode)
+QT_FORWARD_DECLARE_CLASS(QSGTexture)
+
+class Window : public QWindow
+{
+ Q_OBJECT
+public:
+ Window();
+ ~Window();
+
+ void addItems();
+ void update();
+
+private:
+ void timerEvent(QTimerEvent *);
+ void exposeEvent(QExposeEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void keyPressEvent(QKeyEvent *);
+
+ void sync();
+ void render();
+ void initialize();
+ void invalidate();
+
+ bool m_initialized;
+ QScopedPointer<QOpenGLContext> m_context;
+ QScopedPointer<QSGEngine> m_sgEngine;
+ QScopedPointer<QSGRootNode> m_sgRootNode;
+ QScopedPointer<QSGAbstractRenderer> m_sgRenderer;
+ QScopedPointer<QSGTexture> m_smileTexture;
+ QScopedPointer<QSGTexture> m_qtTexture;
+ QList<QSharedPointer<Item> > m_items;
+
+ QBasicTimer m_updateTimer;
+ QAnimationDriver m_animationDriver;
+};
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 12be33d790..f1d2f63756 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -350,9 +350,9 @@ void QQuickWindowPrivate::syncSceneGraph()
// Copy the current state of clearing from window into renderer.
renderer->setClearColor(clearColor);
- QSGRenderer::ClearMode mode = QSGRenderer::ClearStencilBuffer | QSGRenderer::ClearDepthBuffer;
+ QSGAbstractRenderer::ClearMode mode = QSGAbstractRenderer::ClearStencilBuffer | QSGAbstractRenderer::ClearDepthBuffer;
if (clearBeforeRendering)
- mode |= QSGRenderer::ClearColorBuffer;
+ mode |= QSGAbstractRenderer::ClearColorBuffer;
renderer->setClearMode(mode);
renderer->setCustomRenderMode(customRenderMode);
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
new file mode 100644
index 0000000000..9409822c8f
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgabstractrenderer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSGAbstractRenderer
+ \brief QSGAbstractRenderer gives access to the scene graph nodes and rendering of a QSGEngine.
+ \inmodule QtQuick
+ \since 5.4
+
+ A QSGAbstractRenderer created by a QSGEngine allows you to set your QSGNode
+ tree through setRootNode() and control the rendering viewport through
+ setDeviceRect(), setViewportRect() and setProjectionMatrixToRect().
+ You can finally trigger the rendering to the desired framebuffer through
+ renderScene().
+
+ The QSGAbstractRenderer is only available when used with a QSGEngine
+ and isn't exposed when used internally by QQuickWindow.
+
+ \sa QSGEngine, QSGNode
+ */
+
+/*!
+ \enum QSGAbstractRenderer::ClearModeBit
+
+ Used with setClearMode() to indicate which buffer should
+ be cleared before the scene render.
+
+ \value ClearColorBuffer Clear the color buffer using clearColor().
+ \value ClearDepthBuffer Clear the depth buffer.
+ \value ClearStencilBuffer Clear the stencil buffer.
+
+ \sa setClearMode(), setClearColor()
+ */
+
+/*!
+ \fn void QSGAbstractRenderer::renderScene(GLuint fboId = 0)
+
+ Render the scene to the specified \a fboId
+
+ If \a fboId isn't specified, the scene graph will be rendered
+ to the default framebuffer. You will have to call
+ QOpenGLContext::swapBuffers() yourself afterward.
+
+ The framebuffer specified by \a fboId will be bound automatically.
+
+ \sa QOpenGLContext::swapBuffers(), QOpenGLFramebufferObject::handle()
+ */
+
+/*!
+ \fn void QSGAbstractRenderer::sceneGraphChanged()
+
+ This signal is emitted on the first modification of a node in
+ the tree after the last scene render.
+ */
+
+/*!
+ \internal
+ */
+QSGAbstractRendererPrivate::QSGAbstractRendererPrivate()
+ : m_root_node(0)
+ , m_clear_color(Qt::transparent)
+ , m_clear_mode(QSGAbstractRenderer::ClearColorBuffer | QSGAbstractRenderer::ClearDepthBuffer)
+{
+}
+
+/*!
+ \internal
+ */
+QSGAbstractRenderer::QSGAbstractRenderer(QObject *parent)
+ : QObject(*new QSGAbstractRendererPrivate, parent)
+{
+}
+
+/*!
+ \internal
+ */
+QSGAbstractRenderer::~QSGAbstractRenderer()
+{
+}
+
+/*!
+ Sets the \a node as the root of the QSGNode scene
+ that you want to render. You need to provide a \a node
+ before trying to render the scene.
+
+ \note This doesn't take ownership of \a node.
+
+ \sa rootNode()
+*/
+void QSGAbstractRenderer::setRootNode(QSGRootNode *node)
+{
+ Q_D(QSGAbstractRenderer);
+ if (d->m_root_node == node)
+ return;
+ if (d->m_root_node) {
+ d->m_root_node->m_renderers.removeOne(this);
+ nodeChanged(d->m_root_node, QSGNode::DirtyNodeRemoved);
+ }
+ d->m_root_node = node;
+ if (d->m_root_node) {
+ Q_ASSERT(!d->m_root_node->m_renderers.contains(this));
+ d->m_root_node->m_renderers << this;
+ nodeChanged(d->m_root_node, QSGNode::DirtyNodeAdded);
+ }
+}
+
+/*!
+ Returns the root of the QSGNode scene.
+
+ \sa setRootNode()
+*/
+QSGRootNode *QSGAbstractRenderer::rootNode() const
+{
+ Q_D(const QSGAbstractRenderer);
+ return d->m_root_node;
+}
+
+
+/*!
+ \fn void QSGAbstractRenderer::setDeviceRect(const QSize &size)
+ \overload
+
+ Sets the \a size of the surface being rendered to.
+
+ \sa deviceRect()
+ */
+
+/*!
+ Sets \a rect as the geometry of the surface being rendered to.
+
+ \sa deviceRect()
+ */
+void QSGAbstractRenderer::setDeviceRect(const QRect &rect)
+{
+ Q_D(QSGAbstractRenderer);
+ d->m_device_rect = rect;
+}
+
+/*!
+ Returns the device rect of the surface being rendered to.
+
+ \sa setDeviceRect()
+ */
+QRect QSGAbstractRenderer::deviceRect() const
+{
+ Q_D(const QSGAbstractRenderer);
+ return d->m_device_rect;
+}
+
+/*!
+ \fn void QSGAbstractRenderer::setViewportRect(const QSize &size)
+ \overload
+
+ Sets the \a size of the viewport to render
+ on the surface.
+
+ \sa viewportRect()
+ */
+
+/*!
+ Sets \a rect as the geometry of the viewport to render
+ on the surface.
+
+ \sa viewportRect()
+ */
+void QSGAbstractRenderer::setViewportRect(const QRect &rect)
+{
+ Q_D(QSGAbstractRenderer);
+ d->m_viewport_rect = rect;
+}
+
+/*!
+ Returns the rect of the viewport to render.
+
+ \sa setViewportRect()
+ */
+QRect QSGAbstractRenderer::viewportRect() const
+{
+ Q_D(const QSGAbstractRenderer);
+ return d->m_viewport_rect;
+}
+
+/*!
+ Convenience method that calls setProjectionMatrix() with an
+ orthographic matrix generated from \a rect.
+
+ \sa setProjectionMatrix(), projectionMatrix()
+ */
+void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect)
+{
+ QMatrix4x4 matrix;
+ matrix.ortho(rect.x(),
+ rect.x() + rect.width(),
+ rect.y() + rect.height(),
+ rect.y(),
+ 1,
+ -1);
+ setProjectionMatrix(matrix);
+}
+
+/*!
+ Use \a matrix to project the QSGNode coordinates onto surface pixels.
+
+ \sa projectionMatrix(), setProjectionMatrixToRect()
+ */
+void QSGAbstractRenderer::setProjectionMatrix(const QMatrix4x4 &matrix)
+{
+ Q_D(QSGAbstractRenderer);
+ d->m_projection_matrix = matrix;
+}
+
+/*!
+ Returns the projection matrix
+
+ \sa setProjectionMatrix(), setProjectionMatrixToRect()
+ */
+QMatrix4x4 QSGAbstractRenderer::projectionMatrix() const
+{
+ Q_D(const QSGAbstractRenderer);
+ return d->m_projection_matrix;
+}
+
+/*!
+ Use \a color to clear the framebuffer when clearMode() is
+ set to QSGAbstractRenderer::ClearColorBuffer.
+
+ \sa clearColor(), setClearMode()
+ */
+void QSGAbstractRenderer::setClearColor(const QColor &color)
+{
+ Q_D(QSGAbstractRenderer);
+ d->m_clear_color = color;
+}
+
+/*!
+ Returns the color that clears the framebuffer at the beginning
+ of the rendering.
+
+ \sa setClearColor(), clearMode()
+ */
+QColor QSGAbstractRenderer::clearColor() const
+{
+ Q_D(const QSGAbstractRenderer);
+ return d->m_clear_color;
+}
+
+/*!
+ Defines which attachment of the framebuffer should be cleared
+ before each scene render with the \a mode flag.
+
+ \sa clearMode(), setClearColor()
+ */
+void QSGAbstractRenderer::setClearMode(ClearMode mode)
+{
+ Q_D(QSGAbstractRenderer);
+ d->m_clear_mode = mode;
+}
+
+/*!
+ Flags defining which attachment of the framebuffer will be cleared
+ before each scene render.
+
+ \sa setClearMode(), clearColor()
+ */
+QSGAbstractRenderer::ClearMode QSGAbstractRenderer::clearMode() const
+{
+ Q_D(const QSGAbstractRenderer);
+ return d->m_clear_mode;
+}
+
+/*!
+ \fn void QSGAbstractRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
+ \internal
+ */
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h
new file mode 100644
index 0000000000..671d62e931
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGABSTRACTRENDERER_H
+#define QSGABSTRACTRENDERER_H
+
+#include "qsgnode.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSGAbstractRendererPrivate;
+
+class Q_QUICK_EXPORT QSGAbstractRenderer : public QObject
+{
+ Q_OBJECT
+public:
+ enum ClearModeBit
+ {
+ ClearColorBuffer = 0x0001,
+ ClearDepthBuffer = 0x0002,
+ ClearStencilBuffer = 0x0004
+ };
+ Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
+
+ virtual ~QSGAbstractRenderer();
+
+ void setRootNode(QSGRootNode *node);
+ QSGRootNode *rootNode() const;
+ void setDeviceRect(const QRect &rect);
+ inline void setDeviceRect(const QSize &size) { setDeviceRect(QRect(QPoint(), size)); }
+ QRect deviceRect() const;
+
+ void setViewportRect(const QRect &rect);
+ inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); }
+ QRect viewportRect() const;
+
+ void setProjectionMatrixToRect(const QRectF &rect);
+ void setProjectionMatrix(const QMatrix4x4 &matrix);
+ QMatrix4x4 projectionMatrix() const;
+
+ void setClearColor(const QColor &color);
+ QColor clearColor() const;
+
+ void setClearMode(ClearMode mode);
+ ClearMode clearMode() const;
+
+ virtual void renderScene(GLuint fboId = 0) = 0;
+
+Q_SIGNALS:
+ void sceneGraphChanged();
+
+protected:
+ QSGAbstractRenderer(QObject *parent = 0);
+ virtual void nodeChanged(QSGNode *node, QSGNode::DirtyState state) = 0;
+
+private:
+ Q_DECLARE_PRIVATE(QSGAbstractRenderer)
+ friend class QSGRootNode;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGAbstractRenderer::ClearMode)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
new file mode 100644
index 0000000000..c60a488cc8
--- /dev/null
+++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGABSTRACTRENDERER_P_H
+#define QSGABSTRACTRENDERER_P_H
+
+#include "qsgabstractrenderer.h"
+
+#include "qsgnode.h"
+#include <qcolor.h>
+
+#include <QtCore/private/qobject_p.h>
+#include <QtQuick/private/qtquickglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICK_PRIVATE_EXPORT QSGAbstractRendererPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSGAbstractRenderer)
+public:
+ static const QSGAbstractRendererPrivate *get(const QSGAbstractRenderer *q) { return q->d_func(); }
+
+ QSGAbstractRendererPrivate();
+ void updateProjectionMatrix();
+
+ QSGRootNode *m_root_node;
+ QColor m_clear_color;
+ QSGAbstractRenderer::ClearMode m_clear_mode;
+
+ QRect m_device_rect;
+ QRect m_viewport_rect;
+
+ QMatrix4x4 m_projection_matrix;
+ uint m_mirrored : 1;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h
index 380b7e01e1..be93fd1fce 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.h
+++ b/src/quick/scenegraph/coreapi/qsgnode.h
@@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE
#define QSG_RUNTIME_DESCRIPTION
#endif
+class QSGAbstractRenderer;
class QSGRenderer;
class QSGNode;
@@ -298,11 +299,11 @@ public:
private:
void notifyNodeChange(QSGNode *node, DirtyState state);
- friend class QSGRenderer;
+ friend class QSGAbstractRenderer;
friend class QSGNode;
friend class QSGGeometryNode;
- QList<QSGRenderer *> m_renderers;
+ QList<QSGAbstractRenderer *> m_renderers;
};
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index c056507729..3c9042fee5 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -40,18 +40,9 @@
****************************************************************************/
#include "qsgrenderer_p.h"
-#include "qsgnode.h"
-#include "qsgmaterial.h"
#include "qsgnodeupdater_p.h"
-#include "qsggeometry_p.h"
-
-#include <private/qsgadaptationlayer_p.h>
-#include <private/qsgshadersourcebuilder_p.h>
#include <qopenglframebufferobject.h>
-#include <QtGui/qguiapplication.h>
-
-#include <qdatetime.h>
#include <private/qquickprofiler_p.h>
@@ -63,12 +54,12 @@ static QElapsedTimer frameTimer;
static qint64 preprocessTime;
static qint64 updatePassTime;
-void QSGBindable::clear(QSGRenderer::ClearMode mode) const
+void QSGBindable::clear(QSGAbstractRenderer::ClearMode mode) const
{
GLuint bits = 0;
- if (mode & QSGRenderer::ClearColorBuffer) bits |= GL_COLOR_BUFFER_BIT;
- if (mode & QSGRenderer::ClearDepthBuffer) bits |= GL_DEPTH_BUFFER_BIT;
- if (mode & QSGRenderer::ClearStencilBuffer) bits |= GL_STENCIL_BUFFER_BIT;
+ if (mode & QSGAbstractRenderer::ClearColorBuffer) bits |= GL_COLOR_BUFFER_BIT;
+ if (mode & QSGAbstractRenderer::ClearDepthBuffer) bits |= GL_DEPTH_BUFFER_BIT;
+ if (mode & QSGAbstractRenderer::ClearStencilBuffer) bits |= GL_STENCIL_BUFFER_BIT;
QOpenGLContext::currentContext()->functions()->glClear(bits);
}
@@ -118,18 +109,13 @@ void QSGBindableFboId::bind() const
QSGRenderer::QSGRenderer(QSGRenderContext *context)
- : QObject()
- , m_clear_color(Qt::transparent)
- , m_clear_mode(ClearColorBuffer | ClearDepthBuffer)
- , m_current_opacity(1)
+ : m_current_opacity(1)
, m_current_determinant(1)
, m_device_pixel_ratio(1)
, m_context(context)
- , m_root_node(0)
, m_node_updater(0)
, m_bindable(0)
, m_changed_emitted(false)
- , m_mirrored(false)
, m_is_rendering(false)
{
}
@@ -169,37 +155,30 @@ void QSGRenderer::setNodeUpdater(QSGNodeUpdater *updater)
m_node_updater = updater;
}
-
-void QSGRenderer::setRootNode(QSGRootNode *node)
+bool QSGRenderer::isMirrored() const
{
- if (m_root_node == node)
- return;
- if (m_root_node) {
- m_root_node->m_renderers.removeOne(this);
- nodeChanged(m_root_node, QSGNode::DirtyNodeRemoved);
- }
- m_root_node = node;
- if (m_root_node) {
- Q_ASSERT(!m_root_node->m_renderers.contains(this));
- m_root_node->m_renderers << this;
- nodeChanged(m_root_node, QSGNode::DirtyNodeAdded);
- }
+ QMatrix4x4 matrix = projectionMatrix();
+ // Mirrored relative to the usual Qt coordinate system with origin in the top left corner.
+ return matrix(0, 0) * matrix(1, 1) - matrix(0, 1) * matrix(1, 0) > 0;
}
-
-void QSGRenderer::renderScene()
+void QSGRenderer::renderScene(GLuint fboId)
{
- class B : public QSGBindable
- {
- public:
- void bind() const { QOpenGLFramebufferObject::bindDefault(); }
- } b;
- renderScene(b);
+ if (fboId) {
+ QSGBindableFboId bindable(fboId);
+ renderScene(bindable);
+ } else {
+ class B : public QSGBindable
+ {
+ public:
+ void bind() const { QOpenGLFramebufferObject::bindDefault(); }
+ } bindable;
+ renderScene(bindable);
+ }
}
-
void QSGRenderer::renderScene(const QSGBindable &bindable)
{
- if (!m_root_node)
+ if (!rootNode())
return;
m_is_rendering = true;
@@ -255,30 +234,6 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
}
-void QSGRenderer::setProjectionMatrixToRect(const QRectF &rect)
-{
- QMatrix4x4 matrix;
- matrix.ortho(rect.x(),
- rect.x() + rect.width(),
- rect.y() + rect.height(),
- rect.y(),
- 1,
- -1);
- setProjectionMatrix(matrix);
-}
-
-void QSGRenderer::setProjectionMatrix(const QMatrix4x4 &matrix)
-{
- m_projection_matrix = matrix;
- // Mirrored relative to the usual Qt coordinate system with origin in the top left corner.
- m_mirrored = matrix(0, 0) * matrix(1, 1) - matrix(0, 1) * matrix(1, 0) > 0;
-}
-
-void QSGRenderer::setClearColor(const QColor &color)
-{
- m_clear_color = color;
-}
-
/*!
Updates internal data structures and emits the sceneGraphChanged() signal.
@@ -309,7 +264,8 @@ void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
void QSGRenderer::preprocess()
{
- Q_ASSERT(m_root_node);
+ QSGRootNode *root = rootNode();
+ Q_ASSERT(root);
// We need to take a copy here, in case any of the preprocess calls deletes a node that
// is in the preprocess list and thus, changes the m_nodes_to_preprocess behind our backs
@@ -319,7 +275,7 @@ void QSGRenderer::preprocess()
for (QSet<QSGNode *>::const_iterator it = items.constBegin();
it != items.constEnd(); ++it) {
QSGNode *n = *it;
- if (!nodeUpdater()->isNodeBlocked(n, m_root_node)) {
+ if (!nodeUpdater()->isNodeBlocked(n, root)) {
n->preprocess();
}
}
@@ -328,7 +284,7 @@ void QSGRenderer::preprocess()
if (profileFrames)
preprocessTime = frameTimer.nsecsElapsed();
- nodeUpdater()->updateStates(m_root_node);
+ nodeUpdater()->updateStates(root);
if (profileFrames)
updatePassTime = frameTimer.nsecsElapsed();
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index e24a6b652f..e6e7c13a1d 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -42,54 +42,28 @@
#ifndef QSGRENDERER_P_H
#define QSGRENDERER_P_H
-#include <qcolor.h>
-#include <qset.h>
-#include <qhash.h>
-
+#include "qsgabstractrenderer.h"
+#include "qsgabstractrenderer_p.h"
#include "qsgnode.h"
#include "qsgmaterial.h"
-#include <QtQuick/qsgtexture.h>
#include <QtQuick/private/qsgcontext_p.h>
QT_BEGIN_NAMESPACE
-class QSGMaterialShader;
-struct QSGMaterialType;
-class QOpenGLFramebufferObject;
-class TextureReference;
class QSGBindable;
class QSGNodeUpdater;
Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_fatal_render_error();
Q_QUICK_PRIVATE_EXPORT void qsg_set_fatal_renderer_error();
-class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QObject
+class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QSGAbstractRenderer
{
- Q_OBJECT
public:
- enum ClearModeBit
- {
- ClearColorBuffer = 0x0001,
- ClearDepthBuffer = 0x0002,
- ClearStencilBuffer = 0x0004
- };
- Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
QSGRenderer(QSGRenderContext *context);
virtual ~QSGRenderer();
- void setRootNode(QSGRootNode *node);
- QSGRootNode *rootNode() const { return m_root_node; }
-
- void setDeviceRect(const QRect &rect) { m_device_rect = rect; }
- inline void setDeviceRect(const QSize &size) { setDeviceRect(QRect(QPoint(), size)); }
- QRect deviceRect() const { return m_device_rect; }
-
- void setViewportRect(const QRect &rect) { m_viewport_rect = rect; }
- inline void setViewportRect(const QSize &size) { setViewportRect(QRect(QPoint(), size)); }
- QRect viewportRect() const { return m_viewport_rect; }
-
// Accessed by QSGMaterialShader::RenderState.
QMatrix4x4 currentProjectionMatrix() const { return m_current_projection_matrix; }
QMatrix4x4 currentModelViewMatrix() const { return m_current_model_view_matrix; }
@@ -99,36 +73,22 @@ public:
void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
qreal devicePixelRatio() const { return m_device_pixel_ratio; }
-
- virtual void setProjectionMatrixToRect(const QRectF &rect);
- void setProjectionMatrix(const QMatrix4x4 &matrix);
- QMatrix4x4 projectionMatrix() const { return m_projection_matrix; }
- bool isMirrored() const { return m_mirrored; }
-
- void setClearColor(const QColor &color);
- QColor clearColor() const { return m_clear_color; }
-
QSGRenderContext *context() const { return m_context; }
- void renderScene();
+ bool isMirrored() const;
void renderScene(const QSGBindable &bindable);
- virtual void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
+ virtual void renderScene(GLuint fboId = 0) Q_DECL_FINAL Q_DECL_OVERRIDE;
+ virtual void nodeChanged(QSGNode *node, QSGNode::DirtyState state) Q_DECL_OVERRIDE;
QSGNodeUpdater *nodeUpdater() const;
void setNodeUpdater(QSGNodeUpdater *updater);
inline QSGMaterialShader::RenderState state(QSGMaterialShader::RenderState::DirtyStates dirty) const;
- void setClearMode(ClearMode mode) { m_clear_mode = mode; }
- ClearMode clearMode() const { return m_clear_mode; }
-
virtual void setCustomRenderMode(const QByteArray &) { };
void clearChangedFlag() { m_changed_emitted = false; }
-Q_SIGNALS:
- void sceneGraphChanged(); // Add, remove, ChangeFlags changes...
-
protected:
virtual void render() = 0;
@@ -141,8 +101,6 @@ protected:
void markNodeDirtyState(QSGNode *node, QSGNode::DirtyState state) { node->m_dirtyState |= state; }
- QColor m_clear_color;
- ClearMode m_clear_mode;
QMatrix4x4 m_current_projection_matrix;
QMatrix4x4 m_current_model_view_matrix;
qreal m_current_opacity;
@@ -152,31 +110,22 @@ protected:
QSGRenderContext *m_context;
private:
- QSGRootNode *m_root_node;
QSGNodeUpdater *m_node_updater;
- QRect m_device_rect;
- QRect m_viewport_rect;
-
QSet<QSGNode *> m_nodes_to_preprocess;
- QMatrix4x4 m_projection_matrix;
-
const QSGBindable *m_bindable;
uint m_changed_emitted : 1;
- uint m_mirrored : 1;
uint m_is_rendering : 1;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderer::ClearMode)
-
class Q_QUICK_PRIVATE_EXPORT QSGBindable
{
public:
virtual ~QSGBindable() { }
virtual void bind() const = 0;
- virtual void clear(QSGRenderer::ClearMode mode) const;
+ virtual void clear(QSGAbstractRenderer::ClearMode mode) const;
virtual void reactivate() const;
};
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 1a3565b630..5bc91992e9 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -363,6 +363,7 @@ QSGRenderContext::QSGRenderContext(QSGContext *context)
, m_distanceFieldCacheManager(0)
, m_brokenIBOs(false)
, m_serializedRender(false)
+ , m_attachToGLContext(true)
{
}
@@ -384,12 +385,7 @@ void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
if (m_serializedRender)
qsg_framerender_mutex.lock();
- if (fboId) {
- QSGBindableFboId bindable(fboId);
- renderer->renderScene(bindable);
- } else {
- renderer->renderScene();
- }
+ renderer->renderScene(fboId);
if (m_serializedRender)
qsg_framerender_mutex.unlock();
@@ -441,6 +437,12 @@ QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRaw
return cache;
}
+void QSGRenderContext::setAttachToGLContext(bool attach)
+{
+ Q_ASSERT(!isValid());
+ m_attachToGLContext = attach;
+}
+
#define QSG_RENDERCONTEXT_PROPERTY "_q_sgrendercontext"
QSGRenderContext *QSGRenderContext::from(QOpenGLContext *context)
@@ -473,7 +475,10 @@ void QSGRenderContext::initialize(QOpenGLContext *context)
Q_ASSERT_X(!m_gl, "QSGRenderContext::initialize", "already initialized!");
m_gl = context;
- m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant::fromValue(this));
+ if (m_attachToGLContext) {
+ Q_ASSERT(!context->property(QSG_RENDERCONTEXT_PROPERTY).isValid());
+ context->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant::fromValue(this));
+ }
m_sg->renderContextInitialized(this);
#ifdef Q_OS_LINUX
@@ -541,7 +546,8 @@ void QSGRenderContext::invalidate()
delete m_distanceFieldCacheManager;
m_distanceFieldCacheManager = 0;
- m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant());
+ if (m_gl->property(QSG_RENDERCONTEXT_PROPERTY) == QVariant::fromValue(this))
+ m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant());
m_gl = 0;
m_sg->renderContextInvalidated(this);
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index faad57b893..7113ef8530 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -97,6 +97,7 @@ public:
QOpenGLContext *openglContext() const { return m_gl; }
QSGContext *sceneGraphContext() const { return m_sg; }
+ bool isValid() const { return m_gl; }
virtual void initialize(QOpenGLContext *context);
virtual void invalidate();
@@ -117,6 +118,7 @@ public:
virtual void compile(QSGMaterialShader *shader, QSGMaterial *material, const char *vertexCode = 0, const char *fragmentCode = 0);
virtual void initialize(QSGMaterialShader *shader);
+ void setAttachToGLContext(bool attach);
void registerFontengineForCleanup(QFontEngine *engine);
static QSGRenderContext *from(QOpenGLContext *context);
@@ -146,6 +148,7 @@ protected:
bool m_brokenIBOs;
bool m_serializedRender;
+ bool m_attachToGLContext;
};
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 570d6b92b5..d08fce0336 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -10,12 +10,15 @@ HEADERS += \
$$PWD/coreapi/qsgnode.h \
$$PWD/coreapi/qsgnode_p.h \
$$PWD/coreapi/qsgnodeupdater_p.h \
+ $$PWD/coreapi/qsgabstractrenderer.h \
+ $$PWD/coreapi/qsgabstractrenderer_p.h \
$$PWD/coreapi/qsgrenderer_p.h \
$$PWD/coreapi/qsgrendernode_p.h \
$$PWD/coreapi/qsggeometry_p.h \
$$PWD/coreapi/qsgmaterialshader_p.h
SOURCES += \
+ $$PWD/coreapi/qsgabstractrenderer.cpp \
$$PWD/coreapi/qsgbatchrenderer.cpp \
$$PWD/coreapi/qsggeometry.cpp \
$$PWD/coreapi/qsgmaterial.cpp \
@@ -30,6 +33,8 @@ HEADERS += \
$$PWD/util/qsgareaallocator_p.h \
$$PWD/util/qsgatlastexture_p.h \
$$PWD/util/qsgdepthstencilbuffer_p.h \
+ $$PWD/util/qsgengine.h \
+ $$PWD/util/qsgengine_p.h \
$$PWD/util/qsgflatcolormaterial.h \
$$PWD/util/qsgsimplematerial.h \
$$PWD/util/qsgsimplerectnode.h \
@@ -48,6 +53,7 @@ SOURCES += \
$$PWD/util/qsgareaallocator.cpp \
$$PWD/util/qsgatlastexture.cpp \
$$PWD/util/qsgdepthstencilbuffer.cpp \
+ $$PWD/util/qsgengine.cpp \
$$PWD/util/qsgflatcolormaterial.cpp \
$$PWD/util/qsgsimplerectnode.cpp \
$$PWD/util/qsgsimpletexturenode.cpp \
diff --git a/src/quick/scenegraph/util/qsgengine.cpp b/src/quick/scenegraph/util/qsgengine.cpp
new file mode 100644
index 0000000000..127f624d8b
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine.cpp
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgengine_p.h"
+
+#include <QtQuick/qsgtexture.h>
+#include <private/qsgcontext_p.h>
+#include <private/qsgrenderer_p.h>
+#include <private/qsgtexture_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \class QSGEngine
+ \brief The QSGEngine class allows low level rendering of a scene graph.
+ \inmodule QtQuick
+ \since 5.4
+
+ A QSGEngine can be used to render a tree of QSGNode directly on a QWindow
+ or QOpenGLFramebufferObject without any integration with QML, QQuickWindow
+ or QQuickItem and the convenience that they provide.
+
+ This means that you must handle event propagation, animation timing,
+ and node lifetime yourself.
+
+ \note This class is for very low level access to an independent scene graph.
+ Most of the time you will instead want to subclass QQuickItem and insert
+ your QSGNode in a normal QtQuick scene by overriding QQuickItem::updatePaintNode().
+
+ \sa QSGAbstractRenderer
+ */
+
+/*!
+ \enum QSGEngine::CreateTextureOption
+
+ The CreateTextureOption enums are used to customize how a texture is wrapped.
+
+ \value TextureHasAlphaChannel The texture has an alpha channel and should
+ be drawn using blending.
+
+ \value TextureOwnsGLTexture The texture object owns the texture id and
+ will delete the GL texture when the texture object is deleted.
+
+ \value TextureCanUseAtlas The image can be uploaded into a texture atlas.
+ */
+
+QSGEnginePrivate::QSGEnginePrivate()
+ : sgContext(QSGContext::createDefaultContext())
+ , sgRenderContext(new QSGRenderContext(sgContext.data()))
+{
+}
+
+/*!
+ Constructs a new QSGEngine with its \a parent
+ */
+QSGEngine::QSGEngine(QObject *parent)
+ : QObject(*(new QSGEnginePrivate), parent)
+{
+}
+
+/*!
+ Destroys the engine
+ */
+QSGEngine::~QSGEngine()
+{
+}
+
+/*!
+ Initialize the engine with \a context.
+
+ \warning You have to make sure that you call
+ QOpenGLContext::makeCurrent() on \a context before calling this.
+ */
+void QSGEngine::initialize(QOpenGLContext *context)
+{
+ Q_D(QSGEngine);
+ if (QOpenGLContext::currentContext() != context) {
+ qWarning("WARNING: The context must be current before calling QSGEngine::initialize.");
+ return;
+ }
+
+ if (!d->sgRenderContext->isValid()) {
+ d->sgRenderContext->setAttachToGLContext(false);
+ d->sgRenderContext->initialize(context);
+ connect(context, &QOpenGLContext::aboutToBeDestroyed, this, &QSGEngine::invalidate);
+ }
+}
+
+/*!
+ Invalidate the engine releasing its resources
+
+ You will have to call initialize() and createRenderer() if you
+ want to use it again.
+ */
+void QSGEngine::invalidate()
+{
+ Q_D(QSGEngine);
+ d->sgRenderContext->invalidate();
+}
+
+/*!
+ Returns a renderer that can be used to render a QSGNode tree
+
+ You call initialize() first with the QOpenGLContext that you
+ want to use with this renderer. This will return a null
+ renderer otherwise.
+ */
+QSGAbstractRenderer *QSGEngine::createRenderer() const
+{
+ Q_D(const QSGEngine);
+ if (!d->sgRenderContext->isValid())
+ return 0;
+
+ QSGRenderer *renderer = d->sgRenderContext->createRenderer();
+ renderer->setCustomRenderMode(qgetenv("QSG_VISUALIZE"));
+ return renderer;
+}
+
+/*!
+ Creates a texture using the data of \a image
+
+ Valid \a options are TextureCanUseAtlas
+
+ The caller takes ownership of the texture and the
+ texture should only be used with this engine.
+
+ \sa createTextureFromId(), QSGSimpleTextureNode::setOwnsTexture(), QQuickWindow::createTextureFromImage()
+ */
+QSGTexture *QSGEngine::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
+{
+ Q_D(const QSGEngine);
+ if (!d->sgRenderContext->isValid())
+ return 0;
+
+ if (options & TextureCanUseAtlas)
+ return d->sgRenderContext->createTexture(image);
+ else
+ return d->sgRenderContext->createTextureNoAtlas(image);
+}
+
+/*!
+ Creates a texture object that wraps the GL texture \a id uploaded with \a size
+
+ Valid \a options are TextureHasAlphaChannel and TextureOwnsGLTexture
+
+ The caller takes ownership of the texture object and the
+ texture should only be used with this engine.
+
+ \sa createTextureFromImage(), QSGSimpleTextureNode::setOwnsTexture(), QQuickWindow::createTextureFromId()
+ */
+QSGTexture *QSGEngine::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const
+{
+ Q_D(const QSGEngine);
+ if (d->sgRenderContext->isValid()) {
+ QSGPlainTexture *texture = new QSGPlainTexture();
+ texture->setTextureId(id);
+ texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
+ texture->setOwnsTexture(options & TextureOwnsGLTexture);
+ texture->setTextureSize(size);
+ return texture;
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgengine.h b/src/quick/scenegraph/util/qsgengine.h
new file mode 100644
index 0000000000..7aae882a70
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGENGINE_H
+#define QSGENGINE_H
+
+#include <QtCore/QObject>
+#include <QtQuick/qtquickglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QSGAbstractRenderer;
+class QSGEnginePrivate;
+class QSGTexture;
+
+class Q_QUICK_EXPORT QSGEngine : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGEngine)
+public:
+ enum CreateTextureOption {
+ TextureHasAlphaChannel = 0x0001,
+ TextureOwnsGLTexture = 0x0004,
+ TextureCanUseAtlas = 0x0008
+ };
+ Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption)
+
+ QSGEngine(QObject *parent = 0);
+ ~QSGEngine();
+
+ void initialize(QOpenGLContext *context);
+ void invalidate();
+
+ QSGAbstractRenderer *createRenderer() const;
+ QSGTexture *createTextureFromImage(const QImage &image, CreateTextureOptions options = CreateTextureOption(0)) const;
+ QSGTexture *createTextureFromId(uint id, const QSize &size, CreateTextureOptions options = CreateTextureOption(0)) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGENGINE_H
diff --git a/src/quick/scenegraph/util/qsgengine_p.h b/src/quick/scenegraph/util/qsgengine_p.h
new file mode 100644
index 0000000000..a7e1599fd5
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgengine_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGENGINE_P_H
+#define QSGENGINE_P_H
+
+#include "qsgengine.h"
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGContext;
+class QSGRenderContext;
+
+class QSGEnginePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSGEngine)
+
+public:
+ QSGEnginePrivate();
+
+ QScopedPointer<QSGContext> sgContext;
+ QScopedPointer<QSGRenderContext> sgRenderContext;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGENGINE_P_H