aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-01-11 12:49:33 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-01-23 15:44:14 +0000
commitb9f060f6fae5734216d7088afd0e3b52165551c5 (patch)
treeaed9e436a44f30ae11cd4015b6a3730b23ca25ac /src/quick/items
parenta2252ba7b3942bbafbbb8f4db144f2cfbf0787ab (diff)
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 <andy.nichols@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickpathitemgenericrenderer.cpp100
-rw-r--r--src/quick/items/qquickpathitemgenericrenderer_p.h41
2 files changed, 111 insertions, 30 deletions
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 <QtGui/private/qtriangulator_p.h>
#include <QtGui/private/qtriangulatingstroker_p.h>
-#include <QSGVertexColorMaterial>
#include <QThreadPool>
+#ifndef QT_NO_OPENGL
+#include <QSGVertexColorMaterial>
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QtGui/private/qopenglextensions_p.h>
+#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<QOpenGLContext> dummyContext;
+ QScopedPointer<QOffscreenSurface> 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<QOpenGLExtensions *>(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<ColoredVertex *>(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<quint32>. 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 <qsgnode.h>
#include <qsggeometry.h>
#include <qsgmaterial.h>
+#include <qsgrendererinterface.h>
#include <QtCore/qrunnable.h>
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<QSGGeometry::ColoredPoint2D> VerticesType;
- typedef QVector<quint16> IndicesType;
+ typedef QVector<QSGGeometry::ColoredPoint2D> VertexContainerType;
+ typedef QVector<quint32> 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<VisualPathData> 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<QSGMaterial> m_solidColorMaterial;