Stop the compositing timer when idle.
FEATURE: 155694 svn path=/trunk/KDE/kdebase/workspace/; revision=854913
This commit is contained in:
parent
28e08082d2
commit
c6230db535
3 changed files with 50 additions and 11 deletions
|
@ -188,8 +188,11 @@ void Workspace::setupCompositing()
|
||||||
rate = 1000;
|
rate = 1000;
|
||||||
kDebug( 1212 ) << "Refresh rate " << rate << "Hz";
|
kDebug( 1212 ) << "Refresh rate " << rate << "Hz";
|
||||||
compositeRate = 1000 / rate;
|
compositeRate = 1000 / rate;
|
||||||
compositeTimer.start( compositeRate );
|
|
||||||
lastCompositePaint.start();
|
lastCompositePaint.start();
|
||||||
|
// fake a previous paint, so that the next starts right now
|
||||||
|
nextPaintReference = QTime::currentTime().addMSecs( -compositeRate );
|
||||||
|
compositeTimer.setSingleShot( true );
|
||||||
|
checkCompositeTimer();
|
||||||
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
|
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
|
||||||
new EffectsHandlerImpl( scene->compositingType() ); // sets also the 'effects' pointer
|
new EffectsHandlerImpl( scene->compositingType() ); // sets also the 'effects' pointer
|
||||||
addRepaintFull();
|
addRepaintFull();
|
||||||
|
@ -234,11 +237,11 @@ void Workspace::finishCompositing()
|
||||||
foreach( Deleted* c, deleted )
|
foreach( Deleted* c, deleted )
|
||||||
c->finishCompositing();
|
c->finishCompositing();
|
||||||
XCompositeUnredirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
|
XCompositeUnredirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
|
||||||
compositeTimer.stop();
|
|
||||||
delete effects;
|
delete effects;
|
||||||
effects = NULL;
|
effects = NULL;
|
||||||
delete scene;
|
delete scene;
|
||||||
scene = NULL;
|
scene = NULL;
|
||||||
|
compositeTimer.stop();
|
||||||
repaints_region = QRegion();
|
repaints_region = QRegion();
|
||||||
for( ClientList::ConstIterator it = clients.begin();
|
for( ClientList::ConstIterator it = clients.begin();
|
||||||
it != clients.end();
|
it != clients.end();
|
||||||
|
@ -276,6 +279,7 @@ void Workspace::addRepaint( int x, int y, int w, int h )
|
||||||
if( !compositing())
|
if( !compositing())
|
||||||
return;
|
return;
|
||||||
repaints_region += QRegion( x, y, w, h );
|
repaints_region += QRegion( x, y, w, h );
|
||||||
|
checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::addRepaint( const QRect& r )
|
void Workspace::addRepaint( const QRect& r )
|
||||||
|
@ -283,6 +287,7 @@ void Workspace::addRepaint( const QRect& r )
|
||||||
if( !compositing())
|
if( !compositing())
|
||||||
return;
|
return;
|
||||||
repaints_region += r;
|
repaints_region += r;
|
||||||
|
checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::addRepaint( const QRegion& r )
|
void Workspace::addRepaint( const QRegion& r )
|
||||||
|
@ -290,6 +295,7 @@ void Workspace::addRepaint( const QRegion& r )
|
||||||
if( !compositing())
|
if( !compositing())
|
||||||
return;
|
return;
|
||||||
repaints_region += r;
|
repaints_region += r;
|
||||||
|
checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::addRepaintFull()
|
void Workspace::addRepaintFull()
|
||||||
|
@ -297,6 +303,7 @@ void Workspace::addRepaintFull()
|
||||||
if( !compositing())
|
if( !compositing())
|
||||||
return;
|
return;
|
||||||
repaints_region = QRegion( 0, 0, displayWidth(), displayHeight());
|
repaints_region = QRegion( 0, 0, displayWidth(), displayHeight());
|
||||||
|
checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::performCompositing()
|
void Workspace::performCompositing()
|
||||||
|
@ -308,17 +315,17 @@ void Workspace::performCompositing()
|
||||||
// them - leave at least 1msec time after one repaint is finished and next one
|
// them - leave at least 1msec time after one repaint is finished and next one
|
||||||
// is started.
|
// is started.
|
||||||
if( lastCompositePaint.elapsed() < 1 )
|
if( lastCompositePaint.elapsed() < 1 )
|
||||||
|
{
|
||||||
|
compositeTimer.start( 1 );
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
if( !scene->waitSyncAvailable())
|
||||||
|
nextPaintReference = QTime::currentTime();
|
||||||
checkCursorPos();
|
checkCursorPos();
|
||||||
if(( repaints_region.isEmpty() && !windowRepaintsPending()) // no damage
|
if(( repaints_region.isEmpty() && !windowRepaintsPending()) // no damage
|
||||||
|| !overlay_visible ) // nothing is visible anyway
|
|| !overlay_visible ) // nothing is visible anyway
|
||||||
{
|
{
|
||||||
scene->idle();
|
scene->idle();
|
||||||
// With vsync, next repaint is scheduled dynamically at the end of this function,
|
|
||||||
// and it can have a very short timeout. If we now idle here, make sure the idling
|
|
||||||
// does not actually caused heavy load by firing the timer often too quickly.
|
|
||||||
if( compositeTimer.interval() != compositeRate )
|
|
||||||
compositeTimer.start( compositeRate );
|
|
||||||
// Note: It would seem here we should undo suspended unredirect, but when scenes need
|
// 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
|
// 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.
|
// need this anymore and paints normally will also reset the suspended unredirect.
|
||||||
|
@ -361,11 +368,19 @@ void Workspace::performCompositing()
|
||||||
scene->paint( repaints, windows );
|
scene->paint( repaints, windows );
|
||||||
if( scene->waitSyncAvailable())
|
if( scene->waitSyncAvailable())
|
||||||
{
|
{
|
||||||
// if vsync is used, schedule the next repaint slightly in advance of the next sync,
|
// 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
|
// so that there is still time for the drawing to take place. We have just synced, and
|
||||||
int untilNextSync = compositeRate - ( lastCompositePaint.elapsed() % compositeRate );
|
// nextPaintReference is time from which multiples of compositeRate should be added,
|
||||||
compositeTimer.start( qMax( 1, untilNextSync - 10 )); // 10 ms in advance - TODO maybe less?
|
// 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();
|
||||||
lastCompositePaint.start();
|
lastCompositePaint.start();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -387,6 +402,15 @@ bool Workspace::windowRepaintsPending() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Workspace::setCompositeTimer()
|
||||||
|
{
|
||||||
|
if( !compositing()) // should not really happen, but there may be e.g. some damage events still pending
|
||||||
|
return;
|
||||||
|
// Last paint set nextPaintReference as a reference time from which multiples of compositeRate
|
||||||
|
// should be added for the next paint.
|
||||||
|
compositeTimer.start( nextPaintReference.msecsTo( QTime::currentTime()) % compositeRate );
|
||||||
|
}
|
||||||
|
|
||||||
bool Workspace::createOverlay()
|
bool Workspace::createOverlay()
|
||||||
{
|
{
|
||||||
assert( overlay == None );
|
assert( overlay == None );
|
||||||
|
@ -661,6 +685,7 @@ void Toplevel::addDamage( int x, int y, int w, int h )
|
||||||
damage_region += r;
|
damage_region += r;
|
||||||
repaints_region += r;
|
repaints_region += r;
|
||||||
static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), r );
|
static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), r );
|
||||||
|
workspace()->checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toplevel::addDamageFull()
|
void Toplevel::addDamageFull()
|
||||||
|
@ -670,6 +695,7 @@ void Toplevel::addDamageFull()
|
||||||
damage_region = rect();
|
damage_region = rect();
|
||||||
repaints_region = rect();
|
repaints_region = rect();
|
||||||
static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), rect());
|
static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), rect());
|
||||||
|
workspace()->checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toplevel::resetDamage( const QRect& r )
|
void Toplevel::resetDamage( const QRect& r )
|
||||||
|
@ -689,11 +715,13 @@ void Toplevel::addRepaint( int x, int y, int w, int h )
|
||||||
QRect r( x, y, w, h );
|
QRect r( x, y, w, h );
|
||||||
r &= rect();
|
r &= rect();
|
||||||
repaints_region += r;
|
repaints_region += r;
|
||||||
|
workspace()->checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toplevel::addRepaintFull()
|
void Toplevel::addRepaintFull()
|
||||||
{
|
{
|
||||||
repaints_region = rect();
|
repaints_region = rect();
|
||||||
|
workspace()->checkCompositeTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Toplevel::resetRepaints( const QRect& r )
|
void Toplevel::resetRepaints( const QRect& r )
|
||||||
|
|
|
@ -488,6 +488,7 @@ bool Workspace::workspaceEvent( XEvent * e )
|
||||||
addRepaintFull();
|
addRepaintFull();
|
||||||
QTimer::singleShot( 2000, this, SLOT( addRepaintFull()));
|
QTimer::singleShot( 2000, this, SLOT( addRepaintFull()));
|
||||||
}
|
}
|
||||||
|
checkCompositeTimer();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
10
workspace.h
10
workspace.h
|
@ -331,6 +331,7 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void destroyOverlay();
|
void destroyOverlay();
|
||||||
Window overlayWindow();
|
Window overlayWindow();
|
||||||
void checkUnredirect( bool force = false );
|
void checkUnredirect( bool force = false );
|
||||||
|
void checkCompositeTimer();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void addRepaintFull();
|
void addRepaintFull();
|
||||||
|
@ -573,6 +574,7 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
void updateClientArea( bool force );
|
void updateClientArea( bool force );
|
||||||
|
|
||||||
bool windowRepaintsPending() const;
|
bool windowRepaintsPending() const;
|
||||||
|
void setCompositeTimer();
|
||||||
|
|
||||||
int current_desktop;
|
int current_desktop;
|
||||||
int number_of_desktops;
|
int number_of_desktops;
|
||||||
|
@ -734,6 +736,7 @@ class Workspace : public QObject, public KDecorationDefines
|
||||||
bool compositingSuspended;
|
bool compositingSuspended;
|
||||||
QTimer compositeTimer;
|
QTimer compositeTimer;
|
||||||
QTime lastCompositePaint;
|
QTime lastCompositePaint;
|
||||||
|
QTime nextPaintReference;
|
||||||
int compositeRate;
|
int compositeRate;
|
||||||
QRegion repaints_region;
|
QRegion repaints_region;
|
||||||
Window overlay; // XComposite overlay window
|
Window overlay; // XComposite overlay window
|
||||||
|
@ -966,6 +969,13 @@ inline bool Workspace::hasClient( const Client* c )
|
||||||
return findClient( ClientMatchPredicate( c ));
|
return findClient( ClientMatchPredicate( c ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void Workspace::checkCompositeTimer()
|
||||||
|
{
|
||||||
|
if( !compositeTimer.isActive())
|
||||||
|
setCompositeTimer();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue