Basic screen transformation.

svn path=/branches/work/kwin_composite/; revision=597815
This commit is contained in:
Luboš Luňák 2006-10-21 18:07:00 +00:00
parent 4f3ba33e72
commit 779597a648
8 changed files with 88 additions and 48 deletions

View file

@ -151,6 +151,7 @@ void GrowMove::windowUserMovedResized( Toplevel* c, bool first, bool last )
c->workspace()->addDamage( c->geometry());
}
}
#endif
ShiftWorkspaceUp::ShiftWorkspaceUp( Workspace* ws )
: up( false )
@ -160,13 +161,18 @@ ShiftWorkspaceUp::ShiftWorkspaceUp( Workspace* ws )
timer.start( 2000 );
}
void ShiftWorkspaceUp::transformWorkspace( Matrix& matrix, EffectData& )
void ShiftWorkspaceUp::prePaintScreen( int* mask, QRegion* region )
{
if( !up )
return;
Matrix m;
m.m[ 1 ][ 3 ] = -10;
matrix *= m;
if( up )
*mask |= Scene::PAINT_SCREEN_TRANSFORMED;
effects->nextPrePaintScreen( mask, region );
}
void ShiftWorkspaceUp::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( up )
data.yTranslate -= 10;
effects->nextPaintScreen( mask, region, data );
}
void ShiftWorkspaceUp::tick()
@ -175,12 +181,6 @@ void ShiftWorkspaceUp::tick()
wspace->addDamage( 0, 0, displayWidth(), displayHeight());
}
static MakeHalfTransparent* mht;
static ShakyMove* sm;
static GrowMove* gm;
static ShiftWorkspaceUp* swu;
#endif
//****************************************
// EffectsHandler
//****************************************
@ -194,9 +194,9 @@ EffectsHandler::EffectsHandler( Workspace* ws )
// effects.append( new MakeHalfTransparent );
// effects.append( new ShakyMove );
// effects.append( new GrowMove );
// effects.append( new ShiftWorkspaceUp( ws ));
effects.append( new ShiftWorkspaceUp( ws ));
}
EffectsHandler::~EffectsHandler()
{
foreach( Effect* e, effects )

View file

@ -116,6 +116,7 @@ class GrowMove
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
};
#endif
class ShiftWorkspaceUp
: public QObject, public Effect
@ -123,7 +124,8 @@ class ShiftWorkspaceUp
Q_OBJECT
public:
ShiftWorkspaceUp( Workspace* ws );
virtual void transformWorkspace( Matrix& m, EffectData& data );
virtual void prePaintScreen( int* mask, QRegion* region );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
private slots:
void tick();
private:
@ -131,7 +133,6 @@ class ShiftWorkspaceUp
bool up;
Workspace* wspace;
};
#endif
// a special effect that is last in the order that'll actually call the painting functions
// TODO this should actually be in scene.h

View file

@ -50,30 +50,30 @@ void Scene::WrapperEffect::prePaintScreen( int*, QRegion* )
void Scene::WrapperEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( mask & PAINT_SCREEN_REGION )
scene->paintSimpleScreen( region );
scene->paintSimpleScreen( mask, region );
else
scene->paintGenericScreen();
scene->paintGenericScreen( mask, data );
}
// the generic painting code that should eventually handle even
// transformations
void Scene::paintGenericScreen()
void Scene::paintGenericScreen( int mask, ScreenPaintData )
{
paintBackground( infiniteRegion());
foreach( Window* w, stacking_order ) // bottom to top
{
if( !w->isVisible())
continue;
paintWindow( w, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT, infiniteRegion());
paintWindow( w, mask | PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT, infiniteRegion());
}
}
// the optimized case without any transformations at all
void Scene::paintSimpleScreen( QRegion region )
void Scene::paintSimpleScreen( int mask, QRegion region )
{
assert(( mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED
| PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_OPAQUE )) == 0 );
QList< Phase2Data > phase2;
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
region = QRegion( 0, 0, displayWidth(), displayHeight());
// 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 = stacking_order.count() - 1; // top to bottom
@ -90,7 +90,7 @@ void Scene::paintSimpleScreen( QRegion region )
phase2.prepend( Phase2Data( w, region ));
continue;
}
paintWindow( w, PAINT_WINDOW_OPAQUE, region );
paintWindow( w, mask | PAINT_WINDOW_OPAQUE, region );
// window is opaque, clip windows below
region -= w->shape().translated( w->x(), w->y());
}
@ -102,7 +102,7 @@ void Scene::paintSimpleScreen( QRegion region )
foreach( Phase2Data d, phase2 )
{
Window* w = d.window;
paintWindow( w, PAINT_WINDOW_TRANSLUCENT, d.region );
paintWindow( w, mask | PAINT_WINDOW_TRANSLUCENT, d.region );
}
}

