[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