Add a check that measures time needed for one compositing pass.

If three successive ones take more than 1 sec, suspend compositing,
as that very likely means the system is totally incapable of decent
compositing. Perhaps may need little tweaking.


svn path=/trunk/KDE/kdebase/workspace/; revision=861906
icc-effect-5.14.5
Luboš Luňák 2008-09-17 13:42:12 +00:00
parent 08571b2f52
commit 503bf3e767
5 changed files with 74 additions and 17 deletions

View File

@ -52,10 +52,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "scene_xrender.h"
#include "scene_opengl.h"
#include "compositingprefs.h"
#include "notifications.h"
#include <stdio.h>
#include <QMenu>
#include <kaction.h>
#include <kactioncollection.h>
#include <klocale.h>
#include <kxerrorhandler.h>
#include <X11/extensions/shape.h>
@ -193,6 +197,7 @@ void Workspace::setupCompositing()
nextPaintReference = QTime::currentTime().addMSecs( -compositeRate );
compositeTimer.setSingleShot( true );
checkCompositeTimer();
composite_paint_times.clear();
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
new EffectsHandlerImpl( scene->compositingType() ); // sets also the 'effects' pointer
addRepaintFull();
@ -269,7 +274,17 @@ void Workspace::lostCMSelection()
// for the shortcut
void Workspace::slotToggleCompositing()
{
compositingSuspended = !compositingSuspended;
suspendCompositing( !compositingSuspended );
}
void Workspace::suspendCompositing()
{
suspendCompositing( true );
}
void Workspace::suspendCompositing( bool suspend )
{
compositingSuspended = suspend;
finishCompositing();
setupCompositing(); // will do nothing if suspended
}
@ -365,6 +380,7 @@ void Workspace::performCompositing()
QRegion repaints = repaints_region;
// clear all repaints, so that post-pass can add repaints for the next repaint
repaints_region = QRegion();
QTime t = QTime::currentTime();
scene->paint( repaints, windows );
if( scene->waitSyncAvailable())
{
@ -381,6 +397,7 @@ void Workspace::performCompositing()
// checkCompositeTime() would restart it again somewhen later, called from functions that
// would again add something pending.
checkCompositeTimer();
checkCompositePaintTime( t.elapsed());
lastCompositePaint.start();
#endif
}
@ -428,6 +445,35 @@ bool Workspace::createOverlay()
#endif
}
void Workspace::checkCompositePaintTime( int msec )
{
if( options->disableCompositingChecks )
return;
composite_paint_times.enqueue( msec );
if( composite_paint_times.count() > 3 )
composite_paint_times.dequeue();
if( composite_paint_times.count() < 3 )
return;
// If last 3 paints were way too slow, disable and warn.
// 1 second seems reasonable, it's not that difficult to get relatively high times
// with high system load.
const int MAX_TIME = 1000;
if( composite_paint_times[ 0 ] > MAX_TIME && composite_paint_times[ 1 ] > MAX_TIME
&& composite_paint_times[ 2 ] > MAX_TIME )
{
kDebug( 1212 ) << "Too long paint times, suspending";
QTimer::singleShot( 0, this, SLOT( suspendCompositing()));
QString shortcut = i18n( "Empty" );
if( KAction* action = qobject_cast<KAction*>( keys->action("Suspend Compositing")))
shortcut = action->globalShortcut().primary().toString();
QString message = i18n( "Compositing was too slow and has been suspended.\n"
"If this was only a temporary problem, you can resume using the '%1' shortcut.\n"
"You can also disable functionality checks in advanced compositing settings.", shortcut );
Notify::raise( Notify::CompositingSlow, message );
compositeTimer.start( 1000 ); // so that it doesn't trigger sooner than suspendCompositing()
}
}
void Workspace::setupOverlay( Window w )
{
assert( overlay != None );

View File

@ -5485,3 +5485,7 @@ Comment[x-test]=xxA window on an inactive virtual desktop demands attentionxx
Comment[zh_CN]=未激活的虚拟桌面上的窗口请求注意
Comment[zh_TW]=在其他虛擬桌面上的視窗要求注意
[Event/compositingslow]
Name=Compositing Performance Is Slow
Comment=The compositing performance was too slow and compositing has been suspended
Action=Popup

View File

@ -27,9 +27,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
QString Notify::eventToName( Event e )
static bool forgetIt = false;
QList< Notify::EventData > Notify::pending_events;
bool Notify::raise( Event e, const QString& message, Client* c )
{
if ( forgetIt )
return false; // no connection was possible, don't try each time
QString event;
KNotification::NotificationFlags flags = KNotification::CloseOnTimeout;
switch ( e )
{
case Activate:
@ -92,6 +99,10 @@ QString Notify::eventToName( Event e )
case DemandAttentionOther:
event = "demandsattentionother";
break;
case CompositingSlow:
event = "compositingslow";
flags = KNotification::Persistent;
break;
default:
if ((e > DesktopChange) && (e <= DesktopChange+20))
{
@ -99,18 +110,6 @@ QString Notify::eventToName( Event e )
}
break;
}
return event;
}
static bool forgetIt = false;
QList< Notify::EventData > Notify::pending_events;
bool Notify::raise( Event e, const QString& message, Client* c )
{
if ( forgetIt )
return false; // no connection was possible, don't try each time
QString event = eventToName( e );
if ( event.isNull() )
return false;
@ -124,12 +123,13 @@ bool Notify::raise( Event e, const QString& message, Client* c )
data.event = event;
data.message = message;
data.window = c ? c->window() : 0;
data.flags = flags;
pending_events.append( data );
return true;
}
return KNotification::event( event, message /*, QPixmap() , c ? c->window() : 0*/ ); //FIXME get the widget ?
return KNotification::event( event, message, QPixmap(), NULL /* TODO c ? c->window() : 0*/, flags );
}
void Notify::sendPendingEvents()
@ -139,7 +139,7 @@ void Notify::sendPendingEvents()
EventData data = pending_events.first();
pending_events.pop_front();
if( !forgetIt )
KNotification::event( data.event, data.message /* , QPixmap() , data.window */ );
KNotification::event( data.event, data.message, QPixmap(), NULL /* TODO data.window*/, data.flags );
}
}

