diff options
Diffstat (limited to 'src/quickshapes/qquickshapegenericrenderer.cpp')
-rw-r--r-- | src/quickshapes/qquickshapegenericrenderer.cpp | 252 |
1 files changed, 124 insertions, 128 deletions
diff --git a/src/quickshapes/qquickshapegenericrenderer.cpp b/src/quickshapes/qquickshapegenericrenderer.cpp index f5fcd72152..a18479f776 100644 --- a/src/quickshapes/qquickshapegenericrenderer.cpp +++ b/src/quickshapes/qquickshapegenericrenderer.cpp @@ -1,56 +1,20 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #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 QT_BEGIN_NAMESPACE -static const qreal TRI_SCALE = 1; - struct ColoredVertex // must match QSGGeometry::ColoredPoint2D { float x, y; @@ -63,11 +27,13 @@ struct ColoredVertex // must match QSGGeometry::ColoredPoint2D static inline QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor &c) { + float r, g, b, a; + c.getRgbF(&r, &g, &b, &a); QQuickShapeGenericRenderer::Color4ub color = { - uchar(qRound(c.redF() * c.alphaF() * 255)), - uchar(qRound(c.greenF() * c.alphaF() * 255)), - uchar(qRound(c.blueF() * c.alphaF() * 255)), - uchar(qRound(c.alphaF() * 255)) + uchar(qRound(r * a * 255)), + uchar(qRound(g * a * 255)), + uchar(qRound(b * a * 255)), + uchar(qRound(a * 255)) }; return color; } @@ -124,7 +90,7 @@ QQuickShapeGenericRenderer::~QQuickShapeGenericRenderer() void QQuickShapeGenericRenderer::beginSync(int totalCount, bool *countChanged) { - if (m_sp.count() != totalCount) { + if (m_sp.size() != totalCount) { m_sp.resize(totalCount); m_accDirty |= DirtyList; *countChanged = true; @@ -145,8 +111,12 @@ void QQuickShapeGenericRenderer::setPath(int index, const QQuickPath *path) void QQuickShapeGenericRenderer::setStrokeColor(int index, const QColor &color) { ShapePathData &d(m_sp[index]); + const bool wasTransparent = d.strokeColor.a == 0; d.strokeColor = colorToColor4ub(color); + const bool isTransparent = d.strokeColor.a == 0; d.syncDirty |= DirtyColor; + if (wasTransparent && !isTransparent) + d.syncDirty |= DirtyStrokeGeom; } void QQuickShapeGenericRenderer::setStrokeWidth(int index, qreal w) @@ -208,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()); @@ -232,15 +202,22 @@ void QQuickShapeGenericRenderer::setFillGradient(int index, QQuickShapeGradient d.syncDirty |= DirtyFillGradient; } +void QQuickShapeGenericRenderer::setTriangulationScale(qreal scale) +{ + // No dirty, this is called at the start of every sync. Just store the value. + m_triangulationScale = scale; +} + void QQuickShapeFillRunnable::run() { - QQuickShapeGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices, &indexType, supportsElementIndexUint); + QQuickShapeGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices, &indexType, + supportsElementIndexUint, triangulationScale); emit done(this); } void QQuickShapeStrokeRunnable::run() { - QQuickShapeGenericRenderer::triangulateStroke(path, pen, strokeColor, &strokeVertices, clipSize); + QQuickShapeGenericRenderer::triangulateStroke(path, pen, strokeColor, &strokeVertices, clipSize, triangulationScale); emit done(this); } @@ -270,7 +247,7 @@ void QQuickShapeGenericRenderer::endSync(bool async) bool didKickOffAsync = false; - for (int i = 0; i < m_sp.count(); ++i) { + for (int i = 0; i < m_sp.size(); ++i) { ShapePathData &d(m_sp[i]); if (!d.syncDirty) continue; @@ -320,12 +297,13 @@ void QQuickShapeGenericRenderer::endSync(bool async) r->path = d.path; r->fillColor = d.fillColor; r->supportsElementIndexUint = supportsElementIndexUint; + r->triangulationScale = m_triangulationScale; // Unlikely in practice but in theory m_sp could be // resized. Therefore, capture 'i' instead of 'd'. QObject::connect(r, &QQuickShapeFillRunnable::done, qApp, [this, i](QQuickShapeFillRunnable *r) { // Bail out when orphaned (meaning either another run was // started after this one, or the renderer got destroyed). - if (!r->orphaned && i < m_sp.count()) { + if (!r->orphaned && i < m_sp.size()) { ShapePathData &d(m_sp[i]); d.fillVertices = r->fillVertices; d.fillIndices = r->fillIndices; @@ -344,7 +322,9 @@ void QQuickShapeGenericRenderer::endSync(bool async) pathWorkThreadPool->start(r); #endif } else { - triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices, &d.indexType, supportsElementIndexUint); + triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices, &d.indexType, + supportsElementIndexUint, + m_triangulationScale); } } @@ -359,8 +339,9 @@ void QQuickShapeGenericRenderer::endSync(bool async) r->pen = d.pen; r->strokeColor = d.strokeColor; r->clipSize = QSize(m_item->width(), m_item->height()); + r->triangulationScale = m_triangulationScale; QObject::connect(r, &QQuickShapeStrokeRunnable::done, qApp, [this, i](QQuickShapeStrokeRunnable *r) { - if (!r->orphaned && i < m_sp.count()) { + if (!r->orphaned && i < m_sp.size()) { ShapePathData &d(m_sp[i]); d.strokeVertices = r->strokeVertices; d.pendingStroke = nullptr; @@ -378,7 +359,7 @@ void QQuickShapeGenericRenderer::endSync(bool async) #endif } else { triangulateStroke(d.path, d.pen, d.strokeColor, &d.strokeVertices, - QSize(m_item->width(), m_item->height())); + QSize(m_item->width(), m_item->height()), m_triangulationScale); } } } @@ -389,7 +370,7 @@ void QQuickShapeGenericRenderer::endSync(bool async) void QQuickShapeGenericRenderer::maybeUpdateAsyncItem() { - for (const ShapePathData &d : qAsConst(m_sp)) { + for (const ShapePathData &d : std::as_const(m_sp)) { if (d.pendingFill || d.pendingStroke) return; } @@ -402,21 +383,22 @@ void QQuickShapeGenericRenderer::maybeUpdateAsyncItem() // the stroke/fill triangulation functions may be invoked either on the gui // thread or some worker thread and must thus be self-contained. void QQuickShapeGenericRenderer::triangulateFill(const QPainterPath &path, - const Color4ub &fillColor, - VertexContainerType *fillVertices, - IndexContainerType *fillIndices, - QSGGeometry::Type *indexType, - bool supportsElementIndexUint) + const Color4ub &fillColor, + VertexContainerType *fillVertices, + IndexContainerType *fillIndices, + QSGGeometry::Type *indexType, + bool supportsElementIndexUint, + qreal triangulationScale) { const QVectorPath &vp = qtVectorPathForPath(path); - QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(TRI_SCALE, TRI_SCALE), 1, supportsElementIndexUint); - const int vertexCount = ts.vertices.count() / 2; // just a qreal vector with x,y hence the / 2 + QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(triangulationScale, triangulationScale), 1, supportsElementIndexUint); + const int vertexCount = ts.vertices.size() / 2; // just a qreal vector with x,y hence the / 2 fillVertices->resize(vertexCount); ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(fillVertices->data()); const qreal *vsrc = ts.vertices.constData(); for (int i = 0; i < vertexCount; ++i) - vdst[i].set(vsrc[i * 2] / TRI_SCALE, vsrc[i * 2 + 1] / TRI_SCALE, fillColor); + vdst[i].set(vsrc[i * 2] / triangulationScale, vsrc[i * 2 + 1] / triangulationScale, fillColor); size_t indexByteSize; if (ts.indices.type() == QVertexIndexVector::UnsignedShort) { @@ -434,14 +416,15 @@ void QQuickShapeGenericRenderer::triangulateFill(const QPainterPath &path, } void QQuickShapeGenericRenderer::triangulateStroke(const QPainterPath &path, - const QPen &pen, - const Color4ub &strokeColor, - VertexContainerType *strokeVertices, - const QSize &clipSize) + const QPen &pen, + const Color4ub &strokeColor, + VertexContainerType *strokeVertices, + const QSize &clipSize, + qreal triangulationScale) { const QVectorPath &vp = qtVectorPathForPath(path); const QRectF clip(QPointF(0, 0), clipSize); - const qreal inverseScale = 1.0 / TRI_SCALE; + const qreal inverseScale = 1.0 / triangulationScale; QTriangulatingStroker stroker; stroker.setInvScale(inverseScale); @@ -598,8 +581,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen gradMat = QQuickShapeGenericStrokeFillNode::MatConicalGradient; break; default: - Q_UNREACHABLE(); - return; + Q_UNREACHABLE_RETURN(); } n->activateMaterial(m_item->window(), gradMat); if (d->effectiveDirty & DirtyFillGradient) { @@ -622,13 +604,13 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen } const int indexCount = d->indexType == QSGGeometry::UnsignedShortType - ? d->fillIndices.count() * 2 : d->fillIndices.count(); + ? d->fillIndices.size() * 2 : d->fillIndices.size(); if (g->indexType() != d->indexType) { g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), - d->fillVertices.count(), indexCount, d->indexType); + d->fillVertices.size(), indexCount, d->indexType); n->setGeometry(g); } else { - g->allocate(d->fillVertices.count(), indexCount); + g->allocate(d->fillVertices.size(), indexCount); } g->setDrawingMode(QSGGeometry::DrawTriangles); memcpy(g->vertexData(), d->fillVertices.constData(), g->vertexCount() * g->sizeOfVertex()); @@ -669,7 +651,7 @@ void QQuickShapeGenericRenderer::updateStrokeNode(ShapePathData *d, QQuickShapeG return; } - g->allocate(d->strokeVertices.count(), 0); + g->allocate(d->strokeVertices.size(), 0); g->setDrawingMode(QSGGeometry::DrawTriangleStrip); memcpy(g->vertexData(), d->strokeVertices.constData(), g->vertexCount() * g->sizeOfVertex()); } @@ -721,10 +703,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, @@ -735,11 +717,15 @@ bool QQuickShapeLinearGradientRhiShader::updateUniformData(RenderState &state, bool changed = false; QByteArray *buf = state.uniformData(); Q_ASSERT(buf->size() >= 84); + 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(); @@ -747,19 +733,19 @@ bool QQuickShapeLinearGradientRhiShader::updateUniformData(RenderState &state, 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, &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 + 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 + 8 + 8, &opacity, 4); changed = true; } @@ -774,8 +760,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; } @@ -797,8 +783,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; @@ -812,10 +798,10 @@ int QQuickShapeLinearGradientMaterial::compare(const QSGMaterial *other) const if (int d = ga->b.y() - gb->b.y()) return d; - if (int d = ga->stops.count() - gb->stops.count()) + if (int d = ga->stops.size() - gb->stops.size()) return d; - for (int i = 0; i < ga->stops.count(); ++i) { + for (int i = 0; i < ga->stops.size(); ++i) { if (int d = ga->stops[i].first - gb->stops[i].first) return d; if (int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba()) @@ -828,28 +814,32 @@ int QQuickShapeLinearGradientMaterial::compare(const QSGMaterial *other) const 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, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type()); - QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(newMaterial); + QQuickShapeRadialGradientMaterial *m = static_cast<QQuickShapeRadialGradientMaterial *>(newMaterial); bool changed = false; QByteArray *buf = state.uniformData(); Q_ASSERT(buf->size() >= 92); + 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(); @@ -863,32 +853,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, &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 + 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 + 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 + 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 + 8 + 8 + 4 + 4, &opacity, 4); changed = true; } @@ -901,10 +891,10 @@ void QQuickShapeRadialGradientRhiShader::updateSampledImage(RenderState &state, if (binding != 1) return; - QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(newMaterial); + 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; } @@ -926,8 +916,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; @@ -946,10 +936,10 @@ int QQuickShapeRadialGradientMaterial::compare(const QSGMaterial *other) const if (int d = ga->v1 - gb->v1) return d; - if (int d = ga->stops.count() - gb->stops.count()) + if (int d = ga->stops.size() - gb->stops.size()) return d; - for (int i = 0; i < ga->stops.count(); ++i) { + for (int i = 0; i < ga->stops.size(); ++i) { if (int d = ga->stops[i].first - gb->stops[i].first) return d; if (int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba()) @@ -962,28 +952,32 @@ int QQuickShapeRadialGradientMaterial::compare(const QSGMaterial *other) const 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, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) { Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type()); - QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(newMaterial); + QQuickShapeConicalGradientMaterial *m = static_cast<QQuickShapeConicalGradientMaterial *>(newMaterial); bool changed = false; QByteArray *buf = state.uniformData(); Q_ASSERT(buf->size() >= 80); + 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(); @@ -994,19 +988,19 @@ bool QQuickShapeConicalGradientRhiShader::updateUniformData(RenderState &state, 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, &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 + 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 + 8 + 4, &opacity, 4); changed = true; } @@ -1019,10 +1013,10 @@ void QQuickShapeConicalGradientRhiShader::updateSampledImage(RenderState &state, if (binding != 1) return; - QQuickShapeLinearGradientMaterial *m = static_cast<QQuickShapeLinearGradientMaterial *>(newMaterial); + 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; } @@ -1044,8 +1038,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; @@ -1055,10 +1049,10 @@ int QQuickShapeConicalGradientMaterial::compare(const QSGMaterial *other) const if (int d = ga->v0 - gb->v0) return d; - if (int d = ga->stops.count() - gb->stops.count()) + if (int d = ga->stops.size() - gb->stops.size()) return d; - for (int i = 0; i < ga->stops.count(); ++i) { + for (int i = 0; i < ga->stops.size(); ++i) { if (int d = ga->stops[i].first - gb->stops[i].first) return d; if (int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba()) @@ -1071,7 +1065,9 @@ int QQuickShapeConicalGradientMaterial::compare(const QSGMaterial *other) const QSGMaterialShader *QQuickShapeConicalGradientMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const { Q_UNUSED(renderMode); - return new QQuickShapeConicalGradientRhiShader; + return new QQuickShapeConicalGradientRhiShader(viewCount()); } QT_END_NAMESPACE + +#include "moc_qquickshapegenericrenderer_p.cpp" |