From fda7e150df207d512b60ba4062be5edafc61d539 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Mon, 25 Oct 2021 12:39:05 +0300 Subject: [PATCH] kwineffects: Fix destruction of s_fbo with shared GLTexture objects The WindowThumbnail item uses the GLTexture class. In order to destroy the thumbnail texture, the item will schedule a destroy job. This means that the GLTexture can be alive during or after graphics reset. On the other hand, as an implementation detail, GLTexture::clear() may allocate a framebuffer object, which is going to be destroyed together with the last texture. Given that window thumbnail textures can be still alive after a graphics reset and the fact that GLTexturePrivate::s_fbo gets destroyed when the last texture is destroyed, kwin can end up trying to clear a decoration texture with now defunct s_fbo. Since the old old s_fbo is inert, the glBindFramebuffer() function will fail and the glClear() operation will affect the default framebuffer, thus leading to black flickering visual artifacts. In order to fix that issue, this change makes GLTexture destroy s_fbo unconditionally in GLTexturePrivate::cleanup() which is called whenever OpenGL stuff is about to tear down, e.g. due to graphics reset, etc. BUG: 443951 --- src/libkwineffects/kwingltexture.cpp | 11 ++++------- src/libkwineffects/kwingltexture_p.h | 1 - 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libkwineffects/kwingltexture.cpp b/src/libkwineffects/kwingltexture.cpp index de08572ef2..8f57be244b 100644 --- a/src/libkwineffects/kwingltexture.cpp +++ b/src/libkwineffects/kwingltexture.cpp @@ -36,7 +36,6 @@ bool GLTexturePrivate::s_supportsUnpack = false; bool GLTexturePrivate::s_supportsTextureStorage = false; bool GLTexturePrivate::s_supportsTextureSwizzle = false; bool GLTexturePrivate::s_supportsTextureFormatRG = false; -uint GLTexturePrivate::s_textureObjectCounter = 0; uint GLTexturePrivate::s_fbo = 0; // Table of GL formats/types associated with different values of QImage::Format. @@ -287,7 +286,6 @@ GLTexturePrivate::GLTexturePrivate() , m_normalizeActive(0) , m_vbo(nullptr) { - ++s_textureObjectCounter; } GLTexturePrivate::~GLTexturePrivate() @@ -296,11 +294,6 @@ GLTexturePrivate::~GLTexturePrivate() if (m_texture != 0 && !m_foreign) { 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() @@ -334,6 +327,10 @@ void GLTexturePrivate::cleanup() { s_supportsFramebufferObjects = false; s_supportsARGB32 = false; + if (s_fbo) { + glDeleteFramebuffers(1, &s_fbo); + s_fbo = 0; + } } bool GLTexture::isNull() const diff --git a/src/libkwineffects/kwingltexture_p.h b/src/libkwineffects/kwingltexture_p.h index fdeb7d0149..63b8de87de 100644 --- a/src/libkwineffects/kwingltexture_p.h +++ b/src/libkwineffects/kwingltexture_p.h @@ -69,7 +69,6 @@ public: static bool s_supportsTextureSwizzle; static bool s_supportsTextureFormatRG; static GLuint s_fbo; - static uint s_textureObjectCounter; private: friend void KWin::cleanupGL(); static void cleanup();