diff --git a/libkwineffects/kwingltexture.cpp b/libkwineffects/kwingltexture.cpp index f6082d88f8..7423ed4a74 100644 --- a/libkwineffects/kwingltexture.cpp +++ b/libkwineffects/kwingltexture.cpp @@ -46,7 +46,10 @@ namespace KWin bool GLTexturePrivate::sNPOTTextureSupported = false; bool GLTexturePrivate::sFramebufferObjectSupported = false; bool GLTexturePrivate::sSaturationSupported = false; -bool GLTexturePrivate::sTextureFormatBGRA = false; +GLenum GLTexturePrivate::sTextureFormat = GL_RGBA; // custom dummy, GL_BGRA is not present on GLES +uint GLTexturePrivate::s_textureObjectCounter = 0; +uint GLTexturePrivate::s_fbo = 0; + GLTexture::GLTexture() : d_ptr(new GLTexturePrivate()) @@ -97,11 +100,8 @@ GLTexture::GLTexture(int width, int height) glGenTextures(1, &d->m_texture); bind(); #ifdef KWIN_HAVE_OPENGLES - 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); - } + glTexImage2D(d->m_target, 0, GLTexturePrivate::sTextureFormat, width, height, + 0, GLTexturePrivate::sTextureFormat, GL_UNSIGNED_BYTE, 0); #else glTexImage2D(d->m_target, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0); #endif @@ -133,6 +133,7 @@ GLTexturePrivate::GLTexturePrivate() m_vbo = 0; m_filterChanged = true; m_wrapModeChanged = false; + ++s_textureObjectCounter; } GLTexturePrivate::~GLTexturePrivate() @@ -143,6 +144,11 @@ GLTexturePrivate::~GLTexturePrivate() if (m_texture != 0) { glDeleteTextures(1, &m_texture); } + // Delete the FBO if this is the last Texture + if (--s_textureObjectCounter == 0 && s_fbo) { + glDeleteFramebuffers(1, &s_fbo); + s_fbo = 0; + } } void GLTexturePrivate::initStatic() @@ -151,14 +157,17 @@ void GLTexturePrivate::initStatic() sNPOTTextureSupported = true; sFramebufferObjectSupported = true; sSaturationSupported = true; - sTextureFormatBGRA = hasGLExtension("GL_EXT_texture_format_BGRA8888"); + if (hasGLExtension("GL_EXT_texture_format_BGRA8888")) + sTextureFormat = GL_BGRA_EXT; + else + sTextureFormat = GL_RGBA; #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; + sTextureFormat = GL_BGRA; #endif } @@ -215,11 +224,8 @@ bool GLTexture::load(const QImage& image, GLenum target) } bind(); #ifdef KWIN_HAVE_OPENGLES - 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()); - } + glTexImage2D(d->m_target, 0, GLTexturePrivate::sTextureFormat, img.width(), img.height(), + 0, GLTexturePrivate::sTextureFormat, 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()); @@ -258,15 +264,8 @@ void GLTexture::update(const QImage &image, const QPoint &offset, const QRect &s const QImage &img = d->convertToGLFormat(tmpImage.isNull() ? image : tmpImage); bind(); -#ifdef KWIN_HAVE_OPENGLES - 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 + glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, + GLTexturePrivate::sTextureFormat, GL_UNSIGNED_BYTE, img.bits()); checkGLError("update texture"); unbind(); setDirty(); @@ -428,6 +427,33 @@ GLenum GLTexture::filter() const return d->m_filter; } +void GLTexture::clear() +{ + Q_D(GLTexture); + if (!GLTexturePrivate::s_fbo && GLRenderTarget::supported() && + GLPlatform::instance()->driver() != Driver_Catalyst) // fail. -> bug #323065 + glGenFramebuffers(1, &GLTexturePrivate::s_fbo); + + if (GLTexturePrivate::s_fbo) { + // Clear the texture + glBindFramebuffer(GL_FRAMEBUFFER, GLTexturePrivate::s_fbo); + glClearColor(0, 0, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, d->m_texture, 0); + glClear(GL_COLOR_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } else { + if (const int size = width()*height()) { + uint32_t *buffer = new uint32_t[size]; + memset(buffer, 0, size*sizeof(uint32_t)); + bind(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width(), height(), + GLTexturePrivate::sTextureFormat, GL_UNSIGNED_BYTE, buffer); + unbind(); + delete[] buffer; + } + } +} + bool GLTexture::isDirty() const { Q_D(const GLTexture); @@ -470,7 +496,7 @@ QImage GLTexturePrivate::convertToGLFormat(const QImage& img) const // Copied from Qt's QGLWidget::convertToGLFormat() QImage res; - if (sTextureFormatBGRA) { + if (sTextureFormat != GL_RGBA) { if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { res = QImage(img.size(), QImage::Format_ARGB32); QImage imgARGB32 = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); diff --git a/libkwineffects/kwingltexture.h b/libkwineffects/kwingltexture.h index 18e0a80081..200d24f322 100644 --- a/libkwineffects/kwingltexture.h +++ b/libkwineffects/kwingltexture.h @@ -93,6 +93,11 @@ public: GLuint texture() const; GLenum target() const; GLenum filter() const; + /** @short + * Make the texture fully transparent + * Warning: this clobbers the current framebuffer binding except on fglrx + */ + void clear(); bool isDirty() const; void setFilter(GLenum filter); void setWrapMode(GLenum mode); diff --git a/libkwineffects/kwingltexture_p.h b/libkwineffects/kwingltexture_p.h index 2afc9aa7a4..0b57d9742b 100644 --- a/libkwineffects/kwingltexture_p.h +++ b/libkwineffects/kwingltexture_p.h @@ -73,7 +73,9 @@ public: static bool sNPOTTextureSupported; static bool sFramebufferObjectSupported; static bool sSaturationSupported; - static bool sTextureFormatBGRA; + static GLenum sTextureFormat; + static uint s_fbo; + static uint s_textureObjectCounter; private: Q_DISABLE_COPY(GLTexturePrivate) }; diff --git a/paintredirector.cpp b/paintredirector.cpp index 982ab6f58b..528827ea53 100644 --- a/paintredirector.cpp +++ b/paintredirector.cpp @@ -28,6 +28,7 @@ DEALINGS IN THE SOFTWARE. #include "client.h" #include "deleted.h" #include "effects.h" +#include #include #include #include @@ -310,21 +311,12 @@ void ImageBasedPaintRedirector::discardScratch() // ------------------------------------------------------------------ - -unsigned int OpenGLPaintRedirector::s_count = 0; -unsigned int OpenGLPaintRedirector::s_fbo = 0; - OpenGLPaintRedirector::OpenGLPaintRedirector(Client *c, QWidget *widget) : ImageBasedPaintRedirector(c, widget) { - s_count++; - for (int i = 0; i < TextureCount; ++i) m_textures[i] = NULL; - if (!s_fbo && GLRenderTarget::supported()) - glGenFramebuffers(1, &s_fbo); - PaintRedirector::resizePixmaps(); } @@ -332,12 +324,6 @@ OpenGLPaintRedirector::~OpenGLPaintRedirector() { for (int i = 0; i < TextureCount; ++i) delete m_textures[i]; - - // Delete the FBO if this is the last OpenGLPaintRedirector - if (--s_count == 0 && s_fbo) { - glDeleteFramebuffers(1, &s_fbo); - s_fbo = 0; - } } void OpenGLPaintRedirector::resizePixmaps(const QRect *rects) @@ -355,8 +341,6 @@ void OpenGLPaintRedirector::resizePixmaps(const QRect *rects) } } - bool fbo_bound = false; - for (int i = 0; i < 2; i++) { if (m_textures[i] && m_textures[i]->size() == size[i]) continue; @@ -370,22 +354,8 @@ void OpenGLPaintRedirector::resizePixmaps(const QRect *rects) m_textures[i] = new GLTexture(size[i].width(), size[i].height()); m_textures[i]->setYInverted(true); m_textures[i]->setWrapMode(GL_CLAMP_TO_EDGE); - - if (s_fbo) { - // Clear the texture - if (!fbo_bound) { - glBindFramebuffer(GL_FRAMEBUFFER, s_fbo); - glClearColor(0, 0, 0, 0); - fbo_bound = true; - } - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[i]->texture(), 0); - glClear(GL_COLOR_BUFFER_BIT); - } + m_textures[i]->clear(); } - - if (fbo_bound) - glBindFramebuffer(GL_FRAMEBUFFER, 0); } void OpenGLPaintRedirector::preparePaint(const QPixmap &pending) diff --git a/paintredirector.h b/paintredirector.h index fbc53042c5..be96f051e6 100644 --- a/paintredirector.h +++ b/paintredirector.h @@ -157,9 +157,6 @@ protected: private: QImage m_tempImage; GLTexture *m_textures[2]; - - static unsigned int s_fbo; - static unsigned int s_count; }; class NativeXRenderPaintRedirector : public PaintRedirector