16
scene.h
View file

@ -37,19 +37,17 @@ class Scene
virtual void windowAdded( Toplevel* );
// a window has been destroyed
virtual void windowDeleted( Toplevel* );
protected:
enum
{
PAINT_WINDOW_OPAQUE = 1 << 0,
PAINT_WINDOW_TRANSLUCENT = 1 << 1
PAINT_WINDOW_TRANSLUCENT = 1 << 1,
PAINT_WINDOW_TRANSFORMED = 1 << 2,
PAINT_SCREEN_REGION = 1 << 3,
PAINT_SCREEN_TRANSFORMED = 1 << 4
};
enum
{
PAINT_SCREEN_REGION = 1 << 0,
PAINT_SCREEN_ALL = 1 << 1
};
virtual void paintGenericScreen();
virtual void paintSimpleScreen( QRegion region );
protected:
virtual void paintGenericScreen( int mask, ScreenPaintData data );
virtual void paintSimpleScreen( int mask, QRegion region );
virtual void paintBackground( QRegion region ) = 0;
virtual void paintWindow( Window* w, int mask, QRegion region );
static QRegion infiniteRegion();

View file

@ -278,10 +278,12 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
glScalef( 1, -1, 1 );
glTranslatef( 0, -displayHeight(), 0 );
int mask = ( damage == QRegion( 0, 0, displayWidth(), displayHeight()))
? PAINT_SCREEN_ALL : PAINT_SCREEN_REGION;
? 0 : PAINT_SCREEN_REGION;
WrapperEffect wrapper;
// preparation step
effects->prePaintScreen( &mask, &damage, &wrapper );
if( mask & ( PAINT_SCREEN_TRANSFORMED | PAINT_WINDOW_TRANSFORMED ))
mask &= ~PAINT_SCREEN_REGION;
// TODO call also prePaintWindow() for all windows
ScreenPaintData data;
effects->paintScreen( mask, damage, data, &wrapper );
@ -301,12 +303,24 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
checkGLError( "PostPaint" );
}
void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data )
{
if( mask & PAINT_SCREEN_TRANSFORMED )
{
glPushMatrix();
glTranslatef( data.xTranslate, data.yTranslate, 0 );
}
Scene::paintGenericScreen( mask, data );
if( mask & PAINT_SCREEN_TRANSFORMED )
glPopMatrix();
}
// the optimized case without any transformations at all
void SceneOpenGL::paintSimpleScreen( QRegion region )
void SceneOpenGL::paintSimpleScreen( int mask, QRegion region )
{
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
region = QRegion( 0, 0, displayWidth(), displayHeight());
Scene::paintSimpleScreen( region );
Scene::paintSimpleScreen( mask, region );
}
void SceneOpenGL::paintBackground( QRegion )

View file

@ -31,7 +31,8 @@ class SceneOpenGL
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
protected:
virtual void paintSimpleScreen( QRegion region );
virtual void paintGenericScreen( int mask, ScreenPaintData data );
virtual void paintSimpleScreen( int mask, QRegion region );
virtual void paintBackground( QRegion region );
private:
void initBuffer();

