From 35110d72c631bfc8d76e1e032dc6c7fa10c7d87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Sat, 13 Dec 2014 14:39:46 +0100 Subject: [PATCH] Avoid converting images in GLTexture when possible Don't convert the QImage when the image format can be specified as a format/type combination to glTex(Sub)Image(). --- libkwineffects/kwingltexture.cpp | 66 +++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/libkwineffects/kwingltexture.cpp b/libkwineffects/kwingltexture.cpp index a84fddcef6..5ce633a41f 100644 --- a/libkwineffects/kwingltexture.cpp +++ b/libkwineffects/kwingltexture.cpp @@ -75,7 +75,6 @@ GLTexture::GLTexture(const QImage& image, GLenum target) return; d->m_target = target; - d->m_internalFormat = GL_RGBA8; if (d->m_target != GL_TEXTURE_RECTANGLE_ARB) { d->m_scale.setWidth(1.0 / image.width()); @@ -96,19 +95,74 @@ GLTexture::GLTexture(const QImage& image, GLenum target) bind(); if (!GLPlatform::instance()->isGLES()) { - const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + // Note: Blending is set up to expect premultiplied data, so non-premultiplied + // formats must always be converted. + struct { + GLenum internalFormat; + GLenum format; + GLenum type; + } static const table[] = { + { 0, 0, 0 }, // QImage::Format_Invalid + { 0, 0, 0 }, // QImage::Format_Mono + { 0, 0, 0 }, // QImage::Format_MonoLSB + { GL_R8, GL_RED, GL_UNSIGNED_BYTE }, // QImage::Format_Indexed8 + { GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, // QImage::Format_RGB32 + { 0, 0, 0 }, // QImage::Format_ARGB32 + { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, // QImage::Format_ARGB32_Premultiplied + { GL_RGB8, GL_BGR, GL_UNSIGNED_SHORT_5_6_5_REV }, // QImage::Format_RGB16 + { 0, 0, 0 }, // QImage::Format_ARGB8565_Premultiplied + { 0, 0, 0 }, // QImage::Format_RGB666 + { GL_RGB5, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV }, // QImage::Format_RGB555 + { 0, 0, 0 }, // QImage::Format_ARGB8555_Premultiplied + { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE }, // QImage::Format_RGB888 + { GL_RGB4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV }, // QImage::Format_RGB444 + { GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV }, // QImage::Format_ARGB4444_Premultiplied + { GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE }, // QImage::Format_RGBX8888 + { 0, 0, 0 }, // QImage::Format_RGBA8888 + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, // QImage::Format_RGBA8888_Premultiplied +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + { GL_RGB10, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_BGR30 + { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_A2BGR30_Premultiplied + { GL_RGB10, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_RGB30 + { GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_A2RGB30_Premultiplied +#endif + }; + + QImage im; + GLenum internalFormat; + GLenum format; + GLenum type; + + const QImage::Format index = image.format(); + + if (index < sizeof(table) / sizeof(table[0]) && table[index].internalFormat && + !(index == QImage::Format_Indexed8 && image.colorCount() > 0)) { + internalFormat = table[index].internalFormat; + format = table[index].format; + type = table[index].type; + im = image; + } else { + im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + internalFormat = GL_RGBA8; + format = GL_BGRA; + type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + d->m_internalFormat = internalFormat; if (d->s_supportsTextureStorage) { - glTexStorage2D(d->m_target, 1, GL_RGBA8, im.width(), im.height()); + glTexStorage2D(d->m_target, 1, internalFormat, im.width(), im.height()); glTexSubImage2D(d->m_target, 0, 0, 0, im.width(), im.height(), - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, im.bits()); + format, type, im.bits()); d->m_immutable = true; } else { glTexParameteri(d->m_target, GL_TEXTURE_MAX_LEVEL, d->m_mipLevels - 1); - glTexImage2D(d->m_target, 0, GL_RGBA8, im.width(), im.height(), 0, - GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, im.bits()); + glTexImage2D(d->m_target, 0, internalFormat, im.width(), im.height(), 0, + format, type, im.bits()); } } else { + d->m_internalFormat = GL_RGBA8; + if (d->s_supportsARGB32) { const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); glTexImage2D(d->m_target, 0, GL_BGRA_EXT, im.width(), im.height(),