|
|
|
|
@ -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 (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++; |
|
|
|
|
|
|
|
|
|
if (sTextureFormatBGRA) { |
|
|
|
|
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
// 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|