diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-01-11 17:05:14 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-01-23 15:44:17 +0000 |
commit | 5daaec1e193bc69f55d4ddbfef8911ce9810ea28 (patch) | |
tree | 56956c277c33aec1ed4d05149b7853e5c367182b /src/quick | |
parent | b9f060f6fae5734216d7088afd0e3b52165551c5 (diff) |
Improve stencil clipping with NVPR
So that it actually performs when clipping the tiger. Add an example.
Change-Id: I7c1c6244710febdb6b02852ebca094665adec417
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquickpathitem.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickpathitemnvprrenderer.cpp | 54 | ||||
-rw-r--r-- | src/quick/items/qquickpathitemnvprrenderer_p.h | 9 |
3 files changed, 36 insertions, 29 deletions
diff --git a/src/quick/items/qquickpathitem.cpp b/src/quick/items/qquickpathitem.cpp index 306e79dc1e..b07a7a6c06 100644 --- a/src/quick/items/qquickpathitem.cpp +++ b/src/quick/items/qquickpathitem.cpp @@ -587,7 +587,7 @@ QSGNode *QQuickPathItemPrivate::createNode() #ifndef QT_NO_OPENGL case QSGRendererInterface::OpenGL: if (QQuickPathItemNvprRenderNode::isSupported()) { - node = new QQuickPathItemNvprRenderNode(q); + node = new QQuickPathItemNvprRenderNode; static_cast<QQuickPathItemNvprRenderer *>(renderer)->setNode( static_cast<QQuickPathItemNvprRenderNode *>(node)); } else { diff --git a/src/quick/items/qquickpathitemnvprrenderer.cpp b/src/quick/items/qquickpathitemnvprrenderer.cpp index 9303f698ac..13fab2dc76 100644 --- a/src/quick/items/qquickpathitemnvprrenderer.cpp +++ b/src/quick/items/qquickpathitemnvprrenderer.cpp @@ -397,11 +397,6 @@ bool QQuickPathItemNvprRenderNode::nvprInited = false; QQuickNvprFunctions QQuickPathItemNvprRenderNode::nvpr; QQuickNvprMaterialManager QQuickPathItemNvprRenderNode::mtlmgr; -QQuickPathItemNvprRenderNode::QQuickPathItemNvprRenderNode(QQuickPathItem *item) - : m_item(item) -{ -} - QQuickPathItemNvprRenderNode::~QQuickPathItemNvprRenderNode() { releaseResources(); @@ -528,6 +523,9 @@ void QQuickPathItemNvprRenderNode::updatePath(VisualPathRenderData *d) // count == 0 -> no dash nvpr.pathDashArray(d->path, d->dashPattern.count(), d->dashPattern.constData()); } + + if (d->dirty) + d->fallbackValid = false; } void QQuickPathItemNvprRenderNode::renderStroke(VisualPathRenderData *d, int strokeStencilValue, int writeMask) @@ -568,23 +566,28 @@ void QQuickPathItemNvprRenderNode::renderFill(VisualPathRenderData *d) void QQuickPathItemNvprRenderNode::renderOffscreenFill(VisualPathRenderData *d) { - QQuickWindow *w = m_item->window(); - const qreal dpr = w->effectiveDevicePixelRatio(); - QSize itemSize = QSize(m_item->width(), m_item->height()) * dpr; - QSize rtSize = w->renderTargetSize(); - if (rtSize.isEmpty()) - rtSize = w->size() * dpr; + if (d->fallbackValid && d->fallbackFbo) + return; + + GLfloat bb[4]; + nvpr.getPathParameterfv(d->path, GL_PATH_STROKE_BOUNDING_BOX_NV, bb); + QSize sz = QSizeF(bb[2] - bb[0] + 1, bb[3] - bb[1] + 1).toSize(); + d->fallbackSize = QSize(qMax(32, sz.width()), qMax(32, sz.height())); + d->fallbackTopLeft = QPointF(bb[0], bb[1]); - if (d->fallbackFbo && d->fallbackFbo->size() != itemSize) { + if (d->fallbackFbo && d->fallbackFbo->size() != d->fallbackSize) { delete d->fallbackFbo; d->fallbackFbo = nullptr; } if (!d->fallbackFbo) - d->fallbackFbo = new QOpenGLFramebufferObject(itemSize, QOpenGLFramebufferObject::CombinedDepthStencil); + d->fallbackFbo = new QOpenGLFramebufferObject(d->fallbackSize, QOpenGLFramebufferObject::CombinedDepthStencil); if (!d->fallbackFbo->bind()) return; - f->glViewport(0, 0, itemSize.width(), itemSize.height()); + GLint prevViewport[4]; + f->glGetIntegerv(GL_VIEWPORT, prevViewport); + + f->glViewport(0, 0, d->fallbackSize.width(), d->fallbackSize.height()); f->glDisable(GL_DEPTH_TEST); f->glClearColor(0, 0, 0, 0); f->glClearStencil(0); @@ -592,16 +595,20 @@ void QQuickPathItemNvprRenderNode::renderOffscreenFill(VisualPathRenderData *d) f->glStencilFunc(GL_NOTEQUAL, 0, 0xFF); f->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - nvpr.matrixLoadIdentity(GL_PATH_MODELVIEW_NV); + QMatrix4x4 mv; + mv.translate(-d->fallbackTopLeft.x(), -d->fallbackTopLeft.y()); + nvpr.matrixLoadf(GL_PATH_MODELVIEW_NV, mv.constData()); QMatrix4x4 proj; - proj.ortho(0, itemSize.width(), itemSize.height(), 0, 1, -1); + proj.ortho(0, d->fallbackSize.width(), d->fallbackSize.height(), 0, 1, -1); nvpr.matrixLoadf(GL_PATH_PROJECTION_NV, proj.constData()); renderFill(d); d->fallbackFbo->release(); f->glEnable(GL_DEPTH_TEST); - f->glViewport(0, 0, rtSize.width(), rtSize.height()); + f->glViewport(prevViewport[0], prevViewport[1], prevViewport[2], prevViewport[3]); + + d->fallbackValid = true; } void QQuickPathItemNvprRenderNode::setupStencilForCover(bool stencilClip, int sv) @@ -655,8 +662,8 @@ void QQuickPathItemNvprRenderNode::render(const RenderState *state) for (VisualPathRenderData &d : m_vp) { updatePath(&d); - const bool hasFill = !qFuzzyIsNull(d.fillColor.w()) || d.fillGradientActive; - const bool hasStroke = d.strokeWidth >= 0.0f && !qFuzzyIsNull(d.strokeColor.w()); + const bool hasFill = d.hasFill(); + const bool hasStroke = d.hasStroke(); if (hasFill && stencilClip) { // Fall back to a texture when complex clipping is in use and we have @@ -686,8 +693,10 @@ void QQuickPathItemNvprRenderNode::render(const RenderState *state) m_fallbackBlitter.create(); f->glStencilFunc(GL_EQUAL, sv, 0xFF); f->glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + QMatrix4x4 mv = *matrix(); + mv.translate(d.fallbackTopLeft.x(), d.fallbackTopLeft.y()); m_fallbackBlitter.texturedQuad(d.fallbackFbo->texture(), d.fallbackFbo->size(), - *state->projectionMatrix(), *matrix(), + *state->projectionMatrix(), mv, inheritedOpacity()); } } @@ -729,11 +738,6 @@ QSGRenderNode::RenderingFlags QQuickPathItemNvprRenderNode::flags() const return DepthAwareRendering; // avoid hitting the less optimal no-opaque-batch path in the renderer } -QRectF QQuickPathItemNvprRenderNode::rect() const -{ - return QRect(0, 0, m_item->width(), m_item->height()); -} - bool QQuickPathItemNvprRenderNode::isSupported() { static const bool nvprDisabled = qEnvironmentVariableIntValue("QT_NO_NVPR") != 0; diff --git a/src/quick/items/qquickpathitemnvprrenderer_p.h b/src/quick/items/qquickpathitemnvprrenderer_p.h index 1617de17e6..61f8b5ebb9 100644 --- a/src/quick/items/qquickpathitemnvprrenderer_p.h +++ b/src/quick/items/qquickpathitemnvprrenderer_p.h @@ -176,14 +176,12 @@ private: class QQuickPathItemNvprRenderNode : public QSGRenderNode { public: - QQuickPathItemNvprRenderNode(QQuickPathItem *item); ~QQuickPathItemNvprRenderNode(); void render(const RenderState *state) override; void releaseResources() override; StateFlags changedStates() const override; RenderingFlags flags() const override; - QRectF rect() const override; static bool isSupported(); @@ -204,6 +202,12 @@ private: bool fillGradientActive; QQuickPathItemGradientCache::GradientDesc fillGradient; QOpenGLFramebufferObject *fallbackFbo = nullptr; + bool fallbackValid = false; + QSize fallbackSize; + QPointF fallbackTopLeft; + + bool hasFill() const { return !qFuzzyIsNull(fillColor.w()) || fillGradientActive; } + bool hasStroke() const { return strokeWidth >= 0.0f && !qFuzzyIsNull(strokeColor.w()); } }; void updatePath(VisualPathRenderData *d); @@ -216,7 +220,6 @@ private: static QQuickNvprFunctions nvpr; static QQuickNvprMaterialManager mtlmgr; - QQuickPathItem *m_item; QQuickNvprBlitter m_fallbackBlitter; QOpenGLExtraFunctions *f = nullptr; |