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
This commit is contained in:
Martin Gräßlin 2013-02-27 08:41:08 +01:00
parent aa549f45d5
commit 9206f530ce
2 changed files with 63 additions and 50 deletions

View file

@ -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;
}

View file

@ -70,6 +70,7 @@ public:
static bool sNPOTTextureSupported;
static bool sFramebufferObjectSupported;
static bool sSaturationSupported;
static bool sTextureFormatBGRA;
private:
Q_DISABLE_COPY(GLTexturePrivate)
};