6#include <QtGui/private/qtriangulator_p.h>
7#include <QtGui/private/qtriangulatingstroker_p.h>
9#include <QSGVertexColorMaterial>
10#include <QSGTextureProvider>
11#include <private/qsgplaintexture_p.h>
13#include <QtQuick/private/qsggradientcache_p.h>
34 c.getRgbF(&r, &g, &b, &a);
36 uchar(qRound(r * a * 255)),
37 uchar(qRound(g * a * 255)),
38 uchar(qRound(b * a * 255)),
39 uchar(qRound(a * 255))
47 setFlag(QSGNode::OwnsGeometry,
true);
48 setFlag(QSGNode::UsePreprocess,
true);
49 setGeometry(
new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0));
50 activateMaterial(window, MatSolidColor);
52 qsgnode_set_description(
this, QLatin1String(
"stroke-fill"));
62 m_material.reset(QQuickShapeGenericMaterialFactory::createVertexColor(window));
64 case MatLinearGradient:
65 m_material.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(window,
this));
67 case MatRadialGradient:
68 m_material.reset(QQuickShapeGenericMaterialFactory::createRadialGradient(window,
this));
70 case MatConicalGradient:
71 m_material.reset(QQuickShapeGenericMaterialFactory::createConicalGradient(window,
this));
74 m_material.reset(QQuickShapeGenericMaterialFactory::createTextureFill(window,
this));
77 qWarning(
"Unknown material %d", m);
81 if (material() != m_material.data())
82 setMaterial(m_material.data());
87 if (m_fillTextureProvider !=
nullptr) {
88 if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(m_fillTextureProvider->texture()))
89 texture->updateTexture();
95 markDirty(QSGNode::DirtyMaterial);
100 m_fillTextureProvider =
nullptr;
101 markDirty(QSGNode::DirtyMaterial);
106 for (ShapePathData &d : m_sp) {
108 d.pendingFill->orphaned =
true;
110 d.pendingStroke->orphaned =
true;
119 for (
int i = totalCount; i < m_sp.size(); i++)
120 setFillTextureProvider(i,
nullptr);
122 if (m_sp.size() != totalCount) {
123 m_sp.resize(totalCount);
125 *countChanged =
true;
127 *countChanged =
false;
129 for (ShapePathData &d : m_sp)
135 ShapePathData &d(m_sp[index]);
142 ShapePathData &d(m_sp[index]);
143 const bool wasTransparent = d.strokeColor
.a == 0;
144 d.strokeColor = colorToColor4ub(color);
145 const bool isTransparent = d.strokeColor
.a == 0;
147 if (wasTransparent && !isTransparent)
153 ShapePathData &d(m_sp[index]);
162 ShapePathData &d(m_sp[index]);
163 d.pen.setCosmetic(c);
171 ShapePathData &d(m_sp[index]);
172 const bool wasTransparent = d.fillColor
.a == 0;
173 d.fillColor = colorToColor4ub(color);
174 const bool isTransparent = d.fillColor
.a == 0;
176 if (wasTransparent && !isTransparent)
182 ShapePathData &d(m_sp[index]);
183 d.fillRule = Qt::FillRule(fillRule);
189 ShapePathData &d(m_sp[index]);
190 d.pen.setJoinStyle(Qt::PenJoinStyle(joinStyle));
191 d.pen.setMiterLimit(miterLimit);
197 ShapePathData &d(m_sp[index]);
198 d.pen.setCapStyle(Qt::PenCapStyle(capStyle));
203 qreal dashOffset,
const QList<qreal> &dashPattern)
205 ShapePathData &d(m_sp[index]);
206 d.pen.setStyle(Qt::PenStyle(strokeStyle));
207 if (strokeStyle == QQuickShapePath::DashLine) {
208 d.pen.setDashPattern(dashPattern);
209 d.pen.setDashOffset(dashOffset);
217 Q_ASSERT(dst !=
nullptr);
218 if (gradient ==
nullptr)
219 return QQuickAbstractPathRenderer::NoGradient;
221 dst->stops = gradient->gradientStops();
222 dst->spread = QGradient::Spread(gradient->spread());
223 if (
const QQuickShapeLinearGradient *g = qobject_cast<
const QQuickShapeLinearGradient *>(gradient)) {
224 dst->a = QPointF(g->x1(), g->y1());
225 dst->b = QPointF(g->x2(), g->y2());
227 return QQuickAbstractPathRenderer::LinearGradient;
228 }
else if (
const QQuickShapeRadialGradient *g = qobject_cast<
const QQuickShapeRadialGradient *>(gradient)) {
229 dst->a = QPointF(g->centerX(), g->centerY());
230 dst->b = QPointF(g->focalX(), g->focalY());
231 dst->v0 = g->centerRadius();
232 dst->v1 = g->focalRadius();
234 return QQuickAbstractPathRenderer::RadialGradient;
235 }
else if (
const QQuickShapeConicalGradient *g = qobject_cast<
const QQuickShapeConicalGradient *>(gradient)) {
236 dst->a = QPointF(g->centerX(), g->centerY());
237 dst->v0 = g->angle();
239 return QQuickAbstractPathRenderer::ConicalGradient;
242 Q_UNREACHABLE_RETURN(QQuickAbstractPathRenderer::NoGradient);
247 ShapePathData &d(m_sp[index]);
248 d.fillGradientActive = copyGenericGradient(gradient, &d.fillGradient);
254 ShapePathData &d(m_sp[index]);
255 d.strokeGradientActive = copyGenericGradient(gradient, &d.strokeGradient);
261 ShapePathData &d(m_sp[index]);
262 if ((d.fillTextureProviderItem ==
nullptr) != (textureProviderItem ==
nullptr))
264 if (d.fillTextureProviderItem !=
nullptr)
265 QQuickItemPrivate::get(d.fillTextureProviderItem)->derefWindow();
266 d.fillTextureProviderItem = textureProviderItem;
267 if (d.fillTextureProviderItem !=
nullptr)
268 QQuickItemPrivate::get(d.fillTextureProviderItem)->refWindow(m_item->window());
274 for (
auto &pathData : m_sp) {
275 if (pathData.fillTextureProviderItem !=
nullptr) {
276 if (window ==
nullptr)
277 QQuickItemPrivate::get(pathData.fillTextureProviderItem)->derefWindow();
279 QQuickItemPrivate::get(pathData.fillTextureProviderItem)->refWindow(window);
287 ShapePathData &d(m_sp[index]);
288 d.fillTransform = transform;
294 ShapePathData &d(m_sp[index]);
295 d.triangulationScale = scale;
304 QMetaObject::invokeMethod(qApp, [
this]() { emit done(
this); }, Qt::QueuedConnection);
311 QMetaObject::invokeMethod(qApp, [
this]() { emit done(
this); }, Qt::QueuedConnection);
316 m_asyncCallback = callback;
317 m_asyncCallbackData = data;
321static QThreadPool *pathWorkThreadPool =
nullptr;
323static void deletePathWorkThreadPool()
325 delete pathWorkThreadPool;
326 pathWorkThreadPool =
nullptr;
332#if !QT_CONFIG(thread)
338 bool didKickOffAsync =
false;
340 for (
int i = 0; i < m_sp.size(); ++i) {
341 ShapePathData &d(m_sp[i]);
345 m_accDirty |= d.syncDirty;
352 d.effectiveDirty |= d.syncDirty;
354 if (d.path.isEmpty()) {
355 d.fillVertices.clear();
356 d.fillIndices.clear();
357 d.strokeVertices.clear();
362 if (async && !pathWorkThreadPool) {
363 qAddPostRoutine(deletePathWorkThreadPool);
364 pathWorkThreadPool =
new QThreadPool;
365 const int idealCount = QThread::idealThreadCount();
366 pathWorkThreadPool->setMaxThreadCount(idealCount > 0 ? idealCount * 2 : 4);
377 const bool supportsElementIndexUint = m_rhiBackendInitialized ? m_supportsElementIndexUint :
true;
379 d.path.setFillRule(d.fillRule);
380 if (m_api == QSGRendererInterface::Unknown)
381 m_api = m_item->window()->rendererInterface()->graphicsApi();
384 r->setAutoDelete(
false);
391 r->triangulationScale = d.triangulationScale;
394 QObject::connect(r, &QQuickShapeFillRunnable::done, qApp, [
this, i](QQuickShapeFillRunnable *r) {
397 if (!r->orphaned && i < m_sp.size()) {
398 ShapePathData &d(m_sp[i]);
399 d.fillVertices = r->fillVertices;
400 d.fillIndices = r->fillIndices;
401 d.indexType = r->indexType;
402 d.pendingFill =
nullptr;
403 d.effectiveDirty |= DirtyFillGeom;
404 maybeUpdateAsyncItem();
408 didKickOffAsync =
true;
412 qtVectorPathForPath(r->path);
413 pathWorkThreadPool->start(r);
416 triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices, &d.indexType,
417 supportsElementIndexUint,
418 d.triangulationScale);
422 if ((d.syncDirty &
DirtyStrokeGeom) && d.strokeWidth > 0.0f && (d.strokeColor
.a || d.strokeGradientActive)) {
425 r->setAutoDelete(
false);
432 r->clipSize = QSize(m_item->width(), m_item->height());
433 r->triangulationScale = d.triangulationScale;
434 QObject::connect(r, &QQuickShapeStrokeRunnable::done, qApp, [
this, i](QQuickShapeStrokeRunnable *r) {
435 if (!r->orphaned && i < m_sp.size()) {
436 ShapePathData &d(m_sp[i]);
437 d.strokeVertices = r->strokeVertices;
438 d.pendingStroke =
nullptr;
439 d.effectiveDirty |= DirtyStrokeGeom;
440 maybeUpdateAsyncItem();
444 didKickOffAsync =
true;
448 qtVectorPathForPath(r->path);
449 pathWorkThreadPool->start(r);
452 triangulateStroke(d.path, d.pen, d.strokeColor, &d.strokeVertices,
453 QSize(m_item->width(), m_item->height()), d.triangulationScale);
458 if (!didKickOffAsync && async && m_asyncCallback)
459 m_asyncCallback(m_asyncCallbackData);
464 for (
const ShapePathData &d : std::as_const(m_sp)) {
465 if (d.pendingFill || d.pendingStroke)
471 m_asyncCallback(m_asyncCallbackData);
480 QSGGeometry::Type *indexType,
481 bool supportsElementIndexUint,
482 qreal triangulationScale)
484 const QVectorPath &vp = qtVectorPathForPath(path);
486 QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(triangulationScale, triangulationScale), 1, supportsElementIndexUint);
487 const int vertexCount = ts.vertices.size() / 2;
488 fillVertices->resize(vertexCount);
490 const qreal *vsrc = ts.vertices.constData();
491 for (
int i = 0; i < vertexCount; ++i)
492 vdst[i]
.set(vsrc[i * 2] / triangulationScale
, vsrc[i * 2 + 1] / triangulationScale
, fillColor
);
494 size_t indexByteSize;
495 if (ts.indices.type() == QVertexIndexVector::UnsignedShort) {
496 *indexType = QSGGeometry::UnsignedShortType;
499 fillIndices->resize(ts.indices.size() / 2);
500 indexByteSize = ts.indices.size() *
sizeof(quint16);
502 *indexType = QSGGeometry::UnsignedIntType;
503 fillIndices->resize(ts.indices.size());
504 indexByteSize = ts.indices.size() *
sizeof(quint32);
506 memcpy(fillIndices->data(), ts.indices.data(), indexByteSize);
513 const QSize &clipSize,
514 qreal triangulationScale)
516 const QVectorPath &vp = qtVectorPathForPath(path);
517 const QRectF clip(QPointF(0, 0), clipSize);
518 const qreal inverseScale = 1.0 / triangulationScale;
520 QTriangulatingStroker stroker;
521 stroker.setInvScale(inverseScale);
523 if (pen.style() == Qt::SolidLine) {
524 stroker.process(vp, pen, clip, {});
526 QDashedStrokeProcessor dashStroker;
527 dashStroker.setInvScale(inverseScale);
528 dashStroker.process(vp, pen, clip, {});
529 QVectorPath dashStroke(dashStroker.points(), dashStroker.elementCount(),
530 dashStroker.elementTypes(), 0);
531 stroker.process(dashStroke, pen, clip, {});
534 if (!stroker.vertexCount()) {
535 strokeVertices->clear();
539 const int vertexCount = stroker.vertexCount() / 2;
540 strokeVertices->resize(vertexCount);
542 const float *vsrc = stroker.vertices();
543 for (
int i = 0; i < vertexCount; ++i)
544 vdst[i]
.set(vsrc[i * 2]
, vsrc[i * 2 + 1]
, strokeColor
);
549 if (m_rootNode != node) {
558 if (!m_rootNode || !m_accDirty)
562 if (!m_rhiBackendInitialized) {
563 auto findRHIBackend = [](QQuickItem *item) -> QRhi * {
564 if (
auto *w = item->window()) {
565 if (
auto *rhi = QQuickWindowPrivate::get(w)->rhi)
570 auto *rhi = findRHIBackend(m_item);
571 if (rhi !=
nullptr) {
572 m_rhiBackendInitialized =
true;
573 m_supportsElementIndexUint = rhi->isFeatureSupported(QRhi::ElementIndexUint);
590 for (ShapePathData &d : m_sp) {
593 *nodePtr =
new QQuickShapeGenericNode;
594 prevNode->m_next = *nodePtr;
595 prevNode->appendChildNode(*nodePtr);
598 QQuickShapeGenericNode *node = *nodePtr;
600 if (m_accDirty & DirtyList) {
601 d.effectiveDirty |= DirtyFillGeom | DirtyStrokeGeom | DirtyColor | DirtyFillGradient
602 | DirtyFillTransform | DirtyFillTexture | DirtyStrokeGradient;
605 if (!d.effectiveDirty) {
607 nodePtr = &node->m_next;
611 if (d.fillColor.a == 0) {
612 delete node->m_fillNode;
613 node->m_fillNode =
nullptr;
614 }
else if (!node->m_fillNode) {
615 node->m_fillNode =
new QQuickShapeGenericStrokeFillNode(m_item->window());
616 if (node->m_strokeNode)
617 node->removeChildNode(node->m_strokeNode);
618 node->appendChildNode(node->m_fillNode);
619 if (node->m_strokeNode)
620 node->appendChildNode(node->m_strokeNode);
621 d.effectiveDirty |= DirtyFillGeom;
624 if (d.strokeWidth <= 0.0f || d.strokeColor.a == 0) {
625 delete node->m_strokeNode;
626 node->m_strokeNode =
nullptr;
627 }
else if (!node->m_strokeNode) {
628 node->m_strokeNode =
new QQuickShapeGenericStrokeFillNode(m_item->window());
629 node->appendChildNode(node->m_strokeNode);
630 d.effectiveDirty |= DirtyStrokeGeom;
633 updateFillNode(&d, node);
634 updateStrokeNode(&d, node);
636 d.effectiveDirty = 0;
639 nodePtr = &node->m_next;
642 if (*nodePtr && prevNode) {
643 prevNode->removeChildNode(*nodePtr);
648 if (m_sp.isEmpty()) {
662 if (d->fillGradientActive) {
664 n->m_gradient = d->fillGradient;
668 bool needsUpdate = d->fillTextureProviderItem ==
nullptr && n->m_fillTextureProvider !=
nullptr;
670 && d->fillTextureProviderItem !=
nullptr
671 && n->m_fillTextureProvider != d->fillTextureProviderItem->textureProvider()) {
676 if (n->m_fillTextureProvider !=
nullptr) {
677 QObject::disconnect(n->m_fillTextureProvider, &QSGTextureProvider::textureChanged,
678 n, &QQuickShapeGenericStrokeFillNode::handleTextureChanged);
679 QObject::disconnect(n->m_fillTextureProvider, &QSGTextureProvider::destroyed,
680 n, &QQuickShapeGenericStrokeFillNode::handleTextureProviderDestroyed);
683 n->m_fillTextureProvider = d->fillTextureProviderItem ==
nullptr
685 : d->fillTextureProviderItem->textureProvider();
687 if (n->m_fillTextureProvider !=
nullptr) {
688 QObject::connect(n->m_fillTextureProvider, &QSGTextureProvider::textureChanged,
689 n, &QQuickShapeGenericStrokeFillNode::handleTextureChanged);
690 QObject::connect(n->m_fillTextureProvider, &QSGTextureProvider::destroyed,
691 n, &QQuickShapeGenericStrokeFillNode::handleTextureProviderDestroyed);
696 n->m_fillTransform = d->fillTransform;
709 updateShadowDataInNode(d, n);
711 QSGGeometry *g = n->geometry();
712 if (d->fillVertices.isEmpty()) {
713 if (g->vertexCount() || g->indexCount()) {
715 n->markDirty(QSGNode::DirtyGeometry);
720 if (d->fillGradientActive) {
722 switch (d->fillGradientActive) {
729 case ConicalGradient:
733 Q_UNREACHABLE_RETURN();
735 n->activateMaterial(m_item->window(), gradMat);
738 n->markDirty(QSGNode::DirtyMaterial);
743 }
else if (d->fillTextureProviderItem !=
nullptr) {
746 n->markDirty(QSGNode::DirtyMaterial);
750 if ((d->effectiveDirty &
DirtyColor) && !(d->effectiveDirty &
DirtyFillGeom) && d->fillTextureProviderItem ==
nullptr) {
751 ColoredVertex *vdst =
reinterpret_cast<ColoredVertex *>(g->vertexData());
752 for (
int i = 0; i < g->vertexCount(); ++i)
754 n->markDirty(QSGNode::DirtyGeometry);
759 const int indexCount = d->indexType == QSGGeometry::UnsignedShortType
760 ? d->fillIndices.size() * 2 : d->fillIndices.size();
761 if (g->indexType() != d->indexType) {
762 g =
new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(),
763 d->fillVertices.size(), indexCount, d->indexType);
766 g->allocate(d->fillVertices.size(), indexCount);
768 g->setDrawingMode(QSGGeometry::DrawTriangles);
770 memcpy(g->vertexData(), d->fillVertices.constData(), g->vertexCount() * g->sizeOfVertex());
771 memcpy(g->indexData(), d->fillIndices.constData(), g->indexCount() * g->sizeOfIndex());
773 n->markDirty(QSGNode::DirtyGeometry);
784 if (d->strokeGradientActive) {
786 n->m_gradient = d->strokeGradient;
789 QSGGeometry *g = n->geometry();
790 if (d->strokeVertices.isEmpty()) {
791 if (g->vertexCount() || g->indexCount()) {
793 n->markDirty(QSGNode::DirtyGeometry);
798 n->markDirty(QSGNode::DirtyGeometry);
803 if (!g->vertexCount())
804 n->markDirty(QSGNode::DirtyMaterial);
806 if (d->strokeGradientActive) {
808 switch (d->strokeGradientActive) {
815 case ConicalGradient:
819 Q_UNREACHABLE_RETURN();
821 n->activateMaterial(m_item->window(), gradMat);
824 n->markDirty(QSGNode::DirtyMaterial);
832 ColoredVertex *vdst =
reinterpret_cast<ColoredVertex *>(g->vertexData());
833 for (
int i = 0; i < g->vertexCount(); ++i)
839 g->allocate(d->strokeVertices.size(), 0);
840 g->setDrawingMode(QSGGeometry::DrawTriangleStrip);
841 memcpy(g->vertexData(), d->strokeVertices.constData(), g->vertexCount() * g->sizeOfVertex());
846 QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
848 if (api == QSGRendererInterface::OpenGL || QSGRendererInterface::isApiRhiBased(api))
849 return new QSGVertexColorMaterial;
851 qWarning(
"Vertex-color material: Unsupported graphics API %d", api);
858 QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
860 if (api == QSGRendererInterface::OpenGL || QSGRendererInterface::isApiRhiBased(api))
863 qWarning(
"Linear gradient material: Unsupported graphics API %d", api);
870 QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
872 if (api == QSGRendererInterface::OpenGL || QSGRendererInterface::isApiRhiBased(api))
875 qWarning(
"Radial gradient material: Unsupported graphics API %d", api);
882 QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
884 if (api == QSGRendererInterface::OpenGL || QSGRendererInterface::isApiRhiBased(api))
887 qWarning(
"Conical gradient material: Unsupported graphics API %d", api);
894 QSGRendererInterface::GraphicsApi api = window->rendererInterface()->graphicsApi();
896 if (api == QSGRendererInterface::OpenGL || QSGRendererInterface::isApiRhiBased(api))
899 qWarning(
"Texture fill material: Unsupported graphics API %d", api);
905 setShaderFileName(VertexStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/lineargradient.vert.qsb"), viewCount);
906 setShaderFileName(FragmentStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/lineargradient.frag.qsb"), viewCount);
910 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
912 Q_ASSERT(oldMaterial ==
nullptr || newMaterial->type() == oldMaterial->type());
914 bool changed =
false;
915 QByteArray *buf = state.uniformData();
916 Q_ASSERT(buf->size() >= 84 + 64);
917 const int shaderMatrixCount = newMaterial->viewCount();
918 const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount);
920 if (state.isMatrixDirty()) {
921 for (
int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
922 const QMatrix4x4 m = state.combinedMatrix();
923 memcpy(buf->data() + 64 * viewIndex, m.constData(), 64);
930 if (!oldMaterial || m_fillTransform != node->m_fillTransform) {
931 memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64);
932 m_fillTransform = node->m_fillTransform;
936 if (!oldMaterial || m_gradA.x() != node->m_gradient.a.x() || m_gradA.y() != node->m_gradient.a.y()) {
937 m_gradA = QVector2D(node->m_gradient.a.x(), node->m_gradient.a.y());
938 Q_ASSERT(
sizeof(m_gradA) == 8);
939 memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_gradA, 8);
943 if (!oldMaterial || m_gradB.x() != node->m_gradient.b.x() || m_gradB.y() != node->m_gradient.b.y()) {
944 m_gradB = QVector2D(node->m_gradient.b.x(), node->m_gradient.b.y());
945 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &m_gradB, 8);
949 if (state.isOpacityDirty()) {
950 const float opacity = state.opacity();
951 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8, &opacity, 4);
959 QSGMaterial *newMaterial, QSGMaterial *)
966 const QSGGradientCacheKey cacheKey(node->m_gradient.stops, QGradient::Spread(node->m_gradient.spread));
967 QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey);
968 t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
974 static QSGMaterialType type;
980 Q_ASSERT(other && type() == other->type());
989 const QSGGradientCache::GradientDesc *ga = &a->m_gradient;
990 const QSGGradientCache::GradientDesc *gb = &b->m_gradient;
992 if (
int d = ga->spread - gb->spread)
995 if (
int d = ga->a.x() - gb->a.x())
997 if (
int d = ga->a.y() - gb->a.y())
999 if (
int d = ga->b.x() - gb->b.x())
1001 if (
int d = ga->b.y() - gb->b.y())
1004 if (
int d = ga->stops.size() - gb->stops.size())
1007 for (
int i = 0; i < ga->stops.size(); ++i) {
1008 if (
int d = ga->stops[i].first - gb->stops[i].first)
1010 if (
int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba())
1014 if (
int d = a->m_fillTransform.compareTo(b->m_fillTransform))
1022 Q_UNUSED(renderMode);
1028 setShaderFileName(VertexStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/radialgradient.vert.qsb"), viewCount);
1029 setShaderFileName(FragmentStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/radialgradient.frag.qsb"), viewCount);
1033 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
1035 Q_ASSERT(oldMaterial ==
nullptr || newMaterial->type() == oldMaterial->type());
1037 bool changed =
false;
1038 QByteArray *buf = state.uniformData();
1039 Q_ASSERT(buf->size() >= 92 + 64);
1040 const int shaderMatrixCount = newMaterial->viewCount();
1041 const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount);
1043 if (state.isMatrixDirty()) {
1044 for (
int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
1045 const QMatrix4x4 m = state.combinedMatrix();
1046 memcpy(buf->data() + 64 * viewIndex, m.constData(), 64);
1053 if (!oldMaterial || m_fillTransform != node->m_fillTransform) {
1054 memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64);
1055 m_fillTransform = node->m_fillTransform;
1059 const QPointF centerPoint = node->m_gradient.a;
1060 const QPointF focalPoint = node->m_gradient.b;
1061 const QPointF focalToCenter = centerPoint - focalPoint;
1062 const float centerRadius = node->m_gradient.v0;
1063 const float focalRadius = node->m_gradient.v1;
1065 if (!oldMaterial || m_focalPoint.x() != focalPoint.x() || m_focalPoint.y() != focalPoint.y()) {
1066 m_focalPoint = QVector2D(focalPoint.x(), focalPoint.y());
1067 Q_ASSERT(
sizeof(m_focalPoint) == 8);
1068 memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_focalPoint, 8);
1072 if (!oldMaterial || m_focalToCenter.x() != focalToCenter.x() || m_focalToCenter.y() != focalToCenter.y()) {
1073 m_focalToCenter = QVector2D(focalToCenter.x(), focalToCenter.y());
1074 Q_ASSERT(
sizeof(m_focalToCenter) == 8);
1075 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &m_focalToCenter, 8);
1079 if (!oldMaterial || m_centerRadius != centerRadius) {
1080 m_centerRadius = centerRadius;
1081 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8, &m_centerRadius, 4);
1085 if (!oldMaterial || m_focalRadius != focalRadius) {
1086 m_focalRadius = focalRadius;
1087 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8 + 4, &m_focalRadius, 4);
1091 if (state.isOpacityDirty()) {
1092 const float opacity = state.opacity();
1093 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 8 + 4 + 4, &opacity, 4);
1101 QSGMaterial *newMaterial, QSGMaterial *)
1108 const QSGGradientCacheKey cacheKey(node->m_gradient.stops, QGradient::Spread(node->m_gradient.spread));
1109 QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey);
1110 t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
1116 static QSGMaterialType type;
1122 Q_ASSERT(other && type() == other->type());
1131 const QSGGradientCache::GradientDesc *ga = &a->m_gradient;
1132 const QSGGradientCache::GradientDesc *gb = &b->m_gradient;
1134 if (
int d = ga->spread - gb->spread)
1137 if (
int d = ga->a.x() - gb->a.x())
1139 if (
int d = ga->a.y() - gb->a.y())
1141 if (
int d = ga->b.x() - gb->b.x())
1143 if (
int d = ga->b.y() - gb->b.y())
1146 if (
int d = ga->v0 - gb->v0)
1148 if (
int d = ga->v1 - gb->v1)
1151 if (
int d = ga->stops.size() - gb->stops.size())
1154 for (
int i = 0; i < ga->stops.size(); ++i) {
1155 if (
int d = ga->stops[i].first - gb->stops[i].first)
1157 if (
int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba())
1161 if (
int d = a->m_fillTransform.compareTo(b->m_fillTransform))
1169 Q_UNUSED(renderMode);
1175 setShaderFileName(VertexStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/conicalgradient.vert.qsb"), viewCount);
1176 setShaderFileName(FragmentStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/conicalgradient.frag.qsb"), viewCount);
1180 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
1182 Q_ASSERT(oldMaterial ==
nullptr || newMaterial->type() == oldMaterial->type());
1184 bool changed =
false;
1185 QByteArray *buf = state.uniformData();
1186 Q_ASSERT(buf->size() >= 80 + 64);
1187 const int shaderMatrixCount = newMaterial->viewCount();
1188 const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount);
1190 if (state.isMatrixDirty()) {
1191 for (
int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
1192 const QMatrix4x4 m = state.combinedMatrix();
1193 memcpy(buf->data() + 64 * viewIndex, m.constData(), 64);
1200 if (!oldMaterial || m_fillTransform != node->m_fillTransform) {
1201 memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64);
1202 m_fillTransform = node->m_fillTransform;
1206 const QPointF centerPoint = node->m_gradient.a;
1207 const float angle = -qDegreesToRadians(node->m_gradient.v0);
1209 if (!oldMaterial || m_centerPoint.x() != centerPoint.x() || m_centerPoint.y() != centerPoint.y()) {
1210 m_centerPoint = QVector2D(centerPoint.x(), centerPoint.y());
1211 Q_ASSERT(
sizeof(m_centerPoint) == 8);
1212 memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_centerPoint, 8);
1216 if (!oldMaterial || m_angle != angle) {
1218 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &m_angle, 4);
1222 if (state.isOpacityDirty()) {
1223 const float opacity = state.opacity();
1224 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8 + 4, &opacity, 4);
1232 QSGMaterial *newMaterial, QSGMaterial *)
1239 const QSGGradientCacheKey cacheKey(node->m_gradient.stops, QGradient::Spread(node->m_gradient.spread));
1240 QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey);
1241 t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
1247 static QSGMaterialType type;
1253 Q_ASSERT(other && type() == other->type());
1262 const QSGGradientCache::GradientDesc *ga = &a->m_gradient;
1263 const QSGGradientCache::GradientDesc *gb = &b->m_gradient;
1265 if (
int d = ga->a.x() - gb->a.x())
1267 if (
int d = ga->a.y() - gb->a.y())
1270 if (
int d = ga->v0 - gb->v0)
1273 if (
int d = ga->stops.size() - gb->stops.size())
1276 for (
int i = 0; i < ga->stops.size(); ++i) {
1277 if (
int d = ga->stops[i].first - gb->stops[i].first)
1279 if (
int d = ga->stops[i].second.rgba() - gb->stops[i].second.rgba())
1283 if (
int d = a->m_fillTransform.compareTo(b->m_fillTransform))
1291 Q_UNUSED(renderMode);
1297 setShaderFileName(VertexStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/texturefill.vert.qsb"), viewCount);
1298 setShaderFileName(FragmentStage, QStringLiteral(
":/qt-project.org/shapes/shaders_ng/texturefill.frag.qsb"), viewCount);
1302 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
1304 Q_ASSERT(oldMaterial ==
nullptr || newMaterial->type() == oldMaterial->type());
1306 bool changed =
false;
1307 QByteArray *buf = state.uniformData();
1308 const int shaderMatrixCount = newMaterial->viewCount();
1309 const int matrixCount = qMin(state.projectionMatrixCount(), shaderMatrixCount);
1310 Q_ASSERT(buf->size() >= 64 * shaderMatrixCount + 64 + 8 + 4);
1312 if (state.isMatrixDirty()) {
1313 for (
int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
1314 const QMatrix4x4 m = state.combinedMatrix();
1315 memcpy(buf->data() + 64 * viewIndex, m.constData(), 64);
1322 if (!oldMaterial || m_fillTransform != node->m_fillTransform) {
1323 memcpy(buf->data() + 64 * shaderMatrixCount, node->m_fillTransform.invertedData(), 64);
1324 m_fillTransform = node->m_fillTransform;
1328 const QSizeF boundsSize = node->m_fillTextureProvider !=
nullptr && node->m_fillTextureProvider->texture() !=
nullptr
1329 ? node->m_fillTextureProvider->texture()->textureSize()
1333 const QVector2D boundsVector(boundsSize.width() / state.devicePixelRatio(),
1334 boundsSize.height() / state.devicePixelRatio());
1335 if (!oldMaterial || m_boundsSize != boundsVector) {
1336 m_boundsSize = boundsVector;
1337 Q_ASSERT(
sizeof(m_boundsSize) == 8);
1338 memcpy(buf->data() + 64 * shaderMatrixCount + 64, &m_boundsSize, 8);
1342 if (state.isOpacityDirty()) {
1343 const float opacity = state.opacity();
1344 memcpy(buf->data() + 64 * shaderMatrixCount + 64 + 8, &opacity, 4);
1352 QSGMaterial *newMaterial, QSGMaterial *)
1359 if (node->m_fillTextureProvider !=
nullptr) {
1360 QSGTexture *providedTexture = node->m_fillTextureProvider->texture();
1361 if (providedTexture !=
nullptr) {
1362 if (providedTexture->isAtlasTexture()) {
1366 QSGTexture *newTexture = providedTexture->removedFromAtlas(state.resourceUpdateBatch());
1367 if (newTexture !=
nullptr)
1368 providedTexture = newTexture;
1371 providedTexture->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
1372 *texture = providedTexture;
1377 if (m->dummyTexture() ==
nullptr) {
1378 QSGPlainTexture *dummyTexture =
new QSGPlainTexture;
1379 dummyTexture->setFiltering(QSGTexture::Nearest);
1380 dummyTexture->setHorizontalWrapMode(QSGTexture::Repeat);
1381 dummyTexture->setVerticalWrapMode(QSGTexture::Repeat);
1382 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
1384 dummyTexture->setImage(img);
1385 dummyTexture->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
1387 m->setDummyTexture(dummyTexture);
1390 *texture = m->dummyTexture();
1395 delete m_dummyTexture;
1400 static QSGMaterialType type;
1406 Q_ASSERT(other && type() == other->type());
1415 if (
int d = a->m_fillTransform.compareTo(b->m_fillTransform))
1418 const qintptr diff = qintptr(a->m_fillTextureProvider) - qintptr(b->m_fillTextureProvider);
1419 return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
1424 Q_UNUSED(renderMode);
1430#include "moc_qquickshapegenericrenderer_p.cpp"
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QQuickShapeConicalGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QQuickShapeGenericStrokeFillNode * node() const
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
QQuickShapeConicalGradientRhiShader(int viewCount)
bool supportsElementIndexUint
QQuickShapeGenericRenderer::Color4ub fillColor
QQuickShapeGenericRenderer::VertexContainerType fillVertices
QQuickShapeGenericRenderer::IndexContainerType fillIndices
QQuickShapeGenericStrokeFillNode * m_fillNode
QQuickShapeGenericStrokeFillNode * m_strokeNode
QQuickShapeGenericNode * m_next
void setAsyncCallback(void(*)(void *), void *) override
void setFillGradient(int index, QQuickShapeGradient *gradient) override
void setStrokeStyle(int index, QQuickShapePath::StrokeStyle strokeStyle, qreal dashOffset, const QList< qreal > &dashPattern) override
void setFillTransform(int index, const QSGTransform &transform) override
QList< quint32 > IndexContainerType
void setCosmeticStroke(int index, bool c) override
void setStrokeGradient(int index, QQuickShapeGradient *gradient) override
QList< QSGGeometry::ColoredPoint2D > VertexContainerType
void setPath(int index, const QPainterPath &path, QQuickShapePath::PathHints pathHints={}) override
void setStrokeColor(int index, const QColor &color) override
void setFillRule(int index, QQuickShapePath::FillRule fillRule) override
void setFillTextureProvider(int index, QQuickItem *textureProviderItem) override
void setFillColor(int index, const QColor &color) override
void setTriangulationScale(int index, qreal scale) override
void setJoinStyle(int index, QQuickShapePath::JoinStyle joinStyle, int miterLimit) override
void setStrokeWidth(int index, qreal w) override
~QQuickShapeGenericRenderer()
void setRootNode(QQuickShapeGenericNode *node)
void handleSceneChange(QQuickWindow *window) override
void beginSync(int totalCount, bool *countChanged) override
void setCapStyle(int index, QQuickShapePath::CapStyle capStyle) override
void updateNode() override
void endSync(bool async) override
void preprocess() override
Override this function to do processing on the node before it is rendered.
void activateMaterial(QQuickWindow *window, Material m)
QQuickShapeLinearGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QQuickShapeGenericStrokeFillNode * node() const
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
QQuickShapeLinearGradientRhiShader(int viewCount)
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
QQuickShapeGenericStrokeFillNode * node() const
QQuickShapeRadialGradientMaterial(QQuickShapeGenericStrokeFillNode *node)
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
QQuickShapeRadialGradientRhiShader(int viewCount)
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
QQuickShapeGenericRenderer::Color4ub strokeColor
QQuickShapeGenericRenderer::VertexContainerType strokeVertices
QQuickShapeTextureFillMaterial(QQuickShapeGenericStrokeFillNode *node)
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QQuickShapeGenericStrokeFillNode * node() const
~QQuickShapeTextureFillMaterial() override
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QQuickShapeTextureFillRhiShader(int viewCount)
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to get the contents of the shader program's uniform buffer...
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override
This function is called by the scene graph to prepare use of sampled images in the shader,...
Combined button and popup list for selecting options.
static QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor &c)
static QQuickAbstractPathRenderer::FillGradientType copyGenericGradient(const QQuickShapeGradient *gradient, QSGGradientCache::GradientDesc *dst)
#define QSG_RUNTIME_DESCRIPTION
void set(float nx, float ny, QQuickShapeGenericRenderer::Color4ub ncolor)