aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-01-09 11:43:31 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-01-23 13:56:09 +0000
commit5575226f6b25bcf507c3412677756e07ce671cef (patch)
tree27cd18fdea64065c2cb944e8150032162a09beba /src/quick
parent03fe99ba3a7d29b1606660baa407cff21c4d4d35 (diff)
PathItem: add optional threaded triangulation
Spending 300+ ms in polish for the tiger when running with the generic backend is not going to fly. Therefore, add an optional mode for asynchronous triangulation. Change-Id: Ida44c7b8a28d38fb11243a6657221f039c62e21b Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/items/qquickpathitem.cpp20
-rw-r--r--src/quick/items/qquickpathitem_p.h5
-rw-r--r--src/quick/items/qquickpathitem_p_p.h3
-rw-r--r--src/quick/items/qquickpathitemgenericrenderer.cpp197
-rw-r--r--src/quick/items/qquickpathitemgenericrenderer_p.h70
-rw-r--r--src/quick/items/qquickpathitemnvprrenderer.cpp2
-rw-r--r--src/quick/items/qquickpathitemnvprrenderer_p.h2
-rw-r--r--src/quick/items/qquickpathitemsoftwarerenderer.cpp2
-rw-r--r--src/quick/items/qquickpathitemsoftwarerenderer_p.h2
9 files changed, 243 insertions, 60 deletions
diff --git a/src/quick/items/qquickpathitem.cpp b/src/quick/items/qquickpathitem.cpp
index d7131b3833..964d997806 100644
--- a/src/quick/items/qquickpathitem.cpp
+++ b/src/quick/items/qquickpathitem.cpp
@@ -361,6 +361,7 @@ QQuickPathItemPrivate::QQuickPathItemPrivate()
: componentComplete(true),
vpChanged(false),
rendererType(QQuickPathItem::UnknownRenderer),
+ async(false),
renderer(nullptr)
{
}
@@ -393,6 +394,23 @@ QQuickPathItem::RendererType QQuickPathItem::rendererType() const
return d->rendererType;
}
+bool QQuickPathItem::asynchronous() const
+{
+ Q_D(const QQuickPathItem);
+ return d->async;
+}
+
+void QQuickPathItem::setAsynchronous(bool async)
+{
+ Q_D(QQuickPathItem);
+ if (d->async != async) {
+ d->async = async;
+ emit asynchronousChanged();
+ if (d->componentComplete)
+ d->_q_visualPathChanged();
+ }
+}
+
static QQuickVisualPath *vpe_at(QQmlListProperty<QQuickVisualPath> *property, int index)
{
QQuickPathItemPrivate *d = QQuickPathItemPrivate::get(static_cast<QQuickPathItem *>(property->object));
@@ -606,7 +624,7 @@ void QQuickPathItemPrivate::sync()
dirty = 0;
}
- renderer->endSync();
+ renderer->endSync(async);
}
// ***** gradient support *****
diff --git a/src/quick/items/qquickpathitem_p.h b/src/quick/items/qquickpathitem_p.h
index 0c1d0f061b..7c962d01fc 100644
--- a/src/quick/items/qquickpathitem_p.h
+++ b/src/quick/items/qquickpathitem_p.h
@@ -263,6 +263,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPathItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(RendererType renderer READ rendererType NOTIFY rendererChanged)
+ Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
Q_PROPERTY(QQmlListProperty<QQuickVisualPath> visualPaths READ visualPaths)
Q_CLASSINFO("DefaultProperty", "visualPaths")
@@ -280,6 +281,9 @@ public:
RendererType rendererType() const;
+ bool asynchronous() const;
+ void setAsynchronous(bool async);
+
QQmlListProperty<QQuickVisualPath> visualPaths();
protected:
@@ -291,6 +295,7 @@ protected:
Q_SIGNALS:
void rendererChanged();
+ void asynchronousChanged();
private:
Q_DISABLE_COPY(QQuickPathItem)
diff --git a/src/quick/items/qquickpathitem_p_p.h b/src/quick/items/qquickpathitem_p_p.h
index 5e6400edc6..faf7b1e451 100644
--- a/src/quick/items/qquickpathitem_p_p.h
+++ b/src/quick/items/qquickpathitem_p_p.h
@@ -79,7 +79,7 @@ public:
virtual void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle,
qreal dashOffset, const QVector<qreal> &dashPattern) = 0;
virtual void setFillGradient(int index, QQuickPathGradient *gradient) = 0;
- virtual void endSync() = 0;
+ virtual void endSync(bool async) = 0;
// Render thread, with gui blocked
virtual void updateNode() = 0;
@@ -144,6 +144,7 @@ public:
bool componentComplete;
bool vpChanged;
QQuickPathItem::RendererType rendererType;
+ bool async;
QQuickAbstractPathRenderer *renderer;
QVector<QQuickVisualPath *> vp;
};
diff --git a/src/quick/items/qquickpathitemgenericrenderer.cpp b/src/quick/items/qquickpathitemgenericrenderer.cpp
index dbbc14d3c8..6e4c89742a 100644
--- a/src/quick/items/qquickpathitemgenericrenderer.cpp
+++ b/src/quick/items/qquickpathitemgenericrenderer.cpp
@@ -39,7 +39,9 @@
#include "qquickpathitemgenericrenderer_p.h"
#include <QtGui/private/qtriangulator_p.h>
+#include <QtGui/private/qtriangulatingstroker_p.h>
#include <QSGVertexColorMaterial>
+#include <QThreadPool>
QT_BEGIN_NAMESPACE
@@ -103,6 +105,8 @@ void QQuickPathItemGenericStrokeFillNode::activateMaterial(Material m)
}
// sync, and so triangulation too, happens on the gui thread
+// - except when async is set, in which case triangulation is moved to worker threads
+
void QQuickPathItemGenericRenderer::beginSync(int totalCount)
{
if (m_vp.count() != totalCount) {
@@ -194,9 +198,22 @@ void QQuickPathItemGenericRenderer::setFillGradient(int index, QQuickPathGradien
d.syncDirty |= DirtyFillGradient;
}
-void QQuickPathItemGenericRenderer::endSync()
+void QQuickPathItemFillRunnable::run()
{
- for (VisualPathData &d : m_vp) {
+ QQuickPathItemGenericRenderer::triangulateFill(path, fillColor, &fillVertices, &fillIndices);
+ emit done(this);
+}
+
+void QQuickPathItemStrokeRunnable::run()
+{
+ QQuickPathItemGenericRenderer::triangulateStroke(path, pen, strokeColor, &strokeVertices, clipSize);
+ emit done(this);
+}
+
+void QQuickPathItemGenericRenderer::endSync(bool async)
+{
+ for (int i = 0; i < m_vp.count(); ++i) {
+ VisualPathData &d(m_vp[i]);
if (!d.syncDirty)
continue;
@@ -217,67 +234,145 @@ void QQuickPathItemGenericRenderer::endSync()
}
if (d.syncDirty & DirtyGeom) {
- if (d.fillColor.a)
- triangulateFill(&d);
- if (d.strokeWidth >= 0.0f && d.strokeColor.a)
- triangulateStroke(&d);
+ static QThreadPool threadPool;
+ static bool threadPoolReady = false;
+ if (async && !threadPoolReady) {
+ threadPoolReady = true;
+ const int idealCount = QThread::idealThreadCount();
+ threadPool.setMaxThreadCount(idealCount > 0 ? idealCount * 2 : 4);
+ }
+ if (d.fillColor.a) {
+ d.path.setFillRule(d.fillRule);
+ if (async) {
+ QQuickPathItemFillRunnable *r = new QQuickPathItemFillRunnable;
+ r->setAutoDelete(false);
+ if (d.pendingFill)
+ d.pendingFill->orphaned = true;
+ d.pendingFill = r;
+ r->path = d.path;
+ r->fillColor = d.fillColor;
+ // 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) {
+ if (!r->orphaned && i < m_vp.count()) {
+ VisualPathData &d(m_vp[i]);
+ d.fillVertices = r->fillVertices;
+ d.fillIndices = r->fillIndices;
+ d.pendingFill = nullptr;
+ d.effectiveDirty |= DirtyGeom;
+ maybeUpdateAsyncItem();
+ }
+ r->deleteLater();
+ });
+ threadPool.start(r);
+ } else {
+ triangulateFill(d.path, d.fillColor, &d.fillVertices, &d.fillIndices);
+ }
+ }
+ if (d.strokeWidth >= 0.0f && d.strokeColor.a) {
+ if (async) {
+ QQuickPathItemStrokeRunnable *r = new QQuickPathItemStrokeRunnable;
+ r->setAutoDelete(false);
+ if (d.pendingStroke)
+ d.pendingStroke->orphaned = true;
+ d.pendingStroke = r;
+ r->path = d.path;
+ r->pen = d.pen;
+ r->strokeColor = d.strokeColor;
+ r->clipSize = QSize(m_item->width(), m_item->height());
+ QObject::connect(r, &QQuickPathItemStrokeRunnable::done, qApp, [this, i](QQuickPathItemStrokeRunnable *r) {
+ if (!r->orphaned && i < m_vp.count()) {
+ VisualPathData &d(m_vp[i]);
+ d.strokeVertices = r->strokeVertices;
+ d.pendingStroke = nullptr;
+ d.effectiveDirty |= DirtyGeom;
+ maybeUpdateAsyncItem();
+ }
+ r->deleteLater();
+ });
+ threadPool.start(r);
+ } else {
+ triangulateStroke(d.path, d.pen, d.strokeColor, &d.strokeVertices,
+ QSize(m_item->width(), m_item->height()));
+ }
+ }
}
}
}
-void QQuickPathItemGenericRenderer::triangulateFill(VisualPathData *d)
+void QQuickPathItemGenericRenderer::maybeUpdateAsyncItem()
{
- d->path.setFillRule(d->fillRule);
+ for (const VisualPathData &d : qAsConst(m_vp)) {
+ if (d.pendingFill || d.pendingStroke)
+ return;
+ }
+ m_accDirty |= DirtyGeom;
+ m_item->update();
+}
- const QVectorPath &vp = qtVectorPathForPath(d->path);
+// the stroke/fill triangulation functions may be invoked either on the gui
+// thread or some worker thread and must thus be self-contained.
+void QQuickPathItemGenericRenderer::triangulateFill(const QPainterPath &path,
+ const Color4ub &fillColor,
+ VerticesType *fillVertices,
+ IndicesType *fillIndices)
+{
+ const QVectorPath &vp = qtVectorPathForPath(path);
QTriangleSet ts = qTriangulate(vp, QTransform::fromScale(SCALE, SCALE));
const int vertexCount = ts.vertices.count() / 2; // just a qreal vector with x,y hence the / 2
- d->fillVertices.resize(vertexCount);
- ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(d->fillVertices.data());
+ 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] / SCALE, vsrc[i * 2 + 1] / SCALE, d->fillColor);
+ vdst[i].set(vsrc[i * 2] / SCALE, vsrc[i * 2 + 1] / SCALE, fillColor);
- d->fillIndices.resize(ts.indices.size());
- quint16 *idst = d->fillIndices.data();
+ fillIndices->resize(ts.indices.size());
+ quint16 *idst = fillIndices->data();
if (ts.indices.type() == QVertexIndexVector::UnsignedShort) {
- memcpy(idst, ts.indices.data(), d->fillIndices.count() * sizeof(quint16));
+ memcpy(idst, ts.indices.data(), fillIndices->count() * sizeof(quint16));
} else {
const quint32 *isrc = (const quint32 *) ts.indices.data();
- for (int i = 0; i < d->fillIndices.count(); ++i)
+ for (int i = 0; i < fillIndices->count(); ++i)
idst[i] = isrc[i];
}
}
-void QQuickPathItemGenericRenderer::triangulateStroke(VisualPathData *d)
+void QQuickPathItemGenericRenderer::triangulateStroke(const QPainterPath &path,
+ const QPen &pen,
+ const Color4ub &strokeColor,
+ VerticesType *strokeVertices,
+ const QSize &clipSize)
{
- const QVectorPath &vp = qtVectorPathForPath(d->path);
-
- const QRectF clip(0, 0, m_item->width(), m_item->height());
+ const QVectorPath &vp = qtVectorPathForPath(path);
+ const QRectF clip(QPointF(0, 0), clipSize);
const qreal inverseScale = 1.0 / SCALE;
- m_stroker.setInvScale(inverseScale);
- if (d->pen.style() == Qt::SolidLine) {
- m_stroker.process(vp, d->pen, clip, 0);
+
+ QTriangulatingStroker stroker;
+ stroker.setInvScale(inverseScale);
+
+ if (pen.style() == Qt::SolidLine) {
+ stroker.process(vp, pen, clip, 0);
} else {
- m_dashStroker.setInvScale(inverseScale);
- m_dashStroker.process(vp, d->pen, clip, 0);
- QVectorPath dashStroke(m_dashStroker.points(), m_dashStroker.elementCount(),
- m_dashStroker.elementTypes(), 0);
- m_stroker.process(dashStroke, d->pen, clip, 0);
+ QDashedStrokeProcessor dashStroker;
+ dashStroker.setInvScale(inverseScale);
+ dashStroker.process(vp, pen, clip, 0);
+ QVectorPath dashStroke(dashStroker.points(), dashStroker.elementCount(),
+ dashStroker.elementTypes(), 0);
+ stroker.process(dashStroke, pen, clip, 0);
}
- if (!m_stroker.vertexCount()) {
- d->strokeVertices.clear();
+ if (!stroker.vertexCount()) {
+ strokeVertices->clear();
return;
}
- const int vertexCount = m_stroker.vertexCount() / 2; // just a float vector with x,y hence the / 2
- d->strokeVertices.resize(vertexCount);
- ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(d->strokeVertices.data());
- const float *vsrc = m_stroker.vertices();
+ const int vertexCount = stroker.vertexCount() / 2; // just a float vector with x,y hence the / 2
+ strokeVertices->resize(vertexCount);
+ ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(strokeVertices->data());
+ const float *vsrc = stroker.vertices();
for (int i = 0; i < vertexCount; ++i)
- vdst[i].set(vsrc[i * 2], vsrc[i * 2 + 1], d->strokeColor);
+ vdst[i].set(vsrc[i * 2], vsrc[i * 2 + 1], strokeColor);
}
void QQuickPathItemGenericRenderer::setRootNode(QQuickPathItemGenericNode *node)
@@ -317,7 +412,7 @@ void QQuickPathItemGenericRenderer::updateNode()
QQuickPathItemGenericNode *node = *nodePtr;
if (m_accDirty & DirtyList)
- d.effectiveDirty |= DirtyGeom;
+ d.effectiveDirty |= DirtyGeom | DirtyColor | DirtyFillGradient;
if (!d.effectiveDirty)
continue;
@@ -361,25 +456,36 @@ void QQuickPathItemGenericRenderer::updateNode()
m_accDirty = 0;
}
+void QQuickPathItemGenericRenderer::updateShadowDataInNode(VisualPathData *d, QQuickPathItemGenericStrokeFillNode *n)
+{
+ if (d->fillGradientActive) {
+ if (d->effectiveDirty & DirtyFillGradient)
+ n->m_fillGradient = d->fillGradient;
+ }
+}
+
void QQuickPathItemGenericRenderer::updateFillNode(VisualPathData *d, QQuickPathItemGenericNode *node)
{
if (!node->m_fillNode)
return;
+ // Make a copy of the data that will be accessed by the material on
+ // the render thread. This must be done even when we bail out below.
QQuickPathItemGenericStrokeFillNode *n = node->m_fillNode;
+ updateShadowDataInNode(d, n);
+
QSGGeometry *g = &n->m_geometry;
if (d->fillVertices.isEmpty()) {
- g->allocate(0, 0);
- n->markDirty(QSGNode::DirtyGeometry);
+ if (g->vertexCount() || g->indexCount()) {
+ g->allocate(0, 0);
+ n->markDirty(QSGNode::DirtyGeometry);
+ }
return;
}
if (d->fillGradientActive) {
n->activateMaterial(QQuickPathItemGenericStrokeFillNode::MatLinearGradient);
if (d->effectiveDirty & DirtyFillGradient) {
- // Make a copy of the data that will be accessed by the material on
- // the render thread.
- n->m_fillGradient = d->fillGradient;
// 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
@@ -414,14 +520,17 @@ void QQuickPathItemGenericRenderer::updateStrokeNode(VisualPathData *d, QQuickPa
return;
QQuickPathItemGenericStrokeFillNode *n = node->m_strokeNode;
- n->markDirty(QSGNode::DirtyGeometry);
-
QSGGeometry *g = &n->m_geometry;
if (d->strokeVertices.isEmpty()) {
- g->allocate(0, 0);
+ if (g->vertexCount() || g->indexCount()) {
+ g->allocate(0, 0);
+ n->markDirty(QSGNode::DirtyGeometry);
+ }
return;
}
+ n->markDirty(QSGNode::DirtyGeometry);
+
if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyGeom)) {
ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData());
for (int i = 0; i < g->vertexCount(); ++i)
diff --git a/src/quick/items/qquickpathitemgenericrenderer_p.h b/src/quick/items/qquickpathitemgenericrenderer_p.h
index 4454b14a13..a4ed090004 100644
--- a/src/quick/items/qquickpathitemgenericrenderer_p.h
+++ b/src/quick/items/qquickpathitemgenericrenderer_p.h
@@ -55,11 +55,14 @@
#include <qsgnode.h>
#include <qsggeometry.h>
#include <qsgmaterial.h>
-#include <QtGui/private/qtriangulatingstroker_p.h>
+#include <QtCore/qrunnable.h>
QT_BEGIN_NAMESPACE
class QQuickPathItemGenericNode;
+class QQuickPathItemGenericStrokeFillNode;
+class QQuickPathItemFillRunnable;
+class QQuickPathItemStrokeRunnable;
class QQuickPathItemGenericRenderer : public QQuickAbstractPathRenderer
{
@@ -88,15 +91,29 @@ public:
void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle,
qreal dashOffset, const QVector<qreal> &dashPattern) override;
void setFillGradient(int index, QQuickPathGradient *gradient) override;
- void endSync() override;
+ void endSync(bool async) override;
void updateNode() override;
void setRootNode(QQuickPathItemGenericNode *node);
struct Color4ub { unsigned char r, g, b, a; };
+ typedef QVector<QSGGeometry::ColoredPoint2D> VerticesType;
+ typedef QVector<quint16> IndicesType;
+
+ static void triangulateFill(const QPainterPath &path,
+ const Color4ub &fillColor,
+ VerticesType *fillVertices,
+ IndicesType *fillIndices);
+ static void triangulateStroke(const QPainterPath &path,
+ const QPen &pen,
+ const Color4ub &strokeColor,
+ VerticesType *strokeVertices,
+ const QSize &clipSize);
private:
+ void maybeUpdateAsyncItem();
+
struct VisualPathData {
float strokeWidth;
QPen pen;
@@ -106,27 +123,60 @@ private:
QPainterPath path;
bool fillGradientActive;
QQuickPathItemGradientCache::GradientDesc fillGradient;
- QVector<QSGGeometry::ColoredPoint2D> fillVertices;
- QVector<quint16> fillIndices;
- QVector<QSGGeometry::ColoredPoint2D> strokeVertices;
+ VerticesType fillVertices;
+ IndicesType fillIndices;
+ VerticesType strokeVertices;
int syncDirty;
int effectiveDirty = 0;
+ QQuickPathItemFillRunnable *pendingFill = nullptr;
+ QQuickPathItemStrokeRunnable *pendingStroke = nullptr;
};
- void triangulateFill(VisualPathData *d);
- void triangulateStroke(VisualPathData *d);
-
+ void updateShadowDataInNode(VisualPathData *d, QQuickPathItemGenericStrokeFillNode *n);
void updateFillNode(VisualPathData *d, QQuickPathItemGenericNode *node);
void updateStrokeNode(VisualPathData *d, QQuickPathItemGenericNode *node);
QQuickItem *m_item;
QQuickPathItemGenericNode *m_rootNode;
- QTriangulatingStroker m_stroker;
- QDashedStrokeProcessor m_dashStroker;
QVector<VisualPathData> m_vp;
int m_accDirty;
};
+class QQuickPathItemFillRunnable : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ void run() override;
+
+ bool orphaned = false;
+ QPainterPath path;
+ QQuickPathItemGenericRenderer::Color4ub fillColor;
+ QQuickPathItemGenericRenderer::VerticesType fillVertices;
+ QQuickPathItemGenericRenderer::IndicesType fillIndices;
+
+Q_SIGNALS:
+ void done(QQuickPathItemFillRunnable *self);
+};
+
+class QQuickPathItemStrokeRunnable : public QObject, public QRunnable
+{
+ Q_OBJECT
+
+public:
+ void run() override;
+
+ bool orphaned = false;
+ QPainterPath path;
+ QPen pen;
+ QQuickPathItemGenericRenderer::Color4ub strokeColor;
+ QQuickPathItemGenericRenderer::VerticesType strokeVertices;
+ QSize clipSize;
+
+Q_SIGNALS:
+ void done(QQuickPathItemStrokeRunnable *self);
+};
+
class QQuickPathItemGenericStrokeFillNode : public QSGGeometryNode
{
public:
diff --git a/src/quick/items/qquickpathitemnvprrenderer.cpp b/src/quick/items/qquickpathitemnvprrenderer.cpp
index 0c4357145a..9303f698ac 100644
--- a/src/quick/items/qquickpathitemnvprrenderer.cpp
+++ b/src/quick/items/qquickpathitemnvprrenderer.cpp
@@ -140,7 +140,7 @@ void QQuickPathItemNvprRenderer::setFillGradient(int index, QQuickPathGradient *
m_accDirty |= DirtyFillGradient;
}
-void QQuickPathItemNvprRenderer::endSync()
+void QQuickPathItemNvprRenderer::endSync(bool)
{
}
diff --git a/src/quick/items/qquickpathitemnvprrenderer_p.h b/src/quick/items/qquickpathitemnvprrenderer_p.h
index 067ecf7355..1617de17e6 100644
--- a/src/quick/items/qquickpathitemnvprrenderer_p.h
+++ b/src/quick/items/qquickpathitemnvprrenderer_p.h
@@ -90,7 +90,7 @@ public:
void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle,
qreal dashOffset, const QVector<qreal> &dashPattern) override;
void setFillGradient(int index, QQuickPathGradient *gradient) override;
- void endSync() override;
+ void endSync(bool async) override;
void updateNode() override;
diff --git a/src/quick/items/qquickpathitemsoftwarerenderer.cpp b/src/quick/items/qquickpathitemsoftwarerenderer.cpp
index 6c3cf73a56..63d4f8f6d4 100644
--- a/src/quick/items/qquickpathitemsoftwarerenderer.cpp
+++ b/src/quick/items/qquickpathitemsoftwarerenderer.cpp
@@ -158,7 +158,7 @@ void QQuickPathItemSoftwareRenderer::setFillGradient(int index, QQuickPathGradie
m_accDirty |= DirtyBrush;
}
-void QQuickPathItemSoftwareRenderer::endSync()
+void QQuickPathItemSoftwareRenderer::endSync(bool)
{
}
diff --git a/src/quick/items/qquickpathitemsoftwarerenderer_p.h b/src/quick/items/qquickpathitemsoftwarerenderer_p.h
index 60b52e2def..38130d7301 100644
--- a/src/quick/items/qquickpathitemsoftwarerenderer_p.h
+++ b/src/quick/items/qquickpathitemsoftwarerenderer_p.h
@@ -82,7 +82,7 @@ public:
void setStrokeStyle(int index, QQuickVisualPath::StrokeStyle strokeStyle,
qreal dashOffset, const QVector<qreal> &dashPattern) override;
void setFillGradient(int index, QQuickPathGradient *gradient) override;
- void endSync() override;
+ void endSync(bool async) override;
void updateNode() override;