From 9f13e9b26035984906896a56d64e85e11522c581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Tue, 26 May 2015 22:52:16 +0200 Subject: [PATCH] WORKAROUND for nvidia VBO failures When switching virtual terminals, suspending to ram and resizing the screen (GL viewport) at least the nvidia driver moves VBO data between the video RAM and the system heap - and something about this isn't reliable: An often perceived resulted are scattered windows but it may also be the cause for entirely black screens reported for same occasions. As a workaround, we hook into the GL debug messages and filter them for the suspicious message, then re-init VBOs TODO: figure whether that's our fault or nvidias REVIEW: 123936 CCBUG: 344326 Patch applies to KWin 5.4 --- scene_opengl.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index c33f5ccc09..9f7399ee79 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -436,9 +436,11 @@ SceneOpenGL::SceneOpenGL(OpenGLBackend *backend, QObject *parent) } } +static SceneOpenGL *gs_debuggedScene = nullptr; SceneOpenGL::~SceneOpenGL() { // do cleanup after initBuffer() + gs_debuggedScene = nullptr; SceneOpenGL::EffectFrame::cleanup(); if (init_ok) { delete m_syncManager; @@ -448,12 +450,32 @@ SceneOpenGL::~SceneOpenGL() } } +static void scheduleVboReInit() +{ + if (!gs_debuggedScene) + return; + + static QPointer timer; + if (!timer) { + delete timer; + timer = new QTimer(gs_debuggedScene); + timer->setSingleShot(true); + QObject::connect(timer, &QTimer::timeout, gs_debuggedScene, []() { + GLVertexBuffer::cleanup(); + GLVertexBuffer::initStatic(); + }); + } + timer->start(250); +} + void SceneOpenGL::initDebugOutput() { const bool have_KHR_debug = hasGLExtension(QByteArrayLiteral("GL_KHR_debug")); if (!have_KHR_debug && !hasGLExtension(QByteArrayLiteral("GL_ARB_debug_output"))) return; + gs_debuggedScene = this; + // Set the callback function auto callback = [](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, @@ -469,10 +491,17 @@ void SceneOpenGL::initDebugOutput() qCWarning(KWIN_CORE, "%#x: %.*s", id, length, message); break; + case GL_DEBUG_TYPE_OTHER: + // at least the nvidia driver seems prone to end up with invalid VBOs after + // transferring them between system heap and VRAM + // so we re-init them whenever this happens (typically when switching VT, resuming + // from STR and XRandR events - #344326 + if (strstr(message, "Buffer detailed info:") && strstr(message, "has been updated")) + scheduleVboReInit(); + // fall through! for general message printing case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: case GL_DEBUG_TYPE_PORTABILITY: case GL_DEBUG_TYPE_PERFORMANCE: - case GL_DEBUG_TYPE_OTHER: default: qCDebug(KWIN_CORE, "%#x: %.*s", id, length, message); break;