summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-01-29 15:53:39 (GMT)
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-01-29 15:53:39 (GMT)
commitda388773f581e251054abd037dc410ae52cfa69c (patch)
tree5801db3f2793ff9b9d418b25814db50880427550 /src/opengl
parent951922772c0c5f8b8833c2793064f8c6ebeecd9c (diff)
downloadQt-da388773f581e251054abd037dc410ae52cfa69c.zip
Qt-da388773f581e251054abd037dc410ae52cfa69c.tar.gz
Qt-da388773f581e251054abd037dc410ae52cfa69c.tar.bz2
Improve performance of QStaticText on OpenGL by caching data on GPU
There's a big improvement to be seen in the OpenGL engine by caching the vertex data for the QStaticText in VBOs. In order to have the buffers properly disposed, I've implemented a userdata concept for QStaticTextItem. By default, the optimizations will be turned off, and can be turned on by using the useBackendOptimizations flag.
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp92
1 files changed, 82 insertions, 10 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 4c3b343..f6ef827 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1284,6 +1284,29 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
QPaintEngineEx::drawTextItem(p, ti);
}
+namespace {
+
+ class QOpenGLStaticTextUserData: public QStaticTextUserData
+ {
+ public:
+ QOpenGLStaticTextUserData(QGLContext *glContext)
+ : QStaticTextUserData(OpenGLUserData),
+ vertexCoordVBOId(0), textureCoordVBOId(0), ctx(glContext) {}
+ ~QOpenGLStaticTextUserData()
+ {
+ if (vertexCoordVBOId != 0)
+ glDeleteBuffers(1, &vertexCoordVBOId);
+
+ if (textureCoordVBOId != 0)
+ glDeleteBuffers(1, &textureCoordVBOId);
+ }
+
+ QGLContext *ctx;
+ GLuint vertexCoordVBOId;
+ GLuint textureCoordVBOId;
+ };
+}
+
void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem)
{
Q_Q(QGL2PaintEngineEx);
@@ -1309,20 +1332,66 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
GLfloat dx = 1.0 / cache->width();
GLfloat dy = 1.0 / cache->height();
- vertexCoordinateArray.clear();
- textureCoordinateArray.clear();
+ if (staticTextItem->userData == 0
+ || staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData
+ || staticTextItem->userDataNeedsUpdate) {
+ vertexCoordinateArray.clear();
+ textureCoordinateArray.clear();
+
+ for (int i=0; i<staticTextItem->numGlyphs; ++i) {
+ const QTextureGlyphCache::Coord &c = cache->coords.value(staticTextItem->glyphs[i]);
+ int x = staticTextItem->glyphPositions[i].x.toInt() + c.baseLineX - margin;
+ int y = staticTextItem->glyphPositions[i].y.toInt() - c.baseLineY - margin;
+
+ vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h));
+ textureCoordinateArray.addRect(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
+ }
+
+
+ if (staticTextItem->useBackendOptimizations) {
+ QOpenGLStaticTextUserData *userData =
+ staticTextItem->userData != 0 && staticTextItem->userData->type == QStaticTextUserData::OpenGLUserData
+ ? static_cast<QOpenGLStaticTextUserData *>(staticTextItem->userData)
+ : new QOpenGLStaticTextUserData(ctx);
+
+ int vertexCoordinateArraySize = vertexCoordinateArray.vertexCount() * sizeof(QGLPoint);
+ if (userData->vertexCoordVBOId == 0)
+ glGenBuffers(1, &userData->vertexCoordVBOId);
+
+ int textureCoordinateArraySize = textureCoordinateArray.vertexCount() * sizeof(QGLPoint);
+ if (userData->textureCoordVBOId == 0)
+ glGenBuffers(1, &userData->textureCoordVBOId);
+
+ glBindBuffer(GL_ARRAY_BUFFER_ARB, userData->vertexCoordVBOId);
+ glBufferData(GL_ARRAY_BUFFER_ARB, vertexCoordinateArraySize,
+ vertexCoordinateArray.data(), GL_STATIC_DRAW_ARB);
+
+ glBindBuffer(GL_ARRAY_BUFFER_ARB, userData->textureCoordVBOId);
+ glBufferData(GL_ARRAY_BUFFER_ARB, textureCoordinateArraySize,
+ textureCoordinateArray.data(), GL_STATIC_DRAW_ARB);
- for (int i=0; i<staticTextItem->numGlyphs; ++i) {
- const QTextureGlyphCache::Coord &c = cache->coords.value(staticTextItem->glyphs[i]);
- int x = staticTextItem->glyphPositions[i].x.toInt() + c.baseLineX - margin;
- int y = staticTextItem->glyphPositions[i].y.toInt() - c.baseLineY - margin;
+ // If a new user data has been created, make sure we delete the old
+ staticTextItem->setUserData(userData);
+ staticTextItem->userDataNeedsUpdate = false;
- vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h));
- textureCoordinateArray.addRect(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
+ } else {
+ setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data());
+ setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data());
+ }
}
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data());
- setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data());
+ if (staticTextItem->useBackendOptimizations) {
+ Q_ASSERT(staticTextItem->userData != 0);
+ Q_ASSERT(staticTextItem->userData->type == QStaticTextUserData::OpenGLUserData);
+
+ QOpenGLStaticTextUserData *userData = static_cast<QOpenGLStaticTextUserData *>(staticTextItem->userData);
+
+ glBindBuffer(GL_ARRAY_BUFFER_ARB, userData->vertexCoordVBOId);
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER_ARB, userData->textureCoordVBOId);
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ }
if (addOffset) {
addOffset = false;
@@ -1420,6 +1489,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT);
glDrawArrays(GL_TRIANGLES, 0, 6 * staticTextItem->numGlyphs);
+
+ // Reset bindings
+ glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
}
void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)