From 6a997b41ae9acccaba8169eb69c354774085fd00 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 21 Nov 2023 16:42:53 +0200 Subject: [PATCH] Fix screen becoming black when its geometry changes while overview is active Offscreen quick views are repainted in the pre paint step because that requires a QOpenGLContext and we don't want it to mess with kwin's opengl context. After a view is updated, its QOpenGLContext is going to be unbound. During normal operation mode, it works as expected: - the view gets updated in the pre paint stage - kwin opengl context is made current when starting the paint stage - the offscreen view is painted on the screen However, effects->renderScreen() has no such separation. The OpenGL context changes from the pre paint stage will leak to the paint stage. So we have - the workspace notifies that the screens have changed - the screen transform effect sees that, makes opengl context current and renders the screen - the offscreen quick view is updated and after OffscreenQuickView is done, it's going to call QOpenGLContext::doneCurrent() - effects->renderScreen() calls m_scene->paint() - since there's no current opengl context, vbo allocation in GLTexture::render() will fail and nothing will be rendered on the screen As a way around it, this change adds a makeOpenGLContextCurrent() call before the paint stage. It doesn't quite belong there, the opengl context has to be made current in the paint stage, e.g. by the ItemRenderer or something. But atm we have no good place where we could stick it in. BUG: 477027 --- src/effect/effecthandler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/effect/effecthandler.cpp b/src/effect/effecthandler.cpp index 3fb923a7f5..53e8ee5bf5 100644 --- a/src/effect/effecthandler.cpp +++ b/src/effect/effecthandler.cpp @@ -1571,14 +1571,18 @@ Output *EffectsHandler::findScreen(int screenId) const void EffectsHandler::renderScreen(Output *output) { - RenderTarget renderTarget(GLFramebuffer::currentFramebuffer()); + Q_ASSERT(effects->isOpenGLCompositing()); RenderLayer layer(output->renderLoop()); SceneDelegate delegate(m_scene, output); delegate.setLayer(&layer); m_scene->prePaint(&delegate); + + effects->makeOpenGLContextCurrent(); // TODO: doesn't belong here, but there's no better place atm either + RenderTarget renderTarget(GLFramebuffer::currentFramebuffer()); m_scene->paint(renderTarget, output->geometry()); + m_scene->postPaint(); }