summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorDavid Boddie <dboddie@trolltech.com>2009-08-27 11:44:36 (GMT)
committerDavid Boddie <dboddie@trolltech.com>2009-08-27 11:44:36 (GMT)
commit6f9e2fb5cb496b826cb41a8127dd57e58d6c5103 (patch)
tree5cff842e7d7aa639c5a7228af527ac89e4487619 /src/opengl
parentc4279ec239e03c8f23bc73416291ad087cc36c4c (diff)
parentf60fedcb490f31576665194153f871eabaf20617 (diff)
downloadQt-6f9e2fb5cb496b826cb41a8127dd57e58d6c5103.zip
Qt-6f9e2fb5cb496b826cb41a8127dd57e58d6c5103.tar.gz
Qt-6f9e2fb5cb496b826cb41a8127dd57e58d6c5103.tar.bz2
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into 4.6
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp16
-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/qglshaderprogram.cpp86
-rw-r--r--src/opengl/qglshaderprogram.h20
-rw-r--r--src/opengl/qpaintengine_opengl.cpp8
-rw-r--r--src/opengl/qpixmapdata_gl.cpp2
11 files changed, 353 insertions, 149 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 2f565cf..cc9b014 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -385,7 +385,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, q->state()->renderHints & QPainter::SmoothPixmapTransform);
}
else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
@@ -411,8 +411,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, q->state()->renderHints & QPainter::SmoothPixmapTransform);
}
brushTextureDirty = false;
@@ -668,7 +667,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);
@@ -1104,10 +1103,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();
@@ -1127,7 +1127,7 @@ 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, QGLContext::InternalBindOption);
GLuint id = texture->id;
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 57ef70c..02991d9 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::MemoryManagedBindOption;
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..aca60bc 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::InvertedYBindOption ? 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::InvertedYBindOption;
+ QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
+ if (texture->options & QGLContext::InvertedYBindOption)
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 83fddd1..0913606 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/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index f8bffd3..8ce50cf 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -104,7 +104,7 @@ QT_BEGIN_NAMESPACE
on desktop systems. The programmer should restrict themselves
to just features that are present in GLSL/ES, and avoid
standard variable names that only work on the desktop.
-
+
\section1 Simple shader example
\code
@@ -199,8 +199,11 @@ QT_BEGIN_NAMESPACE
\value VertexShader Vertex shader written in the OpenGL Shading Language (GLSL).
\value FragmentShader Fragment shader written in the OpenGL Shading Language (GLSL).
+
\value PartialVertexShader Partial vertex shader that will be concatenated with all other partial vertex shaders at link time.
\value PartialFragmentShader Partial fragment shader that will be concatenated with all other partial fragment shaders at link time.
+
+ \omitvalue PartialShader
*/
#ifndef GL_FRAGMENT_SHADER
@@ -251,8 +254,7 @@ public:
, shader(0)
, shaderType(type)
, compiled(false)
- , isPartial(type == QGLShader::PartialVertexShader ||
- type == QGLShader::PartialFragmentShader)
+ , isPartial((type & QGLShader::PartialShader) != 0)
, hasPartialSource(false)
{
}
@@ -348,31 +350,6 @@ QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
}
/*!
- Constructs a new QGLShader object from the source code in \a fileName
- and attaches it to \a parent. If the filename ends in \c{.fsh},
- it is assumed to be a fragment shader, otherwise it is assumed to
- be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
- If the shader could not be loaded, then isCompiled() will return false.
-
- The shader will be associated with the current QGLContext.
-
- \sa isCompiled()
-*/
-QGLShader::QGLShader(const QString& fileName, QObject *parent)
- : QObject(parent)
-{
- if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
- d = new QGLShaderPrivate(QGLShader::FragmentShader, QGLContext::currentContext());
- else
- d = new QGLShaderPrivate(QGLShader::VertexShader, QGLContext::currentContext());
- if (d->create() && !compileFile(fileName)) {
- if (d->shader)
- glDeleteShader(d->shader);
- d->shader = 0;
- }
-}
-
-/*!
Constructs a new QGLShader object of the specified \a type from the
source code in \a fileName and attaches it to \a parent.
If the shader could not be loaded, then isCompiled() will return false.
@@ -413,31 +390,6 @@ QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObj
}
/*!
- Constructs a new QGLShader object from the source code in \a fileName
- and attaches it to \a parent. If the filename ends in \c{.fsh},
- it is assumed to be a fragment shader, otherwise it is assumed to
- be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
- If the shader could not be loaded, then isCompiled() will return false.
-
- The shader will be associated with \a context.
-
- \sa isCompiled()
-*/
-QGLShader::QGLShader(const QString& fileName, const QGLContext *context, QObject *parent)
- : QObject(parent)
-{
- if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
- d = new QGLShaderPrivate(QGLShader::FragmentShader, context);
- else
- d = new QGLShaderPrivate(QGLShader::VertexShader, context);
- if (d->create() && !compileFile(fileName)) {
- if (d->shader)
- glDeleteShader(d->shader);
- d->shader = 0;
- }
-}
-
-/*!
Constructs a new QGLShader object of the specified \a type from the
source code in \a fileName and attaches it to \a parent.
If the shader could not be loaded, then isCompiled() will return false.
@@ -917,6 +869,33 @@ bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QString& sour
}
/*!
+ Compiles the contents of \a fileName as a shader of the specified
+ \a type and adds it to this shader program. Returns true if
+ compilation was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa addShader()
+*/
+bool QGLShaderProgram::addShaderFromFile
+ (QGLShader::ShaderType type, const QString& fileName)
+{
+ if (!init())
+ return false;
+ QGLShader *shader = new QGLShader(type, this);
+ if (!shader->compileFile(fileName)) {
+ d->log = shader->log();
+ delete shader;
+ return false;
+ }
+ d->anonShaders.append(shader);
+ return addShader(shader);
+}
+
+/*!
Removes \a shader from this shader program. The object is not deleted.
\sa addShader(), link(), removeAllShaders()
@@ -2983,6 +2962,7 @@ bool QGLShaderProgram::hasShaderPrograms(const QGLContext *context)
#endif
}
+
#endif
QT_END_NAMESPACE
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index c5295eb..4f95ef3 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -63,19 +63,21 @@ class Q_OPENGL_EXPORT QGLShader : public QObject
{
Q_OBJECT
public:
- enum ShaderType
+ enum ShaderTypeBits
{
- VertexShader,
- FragmentShader,
- PartialVertexShader,
- PartialFragmentShader
+ VertexShader = 0x0001,
+ FragmentShader = 0x0002,
+
+ PartialShader = 0x1000,
+
+ PartialVertexShader = PartialShader | VertexShader,
+ PartialFragmentShader = PartialShader | FragmentShader
};
+ Q_DECLARE_FLAGS(ShaderType, ShaderTypeBits);
explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0);
- explicit QGLShader(const QString& fileName, QObject *parent = 0);
QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0);
QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
- QGLShader(const QString& fileName, const QGLContext *context, QObject *parent = 0);
QGLShader(const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
virtual ~QGLShader();
@@ -106,6 +108,9 @@ private:
Q_DISABLE_COPY(QGLShader)
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType);
+
+
class QGLShaderProgramPrivate;
class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
@@ -123,6 +128,7 @@ public:
bool addShader(QGLShader::ShaderType type, const char *source);
bool addShader(QGLShader::ShaderType type, const QByteArray& source);
bool addShader(QGLShader::ShaderType type, const QString& source);
+ bool addShaderFromFile(QGLShader::ShaderType type, const QString& fileName);
void removeAllShaders();
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