diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2010-02-20 08:04:29 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2010-02-20 08:04:29 (GMT) |
commit | 30b45ba2b11342a9e7cc06b68237b68a68955213 (patch) | |
tree | 1018c188375b3217b31abe9b7a0883ee1184a447 /src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | |
parent | ce27cf24539e0c7971937e55d8539496ad51ee52 (diff) | |
parent | 8f10ca802dee1ed110f301191c4a56a85575033c (diff) | |
download | Qt-30b45ba2b11342a9e7cc06b68237b68a68955213.zip Qt-30b45ba2b11342a9e7cc06b68237b68a68955213.tar.gz Qt-30b45ba2b11342a9e7cc06b68237b68a68955213.tar.bz2 |
Merge remote branch 'origin/master' into qt-master-from-4.6
Conflicts:
configure.exe
src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
src/opengl/qgl.cpp
Diffstat (limited to 'src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp')
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 200 |
1 files changed, 175 insertions, 25 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index be2b098..ea464d5 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -77,6 +77,7 @@ #include <private/qfontengine_p.h> #include <private/qpixmapdata_gl_p.h> #include <private/qdatabuffer_p.h> +#include <private/qstatictext_p.h> #include <private/qtriangulator_p.h> #include "qglgradientcache_p.h" @@ -108,6 +109,11 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() e->data = 0; e->engine = 0; } + + if (elementIndicesVBOId != 0) { + glDeleteBuffers(1, &elementIndicesVBOId); + elementIndicesVBOId = 0; + } } void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) @@ -1293,6 +1299,20 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); } +void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) +{ + Q_D(QGL2PaintEngineEx); + + ensureActive(); + + QFontEngineGlyphCache::Type glyphType = textItem->fontEngine->glyphFormat >= 0 + ? QFontEngineGlyphCache::Type(textItem->fontEngine->glyphFormat) + : d->glyphCacheType; + + // ### What about huge fonts? These are not passed through cache in drawTextItem(). + d->drawCachedGlyphs(glyphType, textItem, true); +} + void QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src) { Q_D(QGL2PaintEngineEx); @@ -1346,33 +1366,72 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem } if (drawCached) { - d->drawCachedGlyphs(p, glyphType, ti); + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> glyphs; + QTransform matrix = QTransform::fromTranslate(p.x(), p.y()); + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + + { + QStaticTextItem staticTextItem; + staticTextItem.chars = ti.chars; + staticTextItem.fontEngine = ti.fontEngine; + staticTextItem.glyphs = glyphs.data(); + staticTextItem.numChars = ti.num_chars; + staticTextItem.numGlyphs = glyphs.size(); + staticTextItem.glyphPositions = positions.data(); + + d->drawCachedGlyphs(glyphType, &staticTextItem, false); + } return; } QPaintEngineEx::drawTextItem(p, ti); } -void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, - const QTextItemInt &ti) +namespace { + + class QOpenGLStaticTextUserData: public QStaticTextUserData + { + public: + QOpenGLStaticTextUserData() + : QStaticTextUserData(OpenGLUserData) + { + } + + ~QOpenGLStaticTextUserData() + { + } + + QGL2PEXVertexArray vertexCoordinateArray; + QGL2PEXVertexArray textureCoordinateArray; + }; + +} + +// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO + +void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, + QStaticTextItem *staticTextItem, + bool includeMatrixInCache) { Q_Q(QGL2PaintEngineEx); - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix = QTransform::fromTranslate(p.x(), p.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + QOpenGL2PaintEngineState *s = q->state(); QGLTextureGlyphCache *cache = - (QGLTextureGlyphCache *) ti.fontEngine->glyphCache(ctx, glyphType, QTransform()); - + (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, + includeMatrixInCache + ? s->matrix + : QTransform()); if (!cache || cache->cacheType() != glyphType) { - cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); - ti.fontEngine->setGlyphCache(ctx, cache); + cache = new QGLTextureGlyphCache(ctx, glyphType, + includeMatrixInCache ? s->matrix : QTransform()); + staticTextItem->fontEngine->setGlyphCache(ctx, cache); } cache->setPaintEnginePrivate(this); - cache->populate(ti, glyphs, positions); + cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, + staticTextItem->glyphPositions); if (cache->width() == 0 || cache->height() == 0) return; @@ -1384,20 +1443,83 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly GLfloat dx = 1.0 / cache->width(); GLfloat dy = 1.0 / cache->height(); - vertexCoordinateArray.clear(); - textureCoordinateArray.clear(); + bool recreateVertexArrays = false; + if (staticTextItem->userDataNeedsUpdate) + recreateVertexArrays = true; + else if (staticTextItem->userData == 0) + recreateVertexArrays = true; + else if (staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData) + recreateVertexArrays = true; + + // Use global arrays by default + QGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray; + QGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray; - for (int i=0; i<glyphs.size(); ++i) { - const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); - int x = positions[i].x.toInt() + c.baseLineX - margin; - int y = positions[i].y.toInt() - c.baseLineY - margin; + if (staticTextItem->useBackendOptimizations) { + QOpenGLStaticTextUserData *userData = 0; - 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->userData == 0 + || staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData) { + + userData = new QOpenGLStaticTextUserData(); + staticTextItem->setUserData(userData); + + } else { + userData = static_cast<QOpenGLStaticTextUserData*>(staticTextItem->userData); + } + + // Use cache if backend optimizations is turned on + vertexCoordinates = &userData->vertexCoordinateArray; + textureCoordinates = &userData->textureCoordinateArray; + } + + + if (recreateVertexArrays) { + vertexCoordinates->clear(); + textureCoordinates->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; + + vertexCoordinates->addQuad(QRectF(x, y, c.w, c.h)); + textureCoordinates->addQuad(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy)); + } + + staticTextItem->userDataNeedsUpdate = false; } - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data()); - setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data()); + if (elementIndices.size() < staticTextItem->numGlyphs*6) { + Q_ASSERT(elementIndices.size() % 6 == 0); + int j = elementIndices.size() / 6 * 4; + while (j < staticTextItem->numGlyphs*4) { + elementIndices.append(j + 0); + elementIndices.append(j + 0); + elementIndices.append(j + 1); + elementIndices.append(j + 2); + elementIndices.append(j + 3); + elementIndices.append(j + 3); + + j += 4; + } + +#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) + if (elementIndicesVBOId == 0) + glGenBuffers(1, &elementIndicesVBOId); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementIndices.size() * sizeof(GLushort), + elementIndices.constData(), GL_STATIC_DRAW); +#endif + } else { +#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId); +#endif + } + + setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data()); + setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data()); if (addOffset) { addOffset = false; @@ -1411,6 +1533,13 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly QBrush pensBrush = q->state()->pen.brush(); setBrush(pensBrush); + // When painting a QStaticTextItem, the glyph positions are already in device coordinates, + // therefore we temporarily set an identity matrix on the painter for the draw call to + // avoid transforming the positions twice. + QTransform old = s->matrix; + if (includeMatrixInCache) + s->matrix = QTransform(); + if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { // Subpixel antialiasing without gamma correction @@ -1464,7 +1593,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); - glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); +#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) + glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); +#else + glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data()); +#endif shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2); @@ -1490,11 +1623,23 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly //### TODO: Gamma correction glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); - glBindTexture(GL_TEXTURE_2D, cache->texture()); + if (lastMaskTextureUsed != cache->texture()) { + glBindTexture(GL_TEXTURE_2D, cache->texture()); + lastMaskTextureUsed = cache->texture(); + } updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); - glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); + +#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) + glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#else + glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data()); +#endif + + if (includeMatrixInCache) + s->matrix = old; } void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) @@ -1640,7 +1785,11 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) case QInternal::FramebufferObject: { GLenum f = static_cast<QGLFramebufferObject *>(pdev)->format().internalTextureFormat(); +#ifndef QT_OPENGL_ES d->deviceHasAlpha = (f != GL_RGB && f != GL_RGB5 && f != GL_RGB8); +#else + d->deviceHasAlpha = (f == GL_RGBA); +#endif } break; default: @@ -1746,6 +1895,7 @@ void QGL2PaintEngineEx::ensureActive() d->transferMode(BrushDrawingMode); glViewport(0, 0, d->width, d->height); d->needsSync = false; + d->lastMaskTextureUsed = 0; d->shaderManager->setDirty(); d->ctx->d_func()->syncGlState(); for (int i = 0; i < 3; ++i) |