View file

@ -50,6 +50,7 @@ kdbgstream& operator<<( kdbgstream& stream, RegionDebug r )
#endif
Picture SceneXrender::buffer;
ScreenPaintData SceneXrender::screen_paint;
SceneXrender::SceneXrender( Workspace* ws )
: Scene( ws )
@ -84,10 +85,12 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
stacking_order.append( &windows[ c ] );
}
int mask = ( damage == QRegion( 0, 0, displayWidth(), displayHeight()))
? PAINT_SCREEN_ALL : PAINT_SCREEN_REGION;
? 0 : PAINT_SCREEN_REGION;
WrapperEffect wrapper;
// preparation step
effects->prePaintScreen( &mask, &damage, &wrapper );
if( mask & ( PAINT_SCREEN_TRANSFORMED | PAINT_WINDOW_TRANSFORMED ))
mask &= ~PAINT_SCREEN_REGION;
// TODO call also prePaintWindow() for all windows
ScreenPaintData data;
effects->paintScreen( mask, damage, data, &wrapper );
@ -101,6 +104,7 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
// 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());
XFixesSetPictureClipRegion( display(), front, 0, 0, None );
XFlush( display());
}
else
@ -111,13 +115,23 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
}
}
void SceneXrender::paintGenericScreen( int mask, ScreenPaintData data )
{
screen_paint = data; // save, transformations will be done when painting windows
Scene::paintGenericScreen( mask, data );
}
void SceneXrender::paintBackground( QRegion region )
{
XserverRegion background_region = toXserverRegion( region );
XFixesSetPictureClipRegion( display(), buffer, 0, 0, background_region );
XFixesDestroyRegion( display(), background_region );
if( region != infiniteRegion())
{
XserverRegion background_region = toXserverRegion( region );
XFixesSetPictureClipRegion( display(), buffer, 0, 0, background_region );
XFixesDestroyRegion( display(), background_region );
}
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
}
void SceneXrender::windowGeometryShapeChanged( Toplevel* c )
@ -307,22 +321,32 @@ void SceneXrender::Window::performPaint( QRegion region, int mask )
if( isOpaque())
return;
}
XserverRegion clip_region = toXserverRegion( region );
XFixesSetPictureClipRegion( display(), buffer, 0, 0, clip_region );
XFixesDestroyRegion( display(), clip_region );
if( region != infiniteRegion())
{
XserverRegion clip_region = toXserverRegion( region );
XFixesSetPictureClipRegion( display(), buffer, 0, 0, clip_region );
XFixesDestroyRegion( display(), clip_region );
}
Picture pic = picture();
if( pic == None ) // The render format can be null for GL and/or Xv visuals
return;
int x = toplevel->x();
int y = toplevel->y();
if( mask & PAINT_SCREEN_TRANSFORMED )
{
x += screen_paint.xTranslate;
y += screen_paint.yTranslate;
}
if( isOpaque())
{
XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0,
toplevel->x(), toplevel->y(), toplevel->width(), toplevel->height());
x, y, toplevel->width(), toplevel->height());
}
else
{
Picture alpha = alphaMask();
XRenderComposite( display(), PictOpOver, pic, alpha, buffer, 0, 0, 0, 0,
toplevel->x(), toplevel->y(), toplevel->width(), toplevel->height());
x, y, toplevel->width(), toplevel->height());
}
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
}

View file

@ -36,12 +36,14 @@ class SceneXrender
virtual void windowDeleted( Toplevel* );
protected:
virtual void paintBackground( QRegion region );
virtual void paintGenericScreen( int mask, ScreenPaintData data );
private:
void createBuffer();
static XserverRegion toXserverRegion( QRegion region );
XRenderPictFormat* format;
Picture front;
static Picture buffer;
static ScreenPaintData screen_paint;
class Window;
QMap< Toplevel*, Window > windows;
};