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().
This commit is contained in:
Fredrik Höglund 2014-12-13 14:39:46 +01:00
parent 7fd4cf0227
commit 35110d72c6

View file

@ -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(),