From 66ffd9f0f66c1fbdfe9123a3f711e9a2bd2abdcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Mon, 9 Sep 2013 19:38:30 +0200 Subject: [PATCH 1/6] input window: ensure input shaping is supported BUG: 320459 FIXED-IN: 4.11.2 REVIEW: 112623 --- client.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client.cpp b/client.cpp index 5a76c25185..e8e20d5ba2 100644 --- a/client.cpp +++ b/client.cpp @@ -371,6 +371,9 @@ void Client::updateInputWindow() if (brokenQtInputHandling) return; + if (!Xcb::Extensions::self()->isShapeInputAvailable()) + return; + QRegion region; if (!noBorder()) { From 149e97fcb9e3cf98bda8b6561cc05b9240a149ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Sun, 22 Sep 2013 00:36:47 +0200 Subject: [PATCH 2/6] reset invert shader on viewport resize General problem known from bug #325154 BUG: 325154 FXED-IN: 4.11.2 REVIEW: 112877 --- effects/invert/invert.cpp | 6 ++++++ effects/invert/invert.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/effects/invert/invert.cpp b/effects/invert/invert.cpp index c412e31644..291aa6b017 100644 --- a/effects/invert/invert.cpp +++ b/effects/invert/invert.cpp @@ -56,6 +56,7 @@ InvertEffect::InvertEffect() b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_U)); connect(b, SIGNAL(triggered(bool)), this, SLOT(toggleWindow())); connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*))); + connect(effects, SIGNAL(screenGeometryChanged(const QSize&)), this, SLOT(resetShader())); } InvertEffect::~InvertEffect() @@ -175,6 +176,11 @@ bool InvertEffect::provides(Feature f) return f == ScreenInversion; } +void InvertEffect::resetShader() +{ + ShaderManager::instance()->resetShader(m_shader, ShaderManager::GenericShader); +} + } // namespace #include "invert.moc" diff --git a/effects/invert/invert.h b/effects/invert/invert.h index 908eef4aff..ef6cd91424 100644 --- a/effects/invert/invert.h +++ b/effects/invert/invert.h @@ -54,6 +54,9 @@ public slots: void toggleWindow(); void slotWindowClosed(KWin::EffectWindow *w); +private Q_SLOTS: + void resetShader(); + protected: bool loadData(); From 67cb571f86579784c777940c216f31ae939ae6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Wed, 11 Sep 2013 23:27:30 +0200 Subject: [PATCH 3/6] fix two damage artifact causes 1. when adding a full damange, that must not replace existing (larger) repaints 2. emit geometryChanged before invoking and to update shadowGeometry through addRepaintFull BUG: 324560 FIXED-IN: 4.11.2 --- composite.cpp | 2 +- events.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/composite.cpp b/composite.cpp index 097d08500f..de674b6c91 100644 --- a/composite.cpp +++ b/composite.cpp @@ -989,7 +989,7 @@ void Toplevel::addDamageFull() return; damage_region = rect(); - repaints_region = rect(); + repaints_region |= rect(); emit damaged(this, rect()); } diff --git a/events.cpp b/events.cpp index 904811864b..1e8ba5008f 100644 --- a/events.cpp +++ b/events.cpp @@ -1521,6 +1521,7 @@ void Unmanaged::configureNotifyEvent(XConfigureEvent* e) addWorkspaceRepaint(visibleRect()); // damage old area QRect old = geom; geom = newgeom; + emit geometryChanged(); // update shadow region addRepaintFull(); if (old.size() != geom.size()) discardWindowPixmap(); From 4fd554a2e22aa2c7a6d5cf208a96c987d63d86c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Sun, 8 Sep 2013 22:56:27 +0200 Subject: [PATCH 4/6] fix xcb CurrentInput implementation broke on interim Wrapper() constructor change The Constructor needs to explicitly pass XCB_WINDOW_NONE to the inherited Constructor to trigger a request Thanks to Alex Leach for finding this CCBUG: 256242 FIXED-IN: 4.11.2 REVIEW: 112595 --- xcbutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcbutils.h b/xcbutils.h index 1a4befd751..fca15f849d 100644 --- a/xcbutils.h +++ b/xcbutils.h @@ -197,7 +197,7 @@ inline xcb_get_input_focus_cookie_t get_input_focus(xcb_connection_t *c, xcb_win class CurrentInput : public Wrapper { public: - CurrentInput() : Wrapper() {} + CurrentInput() : Wrapper(XCB_WINDOW_NONE) {} inline xcb_window_t window() { if (isNull()) From 3f5ef10c8efbf8d5223013bd821768116429cfe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Thu, 5 Sep 2013 21:10:13 +0200 Subject: [PATCH 5/6] introduce GLTexture::clear and use it from paintredirector also work around broken fbo texture clearing on fglrx so far supports FBO/glClear and resorts to glTexSubImage2D if the fbo cannot be created or is (in case of fglrx) known to break, resort to glTexImage2D loading of an argb array of zeros BUG: 323065 FIXED-IN: 4.11.2 REVIEW: 112526 --- libkwineffects/kwingltexture.cpp | 72 ++++++++++++++++++++++---------- libkwineffects/kwingltexture.h | 5 +++ libkwineffects/kwingltexture_p.h | 4 +- paintredirector.cpp | 34 +-------------- paintredirector.h | 3 -- 5 files changed, 59 insertions(+), 59 deletions(-) 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 From 3eb0b27d00fc292413734b5701e423e2b29f7749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Sat, 21 Sep 2013 00:42:21 +0200 Subject: [PATCH 6/6] windowgeometry effect, keep hint inside screen and use passed geometry parameter to position the labels (required with resize effect because the actual geometry is not updated) REVIEW: 112849 --- effects/windowgeometry/windowgeometry.cpp | 24 +++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/effects/windowgeometry/windowgeometry.cpp b/effects/windowgeometry/windowgeometry.cpp index fca5bda351..5f3176f1eb 100644 --- a/effects/windowgeometry/windowgeometry.cpp +++ b/effects/windowgeometry/windowgeometry.cpp @@ -150,8 +150,15 @@ void WindowGeometry::slotWindowStepUserMovedResized(EffectWindow *w, const QRect myExtraDirtyArea = QRect(); myCurrentGeometry = geometry; + QPoint center = geometry.center(); const QRect &r = geometry; const QRect &r2 = myOriginalGeometry; + const QRect screen = effects->clientArea(ScreenArea, center, w->desktop()); + QRect expandedGeometry = w->expandedGeometry(); + expandedGeometry = geometry.adjusted(expandedGeometry.x() - w->x(), + expandedGeometry.y() - w->y(), + expandedGeometry.right() - w->geometry().right(), + expandedGeometry.bottom() - w->geometry().bottom()); // sufficient for moves, resizes calculated otherwise int dx = r.x() - r2.x(); @@ -162,7 +169,9 @@ void WindowGeometry::slotWindowStepUserMovedResized(EffectWindow *w, const QRect myMeasure[0]->setText( i18nc(myCoordString_1, r.x(), r.y(), number(dx), number(dy) ) ); else myMeasure[0]->setText( i18nc(myCoordString_0, r.x(), r.y() ) ); - myMeasure[0]->setPosition(w->expandedGeometry().topLeft() + QPoint(6,6)); // "6" is magic number because the unstyled effectframe has 5px padding + QPoint pos = expandedGeometry.topLeft(); + pos = QPoint(qMax(pos.x(), screen.x()), qMax(pos.y(), screen.y())); + myMeasure[0]->setPosition(pos + QPoint(6,6)); // "6" is magic number because the unstyled effectframe has 5px padding // center ---------------------- if (w->isUserResize()) { @@ -183,15 +192,22 @@ void WindowGeometry::slotWindowStepUserMovedResized(EffectWindow *w, const QRect dy = r.bottom() - r2.bottom(); } else myMeasure[1]->setText( i18nc(myCoordString_0, number(dx), number(dy) ) ); - - myMeasure[1]->setPosition(geometry.center()); + const int cdx = myMeasure[1]->geometry().width() / 2 + 3; // "3" = 6/2 is magic number because + const int cdy = myMeasure[1]->geometry().height() / 2 + 3; // the unstyled effectframe has 5px padding + center = QPoint(qMax(center.x(), screen.x() + cdx), + qMax(center.y(), screen.y() + cdy)); + center = QPoint(qMin(center.x(), screen.right() - cdx), + qMin(center.y(), screen.bottom() - cdy)); + myMeasure[1]->setPosition(center); // lower right ---------------------- if (w->isUserResize()) myMeasure[2]->setText( i18nc(myCoordString_1, r.right(), r.bottom(), number(dx), number(dy) ) ); else myMeasure[2]->setText( i18nc(myCoordString_0, r.right(), r.bottom() ) ); - myMeasure[2]->setPosition(w->expandedGeometry().bottomRight() - QPoint(6,6)); // "6" is magic number because the unstyled effectframe has 5px padding + pos = expandedGeometry.bottomRight(); + pos = QPoint(qMin(pos.x(), screen.right()), qMin(pos.y(), screen.bottom())); + myMeasure[2]->setPosition(pos - QPoint(6,6)); // "6" is magic number because the unstyled effectframe has 5px padding myExtraDirtyArea |= myMeasure[0]->geometry(); myExtraDirtyArea |= myMeasure[1]->geometry();