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

List:       kde-commits
Subject:    KDE/kdebase/workspace/kwin
From:       Thomas Lübking <thomas.luebking () gmail ! com>
Date:       2010-12-31 13:14:12
Message-ID: 20101231131412.45692AC8AE () svn ! kde ! org
[Download RAW message or body]

SVN commit 1210445 by luebking:

revert vsync strategy, fix timeouts
differecens to patch atteched to 258971:
- removed debug statements
- fixed indention...
- NON vsync strategy does not rely on the estimation, but on the time passed since \
the last repaint trigger, allowing a precise framerate

CCBUG: 258971



 M  +40 -10    composite.cpp  
 M  +1 -1      options.cpp  
 M  +2 -0      scene.h  
 M  +2 -0      scene_basic.cpp  
 M  +7 -21     scene_opengl.cpp  
 M  +0 -2      scene_opengl.h  
 M  +2 -0      scene_xrender.cpp  
 M  +0 -1      workspace.cpp  
 M  +1 -1      workspace.h  


--- trunk/KDE/kdebase/workspace/kwin/composite.cpp #1210444:1210445
@@ -199,8 +199,17 @@
         return;
         }
     xrrRefreshRate = KWin::currentRefreshRate();
-    // invalidate timer -> bounds delay to 0 and the update happens instantly
-    nextPaintReference = QTime::currentTime().addMSecs( -1000 );
+    fpsInterval = (options->maxFpsInterval<<10);
+    if ( scene->waitSyncAvailable() ) // if we do vsync, set the fps to the next \
multiple of the vblank rate +        {
+        vBlankInterval = (1000<<10)/xrrRefreshRate;
+        fpsInterval -= (fpsInterval % vBlankInterval);
+        fpsInterval = qMax(fpsInterval, vBlankInterval);
+        }
+    else
+        vBlankInterval = 1<<10; // no sync - DO NOT set "0", would cause div-by-zero \
segfaults. +    vBlankPadding = 3; // vblank rounding errors... :-(
+    nextPaintReference = QTime::currentTime();
     checkCompositeTimer();
     composite_paint_times.clear();
     XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual \
); @@ -388,9 +397,7 @@
     if((( repaints_region.isEmpty() && !windowRepaintsPending()) // no damage
         || !overlay_visible )) // nothing is visible anyway
         {
-        // invalidate timer, we're idle, thus have already waited maxFps don't want \
                to
-        // wait more when we woke up
-        nextPaintReference = QTime::currentTime().addMSecs( -1000 );
+        vBlankPadding += 3;
         scene->idle();
         // 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 @@ -398,8 +405,6 @@
         // Otherwise the window would not be painted normally anyway.
         return;
         }
-    // we paint now, how much time ever it takes, we wanna show up in maxfps from \
                now
-    nextPaintReference = QTime::currentTime();
     // create a list of all windows in the stacking order
     ToplevelList windows = xStackingOrder();
     foreach( EffectWindow* c, static_cast< EffectsHandlerImpl* >( effects \
)->elevatedWindows()) @@ -432,7 +437,18 @@
     // clear all repaints, so that post-pass can add repaints for the next repaint
     repaints_region = QRegion();
     QTime t = QTime::currentTime();
+    if ( scene->waitSyncAvailable() )
+    {   // vsync: paint the scene, than rebase the timer and use the duration for \
next timeout estimation  scene->paint( repaints, windows );
+        nextPaintReference = QTime::currentTime();
+    }
+    else
+    {   // no vsyc -> inversion: reset the timer, then paint the scene, this way we \
can provide a constant framerate +        nextPaintReference = QTime::currentTime();
+        scene->paint( repaints, windows );
+    }
+    // reset the roundin error corrective... :-(
+    vBlankPadding = 3;
     // 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
     // checkCompositeTime() would restart it again somewhen later, called from \
