Skip to content

Commit

Permalink
Workaround for glyph upload bug with the Mali-400 GPU.
Browse files Browse the repository at this point in the history
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 <eskil.abrahamsen-blomfeldt@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
  • Loading branch information
marseyeah authored and The Qt Project committed Nov 9, 2013
1 parent 040c835 commit 4f63f43
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
55 changes: 48 additions & 7 deletions src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
Expand Up @@ -167,7 +167,7 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
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) {
Expand All @@ -177,7 +177,19 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
}
}

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
Expand All @@ -204,7 +216,7 @@ void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &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) { }
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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<const char*>(glGetString(GL_RENDERER)),
"Mali-400 MP") == 0;
set = true;
}
return useWorkaround;
}

int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const
{
if (!m_maxTextureSize)
Expand Down
3 changes: 2 additions & 1 deletion src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
Expand Up @@ -62,7 +62,8 @@ class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDista
void referenceGlyphs(const QSet<glyph_t> &glyphs);
void releaseGlyphs(const QSet<glyph_t> &glyphs);

bool useWorkaround() const;
bool useTextureResizeWorkaround() const;
bool useTextureUploadWorkaround() const;
int maxTextureSize() const;

void setMaxTextureCount(int max) { m_maxTextureCount = max; }
Expand Down

0 comments on commit 4f63f43

Please sign in to comment.