diff options
Diffstat (limited to 'src/gui/opengl/qopenglpaintengine.cpp')
-rw-r--r-- | src/gui/opengl/qopenglpaintengine.cpp | 99 |
1 files changed, 67 insertions, 32 deletions
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index 9fd8a7ada7..555c47f265 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -624,7 +624,7 @@ void QOpenGL2PaintEngineExPrivate::transferMode(EngineMode newMode) if (newMode == mode) return; - if (mode == TextDrawingMode || mode == ImageDrawingMode || mode == ImageArrayDrawingMode) { + if (mode != BrushDrawingMode) { lastTextureUsed = GLuint(-1); } @@ -639,10 +639,12 @@ void QOpenGL2PaintEngineExPrivate::transferMode(EngineMode newMode) setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray); } - if (newMode == ImageArrayDrawingMode) { + if (newMode == ImageArrayDrawingMode || newMode == ImageOpacityArrayDrawingMode) { setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data()); setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data()); - setVertexAttributePointer(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data()); + + if (newMode == ImageOpacityArrayDrawingMode) + setVertexAttributePointer(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data()); } // This needs to change when we implement high-quality anti-aliasing... @@ -1069,9 +1071,23 @@ void QOpenGL2PaintEngineExPrivate::resetClipIfNeeded() glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } +bool QOpenGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache) +{ + Q_Q(QOpenGL2PaintEngineEx); + + Q_ASSERT(cache.transform().type() <= QTransform::TxScale); + + QTransform &transform = q->state()->matrix; + transform.scale(1.0 / cache.transform().m11(), 1.0 / cache.transform().m22()); + bool ret = prepareForDraw(false); + transform.scale(cache.transform().m11(), cache.transform().m22()); + + return ret; +} + bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) { - if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode) + if (brushTextureDirty && (mode == TextDrawingMode || mode == BrushDrawingMode)) updateBrushTexture(); if (compositionModeDirty) @@ -1091,12 +1107,12 @@ bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) } QOpenGLEngineShaderManager::OpacityMode opacityMode; - if (mode == ImageArrayDrawingMode) { + if (mode == ImageOpacityArrayDrawingMode) { opacityMode = QOpenGLEngineShaderManager::AttributeOpacity; } else { opacityMode = stateHasOpacity ? QOpenGLEngineShaderManager::UniformOpacity : QOpenGLEngineShaderManager::NoOpacity; - if (stateHasOpacity && (mode != ImageDrawingMode)) { + if (stateHasOpacity && (mode != ImageDrawingMode && mode != ImageArrayDrawingMode)) { // Using a brush bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) && (currentBrush.style() <= Qt::DiagCrossPattern); @@ -1116,7 +1132,7 @@ bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) matrixUniformDirty = true; } - if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode) + if (brushUniformsDirty && (mode == TextDrawingMode || mode == BrushDrawingMode)) updateBrushUniforms(); if (opacityMode == QOpenGLEngineShaderManager::UniformOpacity && opacityUniformDirty) { @@ -1407,11 +1423,9 @@ void QOpenGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) ensureActive(); QPainterState *s = state(); - float det = s->matrix.determinant(); - // don't try to cache huge fonts or vastly transformed fonts QFontEngine *fontEngine = textItem->fontEngine(); - if (shouldDrawCachedGlyphs(fontEngine, s->matrix) && det >= 0.25f && det <= 4.f) { + if (shouldDrawCachedGlyphs(fontEngine, s->matrix)) { QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat) : d->glyphCacheType; @@ -1461,13 +1475,6 @@ void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &text QTransform::TransformationType txtype = s->matrix.type(); - float det = s->matrix.determinant(); - bool drawCached = txtype < QTransform::TxProject; - - // don't try to cache huge fonts or vastly transformed fonts - if (!shouldDrawCachedGlyphs(ti.fontEngine, s->matrix) || det < 0.25f || det > 4.f) - drawCached = false; - QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) : d->glyphCacheType; @@ -1482,7 +1489,7 @@ void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &text } } - if (drawCached) { + if (shouldDrawCachedGlyphs(ti.fontEngine, s->matrix)) { QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; QTransform matrix = QTransform::fromTranslate(p.x(), p.y()); @@ -1531,6 +1538,12 @@ namespace { // #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO +bool QOpenGL2PaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &t) const +{ + // Don't try to cache vastly transformed fonts + return t.type() < QTransform::TxProject && QPaintEngineEx::shouldDrawCachedGlyphs(fontEngine, t); +} + void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem) { @@ -1542,10 +1555,18 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type bool recreateVertexArrays = false; QFontEngine *fe = staticTextItem->fontEngine(); + // We allow scaling, so that the glyph-cache will contain glyphs with the + // appropriate resolution in the case of displays with a device-pixel-ratio != 1. + QTransform transform = s->matrix.type() < QTransform::TxRotate ? + QTransform::fromScale(qAbs(s->matrix.m11()), qAbs(s->matrix.m22())) : + QTransform::fromScale( + QVector2D(s->matrix.m11(), s->matrix.m12()).length(), + QVector2D(s->matrix.m21(), s->matrix.m22()).length()); + QOpenGLTextureGlyphCache *cache = - (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, QTransform()); + (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphType, transform); if (!cache || cache->cacheType() != glyphType || cache->contextGroup() == 0) { - cache = new QOpenGLTextureGlyphCache(glyphType, QTransform()); + cache = new QOpenGLTextureGlyphCache(glyphType, transform); fe->setGlyphCache(cacheKey, cache); recreateVertexArrays = true; } @@ -1583,7 +1604,10 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type if (cache->width() == 0 || cache->height() == 0) return; - transferMode(TextDrawingMode); + if (glyphType == QFontEngineGlyphCache::Raster_ARGB) + transferMode(ImageArrayDrawingMode); + else + transferMode(TextDrawingMode); int margin = fe->glyphMargin(glyphType); @@ -1637,8 +1661,8 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type if (c.isNull()) continue; - int x = qFloor(staticTextItem->glyphPositions[i].x) + c.baseLineX - margin; - int y = qRound(staticTextItem->glyphPositions[i].y) - c.baseLineY - margin; + int x = qFloor(staticTextItem->glyphPositions[i].x.toReal() * cache->transform().m11()) + c.baseLineX - margin; + int y = qRound(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22()) - 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)); @@ -1679,8 +1703,10 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type #endif } - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data()); - setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data()); + if (glyphType != QFontEngineGlyphCache::Raster_ARGB || recreateVertexArrays) { + setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data()); + setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data()); + } if (!snapToPixelGrid) { snapToPixelGrid = true; @@ -1711,9 +1737,9 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type } compositionModeDirty = false; // I can handle this myself, thank you very much - prepareForDraw(false); // Text always causes src pixels to be transparent + prepareForCachedGlyphDraw(*cache); - // prepareForDraw() have set the opacity on the current shader, so the opacity state can now be reset. + // prepareForCachedGlyphDraw() have set the opacity on the current shader, so the opacity state can now be reset. if (compMode == QPainter::CompositionMode_Source) { q->state()->opacity = oldOpacity; opacityUniformDirty = true; @@ -1734,7 +1760,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type } compositionModeDirty = false; // I can handle this myself, thank you very much - prepareForDraw(false); // Text always causes src pixels to be transparent + prepareForCachedGlyphDraw(*cache); glEnable(GL_BLEND); glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); @@ -1758,22 +1784,31 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type } compositionModeDirty = false; - prepareForDraw(false); // Text always causes src pixels to be transparent + prepareForCachedGlyphDraw(*cache); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); } compositionModeDirty = true; + } else if (glyphType == QFontEngineGlyphCache::Raster_ARGB) { + currentBrush = noBrush; + shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); + if (prepareForCachedGlyphDraw(*cache)) + shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); } else { // Greyscale/mono glyphs shaderManager->setMaskType(QOpenGLEngineShaderManager::PixelMask); - prepareForDraw(false); // Text always causes src pixels to be transparent + prepareForCachedGlyphDraw(*cache); } QOpenGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QOpenGLTextureGlyphCache::Linear:QOpenGLTextureGlyphCache::Nearest; if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { - funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); + if (glyphType == QFontEngineGlyphCache::Raster_ARGB) + funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + else + funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); + if (lastMaskTextureUsed != cache->texture()) { glBindTexture(GL_TEXTURE_2D, cache->texture()); lastMaskTextureUsed = cache->texture(); @@ -1889,7 +1924,7 @@ void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFra funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap); - transferMode(ImageArrayDrawingMode); + transferMode(ImageOpacityArrayDrawingMode); bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque; |