diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2009-10-07 12:59:34 (GMT) |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2009-10-07 16:15:45 (GMT) |
commit | 14a8f1fb7414885cc3868b1d27699b5a0d59e7ee (patch) | |
tree | cd5527e8aec4c38a561d6bc81fac098491a334e7 /src/opengl | |
parent | 57209cf902f9d0c9bea5b599b54fa4bdc015d2b5 (diff) | |
download | Qt-14a8f1fb7414885cc3868b1d27699b5a0d59e7ee.zip Qt-14a8f1fb7414885cc3868b1d27699b5a0d59e7ee.tar.gz Qt-14a8f1fb7414885cc3868b1d27699b5a0d59e7ee.tar.bz2 |
Optimized rasterizing of paths using stencil method in GL 2 engine.
Making the triangle fan of each sub path start at the sub path's
centroid will on average improve performance for complex paths, because
less pixels that are outside the path need to be touched. The centroid
is a more balanced choice than just picking the first element of the
sub path as triangle fan origin.
A performance improvement of 20 % was measured for star formed paths.
Reviewed-by: Trond
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp | 37 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h | 5 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 6 |
3 files changed, 43 insertions, 5 deletions
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp index 866d1a2..1fe3999 100644 --- a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp +++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp @@ -67,7 +67,30 @@ void QGL2PEXVertexArray::addRect(const QRectF &rect) << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); } -void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale) +void QGL2PEXVertexArray::addClosingLine(int index) +{ + if (QPointF(vertexArray.at(index)) != QPointF(vertexArray.last())) + vertexArray.add(vertexArray.at(index)); +} + +void QGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex) +{ + const QPointF *const points = reinterpret_cast<const QPointF *>(path.points()); + const QPainterPath::ElementType *const elements = path.elements(); + + QPointF sum = points[subPathIndex]; + int count = 1; + + for (int i = subPathIndex + 1; i < path.elementCount() && (!elements || elements[i] != QPainterPath::MoveToElement); ++i) { + sum += points[i]; + ++count; + } + + const QPointF centroid = sum / qreal(count); + vertexArray.add(centroid); +} + +void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline) { const QPointF* const points = reinterpret_cast<const QPointF*>(path.points()); const QPainterPath::ElementType* const elements = path.elements(); @@ -78,6 +101,10 @@ void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseSc boundingRectDirty = false; } + if (!outline) + addCentroid(path, 0); + + int lastMoveTo = vertexArray.size(); vertexArray.add(points[0]); // The first element is always a moveTo do { @@ -96,8 +123,14 @@ void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseSc const QPainterPath::ElementType elementType = elements[i]; switch (elementType) { case QPainterPath::MoveToElement: + if (!outline) + addClosingLine(lastMoveTo); // qDebug("element[%d] is a MoveToElement", i); vertexArrayStops.append(vertexArray.size()); + if (!outline) { + addCentroid(path, i); + lastMoveTo = vertexArray.size(); + } lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex break; case QPainterPath::LineToElement: @@ -115,6 +148,8 @@ void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseSc } } while (0); + if (!outline) + addClosingLine(lastMoveTo); vertexArrayStops.append(vertexArray.size()); } diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h index 08ce234..719904f 100644 --- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h +++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h @@ -104,7 +104,7 @@ public: boundingRectDirty(true) {} void addRect(const QRectF &rect); - void addPath(const QVectorPath &path, GLfloat curveInverseScale); + void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true); void clear(); QGLPoint* data() {return vertexArray.data();} @@ -124,6 +124,9 @@ private: bool boundingRectDirty; inline void curveToArray(const QGLPoint &cp1, const QGLPoint &cp2, const QGLPoint &ep, GLfloat inverseScale); + + void addClosingLine(int index); + void addCentroid(const QVectorPath &path, int subPathIndex); }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index b3638ff..ab02c69 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -880,13 +880,13 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) || path.shape() == QVectorPath::ConvexPolygonHint) { vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale); + vertexCoordinateArray.addPath(path, inverseScale, false); prepareForDraw(currentBrush->isOpaque()); drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); } else { // The path is too complicated & needs the stencil technique vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale); + vertexCoordinateArray.addPath(path, inverseScale, false); fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); @@ -1825,7 +1825,7 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) glStencilFunc(GL_ALWAYS, 0, 0xff); vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale); + vertexCoordinateArray.addPath(path, inverseScale, false); if (!singlePass) fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); |