aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2016-07-15 13:43:08 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2016-07-19 10:40:55 +0000
commit4cb2552313280384b59ee1e7d7fc557c7bd64a68 (patch)
tree1a6bf0e0abd9a6d952d2d4ab72f20f71e13ba79b
parentb4fc940978e7995e75f17a5386c30ef42333bd38 (diff)
software: Add support for QSGRenderNode
Have to change getResource() a bit since it turns out it is not suitable currently for backends that do not have a per-window rendercontext and do not implement the interface on the rendercontext. Pass in the window to make sure it can always figure out which window we want the resources for. (we do not want rendererInterface() to return window-specific instances created on the fly, with ownership issues, so stick with the simple model where backends implement the interface on one of their existing classes) To support clipping, QSGRenderNode::RenderState is extended accordingly. Also updated the docs since some claims in the rendernode docs are not true since Qt 5.3. Change-Id: I34779c83926f5231b888fcab7131e873ae97964f Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--examples/quick/scenegraph/rendernode/customrenderitem.cpp5
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.cpp4
-rw-r--r--examples/quick/scenegraph/rendernode/main.qml5
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.cpp4
-rw-r--r--examples/quick/scenegraph/rendernode/rendernode.pro4
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.cpp91
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.h62
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp6
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp1
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp6
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp11
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp53
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h5
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp19
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp4
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder.cpp12
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderlistbuilder_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp1
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.cpp17
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendererinterface.h9
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp34
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.h1
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp8
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h3
31 files changed, 344 insertions, 40 deletions
diff --git a/examples/quick/scenegraph/rendernode/customrenderitem.cpp b/examples/quick/scenegraph/rendernode/customrenderitem.cpp
index 433f3c5a1e..2465f4cbc7 100644
--- a/examples/quick/scenegraph/rendernode/customrenderitem.cpp
+++ b/examples/quick/scenegraph/rendernode/customrenderitem.cpp
@@ -44,6 +44,7 @@
#include "openglrenderer.h"
#include "d3d12renderer.h"
+#include "softwarerenderer.h"
CustomRenderItem::CustomRenderItem(QQuickItem *parent)
: QQuickItem(parent)
@@ -70,6 +71,10 @@ QSGNode *CustomRenderItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
n = new D3D12RenderNode(this);
break;
#endif
+ case QSGRendererInterface::Software:
+ n = new SoftwareRenderNode(this);
+ break;
+
default:
return nullptr;
}
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
index b7dc62fe86..f475ec838b 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
@@ -78,7 +78,7 @@ void D3D12RenderNode::releaseResources()
void D3D12RenderNode::init()
{
QSGRendererInterface *rif = m_item->window()->rendererInterface();
- m_device = static_cast<ID3D12Device *>(rif->getResource(QSGRendererInterface::Device));
+ m_device = static_cast<ID3D12Device *>(rif->getResource(m_item->window(), QSGRendererInterface::Device));
Q_ASSERT(m_device);
D3D12_ROOT_PARAMETER rootParameter;
@@ -235,7 +235,7 @@ void D3D12RenderNode::render(const RenderState *state)
init();
QSGRendererInterface *rif = m_item->window()->rendererInterface();
- ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(rif->getResource(QSGRendererInterface::CommandList));
+ ID3D12GraphicsCommandList *commandList = static_cast<ID3D12GraphicsCommandList *>(rif->getResource(m_item->window(), QSGRendererInterface::CommandList));
Q_ASSERT(commandList);
const int msize = 16 * sizeof(float);
diff --git a/examples/quick/scenegraph/rendernode/main.qml b/examples/quick/scenegraph/rendernode/main.qml
index a91656dfaa..7c8d82181f 100644
--- a/examples/quick/scenegraph/rendernode/main.qml
+++ b/examples/quick/scenegraph/rendernode/main.qml
@@ -90,7 +90,10 @@ Item {
anchors.margins: 20
wrapMode: Text.WordWrap
property int api: GraphicsInfo.api
- text: "Custom rendering via the graphics API " + (api === GraphicsInfo.OpenGL ? "OpenGL" : (api === GraphicsInfo.Direct3D12 ? "Direct3D 12" : ""))
+ text: "Custom rendering via the graphics API "
+ + (api === GraphicsInfo.OpenGL ? "OpenGL"
+ : api === GraphicsInfo.Direct3D12 ? "Direct3D 12"
+ : api === GraphicsInfo.Software ? "Software" : "")
color: "yellow"
}
}
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
index 3eff70cb42..33c59198b8 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
@@ -97,8 +97,6 @@ void OpenGLRenderNode::init()
const int VERTEX_SIZE = 6 * sizeof(GLfloat);
- // A fully featured renderer should also take inheritedOpacity() into account
- // and blend, but ignore that for now.
static GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
@@ -140,6 +138,8 @@ void OpenGLRenderNode::render(const RenderState *state)
m_program->enableAttributeArray(0);
m_program->enableAttributeArray(1);
+ // Note that clipping (scissor or stencil) is ignored in this example.
+
f->glEnable(GL_BLEND);
f->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
diff --git a/examples/quick/scenegraph/rendernode/rendernode.pro b/examples/quick/scenegraph/rendernode/rendernode.pro
index d7ae715a7d..851d5927bd 100644
--- a/examples/quick/scenegraph/rendernode/rendernode.pro
+++ b/examples/quick/scenegraph/rendernode/rendernode.pro
@@ -1,10 +1,12 @@
QT += qml quick
HEADERS += customrenderitem.h \
- openglrenderer.h
+ openglrenderer.h \
+ softwarerenderer.h
SOURCES += customrenderitem.cpp \
openglrenderer.cpp \
+ softwarerenderer.cpp \
main.cpp
RESOURCES += rendernode.qrc
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
new file mode 100644
index 0000000000..2f11c56f29
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd 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 "softwarerenderer.h"
+#include <QQuickItem>
+#include <QQuickWindow>
+#include <QSGRendererInterface>
+#include <QPainter>
+
+SoftwareRenderNode::SoftwareRenderNode(QQuickItem *item)
+ : m_item(item)
+{
+}
+
+SoftwareRenderNode::~SoftwareRenderNode()
+{
+ releaseResources();
+}
+
+void SoftwareRenderNode::releaseResources()
+{
+}
+
+void SoftwareRenderNode::render(const RenderState *renderState)
+{
+ QSGRendererInterface *rif = m_item->window()->rendererInterface();
+ QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::Painter));
+ Q_ASSERT(p);
+
+ p->setTransform(matrix()->toTransform());
+ p->setOpacity(inheritedOpacity());
+ const QRegion *clipRegion = renderState->clipRegion();
+ if (clipRegion && !clipRegion->isEmpty())
+ p->setClipRegion(*clipRegion);
+
+ const QPointF p0(m_item->width() - 1, m_item->height() - 1);
+ const QPointF p1(0, 0);
+ const QPointF p2(0, m_item->height() - 1);
+ QPainterPath path(p0);
+ path.lineTo(p1);
+ path.lineTo(p2);
+ path.closeSubpath();
+
+ QLinearGradient gradient(QPointF(0, 0), QPointF(m_item->width(), m_item->height()));
+ gradient.setColorAt(0, Qt::green);
+ gradient.setColorAt(1, Qt::red);
+
+ p->fillPath(path, gradient);
+}
+
+QSGRenderNode::StateFlags SoftwareRenderNode::changedStates() const
+{
+ return 0;
+}
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.h b/examples/quick/scenegraph/rendernode/softwarerenderer.h
new file mode 100644
index 0000000000..60036f96a1
--- /dev/null
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** 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 The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SOFTWARERENDERER_H
+#define SOFTWARERENDERER_H
+
+#include <qsgrendernode.h>
+
+class QQuickItem;
+
+class SoftwareRenderNode : public QSGRenderNode
+{
+public:
+ SoftwareRenderNode(QQuickItem *item);
+ ~SoftwareRenderNode();
+
+ void render(const RenderState *state) override;
+ void releaseResources() override;
+ StateFlags changedStates() const override;
+
+private:
+ QQuickItem *m_item;
+};
+
+#endif
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
index 43f765cd38..eab762f7c1 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
@@ -549,7 +549,7 @@ void QSGD3D12Engine::simulateDeviceLoss()
d->simulateDeviceLoss();
}
-void *QSGD3D12Engine::getResource(QSGRendererInterface::Resource resource) const
+void *QSGD3D12Engine::getResource(QQuickWindow *, QSGRendererInterface::Resource resource) const
{
return d->getResource(resource);
}
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h
index 72007b96db..46cd73e63a 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine_p.h
@@ -372,7 +372,7 @@ public:
void simulateDeviceLoss();
- void *getResource(QSGRendererInterface::Resource resource) const;
+ void *getResource(QQuickWindow *window, QSGRendererInterface::Resource resource) const;
private:
QSGD3D12EnginePrivate *d;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp
index 09129c954d..4ee4656e63 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext.cpp
@@ -141,14 +141,14 @@ QSGRendererInterface::GraphicsApi QSGD3D12RenderContext::graphicsApi() const
return Direct3D12;
}
-void *QSGD3D12RenderContext::getResource(Resource resource) const
+void *QSGD3D12RenderContext::getResource(QQuickWindow *window, Resource resource) const
{
if (!m_engine) {
qWarning("getResource: No D3D12 engine available yet (window not exposed?)");
return nullptr;
}
-
- return m_engine->getResource(resource);
+ // window can be ignored since the rendercontext and engine are both per window
+ return m_engine->getResource(window, resource);
}
QSGRendererInterface::ShaderType QSGD3D12RenderContext::shaderType() const
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h
index ca85aaa46f..35aca100f4 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12rendercontext_p.h
@@ -75,7 +75,7 @@ public:
// QSGRendererInterface
GraphicsApi graphicsApi() const override;
- void *getResource(Resource resource) const override;
+ void *getResource(QQuickWindow *window, Resource resource) const override;
ShaderType shaderType() const override;
ShaderCompilationTypes shaderCompilationType() const override;
ShaderSourceTypes shaderSourceType() const override;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp
index 5e5d7a13f8..ce633ae996 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12renderer.cpp
@@ -451,6 +451,7 @@ struct RenderNodeState : public QSGRenderNode::RenderState
bool scissorEnabled() const { return m_scissorEnabled; }
int stencilValue() const { return m_stencilValue; }
bool stencilEnabled() const { return m_stencilEnabled; }
+ const QRegion *clipRegion() const override { return nullptr; }
const QMatrix4x4 *m_projectionMatrix;
QRect m_scissorRect;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
index ec3427a9cc..c53a1fa6c1 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
@@ -279,6 +279,8 @@ QSGContext *QSGD3D12RenderLoop::sceneGraphContext() const
QSGRenderContext *QSGD3D12RenderLoop::createRenderContext(QSGContext *) const
{
+ // The rendercontext and engine are per-window, like with the threaded
+ // loop, but unlike the non-threaded OpenGL variants.
return sg->createRenderContext();
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index af91722432..56466fdbd1 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -4506,6 +4506,12 @@ qreal QQuickWindow::effectiveDevicePixelRatio() const
QSGRendererInterface::graphicsApi() or QSGRendererInterface::shaderType(),
will always be functional on the other hand.
+ \note The ownership of the returned pointer stays with Qt. The returned
+ instance may or may not be shared between different QQuickWindow instances,
+ depending on the scenegraph backend in use. Therefore applications are
+ expected to query the interface object for each QQuickWindow instead of
+ reusing the already queried pointer.
+
\sa QSGRenderNode, QSGRendererInterface
\since 5.8
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);
};