xrender compositing work - now it uses damage areas
to reduce amount of painting svn path=/branches/work/kwin_composite/; revision=558580
This commit is contained in:
parent
29111875e1
commit
f400646a6d
20 changed files with 151 additions and 74 deletions
|
@ -63,6 +63,9 @@ endif (X11_Xdamage_FOUND)
|
|||
if (X11_Xrender_FOUND)
|
||||
target_link_libraries(kdeinit_kwin ${X11_Xrender_LIB})
|
||||
endif (X11_Xrender_FOUND)
|
||||
if (X11_Xfixes_FOUND)
|
||||
target_link_libraries(kdeinit_kwin ${X11_Xfixes_LIB})
|
||||
endif (X11_Xfixes_FOUND)
|
||||
|
||||
install(TARGETS kdeinit_kwin DESTINATION ${LIB_INSTALL_DIR} )
|
||||
|
||||
|
|
|
@ -88,8 +88,7 @@ Client::Client( Workspace *ws )
|
|||
border_top( 0 ),
|
||||
border_bottom( 0 ),
|
||||
sm_stacking_order( -1 ),
|
||||
demandAttentionKNotifyTimer( NULL ),
|
||||
damage( None )
|
||||
demandAttentionKNotifyTimer( NULL )
|
||||
// SELI do all as initialization
|
||||
{
|
||||
autoRaiseTimer = 0;
|
||||
|
|
2
client.h
2
client.h
|
@ -316,7 +316,6 @@ class Client
|
|||
void visibilityNotifyEvent( XVisibilityEvent* e );
|
||||
void focusInEvent( XFocusInEvent* e );
|
||||
void focusOutEvent( XFocusOutEvent* e );
|
||||
void damageNotifyEvent( XDamageNotifyEvent* e );
|
||||
|
||||
bool buttonPressEvent( Window w, int button, int state, int x, int y, int x_root, int y_root );
|
||||
bool buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root );
|
||||
|
@ -516,7 +515,6 @@ class Client
|
|||
void show() { assert( false ); } // SELI remove after Client is no longer QWidget
|
||||
void hide() { assert( false ); }
|
||||
QTimer* demandAttentionKNotifyTimer;
|
||||
Damage damage;
|
||||
};
|
||||
|
||||
// helper for Client::postponeGeometryUpdates() being called in pairs (true/false)
|
||||
|
|
104
composite.cpp
104
composite.cpp
|
@ -23,7 +23,7 @@ namespace KWinInternal
|
|||
// Workspace
|
||||
//****************************************
|
||||
|
||||
#if defined( HAVE_XCOMPOSITE ) && defined( HAVE_XDAMAGE )
|
||||
#if defined( HAVE_XCOMPOSITE ) && defined( HAVE_XDAMAGE ) && defined( HAVE_XFIXES )
|
||||
void Workspace::setupCompositing()
|
||||
{
|
||||
if( !Extensions::compositeAvailable() || !Extensions::damageAvailable())
|
||||
|
@ -33,9 +33,9 @@ void Workspace::setupCompositing()
|
|||
// TODO start tracking unmanaged windows
|
||||
compositeTimer.start( 20 );
|
||||
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
|
||||
setDamaged();
|
||||
// scene = new SceneBasic( this );
|
||||
scene = new SceneXrender( this );
|
||||
addDamage( 0, 0, displayWidth(), displayHeight());
|
||||
}
|
||||
|
||||
void Workspace::finishCompositing()
|
||||
|
@ -49,18 +49,69 @@ void Workspace::finishCompositing()
|
|||
scene = NULL;
|
||||
}
|
||||
|
||||
void Workspace::setDamaged()
|
||||
void Workspace::addDamage( const QRect& r )
|
||||
{
|
||||
addDamage( r.x(), r.y(), r.height(), r.width());
|
||||
}
|
||||
|
||||
void Workspace::addDamage( int x, int y, int w, int h )
|
||||
{
|
||||
XRectangle r;
|
||||
r.x = x;
|
||||
r.y = y;
|
||||
r.width = w;
|
||||
r.height = h;
|
||||
addDamage( XFixesCreateRegion( display(), &r, 1 ), true );
|
||||
}
|
||||
|
||||
struct XXX
|
||||
{
|
||||
XXX( XserverRegion r ) : rr( r ) {}
|
||||
XserverRegion rr;
|
||||
};
|
||||
|
||||
kdbgstream& operator<<( kdbgstream& stream, XXX r )
|
||||
{
|
||||
if( r.rr == None )
|
||||
return stream << "NONE";
|
||||
int num;
|
||||
XRectangle* rects = XFixesFetchRegion( display(), r.rr, &num );
|
||||
if( rects == NULL || num == 0 )
|
||||
return stream << "NONE";
|
||||
for( int i = 0;
|
||||
i < num;
|
||||
++i )
|
||||
stream << "[" << rects[ i ].x << "+" << rects[ i ].y << " " << rects[ i ].width << "x" << rects[ i ].height << "]";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
void Workspace::addDamage( XserverRegion r, bool destroy )
|
||||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
damaged = true;
|
||||
if( damage != None )
|
||||
{
|
||||
XFixesUnionRegion( display(), damage, damage, r );
|
||||
if( destroy )
|
||||
XFixesDestroyRegion( display(), r );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( destroy )
|
||||
damage = r;
|
||||
else
|
||||
{
|
||||
damage = XFixesCreateRegion( display(), NULL, 0 );
|
||||
XFixesCopyRegion( display(), damage, r );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::compositeTimeout()
|
||||
{
|
||||
if( !damaged )
|
||||
if( damage == None )
|
||||
return;
|
||||
damaged = false;
|
||||
ToplevelList windows;
|
||||
Window* children;
|
||||
unsigned int children_count;
|
||||
|
@ -79,7 +130,9 @@ void Workspace::compositeTimeout()
|
|||
windows.append( c );
|
||||
}
|
||||
scene->setWindows( windows );
|
||||
scene->paint();
|
||||
scene->paint( damage );
|
||||
XFixesDestroyRegion( display(), damage );
|
||||
damage = None;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
|
@ -90,18 +143,17 @@ void Toplevel::setupCompositing()
|
|||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
if( damage != None )
|
||||
if( damage_handle != None )
|
||||
return;
|
||||
damage = XDamageCreate( display(), handle(), XDamageReportRawRectangles );
|
||||
setDamaged();
|
||||
damage_handle = XDamageCreate( display(), handle(), XDamageReportRawRectangles );
|
||||
}
|
||||
|
||||
void Toplevel::finishCompositing()
|
||||
{
|
||||
if( damage == None )
|
||||
if( damage_handle == None )
|
||||
return;
|
||||
XDamageDestroy( display(), damage );
|
||||
damage = None;
|
||||
XDamageDestroy( display(), damage_handle );
|
||||
damage_handle = None;
|
||||
if( window_pixmap != None )
|
||||
{
|
||||
XFreePixmap( display(), window_pixmap );
|
||||
|
@ -109,13 +161,6 @@ void Toplevel::finishCompositing()
|
|||
}
|
||||
}
|
||||
|
||||
void Toplevel::setDamaged()
|
||||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
workspace()->setDamaged();
|
||||
}
|
||||
|
||||
void Toplevel::resetWindowPixmap()
|
||||
{
|
||||
if( !compositing())
|
||||
|
@ -132,22 +177,11 @@ Pixmap Toplevel::windowPixmap() const
|
|||
return window_pixmap;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Client
|
||||
//****************************************
|
||||
|
||||
void Client::damageNotifyEvent( XDamageNotifyEvent* )
|
||||
void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e )
|
||||
{
|
||||
setDamaged();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Unmanaged
|
||||
//****************************************
|
||||
|
||||
void Unmanaged::damageNotifyEvent( XDamageNotifyEvent* )
|
||||
{
|
||||
setDamaged();
|
||||
XserverRegion r = XFixesCreateRegion( display(), &e->area, 1 );
|
||||
XFixesTranslateRegion( display(), r, x(), y());
|
||||
workspace()->addDamage( r, true );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
10
events.cpp
10
events.cpp
|
@ -473,8 +473,8 @@ bool Workspace::workspaceEvent( XEvent * e )
|
|||
tab_box->updateKeyMapping();
|
||||
break;
|
||||
case Expose:
|
||||
if( e->xexpose.window == rootWindow() && compositing())
|
||||
setDamaged(); // root window needs repainting
|
||||
if( e->xexpose.window == rootWindow() && compositing()) // root window needs repainting
|
||||
addDamage( e->xexpose.x, e->xexpose.y, e->xexpose.width, e->xexpose.height );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1624,9 +1624,11 @@ void Unmanaged::unmapNotifyEvent( XUnmapEvent* )
|
|||
|
||||
void Unmanaged::configureNotifyEvent( XConfigureEvent* e )
|
||||
{
|
||||
geom = QRect( e->x, e->y, e->width, e->height );
|
||||
resetWindowPixmap();
|
||||
setDamaged();
|
||||
// add old and new geometry to damage
|
||||
workspace()->addDamage( geometry());
|
||||
geom = QRect( e->x, e->y, e->width, e->height );
|
||||
workspace()->addDamage( geometry());
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
|
|
|
@ -1660,6 +1660,7 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
|
|||
}
|
||||
if( force == NormalGeometrySet && geom == QRect( x, y, w, h ))
|
||||
return;
|
||||
workspace()->addDamage( geometry()); // TODO cache the previous real geometry
|
||||
geom = QRect( x, y, w, h );
|
||||
updateWorkareaDiffs();
|
||||
if( postpone_geometry_updates != 0 )
|
||||
|
@ -1684,8 +1685,8 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
|
|||
sendSyntheticConfigureNotify();
|
||||
updateWindowRules();
|
||||
checkMaximizeGeometry();
|
||||
setDamaged();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
}
|
||||
|
||||
void Client::plainResize( int w, int h, ForceGeometry_t force )
|
||||
|
@ -1717,6 +1718,7 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
|
|||
}
|
||||
if( force == NormalGeometrySet && geom.size() == QSize( w, h ))
|
||||
return;
|
||||
workspace()->addDamage( geometry()); // TODO cache the previous real geometry
|
||||
geom.setSize( QSize( w, h ));
|
||||
updateWorkareaDiffs();
|
||||
if( postpone_geometry_updates != 0 )
|
||||
|
@ -1740,8 +1742,8 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
|
|||
sendSyntheticConfigureNotify();
|
||||
updateWindowRules();
|
||||
checkMaximizeGeometry();
|
||||
setDamaged();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1751,6 +1753,7 @@ void Client::move( int x, int y, ForceGeometry_t force )
|
|||
{
|
||||
if( force == NormalGeometrySet && geom.topLeft() == QPoint( x, y ))
|
||||
return;
|
||||
workspace()->addDamage( geometry()); // TODO cache the previous real geometry
|
||||
geom.moveTopLeft( QPoint( x, y ));
|
||||
updateWorkareaDiffs();
|
||||
if( postpone_geometry_updates != 0 )
|
||||
|
@ -1762,7 +1765,7 @@ void Client::move( int x, int y, ForceGeometry_t force )
|
|||
sendSyntheticConfigureNotify();
|
||||
updateWindowRules();
|
||||
checkMaximizeGeometry();
|
||||
setDamaged();
|
||||
workspace()->addDamage( geometry());
|
||||
}
|
||||
|
||||
void Client::postponeGeometryUpdates( bool postpone )
|
||||
|
|
|
@ -518,6 +518,9 @@ bool Client::manage( Window w, bool isMapped )
|
|||
// sendSyntheticConfigureNotify(); done when setting mapping state
|
||||
|
||||
delete session;
|
||||
|
||||
if( isMapped ) // otherwise damage will come when the client paints it
|
||||
workspace()->addDamage( geometry());
|
||||
|
||||
ungrabXServer();
|
||||
|
||||
|
|
2
scene.h
2
scene.h
|
@ -24,7 +24,7 @@ class Scene
|
|||
Scene( Workspace* ws );
|
||||
virtual ~Scene();
|
||||
void setWindows( const ToplevelList& list );
|
||||
virtual void paint() = 0;
|
||||
virtual void paint( XserverRegion damage ) = 0;
|
||||
protected:
|
||||
Workspace* wspace;
|
||||
ToplevelList windows;
|
||||
|
|
|
@ -29,7 +29,7 @@ SceneBasic::~SceneBasic()
|
|||
{
|
||||
}
|
||||
|
||||
void SceneBasic::paint()
|
||||
void SceneBasic::paint( XserverRegion )
|
||||
{
|
||||
Pixmap composite_pixmap = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(), QX11Info::appDepth());
|
||||
XGCValues val;
|
||||
|
|
|
@ -22,7 +22,7 @@ class SceneBasic
|
|||
public:
|
||||
SceneBasic( Workspace* ws );
|
||||
virtual ~SceneBasic();
|
||||
virtual void paint();
|
||||
virtual void paint( XserverRegion damage );
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -48,28 +48,41 @@ void SceneXrender::createBuffer()
|
|||
XFreePixmap( display(), pixmap ); // The picture owns the pixmap now
|
||||
}
|
||||
|
||||
void SceneXrender::paint()
|
||||
void SceneXrender::paint( XserverRegion damage )
|
||||
{
|
||||
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
|
||||
for( ToplevelList::ConstIterator it = windows.begin();
|
||||
it != windows.end();
|
||||
++it )
|
||||
// Use the damage region as the clip region for the root window
|
||||
XFixesSetPictureClipRegion( display(), front, 0, 0, damage );
|
||||
// Draw each opaque window top to bottom, subtracting the bounding rect of
|
||||
// each window from the clip region after it's been drawn.
|
||||
for( int i = windows.count() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
QRect r = (*it)->geometry().intersect( QRect( 0, 0, displayWidth(), displayHeight()));
|
||||
if( !r.isEmpty())
|
||||
Toplevel* c = windows[ i ];
|
||||
XWindowAttributes attrs;
|
||||
if( !XGetWindowAttributes( display(), c->handle(), &attrs ))
|
||||
continue;
|
||||
if( XRenderPictFormat* clientFormat = XRenderFindVisualFormat( display(), attrs.visual ))
|
||||
{
|
||||
XWindowAttributes attrs;
|
||||
if( !XGetWindowAttributes( display(), (*it)->handle(), &attrs ))
|
||||
continue;
|
||||
if( XRenderPictFormat* clientFormat = XRenderFindVisualFormat( display(), attrs.visual ))
|
||||
{
|
||||
Picture picture = XRenderCreatePicture( display(), (*it)->windowPixmap(), clientFormat, 0, 0 );
|
||||
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
|
||||
(*it)->x(), (*it)->y(), (*it)->width(), (*it)->height());
|
||||
}
|
||||
Picture picture = XRenderCreatePicture( display(), c->windowPixmap(), clientFormat, 0, 0 );
|
||||
// Set the clip region for the buffer to the damage region, and
|
||||
// subtract the clients shape from the damage region
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||
XserverRegion cr = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
||||
XFixesTranslateRegion( display(), cr, c->x(), c->y());
|
||||
XFixesSubtractRegion( display(), damage, damage, cr );
|
||||
XFixesDestroyRegion( display(), cr );
|
||||
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
|
||||
c->x(), c->y(), c->width(), c->height());
|
||||
XRenderFreePicture( display(), picture );
|
||||
}
|
||||
}
|
||||
// fill background
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
|
||||
// copy composed buffer to the root window
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
|
||||
XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
|
||||
XFlush( display());
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class SceneXrender
|
|||
public:
|
||||
SceneXrender( Workspace* ws );
|
||||
virtual ~SceneXrender();
|
||||
virtual void paint();
|
||||
virtual void paint( XserverRegion damage );
|
||||
private:
|
||||
void createBuffer();
|
||||
XRenderPictFormat* format;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace KWinInternal
|
|||
Toplevel::Toplevel( Workspace* ws )
|
||||
: id( None )
|
||||
, wspace( ws )
|
||||
, damage( None )
|
||||
, damage_handle( None )
|
||||
, window_pixmap( None )
|
||||
{
|
||||
}
|
||||
|
|
|
@ -43,16 +43,16 @@ class Toplevel
|
|||
protected:
|
||||
void setupCompositing();
|
||||
void finishCompositing();
|
||||
void setDamaged();
|
||||
void setHandle( Window id );
|
||||
void resetWindowPixmap();
|
||||
void damageNotifyEvent( XDamageNotifyEvent* e );
|
||||
QRect geom;
|
||||
virtual void debug( kdbgstream& stream ) const = 0;
|
||||
friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* );
|
||||
private:
|
||||
Window id;
|
||||
Workspace* wspace;
|
||||
Damage damage;
|
||||
Damage damage_handle;
|
||||
mutable Pixmap window_pixmap;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ bool Unmanaged::track( Window w )
|
|||
geom = QRect( attr.x, attr.y, attr.width, attr.height );
|
||||
setupCompositing();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ class Unmanaged
|
|||
void mapNotifyEvent( XMapEvent* e );
|
||||
void unmapNotifyEvent( XUnmapEvent*e );
|
||||
void configureNotifyEvent( XConfigureEvent* e );
|
||||
void damageNotifyEvent( XDamageNotifyEvent* e );
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -48,6 +48,7 @@ int Extensions::shape_event_base = 0;
|
|||
bool Extensions::has_damage = 0;
|
||||
int Extensions::damage_event_base = 0;
|
||||
bool Extensions::has_composite = 0;
|
||||
bool Extensions::has_fixes = 0;
|
||||
|
||||
void Extensions::init()
|
||||
{
|
||||
|
@ -70,6 +71,11 @@ void Extensions::init()
|
|||
}
|
||||
#else
|
||||
has_composite = false;
|
||||
#endif
|
||||
#ifdef HAVE_XFIXES
|
||||
has_fixes = XFixesQueryExtension( display(), &dummy, &dummy );
|
||||
#else
|
||||
has_fixes = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
10
utils.h
10
utils.h
|
@ -21,6 +21,9 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#ifdef HAVE_XDAMAGE
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
#ifdef HAVE_XFIXES
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#endif
|
||||
|
||||
#include <fixx11h.h>
|
||||
|
||||
|
@ -40,6 +43,11 @@ struct XDamageNotifyEvent
|
|||
{
|
||||
};
|
||||
#endif
|
||||
#ifndef HAVE_XFIXES
|
||||
struct XserverRegion
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
|
||||
| NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
|
||||
|
@ -143,12 +151,14 @@ class Extensions
|
|||
static bool damageAvailable() { return has_damage; }
|
||||
static int damageNotifyEvent();
|
||||
static bool compositeAvailable() { return has_composite; }
|
||||
static bool fixesAvailable() { return has_fixes; }
|
||||
private:
|
||||
static bool has_shape;
|
||||
static int shape_event_base;
|
||||
static bool has_damage;
|
||||
static int damage_event_base;
|
||||
static bool has_composite;
|
||||
static bool has_fixes;
|
||||
};
|
||||
|
||||
class Motif
|
||||
|
|
|
@ -124,7 +124,7 @@ Workspace::Workspace( bool restore )
|
|||
set_active_client_recursion( 0 ),
|
||||
block_stacking_updates( 0 ),
|
||||
forced_global_mouse_grab( false ),
|
||||
damaged( false )
|
||||
damage( None )
|
||||
{
|
||||
new KWinAdaptor( "org.kde.kwin", "/KWin", QDBus::sessionBus(), this );
|
||||
|
||||
|
@ -471,6 +471,10 @@ Workspace::~Workspace()
|
|||
foreach ( SessionInfo* s, session )
|
||||
delete s;
|
||||
XDestroyWindow( display(), null_focus_window );
|
||||
#ifdef HAVE_XFIXES
|
||||
if( damage != None )
|
||||
XFixesDestroyRegion( display(), damage );
|
||||
#endif
|
||||
// TODO ungrabXServer();
|
||||
_self = 0;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,9 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
|
||||
void toggleTopDockShadows(bool on);
|
||||
|
||||
void setDamaged();
|
||||
void addDamage( const QRect& r );
|
||||
void addDamage( int x, int y, int w, int h );
|
||||
void addDamage( XserverRegion r, bool destroy );
|
||||
|
||||
public slots:
|
||||
void refresh();
|
||||
|
@ -630,8 +632,8 @@ class Workspace : public QObject, public KDecorationDefines
|
|||
bool forced_global_mouse_grab;
|
||||
friend class StackingUpdatesBlocker;
|
||||
|
||||
bool damaged;
|
||||
QTimer compositeTimer;
|
||||
XserverRegion damage;
|
||||
|
||||
//kompmgr
|
||||
QSlider *transSlider;
|
||||
|
|
Loading…
Reference in a new issue