Here is a patch which can be applied on top of the kwin package to
include the two patches which modify GlxBackend::GlxBackend.
From ad5f05d207edd32fc8571c9ae6bb916e61b291d4 Mon Sep 17 00:00:00 2001
From: Charlemagne Lasse <charlemagnela...@gmail.com>
Date: Tue, 26 Mar 2019 15:30:19 +0100
Subject: [PATCH] Fix missing vsync and high CPU load with Nvidia's proprietary
 driver

---
 debian/changelog                              |  8 ++
 .../patches/Fix-flickering-with-Qt-5.12.patch | 47 ++++++++++
 ...pBuffers-to-block-with-NVIDIA-driver.patch | 94 +++++++++++++++++++
 debian/patches/series                         |  2 +
 4 files changed, 151 insertions(+)
 create mode 100644 debian/patches/Fix-flickering-with-Qt-5.12.patch
 create mode 100644 debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch

diff --git a/debian/changelog b/debian/changelog
index 0f0e4d3..4f4ce7b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+kwin (4:5.14.5-2) UNRELEASED; urgency=medium
+
+  [ Charlemagne Lasse ]
+  * Backport upstream patches to fix missing vsync and high CPU load with
+    Nvidia's proprietary driver (Closes: #925528)
+
+ -- Charlemagne Lasse <charlemagnela...@gmail.com>  Tue, 26 Mar 2019 15:26:54 +0100
+
 kwin (4:5.14.5-1) unstable; urgency=medium
 
   * New upstream release (5.14.5).
