diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 4 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgabstractrenderer.cpp | 318 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgabstractrenderer.h | 103 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgabstractrenderer_p.h | 77 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgnode.h | 5 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrenderer.cpp | 96 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrenderer_p.h | 65 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext.cpp | 22 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext_p.h | 3 | ||||
-rw-r--r-- | src/quick/scenegraph/scenegraph.pri | 6 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgengine.cpp | 204 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgengine.h | 80 | ||||
-rw-r--r-- | src/quick/scenegraph/util/qsgengine_p.h | 66 |
13 files changed, 909 insertions, 140 deletions
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 |