From bf7c6226264bd45095711b2c0556c42b6f267f72 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 19 Dec 2016 13:53:29 +0100 Subject: software backend: Fix clipping of QSGRenderNodes Change-Id: I27aa5f94165fb07807d2bb711d81eade552b9f76 Reviewed-by: Andy Nichols --- src/quick/items/qquickpathitemsoftwarerenderer.cpp | 8 ++++---- .../adaptations/software/qsgsoftwarerenderablenode.cpp | 17 ++++++++++------- src/quick/scenegraph/coreapi/qsgrendernode.cpp | 5 ++++- 3 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickpathitemsoftwarerenderer.cpp b/src/quick/items/qquickpathitemsoftwarerenderer.cpp index 40732e4bf9..f089904fdf 100644 --- a/src/quick/items/qquickpathitemsoftwarerenderer.cpp +++ b/src/quick/items/qquickpathitemsoftwarerenderer.cpp @@ -202,12 +202,12 @@ void QQuickPathItemSoftwareRenderNode::render(const RenderState *state) QPainter *p = static_cast(rif->getResource(m_item->window(), QSGRendererInterface::PainterResource)); Q_ASSERT(p); - p->setTransform(matrix()->toTransform()); - p->setOpacity(inheritedOpacity()); - const QRegion *clipRegion = state->clipRegion(); if (clipRegion && !clipRegion->isEmpty()) - p->setClipRegion(*clipRegion, Qt::IntersectClip); + p->setClipRegion(*clipRegion, Qt::ReplaceClip); // must be done before setTransform + + p->setTransform(matrix()->toTransform()); + p->setOpacity(inheritedOpacity()); p->setPen(!qFuzzyIsNull(m_pen.widthF()) && m_pen.color() != Qt::transparent ? m_pen : Qt::NoPen); p->setBrush(m_brush.color() != Qt::transparent ? m_brush : Qt::NoBrush); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index 59c47db0c4..7adb39d9a8 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -254,18 +254,21 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu QMatrix4x4 m = m_transform; rd->m_matrix = &m; 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()); + // all the clip region below is in world coordinates, taking m_transform into account already + QRegion cr = m_dirtyRegion; + if (m_clipRegion.rectCount() > 1) + cr &= m_clipRegion; painter->save(); - painter->setClipRegion(br, Qt::ReplaceClip); + RenderNodeState rs; + rs.cr = cr; m_handle.renderNode->render(&rs); painter->restore(); + const QRect br = m_handle.renderNode->flags().testFlag(QSGRenderNode::BoundedRectRendering) + ? m_boundingRect // already mapped to world + : QRect(0, 0, painter->device()->width(), painter->device()->height()); m_previousDirtyRegion = QRegion(br); m_isDirty = false; m_dirtyRegion = QRegion(); @@ -276,7 +279,7 @@ QRegion QSGSoftwareRenderableNode::renderNode(QPainter *painter, bool forceOpaqu painter->save(); painter->setOpacity(m_opacity); - // Set clipRegion to m_dirtyRegion (in world coordinates) + // Set clipRegion to m_dirtyRegion (in world coordinates, so must be done before the setTransform below) // as m_dirtyRegion already accounts for clipRegion painter->setClipRegion(m_dirtyRegion, Qt::ReplaceClip); if (m_clipRegion.rectCount() > 1) diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp index 1bc0210b72..3007e0000c 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp @@ -359,7 +359,10 @@ QSGRenderNode::RenderState::~RenderState() 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. + this function. The region is in world coordinates and can be passed + to QPainter::setClipRegion() with Qt::ReplaceClip. This must be done before + calling QPainter::setTransform() since the clip region is already mapped to + the transform provided in QSGRenderNode::matrix(). */ /*! -- cgit v1.2.3