Add post-painting pass to be used for triggering

repaints with animations.


svn path=/branches/work/kwin_composite/; revision=600156
This commit is contained in:
Luboš Luňák 2006-10-29 19:07:10 +00:00
parent 6b41c062c8
commit 3f9b754ee7
9 changed files with 95 additions and 36 deletions

View file

@ -115,8 +115,6 @@ TODO:
be created, but the old animation should be stopped - compare window id's? be created, but the old animation should be stopped - compare window id's?
? maybe just keep the object around in a special list ? maybe just keep the object around in a special list
* add a postpaint pass * don't add workspace damage in Toplevel::addDamage()
- needed for animations to trigger next repaint, currently window damage is reset after - instead add damage of windows to the screen only before doing the painting
the painting pass, meaning the damage cannot be added from there - this should prevent repaints because of obscured windows
- current workaround is to damage the whole screen, as there's a for resetting that damage
in advance

View file

@ -156,13 +156,12 @@ void Workspace::compositeTimeout()
else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] ))) else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( children[ i ] )))
windows.append( c ); windows.append( c );
} }
effects->startPaint(); scene->prePaint();
// TODO when effects cause damage, it should be only enqueued for next repaint scene->paint( damage_region, windows );
QRegion r = damage_region;
damage_region = QRegion(); damage_region = QRegion();
scene->paint( r, windows );
foreach( Toplevel* c, windows ) foreach( Toplevel* c, windows )
c->resetDamage(); c->resetDamage();
scene->postPaint();
lastCompositePaint.start(); lastCompositePaint.start();
} }

View file