functions that @@ -468,12 +484,26 @@
     {
     if( !compositing()) // should not really happen, but there may be e.g. some \
damage events still pending  return;
-    // should be added for the next paint. qBound() for protection; system time can \
change without notice. +    
     if ( compositeTimer )
         killTimer( compositeTimer );
-    int delay = options->maxFpsInterval - (qBound( 0, nextPaintReference.msecsTo( \
                QTime::currentTime() ), 250 ) % options->maxFpsInterval);
-    compositeTimer = startTimer( delay );
+
+    // interval - "time since last paint completion" - "time we need to paint"
+    uint passed = nextPaintReference.msecsTo( QTime::currentTime() ) << 10;
+    uint delay = fpsInterval;
+    if ( scene->waitSyncAvailable() )
+        {
+        if ( passed > fpsInterval )
+            {
+            delay = vBlankInterval;
+            passed %= vBlankInterval;
     }
+        delay -= ( (passed + ((scene->estimatedRenderTime() + vBlankPadding)<<10) ) \
% vBlankInterval ); +        }
+    else
+        delay = qBound( 0, int(delay - passed), 250<<10 );
+    compositeTimer = startTimer( delay>>10 );
+    }
 
 void Workspace::startMousePolling()
     {
--- trunk/KDE/kdebase/workspace/kwin/options.cpp #1210444:1210445
@@ -251,7 +251,7 @@
     CmdAllWheel = mouseWheelCommand(config.readEntry("CommandAllWheel","Nothing"));
 
     config=KConfigGroup(_config,"Compositing");
-    maxFpsInterval = qRound(1000.0/config.readEntry( "MaxFPS", 35 ));
+    maxFpsInterval = qRound(1000.0/config.readEntry( "MaxFPS", 60 ));
     refreshRate = config.readEntry( "RefreshRate", 0 );
 
     // Read button tooltip animation effect from kdeglobals
--- trunk/KDE/kdebase/workspace/kwin/scene.h #1210444:1210445
@@ -92,6 +92,7 @@
             };
         // types of filtering available
         enum ImageFilterType { ImageFilterFast, ImageFilterGood };
+        inline uint estimatedRenderTime() { return lastRenderTime; }
         // there's nothing to paint (adjust time_diff later)
         void idle();
         bool waitSyncAvailable() { return has_waitSync; }
@@ -143,6 +144,7 @@
         QRegion painted_region;
         // time since last repaint
         int time_diff;
+        uint lastRenderTime;
         QTime last_time;
         Workspace* wspace;
         bool has_waitSync;
--- trunk/KDE/kdebase/workspace/kwin/scene_basic.cpp #1210444:1210445
@@ -44,6 +44,7 @@
     
 void SceneBasic::paint( QRegion, ToplevelList windows )
     {
+    QTime t = QTime::currentTime();
     Pixmap composite_pixmap = XCreatePixmap( display(), rootWindow(), \
displayWidth(), displayHeight(), DefaultDepth( display(), DefaultScreen( \
display())));  XGCValues val;
     val.foreground = WhitePixel( display(), DefaultScreen( display()));
@@ -64,6 +65,7 @@
                 qMax( 0, -(*it)->x()), qMax( 0, -(*it)->y()), r.width(), r.height(), \
r.x(), r.y());  }
         }
+    lastRenderTime = t.elapsed();
     XCopyArea( display(), composite_pixmap, rootWindow(), gc, 0, 0, displayWidth(), \
displayHeight(), 0, 0 );  XFreeGC( display(), gc );
     XFreePixmap( display(), composite_pixmap );
--- trunk/KDE/kdebase/workspace/kwin/scene_opengl.cpp #1210444:1210445
@@ -111,9 +111,6 @@
 bool SceneOpenGL::tfp_mode; // using glXBindTexImageEXT (texture_from_pixmap)
 bool SceneOpenGL::db; // destination drawable is double-buffered
 bool SceneOpenGL::shm_mode;
-uint SceneOpenGL::vBlankInterval;
-uint SceneOpenGL::estimatedRenderTime = 0xfffffff; // Looooong - to ensure we wait \
                on the first frame
-QTime SceneOpenGL::lastVBlank;
 #ifdef HAVE_XSHM
 XShmSegmentInfo SceneOpenGL::shm;
 #endif
@@ -129,8 +126,6 @@
         kDebug( 1212 ) << "No glx extensions available";
         return; // error
         }
-    vBlankInterval = (1000<<10) / KWin::currentRefreshRate();
-    lastVBlank = QTime::currentTime();
     initGLX();
     // check for FBConfig support
     if( !hasGLExtension( "GLX_SGIX_fbconfig" ) || !glXGetFBConfigAttrib || \
!glXGetFBConfigs || @@ -171,7 +166,11 @@
             {
             if( glXWaitVideoSync( 1, 0, &sync ) == 0 )
                 has_waitSync = true;
+            else
+                qWarning() << "NO VSYNC! glXWaitVideoSync(1,0,&uint) isn't 0 but" << \
glXWaitVideoSync( 1, 0, &sync );  }
+        else
+            qWarning() << "NO VSYNC! glXGetVideoSync(&uint) isn't 0 but" << \
glXGetVideoSync( &sync );  }
 
     // OpenGL scene setup
