From 4f63f43cf2da59c2e87ae96e8bd84950490a070b Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 8 Nov 2013 15:55:15 +0100 Subject: [PATCH] Workaround for glyph upload bug with the Mali-400 GPU. Uploading unaligned and alpha-only data seems to be broken with that GPU, uploading line by line does the trick. Task-number: QTBUG-33951 Change-Id: I2790990ca1d3a3016ec3d9fefaea7002b92faeb7 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Shawn Rutledge --- .../qsgdefaultdistancefieldglyphcache.cpp | 55 ++++++++++++++++--- .../qsgdefaultdistancefieldglyphcache_p.h | 3 +- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 635f07f2ea..25ff98bc67 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -167,7 +167,7 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList if (glyph.width() != expectedWidth) glyph = glyph.copy(0, 0, expectedWidth, glyph.height()); - if (useWorkaround()) { + if (useTextureResizeWorkaround()) { uchar *inBits = glyph.scanLine(0); uchar *outBits = texInfo->image.scanLine(int(c.y)) + int(c.x); for (int y = 0; y < glyph.height(); ++y) { @@ -177,7 +177,19 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList } } - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits()); + if (useTextureUploadWorkaround()) { + for (int i = 0; i < glyph.height(); ++i) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + c.x, c.y + i, glyph.width(),1, + GL_ALPHA, GL_UNSIGNED_BYTE, + glyph.scanLine(i)); + } + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, + c.x, c.y, glyph.width(), glyph.height(), + GL_ALPHA, GL_UNSIGNED_BYTE, + glyph.constBits()); + } } // restore to previous alignment @@ -204,7 +216,7 @@ void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet &glyph void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int width, int height) { - if (useWorkaround() && texInfo->image.isNull()) + if (useTextureResizeWorkaround() && texInfo->image.isNull()) texInfo->image = QDistanceField(width, height); while (glGetError() != GL_NO_ERROR) { } @@ -255,12 +267,24 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int updateTexture(oldTexture, texInfo->texture, texInfo->size); - if (useWorkaround()) { + if (useTextureResizeWorkaround()) { GLint alignment = 4; // default value glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, texInfo->image.constBits()); + if (useTextureUploadWorkaround()) { + for (int i = 0; i < texInfo->image.height(); ++i) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, i, oldWidth, 1, + GL_ALPHA, GL_UNSIGNED_BYTE, + texInfo->image.scanLine(i)); + } + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, 0, oldWidth, oldHeight, + GL_ALPHA, GL_UNSIGNED_BYTE, + texInfo->image.constBits()); + } glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); // restore to previous value @@ -334,7 +358,12 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int glBindTexture(GL_TEXTURE_2D, texInfo->texture); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); + if (useTextureUploadWorkaround()) { + for (int i = 0; i < oldHeight; ++i) + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, 0, i, oldWidth, 1); + } else { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); + } ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); @@ -359,7 +388,7 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); } -bool QSGDefaultDistanceFieldGlyphCache::useWorkaround() const +bool QSGDefaultDistanceFieldGlyphCache::useTextureResizeWorkaround() const { static bool set = false; static bool useWorkaround = false; @@ -372,6 +401,18 @@ bool QSGDefaultDistanceFieldGlyphCache::useWorkaround() const return useWorkaround; } +bool QSGDefaultDistanceFieldGlyphCache::useTextureUploadWorkaround() const +{ + static bool set = false; + static bool useWorkaround = false; + if (!set) { + useWorkaround = qstrcmp(reinterpret_cast(glGetString(GL_RENDERER)), + "Mali-400 MP") == 0; + set = true; + } + return useWorkaround; +} + int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const { if (!m_maxTextureSize) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index 54b0bcb889..3fee6c9ef3 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -62,7 +62,8 @@ class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDista void referenceGlyphs(const QSet &glyphs); void releaseGlyphs(const QSet &glyphs); - bool useWorkaround() const; + bool useTextureResizeWorkaround() const; + bool useTextureUploadWorkaround() const; int maxTextureSize() const; void setMaxTextureCount(int max) { m_maxTextureCount = max; }