@ -46,6 +46,11 @@ void Effect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{ {
effects->paintScreen( mask, region, data ); effects->paintScreen( mask, region, data );
} }
void Effect::postPaintScreen()
{
effects->postPaintScreen();
}
void Effect::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ) void Effect::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
{ {
@ -57,6 +62,11 @@ void Effect::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPain
effects->paintWindow( w, mask, region, data ); effects->paintWindow( w, mask, region, data );
} }
void Effect::postPaintWindow( Scene::Window* w )
{
effects->postPaintWindow( w );
}
void MakeHalfTransparent::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ) void MakeHalfTransparent::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
{ {
const Client* c = dynamic_cast< const Client* >( w->window()); const Client* c = dynamic_cast< const Client* >( w->window());
@ -188,17 +198,9 @@ ShiftWorkspaceUp::ShiftWorkspaceUp( Workspace* ws )
void ShiftWorkspaceUp::prePaintScreen( int* mask, QRegion* region, int time ) void ShiftWorkspaceUp::prePaintScreen( int* mask, QRegion* region, int time )
{ {
if( up && diff < 1000 ) if( up && diff < 1000 )
{
diff = qBound( 0, diff + time, 1000 ); // KDE3: note this differs from KCLAMP diff = qBound( 0, diff + time, 1000 ); // KDE3: note this differs from KCLAMP
if( diff < 1000 )
wspace->addDamageFull(); // affects next redraw
}
if( !up && diff > 0 ) if( !up && diff > 0 )
{
diff = qBound( 0, diff - time, 1000 ); diff = qBound( 0, diff - time, 1000 );
if( diff > 0 )
wspace->addDamageFull(); // affects next redraw
}
if( diff != 0 ) if( diff != 0 )
*mask |= Scene::PAINT_SCREEN_TRANSFORMED; *mask |= Scene::PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( mask, region, time ); effects->prePaintScreen( mask, region, time );
@ -211,6 +213,13 @@ void ShiftWorkspaceUp::paintScreen( int mask, QRegion region, ScreenPaintData& d
effects->paintScreen( mask, region, data ); effects->paintScreen( mask, region, data );
} }
void ShiftWorkspaceUp::postPaintScreen()
{
if( up ? diff < 1000 : diff > 0 )
wspace->addDamageFull(); // trigger next animation repaint
effects->postPaintScreen();
}
void ShiftWorkspaceUp::tick() void ShiftWorkspaceUp::tick()
{ {
up = !up; up = !up;
@ -227,9 +236,6 @@ void FadeIn::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int t
{ {
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT; *mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
*mask &= ~Scene::PAINT_WINDOW_OPAQUE; *mask &= ~Scene::PAINT_WINDOW_OPAQUE;
// TODO this should just damage the window, but right now window
// damage is cleared after the painting pass - a postpaint pass is needed
w->window()->workspace()->addDamageFull();
} }
else else
windows.remove( w->window()); windows.remove( w->window());
@ -246,6 +252,13 @@ void FadeIn::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPain
effects->paintWindow( w, mask, region, data ); effects->paintWindow( w, mask, region, data );
} }
void FadeIn::postPaintWindow( Scene::Window* w )
{
if( windows.contains( w->window()))
w->window()->addDamageFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
void FadeIn::windowAdded( Toplevel* c ) void FadeIn::windowAdded( Toplevel* c )
{ {
Client* cc = dynamic_cast< Client* >( c ); Client* cc = dynamic_cast< Client* >( c );
@ -268,12 +281,7 @@ void ScaleIn::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int
{ {
windows[ w->window() ] += time / 500.; // complete change in 500ms windows[ w->window() ] += time / 500.; // complete change in 500ms
if( windows[ w->window() ] < 1 ) if( windows[ w->window() ] < 1 )
{
*mask |= Scene::PAINT_WINDOW_TRANSFORMED; *mask |= Scene::PAINT_WINDOW_TRANSFORMED;
// TODO this should just damage the window, but right now window
// damage is cleared after the painting pass - a postpaint pass is needed
w->window()->workspace()->addDamageFull();
}
else else
windows.remove( w->window()); windows.remove( w->window());
} }
@ -286,12 +294,19 @@ void ScaleIn::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPai
{ {
data.xScale *= windows[ w->window()]; data.xScale *= windows[ w->window()];
data.yScale *= windows[ w->window()]; data.yScale *= windows[ w->window()];
data.xTranslate += w->window()->width() / 2 * ( 1 - windows[ w->window()] ); data.xTranslate += int( w->window()->width() / 2 * ( 1 - windows[ w->window()] ));
data.yTranslate += w->window()->height() / 2 * ( 1 - windows[ w->window()] ); data.yTranslate += int( w->window()->height() / 2 * ( 1 - windows[ w->window()] ));
} }
effects->paintWindow( w, mask, region, data ); effects->paintWindow( w, mask, region, data );
} }
void ScaleIn::postPaintWindow( Scene::Window* w )
{
if( windows.contains( w->window()))
w->window()->addDamageFull(); // trigger next animation repaint
effects->postPaintWindow( w );
}
void ScaleIn::windowAdded( Toplevel* c ) void ScaleIn::windowAdded( Toplevel* c )
{ {
Client* cc = dynamic_cast< Client* >( c ); Client* cc = dynamic_cast< Client* >( c );
@ -359,7 +374,7 @@ void EffectsHandler::startPaint()
// the idea is that effects call this function again which calls the next one // the idea is that effects call this function again which calls the next one
void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time ) void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time )
{ {
if( current_paint_screen < effects.size() - 1 ) if( current_paint_screen < effects.size())
{ {
effects[ current_paint_screen++ ]->prePaintScreen( mask, region, time ); effects[ current_paint_screen++ ]->prePaintScreen( mask, region, time );
--current_paint_screen; --current_paint_screen;
@ -369,7 +384,7 @@ void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time )
void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& data ) void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{ {
if( current_paint_screen < effects.size() - 1 ) if( current_paint_screen < effects.size())
{ {
effects[ current_paint_screen++ ]->paintScreen( mask, region, data ); effects[ current_paint_screen++ ]->paintScreen( mask, region, data );
--current_paint_screen; --current_paint_screen;
@ -378,9 +393,19 @@ void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& dat
scene->finalPaintScreen( mask, region, data ); scene->finalPaintScreen( mask, region, data );
} }
void EffectsHandler::postPaintScreen()
{
if( current_paint_screen < effects.size())
{
effects[ current_paint_screen++ ]->postPaintScreen();
--current_paint_screen;
}
// no special final code
}
void EffectsHandler::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ) void EffectsHandler::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time )
{ {
if( current_paint_window < effects.size() - 1 ) if( current_paint_window < effects.size())
{ {
effects[ current_paint_window++ ]->prePaintWindow( w, mask, region, time ); effects[ current_paint_window++ ]->prePaintWindow( w, mask, region, time );
--current_paint_window; --current_paint_window;
@ -390,7 +415,7 @@ void EffectsHandler::prePaintWindow( Scene::Window* w, int* mask, QRegion* regio
void EffectsHandler::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data ) void EffectsHandler::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data )
{ {
if( current_paint_window < effects.size() - 1 ) if( current_paint_window < effects.size())
{ {
effects[ current_paint_window++ ]->paintWindow( w, mask, region, data ); effects[ current_paint_window++ ]->paintWindow( w, mask, region, data );
--current_paint_window; --current_paint_window;
@ -399,6 +424,16 @@ void EffectsHandler::paintWindow( Scene::Window* w, int mask, QRegion region, Wi
scene->finalPaintWindow( w, mask, region, data ); scene->finalPaintWindow( w, mask, region, data );
} }
void EffectsHandler::postPaintWindow( Scene::Window* w )
{
if( current_paint_window < effects.size())
{
effects[ current_paint_window++ ]->postPaintWindow( w );
--current_paint_window;
}
// no special final code
}
EffectsHandler* effects; EffectsHandler* effects;
} // namespace } // namespace

View file

@ -50,8 +50,10 @@ class Effect
virtual ~Effect(); virtual ~Effect();
virtual void prePaintScreen( int* mask, QRegion* region, int time ); virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ); virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data ); virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( Scene::Window* w );
// called when moved/resized or once after it's finished // called when moved/resized or once after it's finished
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last ); virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void windowAdded( Toplevel* c ); virtual void windowAdded( Toplevel* c );
@ -66,8 +68,10 @@ class EffectsHandler
// for use by effects // for use by effects
void prePaintScreen( int* mask, QRegion* region, int time ); void prePaintScreen( int* mask, QRegion* region, int time );
void paintScreen( int mask, QRegion region, ScreenPaintData& data ); void paintScreen( int mask, QRegion region, ScreenPaintData& data );
void postPaintScreen();
void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ); void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data ); void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
void postPaintWindow( Scene::Window* w );
// internal (used by kwin core or compositing code) // internal (used by kwin core or compositing code)
void startPaint(); void startPaint();
void windowUserMovedResized( Toplevel* c, bool first, bool last ); void windowUserMovedResized( Toplevel* c, bool first, bool last );
@ -126,6 +130,7 @@ class ShiftWorkspaceUp
ShiftWorkspaceUp( Workspace* ws ); ShiftWorkspaceUp( Workspace* ws );
virtual void prePaintScreen( int* mask, QRegion* region, int time ); virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
private slots: private slots:
void tick(); void tick();
private: private:
@ -141,6 +146,7 @@ class FadeIn
public: public:
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ); virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data ); virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( Scene::Window* w );
// TODO react also on virtual desktop changes // TODO react also on virtual desktop changes
virtual void windowAdded( Toplevel* c ); virtual void windowAdded( Toplevel* c );
virtual void windowDeleted( Toplevel* c ); virtual void windowDeleted( Toplevel* c );
@ -154,6 +160,7 @@ class ScaleIn
public: public:
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time ); virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int time );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data ); virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( Scene::Window* w );
// TODO react also on virtual desktop changes // TODO react also on virtual desktop changes
virtual void windowAdded( Toplevel* c ); virtual void windowAdded( Toplevel* c );
virtual void windowDeleted( Toplevel* c ); virtual void windowDeleted( Toplevel* c );

View file

@ -33,6 +33,12 @@ Scene::~Scene()
{ {
} }
void Scene::prePaint()
{
effects->startPaint();
// do the rest of prepaint pass together with paint pass
}
// returns mask and possibly modified region // returns mask and possibly modified region
void Scene::paintScreen( int* mask, QRegion* region ) void Scene::paintScreen( int* mask, QRegion* region )
{ {
@ -148,6 +154,14 @@ void Scene::finalPaintWindow( Scene::Window* w, int mask, QRegion region, Window
w->performPaint( mask, region, data ); w->performPaint( mask, region, data );
} }
void Scene::postPaint()
{
effects->postPaintScreen();
foreach( Window* w, stacking_order )
effects->postPaintWindow( w );
stacking_order.clear();
}
void Scene::windowGeometryShapeChanged( Toplevel* ) void Scene::windowGeometryShapeChanged( Toplevel* )
{ {
} }

View file

@ -29,8 +29,10 @@ class Scene
Scene( Workspace* ws ); Scene( Workspace* ws );
virtual ~Scene() = 0; virtual ~Scene() = 0;
class Window; class Window;
virtual void prePaint();
// repaints the given screen areas, windows provides the stacking order // repaints the given screen areas, windows provides the stacking order
virtual void paint( QRegion damage, ToplevelList windows ) = 0; virtual void paint( QRegion damage, ToplevelList windows ) = 0;
virtual void postPaint();
// shape/size of a window changed // shape/size of a window changed
virtual void windowGeometryShapeChanged( Toplevel* ); virtual void windowGeometryShapeChanged( Toplevel* );
// opacity of a window changed // opacity of a window changed
@ -84,7 +86,7 @@ class Scene::Window
int y() const; int y() const;
int width() const; int width() const;
int height() const; int height() const;
const Toplevel* window() const; Toplevel* window();
bool isVisible() const; bool isVisible() const;
bool isOpaque() const; bool isOpaque() const;
QRegion shape() const; QRegion shape() const;
@ -130,7 +132,7 @@ int Scene::Window::height() const
} }
inline inline
const Toplevel* Scene::Window::window() const Toplevel* Scene::Window::window()
{ {
return toplevel; return toplevel;
} }

