[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-18 16:51:44
Message-ID: 20101218165144.500C4AC8A8 () svn ! kde ! org
[Download RAW message or body]
SVN commit 1207577 by luebking:
commiting http://svn.reviewboard.kde.org/r/6120/#review9304
this should improve v'syncing, maybe v'synced "smoothness"
remaining and exposed issue are "dirty textures" w/o damage events (see the requst \
description) can be diminished by increasing MaxFPS above the fastest update (or \
shadowed below the slowest one)
CCBUG: 258971
M +32 -37 composite.cpp
M +4 -1 options.cpp
M +1 -0 options.h
M +23 -2 scene_opengl.cpp
M +2 -0 scene_opengl.h
M +2 -2 workspace.cpp
M +4 -4 workspace.h
--- trunk/KDE/kdebase/workspace/kwin/composite.cpp #1207576:1207577
@@ -57,6 +57,7 @@
#include <stdio.h>
#include <QMenu>
+#include <QTimerEvent>
#include <kaction.h>
#include <kactioncollection.h>
#include <klocale.h>
@@ -197,12 +198,9 @@
delete cm_selection;
return;
}
- int rate = xrrRefreshRate = KWin::currentRefreshRate();
- compositeRate = 1000 / rate;
- lastCompositePaint.start();
- // fake a previous paint, so that the next starts right now
- nextPaintReference = QTime::currentTime().addMSecs( -compositeRate );
- compositeTimer.setSingleShot( true );
+ xrrRefreshRate = KWin::currentRefreshRate();
+ // invalidate timer -> bounds delay to 0 and the update happens instantly
+ nextPaintReference = QTime::currentTime().addMSecs( -1000 );
checkCompositeTimer();
composite_paint_times.clear();
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual \
); @@ -253,7 +251,9 @@
effects = NULL;
delete scene;
scene = NULL;
- compositeTimer.stop();
+ if (compositeTimer)
+ killTimer(compositeTimer);
+ compositeTimer = 0;
mousePollingTimer.stop();
repaints_region = QRegion();
for( ClientList::ConstIterator it = clients.constBegin();
@@ -370,24 +370,27 @@
checkCompositeTimer();
}
-void Workspace::performCompositing()
+void Workspace::timerEvent( QTimerEvent *te )
{
-#ifdef KWIN_HAVE_COMPOSITING
- // The event loop apparently tries to fire a QTimer as often as possible, even
- // at the expense of not processing many X events. This means that the composite
- // repaints can seriously impact performance of everything else, therefore \
throttle
- // them - leave at least 1msec time after one repaint is finished and next one
- // is started.
- if( lastCompositePaint.elapsed() < 1 )
+ if ( te->timerId() == compositeTimer )
{
- compositeTimer.start( 1 );
- return;
+ killTimer( compositeTimer );
+ compositeTimer = 0;
+ performCompositing();
}
- if( !scene->waitSyncAvailable())
- nextPaintReference = QTime::currentTime();
+ else
+ QObject::timerEvent( te );
+}
+
+void Workspace::performCompositing()
+ {
+#ifdef KWIN_HAVE_COMPOSITING
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 );
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 @@ -395,6 +398,8 @@
// 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()) @@ -403,19 +408,16 @@
windows.removeAll( t );
windows.append( t );
}
+#if 0
// skip windows that are not yet ready for being painted
ToplevelList tmp = windows;
windows.clear();
-#if 0
// There is a bug somewhere that prevents this from working properly (#160393), \
but additionally
// this cannot be used so carelessly - needs protections against broken clients, \
the window
// should not get focus before it's displayed, handle unredirected windows \
properly and so on. foreach( Toplevel* c, tmp )
if( c->readyForPainting())
windows.append( c );
-#else
- foreach( Toplevel* c, tmp )
- windows.append( c );
#endif
foreach( Toplevel* c, windows )
{ // This could be possibly optimized WRT obscuring, but that'd need being \
already @@ -431,23 +433,12 @@
repaints_region = QRegion();
QTime t = QTime::currentTime();
scene->paint( repaints, windows );
- if( scene->waitSyncAvailable())
- {
- // If vsync is used, schedule the next repaint slightly in advance of the \
next sync,
- // so that there is still time for the drawing to take place. We have just \
synced, and
- // nextPaintReference is time from which multiples of compositeRate should \
be added,
- // so set it 10ms back (meaning next paint will be in 'compositeRate - 10').
- // However, make sure the reserve is smaller than the composite rate.
- int reserve = compositeRate <= 10 ? compositeRate - 1 : 10;
- nextPaintReference = QTime::currentTime().addMSecs( -reserve );
- }
// 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 // would again add something pending.
checkCompositeTimer();
checkCompositePaintTime( t.elapsed());
- lastCompositePaint.start();
#endif
}
@@ -477,9 +468,11 @@
{
if( !compositing()) // should not really happen, but there may be e.g. some \
damage events still pending return;
- // The last paint set nextPaintReference as a reference time to which multiples \
of compositeRate
// should be added for the next paint. qBound() for protection; system time can \
change without notice.
- compositeTimer.start( qBound( 0, nextPaintReference.msecsTo( \
QTime::currentTime() ), 250 ) % compositeRate ); + if ( compositeTimer )
+ killTimer( compositeTimer );
+ int delay = options->maxFpsInterval - (qBound( 0, nextPaintReference.msecsTo( \
QTime::currentTime() ), 250 ) % options->maxFpsInterval); + compositeTimer = \
startTimer( delay ); }
void Workspace::startMousePolling()
@@ -567,7 +560,9 @@
"If this was only a temporary problem, you can resume using the '%1' \
shortcut.\n"
"You can disable functionality checks in System Settings (on the \
Advanced tab in Desktop Effects).", shortcut ); Notify::raise( \
Notify::CompositingSlow, message );
- compositeTimer.start( 1000 ); // so that it doesn't trigger sooner than \
suspendCompositing() + if ( compositeTimer )
+ killTimer( compositeTimer );
+ compositeTimer = startTimer( 1000 ); // so that it doesn't trigger sooner \
than suspendCompositing() }
}
--- trunk/KDE/kdebase/workspace/kwin/options.cpp #1207576:1207577
@@ -66,9 +66,11 @@
{
QString reply = QString::fromLocal8Bit( \
nvidia_settings.readAllStandardOutput() ); bool ok;
- rate = reply.split(' \
').first().split(KGlobal::locale()->decimalSymbol()).first().toUInt( &ok ); + \
const float frate = reply.split(' ').first().toFloat( &ok ); if ( !ok )
rate = -1;
+ else
+ rate = qRound(frate);
}
}
#ifdef HAVE_XRANDR
@@ -247,6 +249,7 @@
CmdAllWheel = mouseWheelCommand(config.readEntry("CommandAllWheel","Nothing"));
config=KConfigGroup(_config,"Compositing");
+ maxFpsInterval = qRound(1000.0/config.readEntry( "MaxFPS", 35 ));
refreshRate = config.readEntry( "RefreshRate", 0 );
// Read button tooltip animation effect from kdeglobals
--- trunk/KDE/kdebase/workspace/kwin/options.h #1207576:1207577
@@ -365,6 +365,7 @@
// XRender
bool xrenderSmoothScale;
+ uint maxFpsInterval;
// Settings that should be auto-detected
uint refreshRate;
bool glDirect;
--- trunk/KDE/kdebase/workspace/kwin/scene_opengl.cpp #1207576:1207577
@@ -91,6 +91,8 @@
namespace KWin
{
+extern int currentRefreshRate();
+
//****************************************
// SceneOpenGL
//****************************************
@@ -109,6 +111,9 @@
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
@@ -124,6 +129,8 @@
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 || @@ -796,22 +803,30 @@
{ // NOTE that vsync has no effect with indirect rendering
if( waitSyncAvailable())
{
- unsigned int sync;
-
+ // 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 ) + {
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())
@@ -849,22 +864,28 @@
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 #1207576:1207577
@@ -90,6 +90,8 @@
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/workspace.cpp #1207576:1207577
@@ -151,7 +151,8 @@
, forced_global_mouse_grab( false )
, cm_selection( NULL )
, compositingSuspended( false )
- , compositeRate( 0 )
+ , compositeTimer( 0 )
+ , vBlankInterval( 0 )
, xrrRefreshRate( 0 )
, overlay( None )
, overlay_visible( true )
@@ -384,7 +385,6 @@
connect( &reconfigureTimer, SIGNAL( timeout() ), this, SLOT( slotReconfigure() \
));
connect( &updateToolWindowsTimer, SIGNAL( timeout() ), this, SLOT( \
slotUpdateToolWindows() ));
- connect( &compositeTimer, SIGNAL( timeout() ), SLOT( performCompositing() ));
connect( &mousePollingTimer, SIGNAL( timeout() ), SLOT( performMousePoll() ));
connect( KGlobalSettings::self(), SIGNAL( appearanceChanged() ), this, SLOT( \
reconfigure() ));
--- trunk/KDE/kdebase/workspace/kwin/workspace.h #1207576:1207577
@@ -774,6 +774,7 @@
protected:
bool keyPressMouseEmulation( XKeyEvent& ev );
+ void timerEvent( QTimerEvent *te );
Q_SIGNALS:
Q_SCRIPTABLE void compositingToggled( bool active );
@@ -1058,11 +1059,10 @@
KSelectionOwner* cm_selection;
bool compositingSuspended;
- QTimer compositeTimer;
- QTime lastCompositePaint;
+ int compositeTimer;
QTime nextPaintReference;
QTimer mousePollingTimer;
- int compositeRate;
+ uint vBlankInterval;
int xrrRefreshRate; // used only for compositing
QRegion repaints_region;
Window overlay; // XComposite overlay window
@@ -1348,7 +1348,7 @@
inline void Workspace::checkCompositeTimer()
{
- if( !compositeTimer.isActive() )
+ if( !compositeTimer )
setCompositeTimer();
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic