summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar@trolltech.com>2009-08-26 06:47:40 (GMT)
committerGunnar Sletta <gunnar@trolltech.com>2009-08-26 11:24:01 (GMT)
commit3c9bbed70afcd0603a10872b41bdc4f5196feb91 (patch)
tree0519765931f3bbcf8fe417f42986bfe344d66285 /src
parenta28262e21a9ce4a4df05d4211a9f4b60a8f4337f (diff)
downloadQt-3c9bbed70afcd0603a10872b41bdc4f5196feb91.zip
Qt-3c9bbed70afcd0603a10872b41bdc4f5196feb91.tar.gz
Qt-3c9bbed70afcd0603a10872b41bdc4f5196feb91.tar.bz2
New variant of QGLContext::bindTexture that does not require mipmap generation
and y-axis inversion and overall less conversion, making significantly faster for plain usecases Reviewed-by: Trond
Diffstat (limited to 'src')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp17
-rw-r--r--src/opengl/qgl.cpp282
-rw-r--r--src/opengl/qgl.h33
-rw-r--r--src/opengl/qgl_p.h33
-rw-r--r--src/opengl/qgl_x11.cpp12
-rw-r--r--src/opengl/qglextensions_p.h8
-rw-r--r--src/opengl/qglpixmapfilter.cpp2
-rw-r--r--src/opengl/qpaintengine_opengl.cpp8
-rw-r--r--src/opengl/qpixmapdata_gl.cpp2
9 files changed, 308 insertions, 89 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 2901c1e..31e2429 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -384,7 +384,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
QImage texImage = qt_imageForBrush(style, false);
glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true);
+ ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true, QGLContext::InternalBindOption);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
}
else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
@@ -410,8 +410,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
const QPixmap& texPixmap = currentBrush->texture();
glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- // TODO: Support y-inverted pixmaps as brushes
- ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, true);
+ ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
}
brushTextureDirty = false;
@@ -667,7 +666,7 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s
GLfloat dx = 1.0 / textureSize.width();
GLfloat dy = 1.0 / textureSize.height();
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
+ QGLRect srcTextureRect(src.left*dx, src.top*dy, src.right*dx, src.bottom*dy);
setCoords(staticVertexCoordinateArray, dest);
setCoords(staticTextureCoordinateArray, srcTextureRect);
@@ -1092,10 +1091,11 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true, true);
+ QGLTexture *texture =
+ ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
- GLfloat top = texture->yInverted ? (pixmap.height() - src.top()) : src.top();
- GLfloat bottom = texture->yInverted ? (pixmap.height() - src.bottom()) : src.bottom();
+ GLfloat top = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.top()) : src.top();
+ GLfloat bottom = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.bottom()) : src.bottom();
QGLRect srcRect(src.left(), top, src.right(), bottom);
bool isBitmap = pixmap.isQBitmap();
@@ -1115,7 +1115,8 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
QGLContext *ctx = d->ctx;
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true,
+ QGLContext::InternalBindOption);
GLuint id = texture->id;
d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT,
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 57ef70c..e9c4190 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -1443,7 +1443,7 @@ bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
for (int i = 0; i < keys.size(); ++i) {
QGLTexture *tex = m_cache.object(keys.at(i));
if (tex->id == textureId && tex->context == ctx) {
- tex->clean = true; // forces a glDeleteTextures() call
+ tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
m_cache.remove(keys.at(i));
return true;
}
@@ -1479,7 +1479,7 @@ void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
if (qApp->thread() != QThread::currentThread())
return;
QGLTexture *texture = instance()->getTexture(cacheKey);
- if (texture && texture->clean)
+ if (texture && texture->options & QGLContext::MemoryManagedBindOption)
instance()->remove(cacheKey);
}
@@ -1490,7 +1490,7 @@ void QGLTextureCache::pixmapCleanupHook(QPixmap* pixmap)
if (qApp->thread() == QThread::currentThread()) {
const qint64 cacheKey = pixmap->cacheKey();
QGLTexture *texture = instance()->getTexture(cacheKey);
- if (texture && texture->clean)
+ if (texture && texture->options & QGLContext::MemoryManagedBindOption)
instance()->remove(cacheKey);
}
#if defined(Q_WS_X11)
@@ -1578,6 +1578,39 @@ Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
Please note that QGLContext is not thread safe.
*/
+/*!
+ \enum QGLContext::BindOption
+ A set of options to decide how to bind a texture using bindTexture().
+
+ \value NoBindOption Don't do anything, pass the texture straight
+ thru.
+
+ \value InvertedYBindOption Specifies that the texture should be flipped
+ over the X axis so that the texture coordinate 0,0 corresponds to
+ the top left corner. Inverting the texture implies a deep copy
+ prior to upload.
+
+ \value MipmapBindOption Specifies that bindTexture should try
+ to generate mipmaps. If the GL implementation supports the \c
+ GL_SGIS_generate_mipmap extension, mipmaps will be automatically
+ generated for the texture. Mipmap generation is only supported for
+ the \c GL_TEXTURE_2D target.
+
+ \value PremultipliedAlphaBindOption Specifies that the image should be
+ uploaded with premultiplied alpha and does a conversion accordingly.
+
+ \value LinearFilteringBindOption Specifies that the texture filtering
+ should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
+ also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
+
+ \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
+ would mirror the image and automatically generate mipmaps. This
+ option helps preserve this default behavior.
+
+ \omitvalue MemoryManagedBindOption
+
+ \omitvalue InternalBindOption
+*/
/*!
\obsolete
@@ -1880,7 +1913,8 @@ QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_prem
}
/*! \internal */
-QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, bool clean)
+QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
+ QGLContext::BindOptions options)
{
const qint64 key = image.cacheKey();
QGLTexture *texture = textureCacheLookup(key, target);
@@ -1890,7 +1924,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
}
if (!texture)
- texture = bindTexture(image, target, format, key, clean);
+ texture = bindTexture(image, target, format, key, options);
// NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
Q_ASSERT(texture);
@@ -1900,68 +1934,128 @@ QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
return texture;
}
+// #define QGL_BIND_TEXTURE_DEBUG
+
QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
- const qint64 key, bool clean)
+ const qint64 key, QGLContext::BindOptions options)
{
Q_Q(QGLContext);
- QGLContext *ctx = q;
-
- // the GL_BGRA format is only present in GL version >= 1.2
- GLenum texture_format = (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
- ? GL_BGRA : GL_RGBA;
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), format=%x, options=%x\n",
+ image.width(), image.height(), format, int(options));
+#endif
// Scale the pixmap if needed. GL textures needs to have the
// dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
// 2.0 or use the GL_TEXTURE_RECTANGLE texture target
int tx_w = qt_next_power_of_two(image.width());
int tx_h = qt_next_power_of_two(image.height());
- bool scale = false;
QImage img = image;
if (( !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) &&
!(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) )
&& (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
{
- scale = true;
+ img = img.scaled(tx_w, tx_h);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - upscaled to %dx%d\n", tx_w, tx_h);
+#endif
}
+ GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
+
GLuint tx_id;
glGenTextures(1, &tx_id);
glBindTexture(target, tx_id);
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, filtering);
+
if (glFormat.directRendering()
&& QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap
- && target == GL_TEXTURE_2D && !clean)
+ && target == GL_TEXTURE_2D
+ && options & QGLContext::MipmapBindOption)
{
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - generating mipmaps\n");
+#endif
glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
#ifndef QT_OPENGL_ES
glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
#else
glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
#endif
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
+ ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
} else {
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
}
QImage::Format target_format = img.format();
- // Note: the clean param is only true when a texture is bound
- // from the QOpenGLPaintEngine - in that case we have to force
- // a premultiplied texture format
- if (clean || img.format() != QImage::Format_ARGB32)
- target_format = QImage::Format_ARGB32_Premultiplied;
- if (img.format() != target_format)
- img = img.convertToFormat(target_format);
+ bool premul = options & QGLContext::PremultipliedAlphaBindOption;
+ GLenum texture_format = QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2
+ ? GL_BGRA : GL_RGBA;
+ GLuint pixel_type = GL_UNSIGNED_BYTE;
+
+ switch (target_format) {
+ case QImage::Format_ARGB32:
+ if (premul) {
+ img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - converting ARGB32 -> ARGB32_Premultiplied \n");
+#endif
+ }
+ break;
+ case QImage::Format_ARGB32_Premultiplied:
+ if (!premul) {
+ img = img.convertToFormat(target_format = QImage::Format_ARGB32);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - converting ARGB32_Premultiplied -> ARGB32\n");
+#endif
+ }
+ break;
+ case QImage::Format_RGB16:
+ pixel_type = GL_UNSIGNED_SHORT_5_6_5;
+ texture_format = GL_RGB;
+ break;
+ case QImage::Format_RGB32:
+ if (format == GL_RGBA)
+ format = GL_RGB;
+ break;
+
+ default:
+ if (img.hasAlphaChannel()) {
+ img = img.convertToFormat(premul
+ ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_ARGB32);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - converting to 32-bit alpha format\n");
+#endif
+ } else {
+ img = img.convertToFormat(QImage::Format_RGB32);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - converting to 32-bit\n");
+#endif
+ }
+ }
+
+ if (options & QGLContext::InvertedYBindOption) {
+ int ipl = img.bytesPerLine() / 4;
+ int h = img.height();
+ for (int y=0; y<h/2; ++y) {
+ int *a = (int *) img.scanLine(y);
+ int *b = (int *) img.scanLine(h - y - 1);
+ for (int x=0; x<ipl; ++x)
+ qSwap(a[x], b[x]);
+ }
+ }
- QImage tx(scale ? QSize(tx_w, tx_h) : img.size(), target_format);
- convertToGLFormatHelper(tx, img, texture_format);
- glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format,
- GL_UNSIGNED_BYTE, tx.bits());
+ const QImage &constRef = img; // to avoid detach in bits()...
+ glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format,
+ pixel_type, constRef.bits());
// this assumes the size of a texture is always smaller than the max cache size
int cost = img.width()*img.height()*4/1024;
- QGLTexture *texture = new QGLTexture(q, tx_id, target, clean, false);
+ QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
QGLTextureCache::instance()->insert(q, key, texture, cost);
return texture;
}
@@ -1980,7 +2074,7 @@ QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum targe
/*! \internal */
-QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean, bool canInvert)
+QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
{
Q_Q(QGLContext);
QPixmapData *pd = pixmap.pixmapData();
@@ -2005,9 +2099,9 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
#if defined(Q_WS_X11)
// Try to use texture_from_pixmap
if (pd->classId() == QPixmapData::X11Class) {
- texture = bindTextureFromNativePixmap(pd, key, canInvert);
+ texture = bindTextureFromNativePixmap(pd, key, options);
if (texture) {
- texture->clean = clean;
+ texture->options |= QGLContext::BindMemoryManaged;
texture->boundPixmap = pd;
boundPixmaps.insert(pd, QPixmap(pixmap));
}
@@ -2015,7 +2109,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
#endif
if (!texture)
- texture = bindTexture(pixmap.toImage(), target, format, key, clean);
+ texture = bindTexture(pixmap.toImage(), target, format, key, options);
// NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
Q_ASSERT(texture);
@@ -2061,6 +2155,20 @@ int QGLContextPrivate::maxTextureSize()
}
/*!
+ Generates and binds a 2D GL texture to the current context, based
+ on \a image. The generated texture id is returned and can be used in
+ later \c glBindTexture() calls.
+
+ \overload
+*/
+GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
+{
+ Q_D(QGLContext);
+ QGLTexture *texture = d->bindTexture(image, target, format, false, DefaultBindOption);
+ return texture->id;
+}
+
+/*!
Generates and binds a 2D GL texture to the current context, based
on \a image. The generated texture id is returned and can be used
in later \c glBindTexture() calls.
@@ -2069,12 +2177,7 @@ int QGLContextPrivate::maxTextureSize()
target is \c GL_TEXTURE_2D.
The \a format parameter sets the internal format for the
- texture. The default format is \c GL_RGBA8.
-
- If the GL implementation supports the \c GL_SGIS_generate_mipmap
- extension, mipmaps will be automatically generated for the
- texture. Mipmap generation is only supported for the \c
- GL_TEXTURE_2D target.
+ texture. The default format is \c GL_RGBA.
The texture that is generated is cached, so multiple calls to
bindTexture() with the same QImage will return the same texture
@@ -2085,10 +2188,10 @@ int QGLContextPrivate::maxTextureSize()
\sa deleteTexture()
*/
-GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
+GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
{
Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(image, target, format, false);
+ QGLTexture *texture = d->bindTexture(image, target, format, false, options);
return texture->id;
}
@@ -2097,7 +2200,16 @@ GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
{
Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false);
+ QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
+ return texture->id;
+}
+
+/*! \internal */
+GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
+ BindOptions options)
+{
+ Q_D(QGLContext);
+ QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
return texture->id;
}
#endif
@@ -2109,7 +2221,20 @@ GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMa
GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
{
Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(pixmap, target, format, false, false);
+ QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
+ return texture->id;
+}
+
+/*!
+ \overload
+
+ Generates and binds a 2D GL texture to the current context, based
+ on \a image.
+*/
+GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
+{
+ Q_D(QGLContext);
+ QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
return texture->id;
}
@@ -2118,7 +2243,15 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint forma
GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
{
Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), false, false);
+ QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
+ return texture->id;
+}
+/*! \internal */
+GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
+ BindOptions options)
+{
+ Q_D(QGLContext);
+ QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
return texture->id;
}
#endif
@@ -4118,15 +4251,31 @@ bool QGLWidget::autoBufferSwap() const
GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
{
Q_D(QGLWidget);
- return d->glcx->bindTexture(image, target, format);
+ return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
}
+
+
+GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
+{
+ Q_D(QGLWidget);
+ return d->glcx->bindTexture(image, target, format, options);
+}
+
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
/*! \internal */
GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
{
Q_D(QGLWidget);
- return d->glcx->bindTexture(image, GLenum(target), GLint(format));
+ return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption);
+}
+
+GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
+ QGLContext::BindOptions options)
+{
+ Q_D(QGLWidget);
+ return d->glcx->bindTexture(image, GLenum(target), GLint(format), options);
}
#endif
@@ -4139,7 +4288,14 @@ GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMac
GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
{
Q_D(QGLWidget);
- return d->glcx->bindTexture(pixmap, target, format);
+ return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
+}
+
+GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
+ QGLContext::BindOptions options)
+{
+ Q_D(QGLWidget);
+ return d->glcx->bindTexture(pixmap, target, format, options);
}
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
@@ -4147,7 +4303,14 @@ GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format
GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
{
Q_D(QGLWidget);
- return d->glcx->bindTexture(pixmap, target, format);
+ return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
+}
+
+GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
+ QGLContext::BindOptions options)
+{
+ Q_D(QGLWidget);
+ return d->glcx->bindTexture(pixmap, target, format, options);
}
#endif
@@ -4568,34 +4731,37 @@ QGLFormat QGLDrawable::format() const
return QGLFormat();
}
-GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
+GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format,
+ QGLContext::BindOptions options)
{
QGLTexture *texture = 0;
+ options |= QGLContext::MemoryManagedBindOption;
if (widget)
- texture = widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
+ texture = widget->d_func()->glcx->d_func()->bindTexture(image, target, format, options);
else if (buffer)
- texture = buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
+ texture = buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, options);
else if (fbo && QGLContext::currentContext())
- texture = const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
+ texture = const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, options);
#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
else if (wsurf)
- texture = wsurf->context()->d_func()->bindTexture(image, target, format, true);
+ texture = wsurf->context()->d_func()->bindTexture(image, target, format, options);
#endif
return texture->id;
}
-GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
+GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
+ QGLContext::BindOptions options)
{
QGLTexture *texture = 0;
if (widget)
- texture = widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true, true);
+ texture = widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, options);
else if (buffer)
- texture = buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true, true);
+ texture = buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, options);
else if (fbo && QGLContext::currentContext())
- texture = const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true, true);
+ texture = const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, options);
#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
else if (wsurf)
- texture = wsurf->context()->d_func()->bindTexture(pixmap, target, format, true, true);
+ texture = wsurf->context()->d_func()->bindTexture(pixmap, target, format, options);
#endif
return texture->id;
}
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index 678bbb7..a928d64 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -288,6 +288,25 @@ public:
virtual void swapBuffers() const;
+ enum BindOption {
+ NoBindOption = 0x0000,
+ InvertedYBindOption = 0x0001,
+ MipmapBindOption = 0x0002,
+ PremultipliedAlphaBindOption = 0x0004,
+ LinearFilteringBindOption = 0x0008,
+
+ MemoryManagedBindOption = 0x1000, // internal flag
+
+ DefaultBindOption = LinearFilteringBindOption | InvertedYBindOption | MipmapBindOption,
+ InternalBindOption = MemoryManagedBindOption | PremultipliedAlphaBindOption
+ };
+ Q_DECLARE_FLAGS(BindOptions, BindOption);
+
+ GLuint bindTexture(const QImage &image, GLenum target, GLint format,
+ BindOptions options);
+ GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
+ BindOptions options);
+
GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
@@ -304,6 +323,10 @@ public:
QMacCompatGLint format = GL_RGBA);
GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum = GL_TEXTURE_2D,
QMacCompatGLint format = GL_RGBA);
+ GLuint bindTexture(const QImage &image, QMacCompatGLenum, QMacCompatGLint format,
+ BindOptions);
+ GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum, QMacCompatGLint format,
+ BindOptions);
void deleteTexture(QMacCompatGLuint tx_id);
@@ -446,10 +469,16 @@ public:
const QFont & fnt = QFont(), int listBase = 2000);
QPaintEngine *paintEngine() const;
+ GLuint bindTexture(const QImage &image, GLenum target, GLint format,
+ QGLContext::BindOptions options);
+ GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
+ QGLContext::BindOptions options);
+
GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
+
GLuint bindTexture(const QString &fileName);
void deleteTexture(GLuint tx_id);
@@ -462,6 +491,10 @@ public:
QMacCompatGLint format = GL_RGBA);
GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum = GL_TEXTURE_2D,
QMacCompatGLint format = GL_RGBA);
+ GLuint bindTexture(const QImage &image, QMacCompatGLenum, QMacCompatGLint format,
+ QGLContext::BindOptions);
+ GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum, QMacCompatGLint format,
+ QGLContext::BindOptions);
void deleteTexture(QMacCompatGLuint tx_id);
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index ab040ed..6905199 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -208,10 +208,12 @@ class QGLContextPrivate
public:
explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {groupResources = new QGLContextGroupResources;}
~QGLContextPrivate() {if (!groupResources->refs.deref()) delete groupResources;}
- QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, bool clean);
+ QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
+ QGLContext::BindOptions options);
QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
- bool clean = false);
- QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean, bool canInvert = false);
+ QGLContext::BindOptions options);
+ QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
+ QGLContext::BindOptions options);
QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
void init(QPaintDevice *dev, const QGLFormat &format);
QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
@@ -241,7 +243,8 @@ public:
quint32 gpm;
int screen;
QHash<QPixmapData*, QPixmap> boundPixmaps;
- QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key, bool canInvert);
+ QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
+ QGLContext::BindOptions options);
static void destroyGlSurfaceForPixmap(QPixmapData*);
static void unbindPixmapFromTexture(QPixmapData*);
#endif
@@ -319,8 +322,10 @@ public:
void doneCurrent();
QSize size() const;
QGLFormat format() const;
- GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
- GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
+ GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA,
+ QGLContext::BindOptions = QGLContext::InternalBindOption);
+ GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA,
+ QGLContext::BindOptions = QGLContext::InternalBindOption);
QColor backgroundColor() const;
QGLContext *context() const;
bool autoFillBackground() const;
@@ -404,15 +409,18 @@ extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
class QGLTexture {
public:
QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
- bool _clean = false, bool _yInverted = false)
- : context(ctx), id(tx_id), target(tx_target), clean(_clean), yInverted(_yInverted)
+ QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
+ : context(ctx),
+ id(tx_id),
+ target(tx_target),
+ options(opt)
#if defined(Q_WS_X11)
- , boundPixmap(0)
+ , boundPixmap(0)
#endif
{}
~QGLTexture() {
- if (clean) {
+ if (options & QGLContext::MemoryManagedBindOption) {
QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
QGLContext *ctx = const_cast<QGLContext *>(context);
Q_ASSERT(ctx);
@@ -436,8 +444,9 @@ public:
QGLContext *context;
GLuint id;
GLenum target;
- bool clean;
- bool yInverted; // NOTE: Y-Inverted textures are for internal use only!
+
+ QGLContext::BindOptions options;
+
#if defined(Q_WS_X11)
QPixmapData* boundPixmap;
#endif
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index dccdf63..2337964 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -1599,7 +1599,8 @@ bool qt_resolveTextureFromPixmap()
#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key, bool canInvert)
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key,
+ QGLContext::BindOptions options)
{
#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
return 0;
@@ -1632,7 +1633,7 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, con
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
// QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
- GLX_Y_INVERTED_EXT, canInvert ? GLX_DONT_CARE : False,
+ GLX_Y_INVERTED_EXT, options & QGLContext::BindInvertedY ? GLX_DONT_CARE : False,
XNone
};
configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount);
@@ -1693,9 +1694,10 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, con
glBindTexture(GL_TEXTURE_2D, textureId);
- QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, false);
- texture->yInverted = (hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted);
- if (texture->yInverted)
+ if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted)));
+ options &= ~QGLContext::BindInvertedY;
+ QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
+ if (texture->options & QGLContext::BindInvertedY)
pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
// We assume the cost of bound pixmaps is zero
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index b03fdfa..a5f83a5 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -410,6 +410,14 @@ struct QGLExtensionFuncs
#define GL_BGRA 0x80E1
#endif
+#ifndef GL_RGB16
+#define GL_RGB16 32852
+#endif
+
+#ifndef GL_UNSIGNED_SHORT_5_6_5
+#define GL_UNSIGNED_SHORT_5_6_5 33635
+#endif
+
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index e1ee61a..9ea602d 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const
{
- const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, true, false);
+ const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, QGLContext::BindOptions(QGLContext::DefaultBindOption | QGLContext::MemoryManagedBindOption));
}
void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF& source) const
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index 9434adf..ade67d3 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -4433,13 +4433,13 @@ void QOpenGLPaintEngine::drawTextureRect(int tx_width, int tx_height, const QRec
if (target == GL_TEXTURE_2D) {
x1 = sr.x() / tx_width;
x2 = x1 + sr.width() / tx_width;
- y1 = 1.0 - (sr.bottom() / tx_height);
- y2 = 1.0 - (sr.y() / tx_height);
+ y1 = 1 - (sr.bottom() / tx_height);
+ y2 = 1 - (sr.y() / tx_height);
} else {
x1 = sr.x();
x2 = sr.right();
- y1 = tx_height - sr.bottom();
- y2 = tx_height - sr.y();
+ y1 = sr.bottom();
+ y2 = sr.y();
}
q_vertexType vertexArray[4*2];
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index 80e99a0..c193f12 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -271,7 +271,7 @@ void QGLPixmapData::ensureCreated() const
m_source = QImage();
}
- m_texture.clean = false;
+ m_texture.options &= ~QGLContext::MemoryManagedBindOption;
}
QGLFramebufferObject *QGLPixmapData::fbo() const