View file

@ -279,7 +279,6 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
glTranslatef( 0, -displayHeight(), 0 ); glTranslatef( 0, -displayHeight(), 0 );
int mask = 0; int mask = 0;
paintScreen( &mask, &damage ); paintScreen( &mask, &damage );
stacking_order.clear();
glPopMatrix(); glPopMatrix();
// TODO only partial repaint for mask & PAINT_SCREEN_REGION // TODO only partial repaint for mask & PAINT_SCREEN_REGION
if( root_db ) if( root_db )
@ -292,7 +291,6 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
XFlush( display()); XFlush( display());
} }
ungrabXServer(); ungrabXServer();
checkGLError( "PostPaint" );
} }
void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data ) void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
@ -320,6 +318,12 @@ void SceneOpenGL::paintBackground( QRegion )
// TODO? // TODO?
} }
void SceneOpenGL::postPaint()
{
checkGLError( "PostPaint" );
Scene::postPaint();
}
void SceneOpenGL::windowAdded( Toplevel* c ) void SceneOpenGL::windowAdded( Toplevel* c )
{ {
assert( !windows.contains( c )); assert( !windows.contains( c ));

View file

@ -26,6 +26,7 @@ class SceneOpenGL
SceneOpenGL( Workspace* ws ); SceneOpenGL( Workspace* ws );
virtual ~SceneOpenGL(); virtual ~SceneOpenGL();
virtual void paint( QRegion damage, ToplevelList windows ); virtual void paint( QRegion damage, ToplevelList windows );
virtual void postPaint();
virtual void windowGeometryShapeChanged( Toplevel* ); virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* ); virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* ); virtual void windowAdded( Toplevel* );

View file

@ -86,7 +86,6 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
} }
int mask = 0; int mask = 0;
paintScreen( &mask, &damage ); paintScreen( &mask, &damage );
stacking_order.clear();
if( mask & PAINT_SCREEN_REGION ) if( mask & PAINT_SCREEN_REGION )
{ {
// Use the damage region as the clip region for the root window // Use the damage region as the clip region for the root window