From 905b5676b28f42ed36e272806ecbab08d22bba37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Tue, 22 Jul 2008 18:20:42 +0000 Subject: [PATCH] Try to handle gracefully the case when there are many small changes on the screen and the X server has absolutely no problem with flooding KWin with a huge number of damage events, overloading both the X connection and QRegion. BUG: 163643 svn path=/trunk/KDE/kdebase/workspace/; revision=836664 --- composite.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/composite.cpp b/composite.cpp index e81a359cd2..3a14f9a8a0 100644 --- a/composite.cpp +++ b/composite.cpp @@ -500,8 +500,9 @@ Pixmap Toplevel::createWindowPixmap() #ifdef HAVE_XDAMAGE void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e ) { - addDamage( e->area.x, e->area.y, e->area.width, e->area.height ); + QRegion damage( e->area.x, e->area.y, e->area.width, e->area.height ); // compress + int cnt = 1; while( XPending( display())) { XEvent e2; @@ -509,12 +510,37 @@ void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e ) && e2.xany.window == frameId()) { XNextEvent( display(), &e2 ); + if( cnt > 200 ) + { + // If there are way too many damage events in the queue, just discard them + // and damage the whole window. Otherwise the X server can just overload + // us with a flood of damage events. Should be probably optimized + // in the X server, as this is rather lame. + damage = rect(); + continue; + } XDamageNotifyEvent* e = reinterpret_cast< XDamageNotifyEvent* >( &e2 ); - addDamage( e->area.x, e->area.y, e->area.width, e->area.height ); + QRect r( e->area.x, e->area.y, e->area.width, e->area.height ); + ++cnt; + // If there are too many damaged rectangles, increase them + // to be multiples of 100x100 px grid, since QRegion get quite + // slow with many rectangles, and there is little to gain by using + // many small rectangles (rather the opposite, several large should + // be often faster). + if( cnt > 50 ) + { + r.setLeft( r.left() / 100 * 100 ); + r.setRight(( r.right() + 99 ) / 100 * 100 ); + r.setTop( r.top() / 100 * 100 ); + r.setBottom(( r.bottom() + 99 ) / 100 * 100 ); + } + damage += r; continue; } break; } + foreach( QRect r, damage.rects()) + addDamage( r ); } void Client::damageNotifyEvent( XDamageNotifyEvent* e )