diff options
author | Andy Nichols <andy.nichols@theqtcompany.com> | 2016-06-27 13:30:05 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2016-06-28 10:17:47 +0000 |
commit | 261675f8a404b6d19df72a7d6c3432cc58fbafe6 (patch) | |
tree | c1b03c1b6466b74588e5c23f16be555ca4e3711c /src/quick/scenegraph/adaptations | |
parent | a0aadc3226d99d6d950359383df596928f300001 (diff) |
Software Adaptation: Improve clip node handling
This commit solves two issues that were coming up with nested clip
nodes. The first was that determining the intersection of two or more
nested clip nodes was calculated incorrectly. This was fixed by making
sure the calculated clip region was in the correct coordinate space.
The second issue was because there was no distinction between an empty
unclipped region, and a completely clipped region. So a property was
added to specify when a RenderableNode had a clipRegion so that the
empty QRegion could be interpreted correctly. This makes sure that we
don't end up drawing nodes that were culled.
Change-Id: Id7af092f7fc6a4602b44b585b7dee14084136962
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/quick/scenegraph/adaptations')
4 files changed, 25 insertions, 9 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index 7cfbc2dfda..385b257e44 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -58,6 +58,7 @@ QSGSoftwareRenderableNode::QSGSoftwareRenderableNode(NodeType type, QSGNode *nod : m_nodeType(type) , m_isOpaque(true) , m_isDirty(true) + , m_hasClipRegion(false) , m_opacity(1.0f) { switch (m_nodeType) { @@ -179,8 +180,12 @@ void QSGSoftwareRenderableNode::update() m_boundingRect = m_transform.mapRect(boundingRect); - if (m_clipRegion.rectCount() == 1) { - m_boundingRect = m_boundingRect.intersected(m_clipRegion.rects().first()); + if (m_hasClipRegion && m_clipRegion.rectCount() <= 1) { + // If there is a clipRegion, and it is empty, the item wont be rendered + if (m_clipRegion.isEmpty()) + m_boundingRect = QRect(); + else + m_boundingRect = m_boundingRect.intersected(m_clipRegion.rects().first()); } // Overrides @@ -284,12 +289,13 @@ void QSGSoftwareRenderableNode::setTransform(const QTransform &transform) update(); } -void QSGSoftwareRenderableNode::setClipRegion(const QRegion &clipRect) +void QSGSoftwareRenderableNode::setClipRegion(const QRegion &clipRect, bool hasClipRegion) { - if (m_clipRegion == clipRect) + if (m_clipRegion == clipRect && m_hasClipRegion == hasClipRegion) return; m_clipRegion = clipRect; + m_hasClipRegion = hasClipRegion; update(); } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h index d1a71cd580..fcbea7391a 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode_p.h @@ -97,7 +97,7 @@ public: bool isDirtyRegionEmpty() const; void setTransform(const QTransform &transform); - void setClipRegion(const QRegion &clipRegion); + void setClipRegion(const QRegion &clipRegion, bool hasClipRegion = true); void setOpacity(float opacity); QTransform transform() const { return m_transform; } QRegion clipRegion() const { return m_clipRegion; } @@ -136,6 +136,7 @@ private: QTransform m_transform; QRegion m_clipRegion; + bool m_hasClipRegion; float m_opacity; QRect m_boundingRect; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp index 1681f3c06b..f13edb87fb 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp @@ -58,6 +58,7 @@ QSGSoftwareRenderableNodeUpdater::QSGSoftwareRenderableNodeUpdater(QSGAbstractSo m_opacityState.push(1.0f); // Invalid RectF by default for no clip m_clipState.push(QRegion()); + m_hasClip = false; m_transformState.push(QTransform()); } @@ -81,10 +82,13 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGTransformNode *) bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node) { // Make sure to translate the clip rect into world coordinates - if (m_clipState.top().isEmpty()) { + if (m_clipState.count() == 1) { m_clipState.push(m_transformState.top().map(QRegion(node->clipRect().toRect()))); - } else - m_clipState.push(m_transformState.top().map(QRegion(node->clipRect().toRect()).intersected(m_clipState.top()))); + m_hasClip = true; + } else { + const QRegion transformedClipRect = m_transformState.top().map(QRegion(node->clipRect().toRect())); + m_clipState.push(transformedClipRect.intersected(m_clipState.top())); + } m_stateMap[node] = currentState(node); return true; } @@ -92,6 +96,8 @@ bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node) void QSGSoftwareRenderableNodeUpdater::endVisit(QSGClipNode *) { m_clipState.pop(); + if (m_clipState.count() == 1) + m_hasClip = false; } bool QSGSoftwareRenderableNodeUpdater::visit(QSGGeometryNode *node) @@ -264,6 +270,7 @@ QSGSoftwareRenderableNodeUpdater::NodeState QSGSoftwareRenderableNodeUpdater::cu NodeState state; state.opacity = m_opacityState.top(); state.clip = m_clipState.top(); + state.hasClip = m_hasClip; state.transform = m_transformState.top(); state.parent = node->parent(); return state; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h index 97492d4347..d7c12e8b02 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater_p.h @@ -93,6 +93,7 @@ private: struct NodeState { float opacity; QRegion clip; + bool hasClip; QTransform transform; QSGNode *parent; }; @@ -105,6 +106,7 @@ private: QSGAbstractSoftwareRenderer *m_renderer; QStack<float> m_opacityState; QStack<QRegion> m_clipState; + bool m_hasClip; QStack<QTransform> m_transformState; QHash<QSGNode*,NodeState> m_stateMap; }; @@ -122,7 +124,7 @@ bool QSGSoftwareRenderableNodeUpdater::updateRenderableNode(QSGSoftwareRenderabl //Update the node renderableNode->setTransform(m_transformState.top()); renderableNode->setOpacity(m_opacityState.top()); - renderableNode->setClipRegion(m_clipState.top()); + renderableNode->setClipRegion(m_clipState.top(), m_hasClip); renderableNode->update(); m_stateMap[node] = currentState(node); |