diff options
Diffstat (limited to 'src/quick/scenegraph')
17 files changed, 160 insertions, 28 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp index 94e9c81f70..80112c1121 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp @@ -53,6 +53,7 @@ #include <QtCore/QElapsedTimer> #include <QtGui/QWindow> +#include <QtQuick/private/qquickwindow_p.h> // Used for very high-level info about the renderering and gl context // Includes GL_VERSION, type of render loop, atlas size, etc. @@ -82,8 +83,10 @@ QT_BEGIN_NAMESPACE QSGSoftwareRenderContext::QSGSoftwareRenderContext(QSGContext *ctx) : QSGRenderContext(ctx) , m_initialized(false) + , m_activePainter(nullptr) { } + QSGSoftwareContext::QSGSoftwareContext(QObject *parent) : QSGContext(parent) { @@ -206,4 +209,12 @@ QSGRendererInterface::ShaderSourceTypes QSGSoftwareContext::shaderSourceType() c return 0; } +void *QSGSoftwareContext::getResource(QQuickWindow *window, Resource resource) const +{ + if (resource == Painter && window && window->isSceneGraphInitialized()) + return static_cast<QSGSoftwareRenderContext *>(QQuickWindowPrivate::get(window)->context)->m_activePainter; + + return nullptr; +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h index 3c3686c268..dcc137b4b4 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h @@ -78,6 +78,7 @@ public: int maxTextureSize() const override; bool m_initialized; + QPainter *m_activePainter; }; class QSGSoftwareContext : public QSGContext, public QSGRendererInterface @@ -103,6 +104,7 @@ public: ShaderType shaderType() const override; ShaderCompilationTypes shaderCompilationType() const override; ShaderSourceTypes shaderSourceType() const override; + void *getResource(QQuickWindow *window, Resource resource) const override; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp index 304106a84d..f8c1a3d90b 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qsgsoftwarepixmaprenderer_p.h" +#include "qsgsoftwarecontext_p.h" #include <QtQuick/QSGSimpleRectNode> @@ -84,6 +85,9 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target) QPainter painter(target); painter.setRenderHint(QPainter::Antialiasing); painter.setWindow(m_projectionRect); + auto rc = static_cast<QSGSoftwareRenderContext *>(context()); + QPainter *prevPainter = rc->m_activePainter; + rc->m_activePainter = &painter; renderTimer.start(); buildRenderList(); @@ -100,6 +104,7 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target) QRegion paintedRegion = renderNodes(&painter); qint64 renderTime = renderTimer.elapsed(); + rc->m_activePainter = prevPainter; qCDebug(lcPixmapRenderer) << "pixmapRender" << paintedRegion << buildRenderListTime << optimizeRenderListTime << renderTime; } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index 1b2a836dfa..032a06f946 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -47,8 +47,9 @@ #include "qsgsoftwarepixmaptexture_p.h" #include "qsgsoftwarespritenode_p.h" -#include <QtQuick/QSGSimpleRectNode> -#include <QtQuick/qsgsimpletexturenode.h> +#include <qsgsimplerectnode.h> +#include <qsgsimpletexturenode.h> +#include <private/qsgrendernode_p.h> #include <private/qsgtexture_p.h> Q_LOGGING_CATEGORY(lcRenderable, "qt.scenegraph.softwarecontext.renderable") @@ -93,6 +94,9 @@ QSGSoftwareRenderableNode::QSGSoftwareRenderableNode(NodeType type, QSGNode *nod case QSGSoftwareRenderableNode::SpriteNode: m_handle.spriteNode = static_cast<QSGSoftwareSpriteNode*>(node); break; + case QSGSoftwareRenderableNode::RenderNode: + m_handle.renderNode = static_cast<QSGRenderNode*>(node); + break; case QSGSoftwareRenderableNode::Invalid: m_handle.simpleRectNode = nullptr; break; @@ -182,6 +186,8 @@ void QSGSoftwareRenderableNode::update() m_isOpaque = m_handle.spriteNode->isOpaque(); boundingRect = m_handle.spriteNode->rect().toRect(); break; + case QSGSoftwareRenderableNode::RenderNode: + break; default: break; } @@ -203,15 +209,50 @@ void QSGSoftwareRenderableNode::update() m_dirtyRegion = QRegion(m_boundingRect); } +struct RenderNodeState : public QSGRenderNode::RenderState +{ + const QMatrix4x4 *projectionMatrix() const override { return &ident; } + QRect scissorRect() const { return QRect(); } + bool scissorEnabled() const { return false; } + int stencilValue() const { return 0; } + bool stencilEnabled() const { return false; } + const QRegion *clipRegion() const { return &cr; } + QMatrix4x4 ident; + QRegion cr; +}; + QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaquePainting) { Q_ASSERT(painter); // Check for don't paint conditions - if (!m_isDirty || qFuzzyIsNull(m_opacity) || m_dirtyRegion.isEmpty()) { - m_isDirty = false; - m_dirtyRegion = QRegion(); - return QRegion(); + if (m_nodeType != RenderNode) { + if (!m_isDirty || qFuzzyIsNull(m_opacity) || m_dirtyRegion.isEmpty()) { + m_isDirty = false; + m_dirtyRegion = QRegion(); + return QRegion(); + } + } else { + if (!m_isDirty || qFuzzyIsNull(m_opacity)) { + m_isDirty = false; + m_dirtyRegion = QRegion(); + return QRegion(); + } else { + QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(m_handle.renderNode); + QMatrix4x4 m = m_transform; + rd->m_matrix = &m; + rd->m_opacity = m_opacity; + RenderNodeState rs; + rs.cr = m_clipRegion; + painter->save(); + m_handle.renderNode->render(&rs); + painter->restore(); + const QRect fullRect = QRect(0, 0, painter->device()->width(), painter->device()->height()); + m_previousDirtyRegion = fullRect; + m_isDirty = false; + m_dirtyRegion = QRegion(); + return fullRect; + } } painter->save(); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h index dc224be2c0..0626b1e657 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h @@ -68,6 +68,7 @@ class QSGSoftwareInternalRectangleNode; class QSGSoftwareGlyphNode; class QSGSoftwareNinePatchNode; class QSGSoftwareSpriteNode; +class QSGRenderNode; class QSGSoftwareRenderableNode { @@ -83,7 +84,8 @@ public: NinePatch, SimpleRectangle, SimpleImage, - SpriteNode + SpriteNode, + RenderNode }; QSGSoftwareRenderableNode(NodeType type, QSGNode *node); @@ -126,6 +128,7 @@ private: QSGRectangleNode *simpleRectangleNode; QSGImageNode *simpleImageNode; QSGSoftwareSpriteNode *spriteNode; + QSGRenderNode *renderNode; }; const NodeType m_nodeType; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp index cb866bec12..82f8623b74 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp @@ -47,8 +47,9 @@ #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" -#include <QtQuick/QSGSimpleRectNode> +#include <QtQuick/qsgsimplerectnode.h> #include <QtQuick/qsgsimpletexturenode.h> +#include <QtQuick/qsgrendernode.h> QT_BEGIN_NAMESPACE @@ -190,6 +191,15 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGSpriteNode *) } +bool QSGSoftwareRenderableNodeUpdater::visit(QSGRenderNode *node) +{ + return updateRenderableNode(QSGSoftwareRenderableNode::RenderNode, node); +} + +void QSGSoftwareRenderableNodeUpdater::endVisit(QSGRenderNode *) +{ +} + void QSGSoftwareRenderableNodeUpdater::updateNodes(QSGNode *node, bool isNodeRemoved) { m_opacityState.clear(); @@ -269,6 +279,13 @@ void QSGSoftwareRenderableNodeUpdater::updateNodes(QSGNode *node, bool isNodeRem visitChildren(node); break; } + case QSGNode::RenderNodeType: { + QSGRenderNode *r = static_cast<QSGRenderNode*>(node); + if (visit(r)) + visitChildren(r); + endVisit(r); + break; + } default: Q_UNREACHABLE(); break; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h index 5bc241cce1..f204867236 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h @@ -88,6 +88,8 @@ public: void endVisit(QSGRootNode *) override; bool visit(QSGSpriteNode *) override; void endVisit(QSGSpriteNode *) override; + bool visit(QSGRenderNode *) override; + void endVisit(QSGRenderNode *) override; void updateNodes(QSGNode *node, bool isNodeRemoved = false); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp index 257009472e..ae89ed7d8a 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp @@ -138,6 +138,9 @@ void QSGSoftwareRenderer::render() QPainter painter(m_paintDevice); painter.setRenderHint(QPainter::Antialiasing); + auto rc = static_cast<QSGSoftwareRenderContext *>(context()); + QPainter *prevPainter = rc->m_activePainter; + rc->m_activePainter = &painter; // Render the contents Renderlist m_flushRegion = renderNodes(&painter); @@ -146,6 +149,7 @@ void QSGSoftwareRenderer::render() if (m_backingStore != nullptr) m_backingStore->endPaint(); + rc->m_activePainter = prevPainter; qCDebug(lcRenderer) << "render" << m_flushRegion << buildRenderListTime << optimizeRenderListTime << renderTime; } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp index ac00127b35..4e34517dad 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp @@ -48,8 +48,9 @@ #include "qsgsoftwarepainternode_p.h" #include "qsgsoftwarepixmaptexture_p.h" -#include <QtQuick/QSGSimpleRectNode> +#include <QtQuick/qsgsimplerectnode.h> #include <QtQuick/qsgsimpletexturenode.h> +#include <QtQuick/qsgrendernode.h> QT_BEGIN_NAMESPACE @@ -150,6 +151,15 @@ void QSGSoftwareRenderListBuilder::endVisit(QSGSpriteNode *) } +bool QSGSoftwareRenderListBuilder::visit(QSGRenderNode *node) +{ + return addRenderableNode(node); +} + +void QSGSoftwareRenderListBuilder::endVisit(QSGRenderNode *) +{ +} + bool QSGSoftwareRenderListBuilder::addRenderableNode(QSGNode *node) { auto renderableNode = m_renderer->renderableNode(node); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h index e34cc81e23..807cb7fdbe 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h @@ -82,6 +82,8 @@ public: void endVisit(QSGRootNode *) override; bool visit(QSGSpriteNode *) override; void endVisit(QSGSpriteNode *) override; + bool visit(QSGRenderNode *) override; + void endVisit(QSGRenderNode *) override; private: bool addRenderableNode(QSGNode *node); diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index d45a0ea75d..bee2015007 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -2768,6 +2768,7 @@ struct RenderNodeState : public QSGRenderNode::RenderState bool scissorEnabled() const override { return m_scissorEnabled; } int stencilValue() const override { return m_stencilValue; } bool stencilEnabled() const override { return m_stencilEnabled; } + const QRegion *clipRegion() const override { return nullptr; } const QMatrix4x4 *m_projectionMatrix; QRect m_scissorRect; diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp index 04e71441f6..fa543aecad 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp @@ -81,9 +81,10 @@ QT_BEGIN_NAMESPACE /*! \enum QSGRendererInterface::Resource - \value Device The graphics device - \value CommandQueue The graphics command queue used by the scenergaph - \value CommandList The command list or buffer used by the scenegraph + \value Device The graphics device, when applicable. + \value CommandQueue The graphics command queue used by the scenegraph, when applicable. + \value CommandList The command list or buffer used by the scenegraph, when applicable. + \value Painter The active QPainter used by the scenegraph, when running with the software backend. */ /*! @@ -134,10 +135,13 @@ QSGRendererInterface::~QSGRendererInterface() example, \c{VkDevice dev = *static_cast<VkDevice *>(result)}). The latter is necessary since such handles may have sizes different from a pointer. + \note The ownership of the returned pointer is never transferred to the caller. + \note This function must only be called on the render thread. */ -void *QSGRendererInterface::getResource(Resource resource) const +void *QSGRendererInterface::getResource(QQuickWindow *window, Resource resource) const { + Q_UNUSED(window); Q_UNUSED(resource); return nullptr; } @@ -147,10 +151,13 @@ void *QSGRendererInterface::getResource(Resource resource) const allows supporting any future resources that are not listed in the Resource enum. + \note The ownership of the returned pointer is never transferred to the caller. + \note This function must only be called on the render thread. */ -void *QSGRendererInterface::getResource(const char *resource) const +void *QSGRendererInterface::getResource(QQuickWindow *window, const char *resource) const { + Q_UNUSED(window); Q_UNUSED(resource); return nullptr; } diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h index 234a061d0e..a50b362aeb 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.h +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h @@ -44,6 +44,8 @@ QT_BEGIN_NAMESPACE +class QQuickWindow; + class Q_QUICK_EXPORT QSGRendererInterface { public: @@ -57,7 +59,8 @@ public: enum Resource { Device, CommandQueue, - CommandList + CommandList, + Painter }; enum ShaderType { @@ -83,8 +86,8 @@ public: virtual GraphicsApi graphicsApi() const = 0; - virtual void *getResource(Resource resource) const; - virtual void *getResource(const char *resource) const; + virtual void *getResource(QQuickWindow *window, Resource resource) const; + virtual void *getResource(QQuickWindow *window, const char *resource) const; virtual ShaderType shaderType() const = 0; virtual ShaderCompilationTypes shaderCompilationType() const = 0; diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp index 29e8251cb2..365abd09e2 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp @@ -111,6 +111,10 @@ QSGRenderNodePrivate::QSGRenderNodePrivate() call related settings (root signature, descriptor heaps, etc.) are always set again by the scenegraph so render() can freely change them. + The software backend exposes its QPainter and saves and restores before and + after invoking render(). Therefore reporting any changed states from here + is not necessary. + \note This function may be called before render(). */ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const @@ -125,17 +129,6 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const directly invoking commands in the graphics API (OpenGL, Direct3D, etc.) currently in use. - The states necessary for clipping has already been set before the function - is called. The clip is a combination of a stencil clip and scissor clip. - Information about the clip is found in \a state. - - \note This means that setting viewport, scissor rectangle, stencil - reference value, and similar is not necessary in render() since the - corresponding commands are on the command list (or, in case of OpenGL, the - context) already. However, for APIs other than OpenGL stencil-based - clipping will need enabling stencil testing in the pipeline state that is - used by render(). - The effective opacity can be retrieved with \l inheritedOpacity(). The projection matrix is available through \a state, while the model-view @@ -156,6 +149,12 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const QQuickFramebufferObject, QQuickWindow::beforeRendering(), or the equivalents of those for APIs other than OpenGL. + Clip information is calculated before the function is called, it is however + not enabled. Implementations wishing to take clipping into account can set + up scissoring or stencil based on the information in \a state. Some + scenegraph backends, software in particular, use no scissor or stencil. + There the clip region is provided as an ordinary QRegion. + For OpenGL the following states are set on the render thread's context before this function is called: \list @@ -287,6 +286,19 @@ QSGRenderNode::RenderState::~RenderState() */ /*! + \fn const QRegion *QSGRenderNode::clipRegion() const + + \return the current clip region or null for backends where clipping is + implemented via stencil or scissoring. + + The software backend uses no projection, scissor or stencil, meaning most + of the render state is not in use. However, the clip region that can be set + on the QPainter still has to be communicated since reconstructing this + manually in render() is not reasonable. It can therefore be queried via + this function. + */ + +/*! \return pointer to a \a state value. Reserved for future use. diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.h b/src/quick/scenegraph/coreapi/qsgrendernode.h index 17569f8c59..6eb425c03b 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode.h +++ b/src/quick/scenegraph/coreapi/qsgrendernode.h @@ -68,6 +68,7 @@ public: virtual bool scissorEnabled() const = 0; virtual int stencilValue() const = 0; virtual bool stencilEnabled() const = 0; + virtual const QRegion *clipRegion() const = 0; virtual void *get(const char *state) const; }; diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 9574f2a48e..e219ddd82e 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -46,6 +46,7 @@ #include <private/qrawfont_p.h> #include <QtGui/qguiapplication.h> #include <qdir.h> +#include <qsgrendernode.h> #include <private/qquickprofiler_p.h> #include <QElapsedTimer> @@ -512,6 +513,13 @@ void QSGNodeVisitorEx::visitChildren(QSGNode *node) visitChildren(child); break; } + case QSGNode::RenderNodeType: { + QSGRenderNode *r = static_cast<QSGRenderNode*>(child); + if (visit(r)) + visitChildren(r); + endVisit(r); + break; + } default: Q_UNREACHABLE(); break; diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 00441e1544..a74b38dba8 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -82,6 +82,7 @@ class QSGInternalRectangleNode; class QSGGlyphNode; class QSGRootNode; class QSGSpriteNode; +class QSGRenderNode; class Q_QUICK_PRIVATE_EXPORT QSGNodeVisitorEx { @@ -109,6 +110,8 @@ public: virtual void endVisit(QSGRootNode *) = 0; virtual bool visit(QSGSpriteNode *) = 0; virtual void endVisit(QSGSpriteNode *) = 0; + virtual bool visit(QSGRenderNode *) = 0; + virtual void endVisit(QSGRenderNode *) = 0; void visitChildren(QSGNode *node); }; |