diff --git a/debian/patches/Fix-flickering-with-Qt-5.12.patch b/debian/patches/Fix-flickering-with-Qt-5.12.patch
new file mode 100644
index 0000000..647fc69
--- /dev/null
+++ b/debian/patches/Fix-flickering-with-Qt-5.12.patch
@@ -0,0 +1,47 @@
+From: Alexander Volkov <a.vol...@rusbitech.ru>
+Date: Tue, 22 Jan 2019 22:36:15 +0300
+Subject: Fix flickering with Qt 5.12
+
+Summary:
+Mesa requires XESetWireToEvent xlib callbacks to be called
+when DRI2 is used. This is done by the GLX integration in
+the Qt's xcb plugin, but Qt 5.12 initializes the GLX integration
+only when required, e.g. when a window with OpenGL support is
+created or when availability of OpenGL is checked.
+
+So force initialization of the GLX integration by calling
+QOpenGLContext::supportsThreadedOpenGL().
+
+https://codereview.qt-project.org/#/c/6557/
+https://bugzilla.opensuse.org/show_bug.cgi?id=1120090
+
+Reviewers: #kwin, graesslin
+
+Reviewed By: #kwin, graesslin
+
+Subscribers: davidedmundson, graesslin, fvogt, filipf, kwin
+
+Tags: #kwin
+
+Differential Revision: https://phabricator.kde.org/D18366
+
+Origin: upstream, https://cgit.kde.org/kwin.git/patch/?id=5d63b9c05bbe0c6545b3eeea98d95b40f800fb55
+---
+ plugins/platforms/x11/standalone/glxbackend.cpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp
+index a2c570e..eb2d464 100644
+--- a/plugins/platforms/x11/standalone/glxbackend.cpp
++++ b/plugins/platforms/x11/standalone/glxbackend.cpp
+@@ -115,6 +115,10 @@ GlxBackend::GlxBackend(Display *display)
+     , haveSwapInterval(false)
+     , m_x11Display(display)
+ {
++     // Force initialization of GLX integration in the Qt's xcb backend
++     // to make it call XESetWireToEvent callbacks, which is required
++     // by Mesa when using DRI2.
++     QOpenGLContext::supportsThreadedOpenGL();
+ }
+ 
+ static bool gs_tripleBufferUndetected = true;
diff --git a/debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch b/debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch
new file mode 100644
index 0000000..97b5932
--- /dev/null
+++ b/debian/patches/Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch
@@ -0,0 +1,94 @@
+From: Erik Kurzinger <ekurzin...@nvidia.com>
+Date: Wed, 20 Mar 2019 09:50:13 -0700
+Subject: Force glXSwapBuffers to block with NVIDIA driver
+
+Summary:
+The NVIDIA implementation of glXSwapBuffers will, by default, queue up
+to two frames for presentation before blocking. KWin's compositor,
+however, assumes that calls to glXSwapBuffers will always block until
+the next vblank when rendering double buffered. This assumption isn't
+valid, as glXSwapBuffers is specified as being an implicit glFlush,
+not an implicit glFinish, and so it isn't required to block. When this
+assumption is violated, KWin's frame timing logic will
+break. Specifically, there will be extraneous calls to
+setCompositeTimer with a waitTime of 0 after the non-blocking buffer
+swaps, dramatically reducing desktop responsiveness. To remedy this,
+a call to glXWaitGL was added by Thomas Luebking after glXSwapBuffers
+in 2015 (see bug 346275, commit
+8bea96d7018d02dff9462326ca9456f48e9fe9fb). That glXWaitGL call is
+equivalent to a glFinish call in direct rendering, so it was a good
+way to make glXSwapBuffers behave as though it implied a glFinish
+call.
+
+However, the NVIDIA driver will by default do a busy wait in glFinish,
+for reduced latency. Therefore that change dramatically increased CPU
+usage. GL_YIELD can be set to USLEEP (case insensitive) to change
+the behavior and use usleep instead. When using the NVIDIA driver,
+KWin will disable vsync entirely if GL_YIELD isn't set to USLEEP
+(case sensitive, a bug in KWin).
+
+However, the NVIDIA driver supports another environment variable,
+__GL_MaxFramesAllowed, which can be used to control how many frames
+may be queued by glXSwapBuffers. If this is set to 1 the function
+will always block until retrace, in line with KWin's expectations.
+This allows the now-unnecessary call to glXWaitGL to be removed along
+with the logic to conditionally disable vsync, providing a better
+experience on NVIDIA hardware.
+
+Reviewers: #kwin, davidedmundson, zzag
+
+Reviewed By: #kwin, davidedmundson, zzag
+
+Subscribers: kwin, davidedmundson, zzag
+
+Tags: #kwin
+
+Differential Revision: https://phabricator.kde.org/D19867
+
+Origin: upstream, https://cgit.kde.org/kwin.git/patch/?id=22a441e071515e9c630f3bdac743c678052f88be
+---
+ plugins/platforms/x11/standalone/glxbackend.cpp | 22 +++++-----------------
+ 1 file changed, 5 insertions(+), 17 deletions(-)
+
+diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp
+index eb2d464..70dba60 100644
+--- a/plugins/platforms/x11/standalone/glxbackend.cpp
++++ b/plugins/platforms/x11/standalone/glxbackend.cpp
+@@ -115,6 +115,11 @@ GlxBackend::GlxBackend(Display *display)
+     , haveSwapInterval(false)
+     , m_x11Display(display)
+ {
++     // Ensures calls to glXSwapBuffers will always block until the next
++     // retrace when using the proprietary NVIDIA driver. This must be
++     // set before libGL.so is loaded.
++     setenv("__GL_MaxFramesAllowed", "1", true);
++
+      // Force initialization of GLX integration in the Qt's xcb backend
+      // to make it call XESetWireToEvent callbacks, which is required
+      // by Mesa when using DRI2.
+@@ -696,25 +701,8 @@ void GlxBackend::present()
+                 glXWaitGL();
+                 if (char result = m_swapProfiler.end()) {
+                     gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false;
+-                    if (result == 'd' && GLPlatform::instance()->driver() == Driver_NVidia) {
+-                        // TODO this is a workaround, we should get __GL_YIELD set before libGL checks it
+-                        if (qstrcmp(qgetenv("__GL_YIELD"), "USLEEP")) {
+-                            options->setGlPreferBufferSwap(0);
+-                            setSwapInterval(0);
+-                            result = 0; // hint proper behavior
+-                            qCWarning(KWIN_X11STANDALONE) << "\nIt seems you are using the nvidia driver without triple buffering\n"
+-                                              "You must export __GL_YIELD=\"USLEEP\" to prevent large CPU overhead on synced swaps\n"
+-                                              "Preferably, enable the TripleBuffer Option in the xorg.conf Device\n"
+-                                              "For this reason, the tearing prevention has been disabled.\n"
+-                                              "See https://bugs.kde.org/show_bug.cgi?id=322060\n";;
+-                        }
+-                    }
+                     setBlocksForRetrace(result == 'd');
+                 }
+-            } else if (blocksForRetrace()) {
+-                // at least the nvidia blob manages to swap async, ie. return immediately on double
+-                // buffering - what messes our timing calculation and leads to laggy behavior #346275
+-                glXWaitGL();
+             }
+         } else {
+             waitSync();
diff --git a/debian/patches/series b/debian/patches/series
index 01a57e3..b0da0e0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,5 @@
 Disable-testShadeWobblyWindows.patch
 Ignore-cursor-weird-behaviour-under-a-containerized-xvfb.patch
 disable-MouseMark-and-TrackMouse-effects-loading-test.patch
+Fix-flickering-with-Qt-5.12.patch
+Force-glXSwapBuffers-to-block-with-NVIDIA-driver.patch
-- 
2.20.1

Reply via email to