From b9f060f6fae5734216d7088afd0e3b52165551c5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 11 Jan 2017 12:49:33 +0100 Subject: Path generic PathItem work with both ushort and uint index type Default to uint but keep supporting systems without ElementIndexUint. Change-Id: Ic15f66408e2e2ffb6406c7e854fa65ee1e0f56b3 Reviewed-by: Andy Nichols --- src/quick/items/qquickpathitemgenericrenderer.cpp | 100 ++++++++++++++++++---- src/quick/items/qquickpathitemgenericrenderer_p.h | 41 ++++++--- 2 files changed, 111 insertions(+), 30 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickpathitemgenericrenderer.cpp b/src/quick/items/qquickpathitemgenericrenderer.cpp index e36654ad0c..bf9506ba65 100644 --- a/src/quick/items/qquickpathitemgenericrenderer.cpp +++ b/src/quick/items/qquickpathitemgenericrenderer.cpp @@ -40,9 +40,15 @@ #include "qquickpathitemgenericrenderer_p.h" #include #include -#include #include +#ifndef QT_NO_OPENGL +#include +#include +#include +#include +#endif + QT_BEGIN_NAMESPACE static const qreal SCALE = 100; @@ -69,17 +75,22 @@ static inline QQuickPathItemGenericRenderer::Color4ub colorToColor4ub(const QCol } QQuickPathItemGenericStrokeFillNode::QQuickPathItemGenericStrokeFillNode(QQuickWindow *window) - : m_geometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0), + : m_geometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0)), m_window(window), m_material(nullptr) { - setGeometry(&m_geometry); + setGeometry(m_geometry); activateMaterial(MatSolidColor); #ifdef QSG_RUNTIME_DESCRIPTION qsgnode_set_description(this, QLatin1String("stroke-fill")); #endif } +QQuickPathItemGenericStrokeFillNode::~QQuickPathItemGenericStrokeFillNode() +{ + delete m_geometry; +} + void QQuickPathItemGenericStrokeFillNode::activateMaterial(Material m) { switch (m) { @@ -104,6 +115,39 @@ void QQuickPathItemGenericStrokeFillNode::activateMaterial(Material m) setMaterial(m_material); } +static bool q_supportsElementIndexUint(QSGRendererInterface::GraphicsApi api) +{ + static bool elementIndexUint = true; +#ifndef QT_NO_OPENGL + if (api == QSGRendererInterface::OpenGL) { + static bool elementIndexUintChecked = false; + if (!elementIndexUintChecked) { + elementIndexUintChecked = true; + QOpenGLContext *context = QOpenGLContext::currentContext(); + QScopedPointer dummyContext; + QScopedPointer dummySurface; + bool ok = true; + if (!context) { + dummyContext.reset(new QOpenGLContext); + dummyContext->create(); + context = dummyContext.data(); + dummySurface.reset(new QOffscreenSurface); + dummySurface->setFormat(context->format()); + dummySurface->create(); + ok = context->makeCurrent(dummySurface.data()); + } + if (ok) { + elementIndexUint = static_cast(context->functions())->hasOpenGLExtension( + QOpenGLExtensions::ElementIndexUint); + } + } + } +#else + Q_UNUSED(api); +#endif + return elementIndexUint; +} + QQuickPathItemGenericRenderer::~QQuickPathItemGenericRenderer() { for (VisualPathData &d : m_vp) { @@ -210,7 +254,7 @@ void QQuickPathItemGenericRenderer::setFillGradient(int index, QQuickPathGradien void QQuickPathItemFillRunnable::run() { - QQuickPathItemGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices); + QQuickPathItemGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices, &indexType, supportsElementIndexUint); emit done(this); } @@ -262,6 +306,8 @@ void QQuickPathItemGenericRenderer::endSync(bool async) if ((d.syncDirty & DirtyFillGeom) && d.fillColor.a) { d.path.setFillRule(d.fillRule); + if (m_api == QSGRendererInterface::Unknown) + m_api = m_item->window()->rendererInterface()->graphicsApi(); if (async) { QQuickPathItemFillRunnable *r = new QQuickPathItemFillRunnable; r->setAutoDelete(false); @@ -270,6 +316,7 @@ void QQuickPathItemGenericRenderer::endSync(bool async) d.pendingFill = r; r->path = d.path; r->fillColor = d.fillColor; + r->supportsElementIndexUint = q_supportsElementIndexUint(m_api); // Unlikely in practice but in theory m_vp could be // resized. Therefore, capture 'i' instead of 'd'. QObject::connect(r, &QQuickPathItemFillRunnable::done, qApp, [this, i](QQuickPathItemFillRunnable *r) { @@ -279,6 +326,7 @@ void QQuickPathItemGenericRenderer::endSync(bool async) VisualPathData &d(m_vp[i]); d.fillVertices = r->fillVertices; d.fillIndices = r->fillIndices; + d.indexType = r->indexType; d.pendingFill = nullptr; d.effectiveDirty |= DirtyFillGeom; maybeUpdateAsyncItem(); @@ -288,7 +336,7 @@ void QQuickPathItemGenericRenderer::endSync(bool async) didKickOffAsync = true; threadPool.start(r); } else { - triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices); + triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices, &d.indexType, q_supportsElementIndexUint(m_api)); } } @@ -342,12 +390,14 @@ void QQuickPathItemGenericRenderer::maybeUpdateAsyncItem() // thread or some worker thread and must thus be self-contained. void QQuickPathItemGenericRenderer::triangulateFill(const QPainterPath &path, const Color4ub &fillColor, - VerticesType *fillVertices, - IndicesType *fillIndices) + VertexContainerType *fillVertices, + IndexContainerType *fillIndices, + QSGGeometry::Type *indexType, + bool supportsElementIndexUint) { const QVectorPath &vp = qtVectorPathForPath(path); - QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(SCALE, SCALE)); + QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(SCALE, SCALE), 1, supportsElementIndexUint); const int vertexCount = ts.vertices.count() / 2; // just a qreal vector with x,y hence the / 2 fillVertices->resize(vertexCount); ColoredVertex *vdst = reinterpret_cast(fillVertices->data()); @@ -355,21 +405,25 @@ void QQuickPathItemGenericRenderer::triangulateFill(const QPainterPath &path, for (int i = 0; i < vertexCount; ++i) vdst[i].set(vsrc[i * 2] / SCALE, vsrc[i * 2 + 1] / SCALE, fillColor); - fillIndices->resize(ts.indices.size()); - quint16 *idst = fillIndices->data(); + size_t indexByteSize; if (ts.indices.type() == QVertexIndexVector::UnsignedShort) { - memcpy(idst, ts.indices.data(), fillIndices->count() * sizeof(quint16)); + *indexType = QSGGeometry::UnsignedShortType; + // fillIndices is still QVector. Just resize to N/2 and pack + // the N quint16s into it. + fillIndices->resize(ts.indices.size() / 2); + indexByteSize = ts.indices.size() * sizeof(quint16); } else { - const quint32 *isrc = (const quint32 *) ts.indices.data(); - for (int i = 0; i < fillIndices->count(); ++i) - idst[i] = isrc[i]; + *indexType = QSGGeometry::UnsignedIntType; + fillIndices->resize(ts.indices.size()); + indexByteSize = ts.indices.size() * sizeof(quint32); } + memcpy(fillIndices->data(), ts.indices.data(), indexByteSize); } void QQuickPathItemGenericRenderer::triangulateStroke(const QPainterPath &path, const QPen &pen, const Color4ub &strokeColor, - VerticesType *strokeVertices, + VertexContainerType *strokeVertices, const QSize &clipSize) { const QVectorPath &vp = qtVectorPathForPath(path); @@ -504,7 +558,7 @@ void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPath QQuickPathItemGenericStrokeFillNode *n = node->m_fillNode; updateShadowDataInNode(d, n); - QSGGeometry *g = &n->m_geometry; + QSGGeometry *g = n->m_geometry; if (d->fillVertices.isEmpty()) { if (g->vertexCount() || g->indexCount()) { g->allocate(0, 0); @@ -534,7 +588,17 @@ void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPath } } - g->allocate(d->fillVertices.count(), d->fillIndices.count()); + const int indexCount = d->indexType == QSGGeometry::UnsignedShortType + ? d->fillIndices.count() * 2 : d->fillIndices.count(); + if (g->indexType() != d->indexType) { + g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), + d->fillVertices.count(), indexCount, d->indexType); + n->setGeometry(g); + delete n->m_geometry; + n->m_geometry = g; + } else { + g->allocate(d->fillVertices.count(), indexCount); + } g->setDrawingMode(QSGGeometry::DrawTriangles); memcpy(g->vertexData(), d->fillVertices.constData(), g->vertexCount() * g->sizeOfVertex()); memcpy(g->indexData(), d->fillIndices.constData(), g->indexCount() * g->sizeOfIndex()); @@ -550,7 +614,7 @@ void QQuickPathItemGenericRenderer::updateStrokeNode(VisualPathData *d, QQuickPa return; QQuickPathItemGenericStrokeFillNode *n = node->m_strokeNode; - QSGGeometry *g = &n->m_geometry; + QSGGeometry *g = n->m_geometry; if (d->strokeVertices.isEmpty()) { if (g->vertexCount() || g->indexCount()) { g->allocate(0, 0); diff --git a/src/quick/items/qquickpathitemgenericrenderer_p.h b/src/quick/items/qquickpathitemgenericrenderer_p.h index ca05492841..045c52d610 100644 --- a/src/quick/items/qquickpathitemgenericrenderer_p.h +++ b/src/quick/items/qquickpathitemgenericrenderer_p.h @@ -55,6 +55,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -77,6 +78,7 @@ public: QQuickPathItemGenericRenderer(QQuickItem *item) : m_item(item), + m_api(QSGRendererInterface::Unknown), m_rootNode(nullptr), m_accDirty(0), m_asyncCallback(nullptr) @@ -103,17 +105,19 @@ public: void setRootNode(QQuickPathItemGenericNode *node); struct Color4ub { unsigned char r, g, b, a; }; - typedef QVector VerticesType; - typedef QVector IndicesType; + typedef QVector VertexContainerType; + typedef QVector IndexContainerType; static void triangulateFill(const QPainterPath &path, const Color4ub &fillColor, - VerticesType *fillVertices, - IndicesType *fillIndices); + VertexContainerType *fillVertices, + IndexContainerType *fillIndices, + QSGGeometry::Type *indexType, + bool supportsElementIndexUint); static void triangulateStroke(const QPainterPath &path, const QPen &pen, const Color4ub &strokeColor, - VerticesType *strokeVertices, + VertexContainerType *strokeVertices, const QSize &clipSize); private: @@ -128,9 +132,10 @@ private: QPainterPath path; bool fillGradientActive; QQuickPathItemGradientCache::GradientDesc fillGradient; - VerticesType fillVertices; - IndicesType fillIndices; - VerticesType strokeVertices; + VertexContainerType fillVertices; + IndexContainerType fillIndices; + QSGGeometry::Type indexType; + VertexContainerType strokeVertices; int syncDirty; int effectiveDirty = 0; QQuickPathItemFillRunnable *pendingFill = nullptr; @@ -142,6 +147,7 @@ private: void updateStrokeNode(VisualPathData *d, QQuickPathItemGenericNode *node); QQuickItem *m_item; + QSGRendererInterface::GraphicsApi m_api; QQuickPathItemGenericNode *m_rootNode; QVector m_vp; int m_accDirty; @@ -157,10 +163,16 @@ public: void run() override; bool orphaned = false; + + // input QPainterPath path; QQuickPathItemGenericRenderer::Color4ub fillColor; - QQuickPathItemGenericRenderer::VerticesType fillVertices; - QQuickPathItemGenericRenderer::IndicesType fillIndices; + bool supportsElementIndexUint; + + // output + QQuickPathItemGenericRenderer::VertexContainerType fillVertices; + QQuickPathItemGenericRenderer::IndexContainerType fillIndices; + QSGGeometry::Type indexType; Q_SIGNALS: void done(QQuickPathItemFillRunnable *self); @@ -174,12 +186,16 @@ public: void run() override; bool orphaned = false; + + // input QPainterPath path; QPen pen; QQuickPathItemGenericRenderer::Color4ub strokeColor; - QQuickPathItemGenericRenderer::VerticesType strokeVertices; QSize clipSize; + // output + QQuickPathItemGenericRenderer::VertexContainerType strokeVertices; + Q_SIGNALS: void done(QQuickPathItemStrokeRunnable *self); }; @@ -188,6 +204,7 @@ class QQuickPathItemGenericStrokeFillNode : public QSGGeometryNode { public: QQuickPathItemGenericStrokeFillNode(QQuickWindow *window); + ~QQuickPathItemGenericStrokeFillNode(); enum Material { MatSolidColor, @@ -202,7 +219,7 @@ public: QQuickPathItemGradientCache::GradientDesc m_fillGradient; private: - QSGGeometry m_geometry; + QSGGeometry *m_geometry; QQuickWindow *m_window; QSGMaterial *m_material; QScopedPointer m_solidColorMaterial; -- cgit v1.2.3