aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2014-11-06 12:10:00 +0100
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>2014-11-11 14:30:26 +0100
commitb5403efcb103423f44c707db4b07df0ff5c2203b (patch)
treeebcea41b78200a052dde9d606f74ef29a85b782a /src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
parent868def84fe800aaba937159814388249ebbaf914 (diff)
Add padding to distance field glyph cache
Linear filtering can cause pixels outside the glyph's bounding rect to be sampled. On drivers where uninitialized texture data is actually uninitialized, this could cause artifacts in rendering for glyphs at the right edge of the initiliazed area since they would sometimes sample random pixels. To avoid this, we add padding between the glyphs in the cache. [ChangeLog][Qt Quick] Fixed uncommon artifacts in rendering of distance field glyphs. Task-number: QTBUG-42148 Change-Id: I6982b4a150d9459185d50a4362e1ead588d3860f Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
Diffstat (limited to 'src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp')
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp28
1 files changed, 20 insertions, 8 deletions
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 093e84b618..3d958245d2 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -48,6 +48,10 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND)
+#if !defined(QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING)
+# define QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING 2
+#endif
+
QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
: QSGDistanceFieldGlyphCache(man, c, font)
, m_maxTextureSize(0)
@@ -90,8 +94,9 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
for (QSet<glyph_t>::const_iterator it = glyphs.constBegin(); it != glyphs.constEnd() ; ++it) {
glyph_t glyphIndex = *it;
+ int padding = QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING;
int glyphWidth = qCeil(glyphData(glyphIndex).boundingRect.width()) + distanceFieldRadius() * 2;
- QSize glyphSize(glyphWidth, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()));
+ QSize glyphSize(glyphWidth + padding * 2, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) + padding * 2);
QRect alloc = m_areaAllocator->allocate(glyphSize);
if (alloc.isNull()) {
@@ -101,7 +106,10 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
int unusedGlyphWidth = qCeil(glyphData(unusedGlyph).boundingRect.width()) + distanceFieldRadius() * 2;
- m_areaAllocator->deallocate(QRect(unusedCoord.x, unusedCoord.y, unusedGlyphWidth, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())));
+ m_areaAllocator->deallocate(QRect(unusedCoord.x - padding,
+ unusedCoord.y - padding,
+ padding * 2 + unusedGlyphWidth,
+ padding * 2 + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())));
m_unusedGlyphs.remove(unusedGlyph);
m_glyphsTexture.remove(unusedGlyph);
@@ -117,11 +125,14 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
TextureInfo *tex = textureInfo(alloc.y() / maxTextureSize());
alloc = QRect(alloc.x(), alloc.y() % maxTextureSize(), alloc.width(), alloc.height());
+
tex->allocatedArea |= alloc;
+ Q_ASSERT(tex->padding == padding || tex->padding < 0);
+ tex->padding = padding;
GlyphPosition p;
p.glyph = glyphIndex;
- p.position = alloc.topLeft();
+ p.position = alloc.topLeft() + QPoint(padding, padding);
glyphPositions.append(p);
glyphsToRender.append(glyphIndex);
@@ -153,13 +164,14 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
glyphTextures[texInfo].append(glyphIndex);
+ int padding = texInfo->padding;
int expectedWidth = qCeil(c.width + c.xMargin * 2);
- if (glyph.width() != expectedWidth)
- glyph = glyph.copy(0, 0, expectedWidth, glyph.height());
+ glyph = glyph.copy(-padding, -padding,
+ expectedWidth + padding * 2, glyph.height() + padding * 2);
if (useTextureResizeWorkaround()) {
uchar *inBits = glyph.scanLine(0);
- uchar *outBits = texInfo->image.scanLine(int(c.y)) + int(c.x);
+ uchar *outBits = texInfo->image.scanLine(int(c.y) - padding) + int(c.x) - padding;
for (int y = 0; y < glyph.height(); ++y) {
memcpy(outBits, inBits, glyph.width());
inBits += glyph.width();
@@ -175,13 +187,13 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
if (useTextureUploadWorkaround()) {
for (int i = 0; i < glyph.height(); ++i) {
m_funcs->glTexSubImage2D(GL_TEXTURE_2D, 0,
- c.x, c.y + i, glyph.width(),1,
+ c.x - padding, c.y + i - padding, glyph.width(),1,
format, GL_UNSIGNED_BYTE,
glyph.scanLine(i));
}
} else {
m_funcs->glTexSubImage2D(GL_TEXTURE_2D, 0,
- c.x, c.y, glyph.width(), glyph.height(),
+ c.x - padding, c.y - padding, glyph.width(), glyph.height(),
format, GL_UNSIGNED_BYTE,
glyph.constBits());
}