diff options
Diffstat (limited to 'src/quickshapes/qquickshapegenericrenderer.cpp')
-rw-r--r-- | src/quickshapes/qquickshapegenericrenderer.cpp | 156 |
1 files changed, 103 insertions, 53 deletions
diff --git a/src/quickshapes/qquickshapegenericrenderer.cpp b/src/quickshapes/qquickshapegenericrenderer.cpp index b2b6af041f..20dfe21040 100644 --- a/src/quickshapes/qquickshapegenericrenderer.cpp +++ b/src/quickshapes/qquickshapegenericrenderer.cpp @@ -4,9 +4,11 @@ #include "qquickshapegenericrenderer_p.h" #include <QtGui/private/qtriangulator_p.h> #include <QtGui/private/qtriangulatingstroker_p.h> -#include <QtGui/private/qrhi_p.h> +#include <rhi/qrhi.h> #include <QSGVertexColorMaterial> +#include <QtQuick/private/qsggradientcache_p.h> + #if QT_CONFIG(thread) #include <QThreadPool> #endif @@ -176,7 +178,7 @@ void QQuickShapeGenericRenderer::setFillGradient(int index, QQuickShapeGradient ShapePathData &d(m_sp[index]); if (gradient) { d.fillGradient.stops = gradient->gradientStops(); // sorted - d.fillGradient.spread = gradient->spread(); + d.fillGradient.spread = QGradient::Spread(gradient->spread()); if (QQuickShapeLinearGradient *g = qobject_cast<QQuickShapeLinearGradient *>(gradient)) { d.fillGradientActive = LinearGradient; d.fillGradient.a = QPointF(g->x1(), g->y1()); @@ -200,6 +202,13 @@ void QQuickShapeGenericRenderer::setFillGradient(int index, QQuickShapeGradient d.syncDirty |= DirtyFillGradient; } +void QQuickShapeGenericRenderer::setFillTransform(int index, const QSGTransform &transform) +{ + ShapePathData &d(m_sp[index]); + d.fillTransform = transform; + d.syncDirty |= DirtyFillTransform; +} + void QQuickShapeGenericRenderer::setTriangulationScale(qreal scale) { // No dirty, this is called at the start of every sync. Just store the value. @@ -489,7 +498,7 @@ void QQuickShapeGenericRenderer::updateNode() QQuickShapeGenericNode *node = *nodePtr; if (m_accDirty & DirtyList) - d.effectiveDirty |= DirtyFillGeom | DirtyStrokeGeom | DirtyColor | DirtyFillGradient; + d.effectiveDirty |= DirtyFillGeom | DirtyStrokeGeom | DirtyColor | DirtyFillGradient | DirtyFillTransform; if (!d.effectiveDirty) { prevNode = node; @@ -542,6 +551,8 @@ void QQuickShapeGenericRenderer::updateShadowDataInNode(ShapePathData *d, QQuick if (d->fillGradientActive) { if (d->effectiveDirty & DirtyFillGradient) n->m_fillGradient = d->fillGradient; + if (d->effectiveDirty & DirtyFillTransform) + n->m_fillTransform = d->fillTransform; } } @@ -549,7 +560,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen { if (!node->m_fillNode) return; - if (!(d->effectiveDirty & (DirtyFillGeom | DirtyColor | DirtyFillGradient))) + if (!(d->effectiveDirty & (DirtyFillGeom | DirtyColor | DirtyFillGradient | DirtyFillTransform))) return; // Make a copy of the data that will be accessed by the material on @@ -582,10 +593,10 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen Q_UNREACHABLE_RETURN(); } n->activateMaterial(m_item->window(), gradMat); - if (d->effectiveDirty & DirtyFillGradient) { + if (d->effectiveDirty & (DirtyFillGradient | DirtyFillTransform)) { // Gradients are implemented via a texture-based material. n->markDirty(QSGNode::DirtyMaterial); - // stop here if only the gradient changed; no need to touch the geometry + // stop here if only the gradient or filltransform changed; no need to touch the geometry if (!(d->effectiveDirty & DirtyFillGeom)) return; } @@ -701,10 +712,10 @@ QSGMaterial *QQuickShapeGenericMaterialFactory::createConicalGradient(QQuickWind return nullptr; } -QQuickShapeLinearGradientRhiShader::QQuickShapeLinearGradientRhiShader() +QQuickShapeLinearGradientRhiShader::QQuickShapeLinearGradientRhiShader(int viewCount) { - setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/lineargradient.vert.qsb")); - setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/lineargradient.frag.qsb")); + setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/lineargradient.vert.qsb"), viewCount); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/lineargradient.frag.qsb"), viewCount); } bool QQuickShapeLinearGradientRhiShader::updateUniformData(RenderState &state, @@ -714,32 +725,42 @@ bool QQuickShapeLinearGradientRhiShader::updateUniformData(RenderState &state, QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(newMaterial); bool changed = false; QByteArray *buf = state.uniformData(); - Q_ASSERT(buf->size() >= 84); + Q_ASSERT(buf->size() >= 84 + 64); + const int shaderMatrixCount = newMaterial->viewCount(); + const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount); if (state.isMatrixDirty()) { - const QMatrix4x4 m = state.combinedMatrix(); - memcpy(buf->data(), m.constData(), 64); - changed = true; + for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) { + const QMatrix4x4 m = state.combinedMatrix(); + memcpy(buf->data() + 64 * viewIndex, m.constData(), 64); + changed = true; + } } QQuickShapeGenericStrokeFillNode *node = m->node(); + if (!oldMaterial || m_fillTransform != node->m_fillTransform) { + memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64); + m_fillTransform = node->m_fillTransform; + changed = true; + } + if (!oldMaterial || m_gradA.x() != node->m_fillGradient.a.x() || m_gradA.y() != node->m_fillGradient.a.y()) { m_gradA = QVector2D(node->m_fillGradient.a.x(), node->m_fillGradient.a.y()); Q_ASSERT(sizeof(m_gradA) == 8); - memcpy(buf->data() + 64, &m_gradA, 8); + memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_gradA, 8); changed = true; } if (!oldMaterial || m_gradB.x() != node->m_fillGradient.b.x() || m_gradB.y() != node->m_fillGradient.b.y()) { m_gradB = QVector2D(node->m_fillGradient.b.x(), node->m_fillGradient.b.y()); - memcpy(buf->data() + 72, &m_gradB, 8); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &m_gradB, 8); changed = true; } if (state.isOpacityDirty()) { const float opacity = state.opacity(); - memcpy(buf->data() + 80, &opacity, 4); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8, &opacity, 4); changed = true; } @@ -754,8 +775,8 @@ void QQuickShapeLinearGradientRhiShader::updateSampledImage(RenderState &state, QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(newMaterial); QQuickShapeGenericStrokeFillNode *node = m->node(); - const QQuickShapeGradientCacheKey cacheKey(node->m_fillGradient.stops, node->m_fillGradient.spread); - QSGTexture *t = QQuickShapeGradientCache::cacheForRhi(state.rhi())->get(cacheKey); + const QSGGradientCacheKey cacheKey(node->m_fillGradient.stops, QGradient::Spread(node->m_fillGradient.spread)); + QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey); t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch()); *texture = t; } @@ -777,8 +798,8 @@ int QQuickShapeLinearGradientMaterial::compare(const QSGMaterial *other) const if (a == b) return 0; - const QQuickAbstractPathRenderer::GradientDesc *ga = &a->m_fillGradient; - const QQuickAbstractPathRenderer::GradientDesc *gb = &b->m_fillGradient; + const QSGGradientCache::GradientDesc *ga = &a->m_fillGradient; + const QSGGradientCache::GradientDesc *gb = &b->m_fillGradient; if (int d = ga->spread - gb->spread) return d; @@ -802,19 +823,22 @@ int QQuickShapeLinearGradientMaterial::compare(const QSGMaterial *other) const return d; } + if (int d = a->m_fillTransform.compareTo(b->m_fillTransform)) + return d; + return 0; } QSGMaterialShader *QQuickShapeLinearGradientMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { Q_UNUSED(renderMode); - return new QQuickShapeLinearGradientRhiShader; + return new QQuickShapeLinearGradientRhiShader(viewCount()); } -QQuickShapeRadialGradientRhiShader::QQuickShapeRadialGradientRhiShader() +QQuickShapeRadialGradientRhiShader::QQuickShapeRadialGradientRhiShader(int viewCount) { - setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/radialgradient.vert.qsb")); - setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/radialgradient.frag.qsb")); + setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/radialgradient.vert.qsb"), viewCount); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/radialgradient.frag.qsb"), viewCount); } bool QQuickShapeRadialGradientRhiShader::updateUniformData(RenderState &state, @@ -824,16 +848,26 @@ bool QQuickShapeRadialGradientRhiShader::updateUniformData(RenderState &state, QQuickShapeRadialGradientMaterial *m = static_cast<QQuickShapeRadialGradientMaterial *>(newMaterial); bool changed = false; QByteArray *buf = state.uniformData(); - Q_ASSERT(buf->size() >= 92); + Q_ASSERT(buf->size() >= 92 + 64); + const int shaderMatrixCount = newMaterial->viewCount(); + const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount); if (state.isMatrixDirty()) { - const QMatrix4x4 m = state.combinedMatrix(); - memcpy(buf->data(), m.constData(), 64); - changed = true; + for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) { + const QMatrix4x4 m = state.combinedMatrix(); + memcpy(buf->data() + 64 * viewIndex, m.constData(), 64); + changed = true; + } } QQuickShapeGenericStrokeFillNode *node = m->node(); + if (!oldMaterial || m_fillTransform != node->m_fillTransform) { + memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64); + m_fillTransform = node->m_fillTransform; + changed = true; + } + const QPointF centerPoint = node->m_fillGradient.a; const QPointF focalPoint = node->m_fillGradient.b; const QPointF focalToCenter = centerPoint - focalPoint; @@ -843,32 +877,32 @@ bool QQuickShapeRadialGradientRhiShader::updateUniformData(RenderState &state, if (!oldMaterial || m_focalPoint.x() != focalPoint.x() || m_focalPoint.y() != focalPoint.y()) { m_focalPoint = QVector2D(focalPoint.x(), focalPoint.y()); Q_ASSERT(sizeof(m_focalPoint) == 8); - memcpy(buf->data() + 64, &m_focalPoint, 8); + memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_focalPoint, 8); changed = true; } if (!oldMaterial || m_focalToCenter.x() != focalToCenter.x() || m_focalToCenter.y() != focalToCenter.y()) { m_focalToCenter = QVector2D(focalToCenter.x(), focalToCenter.y()); Q_ASSERT(sizeof(m_focalToCenter) == 8); - memcpy(buf->data() + 72, &m_focalToCenter, 8); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &m_focalToCenter, 8); changed = true; } if (!oldMaterial || m_centerRadius != centerRadius) { m_centerRadius = centerRadius; - memcpy(buf->data() + 80, &m_centerRadius, 4); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8, &m_centerRadius, 4); changed = true; } if (!oldMaterial || m_focalRadius != focalRadius) { m_focalRadius = focalRadius; - memcpy(buf->data() + 84, &m_focalRadius, 4); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8 + 4, &m_focalRadius, 4); changed = true; } if (state.isOpacityDirty()) { const float opacity = state.opacity(); - memcpy(buf->data() + 88, &opacity, 4); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8 + 4 + 4, &opacity, 4); changed = true; } @@ -883,8 +917,8 @@ void QQuickShapeRadialGradientRhiShader::updateSampledImage(RenderState &state, QQuickShapeRadialGradientMaterial *m = static_cast<QQuickShapeRadialGradientMaterial *>(newMaterial); QQuickShapeGenericStrokeFillNode *node = m->node(); - const QQuickShapeGradientCacheKey cacheKey(node->m_fillGradient.stops, node->m_fillGradient.spread); - QSGTexture *t = QQuickShapeGradientCache::cacheForRhi(state.rhi())->get(cacheKey); + const QSGGradientCacheKey cacheKey(node->m_fillGradient.stops, QGradient::Spread(node->m_fillGradient.spread)); + QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey); t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch()); *texture = t; } @@ -906,8 +940,8 @@ int QQuickShapeRadialGradientMaterial::compare(const QSGMaterial *other) const if (a == b) return 0; - const QQuickAbstractPathRenderer::GradientDesc *ga = &a->m_fillGradient; - const QQuickAbstractPathRenderer::GradientDesc *gb = &b->m_fillGradient; + const QSGGradientCache::GradientDesc *ga = &a->m_fillGradient; + const QSGGradientCache::GradientDesc *gb = &b->m_fillGradient; if (int d = ga->spread - gb->spread) return d; @@ -936,19 +970,22 @@ int QQuickShapeRadialGradientMaterial::compare(const QSGMaterial *other) const return d; } + if (int d = a->m_fillTransform.compareTo(b->m_fillTransform)) + return d; + return 0; } QSGMaterialShader *QQuickShapeRadialGradientMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { Q_UNUSED(renderMode); - return new QQuickShapeRadialGradientRhiShader; + return new QQuickShapeRadialGradientRhiShader(viewCount()); } -QQuickShapeConicalGradientRhiShader::QQuickShapeConicalGradientRhiShader() +QQuickShapeConicalGradientRhiShader::QQuickShapeConicalGradientRhiShader(int viewCount) { - setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/conicalgradient.vert.qsb")); - setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/conicalgradient.frag.qsb")); + setShaderFileName(VertexStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/conicalgradient.vert.qsb"), viewCount); + setShaderFileName(FragmentStage, QStringLiteral(":/qt-project.org/shapes/shaders_ng/conicalgradient.frag.qsb"), viewCount); } bool QQuickShapeConicalGradientRhiShader::updateUniformData(RenderState &state, @@ -958,35 +995,45 @@ bool QQuickShapeConicalGradientRhiShader::updateUniformData(RenderState &state, QQuickShapeConicalGradientMaterial *m = static_cast<QQuickShapeConicalGradientMaterial *>(newMaterial); bool changed = false; QByteArray *buf = state.uniformData(); - Q_ASSERT(buf->size() >= 80); + Q_ASSERT(buf->size() >= 80 + 64); + const int shaderMatrixCount = newMaterial->viewCount(); + const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount); if (state.isMatrixDirty()) { - const QMatrix4x4 m = state.combinedMatrix(); - memcpy(buf->data(), m.constData(), 64); - changed = true; + for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) { + const QMatrix4x4 m = state.combinedMatrix(); + memcpy(buf->data() + 64 * viewIndex, m.constData(), 64); + changed = true; + } } QQuickShapeGenericStrokeFillNode *node = m->node(); + if (!oldMaterial || m_fillTransform != node->m_fillTransform) { + memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64); + m_fillTransform = node->m_fillTransform; + changed = true; + } + const QPointF centerPoint = node->m_fillGradient.a; const float angle = -qDegreesToRadians(node->m_fillGradient.v0); if (!oldMaterial || m_centerPoint.x() != centerPoint.x() || m_centerPoint.y() != centerPoint.y()) { m_centerPoint = QVector2D(centerPoint.x(), centerPoint.y()); Q_ASSERT(sizeof(m_centerPoint) == 8); - memcpy(buf->data() + 64, &m_centerPoint, 8); + memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_centerPoint, 8); changed = true; } if (!oldMaterial || m_angle != angle) { m_angle = angle; - memcpy(buf->data() + 72, &m_angle, 4); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &m_angle, 4); changed = true; } if (state.isOpacityDirty()) { const float opacity = state.opacity(); - memcpy(buf->data() + 76, &opacity, 4); + memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 4, &opacity, 4); changed = true; } @@ -1001,8 +1048,8 @@ void QQuickShapeConicalGradientRhiShader::updateSampledImage(RenderState &state, QQuickShapeConicalGradientMaterial *m = static_cast<QQuickShapeConicalGradientMaterial *>(newMaterial); QQuickShapeGenericStrokeFillNode *node = m->node(); - const QQuickShapeGradientCacheKey cacheKey(node->m_fillGradient.stops, node->m_fillGradient.spread); - QSGTexture *t = QQuickShapeGradientCache::cacheForRhi(state.rhi())->get(cacheKey); + const QSGGradientCacheKey cacheKey(node->m_fillGradient.stops, QGradient::Spread(node->m_fillGradient.spread)); + QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey); t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch()); *texture = t; } @@ -1024,8 +1071,8 @@ int QQuickShapeConicalGradientMaterial::compare(const QSGMaterial *other) const if (a == b) return 0; - const QQuickAbstractPathRenderer::GradientDesc *ga = &a->m_fillGradient; - const QQuickAbstractPathRenderer::GradientDesc *gb = &b->m_fillGradient; + const QSGGradientCache::GradientDesc *ga = &a->m_fillGradient; + const QSGGradientCache::GradientDesc *gb = &b->m_fillGradient; if (int d = ga->a.x() - gb->a.x()) return d; @@ -1045,13 +1092,16 @@ int QQuickShapeConicalGradientMaterial::compare(const QSGMaterial *other) const return d; } + if (int d = a->m_fillTransform.compareTo(b->m_fillTransform)) + return d; + return 0; } QSGMaterialShader *QQuickShapeConicalGradientMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { Q_UNUSED(renderMode); - return new QQuickShapeConicalGradientRhiShader; + return new QQuickShapeConicalGradientRhiShader(viewCount()); } QT_END_NAMESPACE |