@@ -756,6 +755,7 @@
 // the entry function for painting
 void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
     {
+    QTime t = QTime::currentTime();
     foreach( Toplevel* c, toplevels )
         {
         assert( windows.contains( c ));
@@ -784,6 +784,7 @@
         damage |= selfCheckRegion();
         }
 #endif
+    lastRenderTime = t.elapsed();
     flushBuffer( mask, damage );
 #if 0
     if( !selfCheckDone )
@@ -803,30 +804,21 @@
     { // NOTE that vsync has no effect with indirect rendering
     if( waitSyncAvailable())
         {
-        // hackalert - we abuse "sync" as "remaining time before next estimated \
                vblank"
-        // reason: we do not "just wait" for the next vsync if we estimate that we \
                can paint the
-        // entire frame before this event, what could effectively mean \
                "usleep(10000)", as it used to
-        uint sync = ((lastVBlank.msecsTo( QTime::currentTime() )<<10) % \
                vBlankInterval);
-        if ( sync < (estimatedRenderTime+1)<<10 )
-            {
+        uint sync;
             glFlush();
             glXGetVideoSync( &sync );
             glXWaitVideoSync( 2, ( sync + 1 ) % 2, &sync );
-            lastVBlank = QTime::currentTime();
             }
         }
-    }
 
 // actually paint to the screen (double-buffer swap or copy from pixmap buffer)
 void SceneOpenGL::flushBuffer( int mask, QRegion damage )
     {
-    QTime t;
     if( db )
         {
         if( mask & PAINT_SCREEN_REGION )
             {
             waitSync();
-            t = QTime::currentTime();
             if( glXCopySubBuffer )
                 {
                 foreach( const QRect &r, damage.rects())
@@ -864,28 +856,22 @@
         else
             {
             waitSync();
-            t = QTime::currentTime();
             glXSwapBuffers( display(), glxbuffer );
             }
         glXWaitGL();
         XFlush( display());
-        estimatedRenderTime = t.elapsed();
         }
     else
         {
-        t = QTime::currentTime();
         glFlush();
         glXWaitGL();
-        estimatedRenderTime = t.elapsed();
         waitSync();
-        t = QTime::currentTime();
         if( mask & PAINT_SCREEN_REGION )
             foreach( const QRect &r, damage.rects())
                 XCopyArea( display(), buffer, rootWindow(), gcroot, r.x(), r.y(), \
r.width(), r.height(), r.x(), r.y());  else
             XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, \
displayWidth(), displayHeight(), 0, 0 );  XFlush( display());
-        estimatedRenderTime += t.elapsed();
         }
     }
 
--- trunk/KDE/kdebase/workspace/kwin/scene_opengl.h #1210444:1210445
@@ -90,8 +90,6 @@
         static GLXDrawable last_pixmap; // for a workaround in bindTexture()
         static bool tfp_mode;
         static bool shm_mode;
-        static uint vBlankInterval, estimatedRenderTime;
-        static QTime lastVBlank;
         QHash< Toplevel*, Window* > windows;
 #ifdef HAVE_XSHM
         static XShmSegmentInfo shm;
--- trunk/KDE/kdebase/workspace/kwin/scene_xrender.cpp #1210444:1210445
@@ -271,6 +271,7 @@
 // the entry point for painting
 void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
     {
+    QTime t = QTime::currentTime();
     foreach( Toplevel* c, toplevels )
         {
         assert( windows.contains( c ));
@@ -285,6 +286,7 @@
         selfCheckSetup();
         damage |= selfCheckRegion();
         }
+    lastRenderTime = t.elapsed();
     flushBuffer( mask, damage );
     if( !selfCheckDone )
         {
--- trunk/KDE/kdebase/workspace/kwin/workspace.cpp #1210444:1210445
@@ -152,7 +152,6 @@
     , cm_selection( NULL )
     , compositingSuspended( false )
     , compositeTimer( 0 )
-    , vBlankInterval( 0 )
     , xrrRefreshRate( 0 )
     , overlay( None )
     , overlay_visible( true )
--- trunk/KDE/kdebase/workspace/kwin/workspace.h #1210444:1210445
@@ -1062,7 +1062,7 @@
         int compositeTimer;
         QTime nextPaintReference;
         QTimer mousePollingTimer;
-        uint vBlankInterval;
+        uint vBlankInterval, vBlankPadding, fpsInterval, estimatedRenderTime;
         int xrrRefreshRate; // used only for compositing
         QRegion repaints_region;
         Window overlay; // XComposite overlay window


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

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