From 9206f530cee2be3de3535815c0b272163f091552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 27 Feb 2013 08:41:08 +0100 Subject: [PATCH] Adding support for GL_EXT_texture_format_BGRA8888 in GLES If extension is present texture format BGRA_EXT is used for loading textures from QImages. REVIEW: 109090 --- libkwineffects/kwingltexture.cpp | 112 +++++++++++++++++-------------- libkwineffects/kwingltexture_p.h | 1 + 2 files changed, 63 insertions(+), 50 deletions(-) diff --git a/libkwineffects/kwingltexture.cpp b/libkwineffects/kwingltexture.cpp index 77b663a4a3..a94d835af4 100644 --- a/libkwineffects/kwingltexture.cpp +++ b/libkwineffects/kwingltexture.cpp @@ -46,6 +46,7 @@ namespace KWin bool GLTexturePrivate::sNPOTTextureSupported = false; bool GLTexturePrivate::sFramebufferObjectSupported = false; bool GLTexturePrivate::sSaturationSupported = false; +bool GLTexturePrivate::sTextureFormatBGRA = false; GLTexture::GLTexture() : d_ptr(new GLTexturePrivate()) @@ -94,9 +95,11 @@ GLTexture::GLTexture(int width, int height) glGenTextures(1, &d->m_texture); bind(); #ifdef KWIN_HAVE_OPENGLES - // format and internal format have to match in ES, GL_RGBA8 and GL_BGRA are not available - // see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml - glTexImage2D(d->m_target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + if (GLTexturePrivate::sTextureFormatBGRA) { + glTexImage2D(d->m_target, 0, GL_BGRA_EXT, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0); + } else { + glTexImage2D(d->m_target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } #else glTexImage2D(d->m_target, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0); #endif @@ -146,12 +149,14 @@ void GLTexturePrivate::initStatic() sNPOTTextureSupported = true; sFramebufferObjectSupported = true; sSaturationSupported = true; + sTextureFormatBGRA = hasGLExtension("GL_EXT_texture_format_BGRA8888"); #else sNPOTTextureSupported = hasGLExtension("GL_ARB_texture_non_power_of_two"); sFramebufferObjectSupported = hasGLExtension("GL_EXT_framebuffer_object"); sSaturationSupported = ((hasGLExtension("GL_ARB_texture_env_crossbar") && hasGLExtension("GL_ARB_texture_env_dot3")) || hasGLVersion(1, 4)) && (glTextureUnitsCount >= 4) && glActiveTexture != NULL; + sTextureFormatBGRA = true; #endif } @@ -206,9 +211,11 @@ bool GLTexture::load(const QImage& image, GLenum target) } bind(); #ifdef KWIN_HAVE_OPENGLES - // format and internal format have to match in ES, GL_RGBA8 and GL_BGRA are not available - // see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml - glTexImage2D(d->m_target, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + if (GLTexturePrivate::sTextureFormatBGRA) { + glTexImage2D(d->m_target, 0, GL_BGRA_EXT, img.width(), img.height(), 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, img.bits()); + } else { + glTexImage2D(d->m_target, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + } #else glTexImage2D(d->m_target, 0, GL_RGBA8, img.width(), img.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, img.bits()); @@ -248,9 +255,11 @@ void GLTexture::update(const QImage &image, const QPoint &offset, const QRect &s bind(); #ifdef KWIN_HAVE_OPENGLES - // format and internal format have to match in ES, GL_RGBA8 and GL_BGRA are not available - // see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml - glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + if (GLTexturePrivate::sTextureFormatBGRA) { + glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, img.bits()); + } else { + glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, GL_RGBA, GL_UNSIGNED_BYTE, img.bits()); + } #else glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, GL_BGRA, GL_UNSIGNED_BYTE, img.bits()); #endif @@ -454,37 +463,36 @@ QImage GLTexturePrivate::convertToGLFormat(const QImage& img) const { // Copied from Qt's QGLWidget::convertToGLFormat() QImage res; -#ifdef KWIN_HAVE_OPENGLES - res = QImage(img.size(), QImage::Format_ARGB32); - QImage imgARGB32 = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); - const int width = img.width(); - const int height = img.height(); - const uint32_t *p = (const uint32_t*) imgARGB32.scanLine(0); - uint32_t *q = (uint32_t*) res.scanLine(0); + if (sTextureFormatBGRA) { + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + res = QImage(img.size(), QImage::Format_ARGB32); + QImage imgARGB32 = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { - for (int i = 0; i < height; ++i) { - const uint32_t *end = p + width; - while (p < end) { - *q = (*p << 8) | ((*p >> 24) & 0xFF); - p++; - q++; + const int width = img.width(); + const int height = img.height(); + const uint32_t *p = (const uint32_t*) imgARGB32.scanLine(0); + uint32_t *q = (uint32_t*) res.scanLine(0); + + // swizzle + for (int i = 0; i < height; ++i) { + const uint32_t *end = p + width; + while (p < end) { + *q = ((*p << 24) & 0xff000000) + | ((*p >> 24) & 0x000000ff) + | ((*p << 8) & 0x00ff0000) + | ((*p >> 8) & 0x0000ff00); + p++; + q++; + } } + } else if (img.format() != QImage::Format_ARGB32_Premultiplied) { + res = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); + } else { + return img; } } else { - // GL_BGRA -> GL_RGBA - for (int i = 0; i < height; ++i) { - const uint32_t *end = p + width; - while (p < end) { - *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00); - p++; - q++; - } - } - } -#else - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { +#ifdef KWIN_HAVE_OPENGLES res = QImage(img.size(), QImage::Format_ARGB32); QImage imgARGB32 = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); @@ -493,24 +501,28 @@ QImage GLTexturePrivate::convertToGLFormat(const QImage& img) const const uint32_t *p = (const uint32_t*) imgARGB32.scanLine(0); uint32_t *q = (uint32_t*) res.scanLine(0); - // swizzle - for (int i = 0; i < height; ++i) { - const uint32_t *end = p + width; - while (p < end) { - *q = ((*p << 24) & 0xff000000) - | ((*p >> 24) & 0x000000ff) - | ((*p << 8) & 0x00ff0000) - | ((*p >> 8) & 0x0000ff00); - p++; - q++; + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + for (int i = 0; i < height; ++i) { + const uint32_t *end = p + width; + while (p < end) { + *q = (*p << 8) | ((*p >> 24) & 0xFF); + p++; + q++; + } + } + } else { + // GL_BGRA -> GL_RGBA + for (int i = 0; i < height; ++i) { + const uint32_t *end = p + width; + while (p < end) { + *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00); + p++; + q++; + } } } - } else if (img.format() != QImage::Format_ARGB32_Premultiplied) { - res = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); - } else { - return img; - } #endif + } return res; } diff --git a/libkwineffects/kwingltexture_p.h b/libkwineffects/kwingltexture_p.h index e16153e7a1..e3916ef553 100644 --- a/libkwineffects/kwingltexture_p.h +++ b/libkwineffects/kwingltexture_p.h @@ -70,6 +70,7 @@ public: static bool sNPOTTextureSupported; static bool sFramebufferObjectSupported; static bool sSaturationSupported; + static bool sTextureFormatBGRA; private: Q_DISABLE_COPY(GLTexturePrivate) };