summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2010-02-20 08:04:29 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2010-02-20 08:04:29 (GMT)
commit30b45ba2b11342a9e7cc06b68237b68a68955213 (patch)
tree1018c188375b3217b31abe9b7a0883ee1184a447 /src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
parentce27cf24539e0c7971937e55d8539496ad51ee52 (diff)
parent8f10ca802dee1ed110f301191c4a56a85575033c (diff)
downloadQt-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.cpp200
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)