summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-10-24 19:50:34 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-25 14:51:30 +0200
commite1325cf26e146b68725cc1a0a02b274ce3dfbe5c (patch)
treedba5e4afa3d2079712bdbc2b63f38475f2a4d2ea
parent788b8aa29d9f7c13ba3755a0b3ffa2dc7833732d (diff)
Do not byteswap RGBA8888 formats
The three RGBA8888 formats was introduced to make it possible to have QImages and QPixmaps in native OpenGL formats, but uploaded textures of these types are still converted to ARGB first and then swapped back. This patch detects the formats and ensures the unneeded back-and-forth conversion does not take place. It also replaces a seemingly unused private API meant for the same goal. Change-Id: Id69d6973bb9c13d1052f2a1b0c516183f63421c2 Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
-rw-r--r--src/gui/opengl/qopengltexturecache.cpp30
-rw-r--r--src/gui/opengl/qopengltexturecache_p.h3
-rw-r--r--src/opengl/qgl.cpp36
3 files changed, 35 insertions, 34 deletions
diff --git a/src/gui/opengl/qopengltexturecache.cpp b/src/gui/opengl/qopengltexturecache.cpp
index 94b82885ff..4238f63cd8 100644
--- a/src/gui/opengl/qopengltexturecache.cpp
+++ b/src/gui/opengl/qopengltexturecache.cpp
@@ -95,10 +95,9 @@ void QOpenGLTextureCacheWrapper::cleanupTexturesForPixmapData(QPlatformPixmap *p
cleanupTexturesForCacheKey(pmd->cacheKey());
}
-QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx, bool useByteSwapImage)
+QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx)
: QOpenGLSharedResource(ctx->shareGroup())
, m_cache(64 * 1024) // 64 MB cache
- , m_useByteSwapImage(useByteSwapImage)
{
}
@@ -152,38 +151,13 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i
return id;
}
-static inline void qgl_byteSwapImage(QImage &img)
-{
- const int width = img.width();
- const int height = img.height();
-
- if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
- {
- for (int i = 0; i < height; ++i) {
- uint *p = (uint *) img.scanLine(i);
- for (int x = 0; x < width; ++x)
- p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
- }
- } else {
- for (int i = 0; i < height; ++i) {
- uint *p = (uint *) img.scanLine(i);
- for (int x = 0; x < width; ++x)
- p[x] = (p[x] << 8) | (p[x] >> 24);
- }
- }
-}
-
GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image)
{
GLuint id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
- QImage tx = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
-
- // Performance could be improved by skipping qgl_byteSwapImage().
- if (m_useByteSwapImage)
- qgl_byteSwapImage(tx);
+ QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, const_cast<const QImage &>(tx).bits());
diff --git a/src/gui/opengl/qopengltexturecache_p.h b/src/gui/opengl/qopengltexturecache_p.h
index d4d3f00069..2e82d5f373 100644
--- a/src/gui/opengl/qopengltexturecache_p.h
+++ b/src/gui/opengl/qopengltexturecache_p.h
@@ -78,7 +78,7 @@ class Q_GUI_EXPORT QOpenGLTextureCache : public QOpenGLSharedResource
public:
static QOpenGLTextureCache *cacheForContext(QOpenGLContext *context);
- QOpenGLTextureCache(QOpenGLContext *, bool useByteSwapImage = true);
+ QOpenGLTextureCache(QOpenGLContext *);
~QOpenGLTextureCache();
GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap);
@@ -94,7 +94,6 @@ private:
QMutex m_mutex;
QCache<quint64, QOpenGLCachedTexture> m_cache;
- bool m_useByteSwapImage;
};
QT_END_NAMESPACE
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 8ee0a8b290..16044df8b1 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -2308,10 +2308,18 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
QImage::Format target_format = img.format();
bool premul = options & QGLContext::PremultipliedAlphaBindOption;
+ bool needsbyteswap = true;
GLenum externalFormat;
GLuint pixel_type;
- if (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
+ if (target_format == QImage::Format_RGBA8888
+ || target_format == QImage::Format_RGBA8888_Premultiplied
+ || target_format == QImage::Format_RGBX8888) {
+ externalFormat = GL_RGBA;
+ pixel_type = GL_UNSIGNED_BYTE;
+ needsbyteswap = false;
+ } else if (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
externalFormat = GL_BGRA;
+ needsbyteswap = false;
if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
else
@@ -2338,14 +2346,34 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
#endif
}
break;
+ case QImage::Format_RGBA8888:
+ if (premul) {
+ img = img.convertToFormat(target_format = QImage::Format_RGBA8888_Premultiplied);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - converted RGBA8888 -> RGBA8888_Premultiplied (%d ms) \n", time.elapsed());
+#endif
+ }
+ break;
+ case QImage::Format_RGBA8888_Premultiplied:
+ if (!premul) {
+ img = img.convertToFormat(target_format = QImage::Format_RGBA8888);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+ printf(" - converted RGBA8888_Premultiplied -> RGBA8888 (%d ms) \n", time.elapsed());
+#endif
+ }
+ break;
case QImage::Format_RGB16:
pixel_type = GL_UNSIGNED_SHORT_5_6_5;
externalFormat = GL_RGB;
internalFormat = GL_RGB;
+ needsbyteswap = false;
break;
case QImage::Format_RGB32:
+ case QImage::Format_RGBX8888:
break;
default:
+ // Ideally more formats would be converted directly to an RGBA8888 format,
+ // but we are only guaranteed to have a fast conversion to an ARGB format.
if (img.hasAlphaChannel()) {
img = img.convertToFormat(premul
? QImage::Format_ARGB32_Premultiplied
@@ -2383,10 +2411,10 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
#endif
}
- if (externalFormat == GL_RGBA) {
+ if (needsbyteswap) {
// The only case where we end up with a depth different from
- // 32 in the switch above is for the RGB16 case, where we set
- // the format to GL_RGB
+ // 32 in the switch above is for the RGB16 case, where we do
+ // not need a byteswap.
Q_ASSERT(img.depth() == 32);
qgl_byteSwapImage(img, pixel_type);
#ifdef QGL_BIND_TEXTURE_DEBUG