aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2016-07-27 11:59:17 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2016-08-02 16:15:31 +0000
commit44e86f701247a86da37e3a94b77853b57ab1b303 (patch)
tree109ece6b5393a159062e9b1eca906c176b66035b
parentcf186c441dd0d68dbfac416ee6d09d4f923a0a4c (diff)
Add optional flags and rect to QSGRenderNode
Having rendernodes triggering fullscreen updates with the software backend is not ideal. Therefore, introduce the option of reporting that the rendernode is well-behaving, meaning it only writes inside the reported bounding rectangle. Similarly, the OpenGL batch renderer can keep using the depth buffer when the rendernode is known to behave like the renderer expects. Change-Id: I6acc434432c2504776f26e8917b5434b44be293d Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.cpp10
-rw-r--r--examples/quick/scenegraph/rendernode/d3d12renderer.h2
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.cpp10
-rw-r--r--examples/quick/scenegraph/rendernode/openglrenderer.h2
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.cpp12
-rw-r--r--examples/quick/scenegraph/rendernode/softwarerenderer.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp18
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp8
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp67
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.h10
10 files changed, 134 insertions, 7 deletions
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
index f475ec838b..d35f82a76a 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.cpp
@@ -270,4 +270,14 @@ void D3D12RenderNode::render(const RenderState *state)
// No need to reimplement changedStates() because no relevant commands are
// added to the command list in render().
+QSGRenderNode::RenderingFlags D3D12RenderNode::flags() const
+{
+ return BoundedRectRendering | DepthAwareRendering;
+}
+
+QRectF D3D12RenderNode::rect() const
+{
+ return QRect(0, 0, m_item->width(), m_item->height());
+}
+
#endif // HAS_D3D12
diff --git a/examples/quick/scenegraph/rendernode/d3d12renderer.h b/examples/quick/scenegraph/rendernode/d3d12renderer.h
index a81db0f398..f13a1d451c 100644
--- a/examples/quick/scenegraph/rendernode/d3d12renderer.h
+++ b/examples/quick/scenegraph/rendernode/d3d12renderer.h
@@ -60,6 +60,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
private:
void init();
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.cpp b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
index 33c59198b8..3de864b7b9 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.cpp
@@ -151,4 +151,14 @@ QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const
return BlendState;
}
+QSGRenderNode::RenderingFlags OpenGLRenderNode::flags() const
+{
+ return BoundedRectRendering | DepthAwareRendering;
+}
+
+QRectF OpenGLRenderNode::rect() const
+{
+ return QRect(0, 0, m_item->width(), m_item->height());
+}
+
#endif // QT_NO_OPENGL
diff --git a/examples/quick/scenegraph/rendernode/openglrenderer.h b/examples/quick/scenegraph/rendernode/openglrenderer.h
index 28d528e617..1ee6350218 100644
--- a/examples/quick/scenegraph/rendernode/openglrenderer.h
+++ b/examples/quick/scenegraph/rendernode/openglrenderer.h
@@ -58,6 +58,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
StateFlags changedStates() const override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
private:
void init();
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
index 2f11c56f29..06e406874a 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.cpp
@@ -68,7 +68,7 @@ void SoftwareRenderNode::render(const RenderState *renderState)
p->setOpacity(inheritedOpacity());
const QRegion *clipRegion = renderState->clipRegion();
if (clipRegion && !clipRegion->isEmpty())
- p->setClipRegion(*clipRegion);
+ p->setClipRegion(*clipRegion, Qt::IntersectClip);
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
const QPointF p1(0, 0);
@@ -89,3 +89,13 @@ QSGRenderNode::StateFlags SoftwareRenderNode::changedStates() const
{
return 0;
}
+
+QSGRenderNode::RenderingFlags SoftwareRenderNode::flags() const
+{
+ return BoundedRectRendering;
+}
+
+QRectF SoftwareRenderNode::rect() const
+{
+ return QRect(0, 0, m_item->width(), m_item->height());
+}
diff --git a/examples/quick/scenegraph/rendernode/softwarerenderer.h b/examples/quick/scenegraph/rendernode/softwarerenderer.h
index 60036f96a1..5b2a475ed8 100644
--- a/examples/quick/scenegraph/rendernode/softwarerenderer.h
+++ b/examples/quick/scenegraph/rendernode/softwarerenderer.h
@@ -54,6 +54,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
StateFlags changedStates() const override;
+ RenderingFlags flags() const override;
+ QRectF rect() const override;
private:
QQuickItem *m_item;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
index 032a06f946..d900688173 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
@@ -187,6 +187,12 @@ void QSGSoftwareRenderableNode::update()
boundingRect = m_handle.spriteNode->rect().toRect();
break;
case QSGSoftwareRenderableNode::RenderNode:
+ if (m_handle.renderNode->flags().testFlag(QSGRenderNode::OpaqueRendering) && !m_transform.isRotating())
+ m_isOpaque = true;
+ else
+ m_isOpaque = false;
+
+ boundingRect = m_handle.renderNode->rect().toRect();
break;
default:
break;
@@ -244,14 +250,20 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu
rd->m_opacity = m_opacity;
RenderNodeState rs;
rs.cr = m_clipRegion;
+
+ const QRect br = m_handle.renderNode->flags().testFlag(QSGRenderNode::BoundedRectRendering)
+ ? m_boundingRect :
+ QRect(0, 0, painter->device()->width(), painter->device()->height());
+
painter->save();
+ painter->setClipRegion(br, Qt::ReplaceClip);
m_handle.renderNode->render(&rs);
painter->restore();
- const QRect fullRect = QRect(0, 0, painter->device()->width(), painter->device()->height());
- m_previousDirtyRegion = fullRect;
+
+ m_previousDirtyRegion = QRegion(br);
m_isDirty = false;
m_dirtyRegion = QRegion();
- return fullRect;
+ return br;
}
}
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index bee2015007..49bbbf0ba8 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -1033,11 +1033,13 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
m_rebuild |= FullRebuild;
} else if (node->type() == QSGNode::RenderNodeType) {
- RenderNodeElement *e = new RenderNodeElement(static_cast<QSGRenderNode *>(node));
+ QSGRenderNode *rn = static_cast<QSGRenderNode *>(node);
+ RenderNodeElement *e = new RenderNodeElement(rn);
snode->data = e;
- Q_ASSERT(!m_renderNodeElements.contains(static_cast<QSGRenderNode *>(node)));
+ Q_ASSERT(!m_renderNodeElements.contains(rn));
m_renderNodeElements.insert(e->renderNode, e);
- m_useDepthBuffer = false;
+ if (!rn->flags().testFlag(QSGRenderNode::DepthAwareRendering))
+ m_useDepthBuffer = false;
m_rebuild |= FullRebuild;
}
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index 365abd09e2..5915d51f2b 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -179,6 +179,11 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
default value according to the OpenGL specification. For other APIs, see
the documentation for changedStates() for more information.
+ \note Depth writes are disabled when this function is called (for example,
+ glDepthMask(false) in case of OpenGL). Enabling depth writes can lead to
+ unexpected results, depending on the scenegraph backend in use, so nodes
+ should avoid this.
+
For APIs other than OpenGL, it will likely be necessary to query certain
API-specific resources (for example, the graphics device or the command
list/buffer to add the commands to). This is done via QSGRendererInterface.
@@ -211,6 +216,68 @@ void QSGRenderNode::releaseResources()
}
/*!
+ \enum QSGRenderNode::RenderingFlag
+
+ Possible values for the bitmask returned from flags().
+
+ \value BoundedRectRendering Indicates that the implementation of render()
+ does not render outside the area reported from rect() in item
+ coordinates. Such node implementations can lead to more efficient rendering,
+ depending on the scenegraph backend. For example, the software backend can
+ continue to use the more optimal partial update path when all render nodes
+ in the scene have this flag set.
+
+ \value DepthAwareRendering Indicates that the implementations of render()
+ conforms to scenegraph expectations by only generating a Z value of 0 in
+ scene coordinates which is then transformed by the matrices retrieved from
+ RenderState::projectionMatrix() and matrix(), as described in the notes for
+ render(). Such node implementations can lead to more efficient rendering,
+ depending on the scenegraph backend. For example, the batching OpenGL
+ renderer can continue to use a more optimal path when all render nodes in
+ the scene have this flag set.
+
+ \value OpaqueRendering Indicates that the implementation of render() writes
+ out opaque pixels for the entire area reported from rect(). By default the
+ renderers must assume that render() can also output semi or fully
+ transparent pixels. Setting this flag can improve performance in some
+ cases.
+
+ \sa render(), rect()
+ */
+
+/*!
+ \return flags describing the behavior of this render node.
+
+ The default implementation returns 0.
+
+ \sa RenderingFlag, rect()
+ */
+QSGRenderNode::RenderingFlags QSGRenderNode::flags() const
+{
+ return 0;
+}
+
+/*!
+ \return the bounding rectangle in item coordinates for the area render()
+ touches. The value is only in use when flags() includes
+ BoundedRectRendering, ignored otherwise.
+
+ Reporting the rectangle in combination with BoundedRectRendering is
+ particularly important with the \c software backend because otherwise
+ having a rendernode in the scene would trigger fullscreen updates, skipping
+ all partial update optimizations.
+
+ For rendernodes covering the entire area of a corresponding QQuickItem the
+ return value will be (0, 0, item->width(), item->height()).
+
+ \sa flags()
+*/
+QRectF QSGRenderNode::rect() const
+{
+ return QRectF();
+}
+
+/*!
\return pointer to the current model-view matrix.
*/
const QMatrix4x4 *QSGRenderNode::matrix() const
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.h b/src/quick/scenegraph/coreapi/qsgrendernode.h
index 6eb425c03b..f6bc40d3ee 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.h
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.h
@@ -61,6 +61,13 @@ public:
};
Q_DECLARE_FLAGS(StateFlags, StateFlag)
+ enum RenderingFlag {
+ BoundedRectRendering = 0x01,
+ DepthAwareRendering = 0x02,
+ OpaqueRendering = 0x04
+ };
+ Q_DECLARE_FLAGS(RenderingFlags, RenderingFlag)
+
struct Q_QUICK_EXPORT RenderState {
virtual ~RenderState();
virtual const QMatrix4x4 *projectionMatrix() const = 0;
@@ -78,6 +85,8 @@ public:
virtual StateFlags changedStates() const;
virtual void render(const RenderState *state) = 0;
virtual void releaseResources();
+ virtual RenderingFlags flags() const;
+ virtual QRectF rect() const;
const QMatrix4x4 *matrix() const;
const QSGClipNode *clipList() const;
@@ -89,6 +98,7 @@ private:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::StateFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::RenderingFlags)
QT_END_NAMESPACE