From 6513e4b9513dfc591c53744517f05aa3c522ace3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 18 Feb 2009 09:42:04 +0100 Subject: Fixes: GL 2 paint engine text rendering optimization. RevBy: Tom Details: Buffer vertex and texture coordinates so that we get away with just a single glDrawArrays call per text item. Also move drawCachedGlyphs() into the private class. --- src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp | 6 ++ src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h | 1 + .../gl2paintengineex/qpaintengineex_opengl2.cpp | 101 +++++++++------------ .../gl2paintengineex/qpaintengineex_opengl2_p.h | 1 - 4 files changed, 52 insertions(+), 57 deletions(-) diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp index 0352d39..f237847 100644 --- a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp +++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp @@ -59,6 +59,12 @@ QGLRect QGL2PEXVertexArray::boundingRect() const return QGLRect(minX, minY, maxX, maxY); } +void QGL2PEXVertexArray::addRect(const QRectF &rect) +{ + vertexArray << rect.topLeft() << rect.topRight() << rect.bottomRight() + << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); +} + void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale) { const QPointF* const points = reinterpret_cast(path.points()); diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h index c205022..65f6d42 100644 --- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h +++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h @@ -98,6 +98,7 @@ public: maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10), boundingRectDirty(true) {} + void addRect(const QRectF &rect); void addPath(const QVectorPath &path, GLfloat curveInverseScale); void clear(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 0e41602..ea0d7b1 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -115,6 +115,7 @@ public: void setBrush(const QBrush* brush); void drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight); + void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti); void fill(const QVectorPath &path); void drawOutline(const QVectorPath& path); @@ -152,7 +153,8 @@ public: GLfloat inverseScale; - QGL2PEXVertexArray pathVertexArray; + QGL2PEXVertexArray vertexCoordinateArray; + QGL2PEXVertexArray textureCoordinateArray; GLfloat pmvMatrix[4][4]; @@ -548,17 +550,17 @@ void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path) if (matrixDirty) updateMatrix(); - pathVertexArray.clear(); - pathVertexArray.addPath(path, inverseScale); + vertexCoordinateArray.clear(); + vertexCoordinateArray.addPath(path, inverseScale); if (path.hasImplicitClose()) { // Close the path's outline - pathVertexArray.lineToArray(path.points()[0], path.points()[1]); - pathVertexArray.stops().last() += 1; + vertexCoordinateArray.lineToArray(path.points()[0], path.points()[1]); + vertexCoordinateArray.stops().last() += 1; } prepareForDraw(); - drawVertexArrays(pathVertexArray, GL_LINE_STRIP); + drawVertexArrays(vertexCoordinateArray, GL_LINE_STRIP); } @@ -578,26 +580,26 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) composite(rect); } else if (path.shape() == QVectorPath::EllipseHint) { - pathVertexArray.clear(); - pathVertexArray.addPath(path, inverseScale); + vertexCoordinateArray.clear(); + vertexCoordinateArray.addPath(path, inverseScale); prepareForDraw(); - drawVertexArrays(pathVertexArray, GL_TRIANGLE_FAN); + drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); } else { // The path is too complicated & needs the stencil technique - pathVertexArray.clear(); - pathVertexArray.addPath(path, inverseScale); + vertexCoordinateArray.clear(); + vertexCoordinateArray.addPath(path, inverseScale); - fillStencilWithVertexArray(pathVertexArray, path.hasWindingFill()); + fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); // Stencil the brush onto the dest buffer glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0 glEnable(GL_STENCIL_TEST); prepareForDraw(); - composite(pathVertexArray.boundingRect()); + composite(vertexCoordinateArray.boundingRect()); glDisable(GL_STENCIL_TEST); - cleanStencilBuffer(pathVertexArray.boundingRect()); + cleanStencilBuffer(vertexCoordinateArray.boundingRect()); } } @@ -876,6 +878,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem) { + Q_D(QGL2PaintEngineEx); QOpenGLPaintEngineState *s = state(); const QTextItemInt &ti = static_cast(textItem); @@ -893,17 +896,17 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem drawCached = false; if (drawCached) { - drawCachedGlyphs(p, ti); + d->drawCachedGlyphs(p, ti); return; } QPaintEngineEx::drawTextItem(p, ti); } -void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti) +void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti) { - Q_D(QGL2PaintEngineEx); - QOpenGLPaintEngineState *s = state(); + Q_Q(QGL2PaintEngineEx); + QOpenGLPaintEngineState *s = q->state(); QVarLengthArray positions; QVarLengthArray glyphs; @@ -927,65 +930,51 @@ void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &t const QImage &image = cache->image(); int margin = cache->glyphMargin(); - QGLContext *ctx = d->ctx; glActiveTexture(QT_BRUSH_TEXTURE_UNIT); - d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); glEnable(GL_BLEND); - d->shaderManager->textShader()->use(); - d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); + shaderManager->textShader()->use(); + updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); - if (d->compositionModeDirty) - d->updateCompositionMode(); + if (compositionModeDirty) + updateCompositionMode(); - if (d->matrixDirty) - d->updateMatrix(); + if (matrixDirty) + updateMatrix(); - if (d->textShaderMatrixUniformDirty) { - d->shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = d->pmvMatrix; - d->textShaderMatrixUniformDirty = false; + if (textShaderMatrixUniformDirty) { + shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix; + textShaderMatrixUniformDirty = false; } - d->shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT; - QColor col = d->premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity); - d->shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col; + shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT; + QColor col = premultiplyColor(s->pen.color(), (GLfloat)s->opacity); + shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col; GLfloat dx = 1.0 / image.width(); GLfloat dy = 1.0 / image.height(); - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + vertexCoordinateArray.clear(); + textureCoordinateArray.clear(); + for (int i=0; icoords.value(glyphs[i]); int x = positions[i].x.toInt() + c.baseLineX - margin; int y = positions[i].y.toInt() - c.baseLineY - margin; - QGLRect dest = QRectF(x, y, c.w, c.h); - QGLRect src = QRectF(c.x, c.y, c.w, c.h); - - GLfloat vertexCoords[] = { - dest.left, dest.top, - dest.left, dest.bottom, - dest.right, dest.bottom, - dest.right, dest.top - }; - - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords); - - QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy); + vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h)); + textureCoordinateArray.addRect(QRectF(c.x*dx, 1 - c.y*dy, c.w * dx, -c.h * dy)); + } - GLfloat textureCoords[] = { - srcTextureRect.left, srcTextureRect.top, - srcTextureRect.left, srcTextureRect.bottom, - srcTextureRect.right, srcTextureRect.bottom, - srcTextureRect.right, srcTextureRect.top - }; + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords); + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data()); + glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data()); + glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index ce66e4b..9f84a25 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -100,7 +100,6 @@ public: virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); - void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti); Type type() const { return OpenGL; } -- cgit v0.12