GL2PaintEngine: centralize logic for updating/preparing textures

Rewrite of updateTextureFilter to include activating and binding as well,
so that we can maintain a single view of which texture was the last one
to be used from within the engine itself.

The behavior should be the same as before.

Change-Id: I41781d00458b0176c614266f4360db3c68b120a1
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
bb10
Tor Arne Vestbø 2014-12-02 20:16:23 +01:00
parent e9222e199d
commit 47326b9c5c
2 changed files with 78 additions and 50 deletions

View File

@ -107,29 +107,6 @@ QOpenGL2PaintEngineExPrivate::~QOpenGL2PaintEngineExPrivate()
}
}
void QOpenGL2PaintEngineExPrivate::updateTextureFilter(GLenum wrapMode, bool smoothPixmapTransform, GLuint id)
{
// funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
if (id != GLuint(-1) && id == lastTextureUsed)
return;
lastTextureUsed = id;
static const GLenum target = GL_TEXTURE_2D;
if (smoothPixmapTransform) {
funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
}
inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
{
qreal alpha = c.alphaF() * opacity;
@ -176,19 +153,74 @@ void QOpenGL2PaintEngineExPrivate::useSimpleShader()
updateMatrix();
}
template<typename T>
void QOpenGL2PaintEngineExPrivate::updateTexture(GLenum textureUnit, const T &texture, GLenum wrapMode, GLenum filterMode, TextureUpdateMode updateMode)
{
static const GLenum target = GL_TEXTURE_2D;
funcs.glActiveTexture(GL_TEXTURE0 + textureUnit);
GLuint textureId = bindTexture(texture);
if (updateMode == UpdateIfNeeded && textureId == lastTextureUsed)
return;
lastTextureUsed = textureId;
funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filterMode);
funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filterMode);
}
template<>
GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const GLuint &textureId)
{
if (textureId != lastTextureUsed)
funcs.glBindTexture(GL_TEXTURE_2D, textureId);
return textureId;
}
template<>
GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QImage &image)
{
return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image);
}
template<>
GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QPixmap &pixmap)
{
return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
}
struct ImageWithBindOptions
{
const QImage &image;
QOpenGLTextureCache::BindOptions options;
};
template<>
GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const ImageWithBindOptions &imageWithOptions)
{
return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, imageWithOptions.image, imageWithOptions.options);
}
void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
{
Q_Q(QOpenGL2PaintEngineEx);
// qDebug("QOpenGL2PaintEngineExPrivate::updateBrushTexture()");
Qt::BrushStyle style = currentBrush.style();
bool smoothPixmapTransform = q->state()->renderHints & QPainter::SmoothPixmapTransform;
GLenum filterMode = smoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) {
// Get the image data for the pattern
QImage texImage = qt_imageForBrush(style, false);
QImage textureImage = qt_imageForBrush(style, false);
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, texImage);
updateTextureFilter(GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
updateTexture(QT_BRUSH_TEXTURE_UNIT, textureImage, GL_REPEAT, filterMode, ForceUpdate);
}
else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
// Gradiant brush: All the gradiants use the same texture
@ -197,7 +229,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
// We apply global opacity in the fragment shaders, so we always pass 1.0
// for opacity to the cache.
GLuint texId = QOpenGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0);
GLuint textureId = QOpenGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0);
GLenum wrapMode = GL_CLAMP_TO_EDGE;
if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient)
@ -205,9 +237,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
else if (g->spread() == QGradient::ReflectSpread)
wrapMode = GL_MIRRORED_REPEAT;
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
funcs.glBindTexture(GL_TEXTURE_2D, texId);
updateTextureFilter(wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform);
updateTexture(QT_BRUSH_TEXTURE_UNIT, textureId, wrapMode, filterMode, ForceUpdate);
}
else if (style == Qt::TexturePattern) {
currentBrushImage = currentBrush.textureImage();
@ -224,9 +254,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
wrapMode = GL_CLAMP_TO_EDGE;
}
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, currentBrushImage);
updateTextureFilter(wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform);
updateTexture(QT_BRUSH_TEXTURE_UNIT, currentBrushImage, wrapMode, filterMode, ForceUpdate);
textureInvertedY = false;
}
@ -1382,9 +1410,8 @@ void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixma
ensureActive();
d->transferMode(ImageDrawingMode);
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
d->updateTextureFilter(GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id);
GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
d->updateTexture(QT_IMAGE_TEXTURE_UNIT, pixmap, GL_CLAMP_TO_EDGE, filterMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && !pixmap.hasAlpha();
@ -1428,9 +1455,9 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
break;
}
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image, bindOption);
d->updateTextureFilter(GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id);
ImageWithBindOptions imageWithOptions = { image, bindOption };
GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
d->updateTexture(QT_IMAGE_TEXTURE_UNIT, imageWithOptions, GL_CLAMP_TO_EDGE, filterMode);
d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel());
}
@ -1471,9 +1498,8 @@ bool QOpenGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, co
ensureActive();
d->transferMode(ImageDrawingMode);
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
d->funcs.glBindTexture(GL_TEXTURE_2D, textureId);
d->updateTextureFilter(GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, textureId);
GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
d->updateTexture(QT_IMAGE_TEXTURE_UNIT, textureId, GL_CLAMP_TO_EDGE, filterMode);
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
@ -1823,9 +1849,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat gly
funcs.glEnable(GL_BLEND);
funcs.glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
funcs.glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
funcs.glBindTexture(GL_TEXTURE_2D, cache->texture());
updateTextureFilter(GL_REPEAT, false);
updateTexture(QT_MASK_TEXTURE_UNIT, cache->texture(), GL_REPEAT, GL_NEAREST, ForceUpdate);
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
@ -1970,9 +1994,8 @@ void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFra
transferMode(ImageOpacityArrayDrawingMode);
funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
updateTextureFilter(GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform, id);
GLenum filterMode = q->state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
updateTexture(QT_IMAGE_TEXTURE_UNIT, pixmap, GL_CLAMP_TO_EDGE, filterMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;

View File

@ -193,7 +193,12 @@ public:
void updateBrushUniforms();
void updateMatrix();
void updateCompositionMode();
void updateTextureFilter(GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
enum TextureUpdateMode { UpdateIfNeeded, ForceUpdate };
template<typename T>
void updateTexture(GLenum textureUnit, const T &texture, GLenum wrapMode, GLenum filterMode, TextureUpdateMode updateMode = UpdateIfNeeded);
template<typename T>
GLuint bindTexture(const T &texture);
void resetGLState();