software backend: Fix clipping of QSGRenderNodes

Change-Id: I27aa5f94165fb07807d2bb711d81eade552b9f76
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2016-12-19 13:53:29 +01:00
parent c9023c2876
commit bf7c622626
4 changed files with 22 additions and 15 deletions

View File

@ -64,11 +64,12 @@ void SoftwareRenderNode::render(const RenderState *renderState)
QPainter *p = static_cast<QPainter *>(rif->getResource(m_item->window(), QSGRendererInterface::PainterResource));
Q_ASSERT(p);
p->setTransform(matrix()->toTransform());
p->setOpacity(inheritedOpacity());
const QRegion *clipRegion = renderState->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());
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
const QPointF p1(0, 0);

View File

@ -202,12 +202,12 @@ void QQuickPathItemSoftwareRenderNode::render(const RenderState *state)
QPainter *p = static_cast<QPainter *>(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);

View File

@ -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)

View File

@ -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().
*/
/*!