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
This commit is contained in:
parent
08571b2f52
commit
503bf3e767
5 changed files with 74 additions and 17 deletions
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue