diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-10-24 19:50:34 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-25 14:51:30 +0200 |
commit | e1325cf26e146b68725cc1a0a02b274ce3dfbe5c (patch) | |
tree | dba5e4afa3d2079712bdbc2b63f38475f2a4d2ea | |
parent | 788b8aa29d9f7c13ba3755a0b3ffa2dc7833732d (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.cpp | 30 | ||||
-rw-r--r-- | src/gui/opengl/qopengltexturecache_p.h | 3 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 36 |
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 |