View File

@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_NOTIFICATIONS_H
#define KWIN_NOTIFICATIONS_H
#include <knotification.h>
#include <stdlib.h>
#include <QString>
#include <QList>
@ -57,18 +58,19 @@ class Notify
ResizeEnd,
DemandAttentionCurrent,
DemandAttentionOther,
CompositingSlow,
DesktopChange = 100
};
static bool raise( Event, const QString& message = QString(), Client* c = NULL );
static void sendPendingEvents();
private:
static QString eventToName( Event );
struct EventData
{
QString event;
QString message;
long window;
KNotification::NotificationFlags flags;
};
static QList< EventData > pending_events;
};

View File

@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kxmessages.h>
#include <QDateTime>
#include <kmanagerselection.h>
#include <qqueue.h>
#include "utils.h"
#include "kdecoration.h"
@ -472,6 +473,8 @@ class Workspace : public QObject, public KDecorationDefines
void slotToggleCompositing();
void updateClientArea();
void suspendCompositing();
void suspendCompositing( bool suspend );
private slots:
void desktopPopupAboutToShow();
@ -577,6 +580,7 @@ class Workspace : public QObject, public KDecorationDefines
void finishCompositing();
bool windowRepaintsPending() const;
void setCompositeTimer();
void checkCompositePaintTime( int msec );
int current_desktop;
int number_of_desktops;
@ -749,6 +753,7 @@ class Workspace : public QObject, public KDecorationDefines
QPushButton *transButton;
QTimer unredirectTimer;
bool forceUnredirectCheck;
QQueue< int > composite_paint_times;
private:
friend bool performTransiencyCheck();