[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kde-workspace/KDE/4.11] kwin: fix scheduling the repaints
From:       Thomas_Lübking <thomas.luebking () gmail ! com>
Date:       2013-09-25 21:15:55
Message-ID: E1VOwR9-0002QQ-J6 () scm ! kde ! org
[Download RAW message or body]

Git commit 0c7fe70a1a89c844f8fbdcc7b3799852ad14d5cd by Thomas Lübking.
Committed on 29/08/2013 at 23:30.
Pushed by luebking into branch 'KDE/4.11'.

fix scheduling the repaints

repaints caused by effects so far polluted the timing calculations
since they started the timer on the old vsync offset
This (together with undercut timing) lead to multiple frames in
the buffer queue, and ultimately to a blocking swap

For unsynced painting, it simply caused wrong timings - leading to
"well, kinda around 60Hz - could be 75 as just well".

REVIEW: 112368
CCBUG: 322060
that part is fixed in 4.11.2

M  +27   -6    kwin/composite.cpp
M  +10   -0    kwin/eglonxbackend.cpp
M  +10   -0    kwin/glxbackend.cpp

http://commits.kde.org/kde-workspace/0c7fe70a1a89c844f8fbdcc7b3799852ad14d5cd

diff --git a/kwin/composite.cpp b/kwin/composite.cpp
index de674b6..4eb8e46 100644
--- a/kwin/composite.cpp
+++ b/kwin/composite.cpp
@@ -270,7 +270,6 @@ void Compositor::slotCompositingOptionsInitialized()
     }
 
     // render at least once
-    compositeTimer.stop();
     performCompositing();
 }
 
@@ -548,7 +547,6 @@ void Compositor::addRepaintFull()
 void Compositor::timerEvent(QTimerEvent *te)
 {
     if (te->timerId() == compositeTimer.timerId()) {
-        compositeTimer.stop();
         performCompositing();
     } else
         QObject::timerEvent(te);
@@ -596,10 +594,12 @@ void Compositor::performCompositing()
 
     if (repaints_region.isEmpty() && !windowRepaintsPending()) {
         m_scene->idle();
+        m_timeSinceLastVBlank = fpsInterval - (options->vBlankTime() + 1); // means \
                "start now"
         // Note: It would seem here we should undo suspended unredirect, but when \
                scenes need
         // it for some reason, e.g. transformations or translucency, the next pass \
                that does not
         // need this anymore and paints normally will also reset the suspended \
unredirect.  // Otherwise the window would not be painted normally anyway.
+        compositeTimer.stop();
         return;
     }
 
@@ -617,6 +617,8 @@ void Compositor::performCompositing()
 
     m_timeSinceLastVBlank = m_scene->paint(repaints, windows);
 
+    compositeTimer.stop(); // stop here to ensure *we* cause the next repaint \
schedule - not some effect through m_scene->paint() +
     // Trigger at least one more pass even if there would be nothing to paint, so \
                that scene->idle()
     // is called the next time. If there would be nothing pending, it will not \
                restart the timer and
     // scheduleRepaint() would restart it again somewhen later, called from \
functions that @@ -676,10 +678,29 @@ void Compositor::setCompositeTimer()
             waitTime = nanoToMilli(padding - options->vBlankTime());
         }
     }
-    else // w/o vsync we just jump to the next demanded tick
-        // the "1" will ensure we don't block out the eventloop - the system's just \
                not faster
-        // "0" would be sufficient, but the compositor isn't the WMs only task
-        waitTime = (m_timeSinceLastVBlank > fpsInterval) ? 1 : \
nanoToMilli(fpsInterval - m_timeSinceLastVBlank); +    else { // w/o blocking vsync \
we just jump to the next demanded tick +        if (fpsInterval > \
m_timeSinceLastVBlank) { +            waitTime = nanoToMilli(fpsInterval - \
m_timeSinceLastVBlank); +            if (!waitTime) {
+                waitTime = 1; // will ensure we don't block out the eventloop - the \
system's just not faster ... +            }
+        }/* else if (m_scene->syncsToVBlank() && m_timeSinceLastVBlank - fpsInterval \
< (vBlankInterval<<1)) { +            // NOTICE - "for later" \
------------------------------------------------------------------ +            // It \
can happen that we push two frames within one refresh cycle. +            // Swapping \
will then block even with triple buffering when the GPU does not discard but +        \
// queues frames +            // now here's the mean part: if we take that as "OMG, \
we're late - next frame ASAP", +            // there'll immediately be 2 frames in \
the pipe, swapping will block, we think we're +            // late ... ewww
+            // so instead we pad to the clock again and add 2ms safety to ensure the \
pipe is really +            // free
+            // NOTICE: obviously m_timeSinceLastVBlank can be too big because we're \
too slow as well +            // So if this code was enabled, we'd needlessly half \
the framerate once more (15 instead of 30) +            waitTime = \
nanoToMilli(vBlankInterval - (m_timeSinceLastVBlank - fpsInterval)%vBlankInterval) + \
2; +        }*/ else {
+            waitTime = 1; // ... "0" would be sufficient, but the compositor isn't \
the WMs only task +        }
+    }
     compositeTimer.start(qMin(waitTime, 250u), this); // force 4fps minimum
 }
 
diff --git a/kwin/eglonxbackend.cpp b/kwin/eglonxbackend.cpp
index ab692d7..39dd824 100644
--- a/kwin/eglonxbackend.cpp
+++ b/kwin/eglonxbackend.cpp
@@ -26,6 +26,8 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  #include <kwinglplatform.h>
 // KDE
 #include <KDE/KDebug>
+// system
+#include <unistd.h>
 
 namespace KWin
 {
@@ -320,6 +322,14 @@ SceneOpenGL::TexturePrivate \
*EglOnXBackend::createBackendTexture(SceneOpenGL::Te  
 void EglOnXBackend::prepareRenderingFrame()
 {
+    if (gs_tripleBufferNeedsDetection) {
+        // the composite timer floors the repaint frequency. This can pollute our \
triple buffering +        // detection because the glXSwapBuffers call for the new \
frame has to wait until the pending +        // one scanned out.
+        // So we compensate for that by waiting an extra milisecond to give the \
driver the chance to +        // fllush the buffer queue
+        usleep(1000);
+    }
     present();
     startRenderTimer();
     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
diff --git a/kwin/glxbackend.cpp b/kwin/glxbackend.cpp
index 9e3064c..f1b9a6a 100644
--- a/kwin/glxbackend.cpp
+++ b/kwin/glxbackend.cpp
@@ -35,6 +35,8 @@ along with this program.  If not, see \
<http://www.gnu.org/licenses/>.  // KDE
 #include <KDE/KDebug>
 #include <KDE/KXErrorHandler>
+// system
+#include <unistd.h>
 
 namespace KWin
 {
@@ -493,6 +495,14 @@ SceneOpenGL::TexturePrivate \
*GlxBackend::createBackendTexture(SceneOpenGL::Textu  
 void GlxBackend::prepareRenderingFrame()
 {
+    if (gs_tripleBufferNeedsDetection) {
+        // the composite timer floors the repaint frequency. This can pollute our \
triple buffering +        // detection because the glXSwapBuffers call for the new \
frame has to wait until the pending +        // one scanned out.
+        // So we compensate for that by waiting an extra milisecond to give the \
driver the chance to +        // fllush the buffer queue
+        usleep(1000);
+    }
     present();
     startRenderTimer();
     glXWaitX();


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic