Ok, I give up, whoever wants more complicated transformations than just

translation are welcome to implement it themselves. I'm no graphics guy
after all and this seems to be far beyond me.


svn path=/branches/work/kwin_composite/; revision=559182
This commit is contained in:
Luboš Luňák 2006-07-06 18:22:01 +00:00
parent 3da31a53af
commit e6c23e4cd3
9 changed files with 191 additions and 100 deletions

View file

@ -165,8 +165,7 @@ 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 );
} }
scene->setWindows( windows ); scene->paint( damage, windows );
scene->paint( damage );
XFixesDestroyRegion( display(), damage ); XFixesDestroyRegion( display(), damage );
damage = None; damage = None;
} }

View file

@ -132,11 +132,11 @@ void Effect::windowUserMovedResized( Toplevel* , bool, bool )
{ {
} }
void Effect::transformWindow( Toplevel*, EffectData& ) void Effect::transformWindow( Toplevel*, Matrix&, EffectData& )
{ {
} }
void Effect::transformWorkspace( Workspace*, EffectData& ) void Effect::transformWorkspace( Workspace*, Matrix&, EffectData& )
{ {
} }
@ -144,7 +144,7 @@ void Effect::windowDeleted( Toplevel* )
{ {
} }
void MakeHalfTransparent::transformWindow( Toplevel* c, EffectData& data ) void MakeHalfTransparent::transformWindow( Toplevel* c, Matrix&, EffectData& data )
{ {
if( c->isDialog()) if( c->isDialog())
data.opacity *= 0.8; data.opacity *= 0.8;
@ -167,13 +167,13 @@ ShakyMove::ShakyMove()
static const int shaky_diff[] = { 0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1 }; static const int shaky_diff[] = { 0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1 };
static const int SHAKY_MAX = sizeof( shaky_diff ) / sizeof( shaky_diff[ 0 ] ); static const int SHAKY_MAX = sizeof( shaky_diff ) / sizeof( shaky_diff[ 0 ] );
void ShakyMove::transformWindow( Toplevel* c, EffectData& data ) void ShakyMove::transformWindow( Toplevel* c, Matrix& matrix, EffectData& )
{ {
if( windows.contains( c )) if( windows.contains( c ))
{ {
Matrix m; Matrix m;
m.m[ 0 ][ 3 ] = shaky_diff[ windows[ c ]]; m.m[ 0 ][ 3 ] = shaky_diff[ windows[ c ]];
data.matrix *= m; matrix *= m;
} }
} }
@ -217,8 +217,31 @@ void ShakyMove::tick()
} }
} }
void GrowMove::transformWindow( Toplevel* c, Matrix& matrix, EffectData& )
{
if( Client* c2 = dynamic_cast< Client* >( c ))
if( c2->isMove())
{
Matrix m;
m.m[ 0 ][ 0 ] = 1.2;
m.m[ 1 ][ 1 ] = 1.4;
matrix *= m;
}
}
void GrowMove::windowUserMovedResized( Toplevel* c, bool first, bool last )
{
if( first || last )
{
c->workspace()->addDamage( c, c->geometry());
scene->updateTransformation( c );
c->workspace()->addDamage( c, c->geometry());
}
}
static MakeHalfTransparent* mht; static MakeHalfTransparent* mht;
static ShakyMove* sm; static ShakyMove* sm;
static GrowMove* gm;
//**************************************** //****************************************
// EffectsHandler // EffectsHandler
@ -228,6 +251,7 @@ EffectsHandler::EffectsHandler()
{ {
mht = new MakeHalfTransparent; mht = new MakeHalfTransparent;
sm = new ShakyMove; sm = new ShakyMove;
// gm = new GrowMove;
} }
void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last ) void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last )
@ -236,22 +260,28 @@ void EffectsHandler::windowUserMovedResized( Toplevel* c, bool first, bool last
mht->windowUserMovedResized( c, first, last ); mht->windowUserMovedResized( c, first, last );
if( sm ) if( sm )
sm->windowUserMovedResized( c, first, last ); sm->windowUserMovedResized( c, first, last );
if( gm )
gm->windowUserMovedResized( c, first, last );
} }
void EffectsHandler::transformWindow( Toplevel* c, EffectData& data ) void EffectsHandler::transformWindow( Toplevel* c, Matrix& matrix, EffectData& data )
{ {
if( mht ) if( mht )
mht->transformWindow( c, data ); mht->transformWindow( c, matrix, data );
if( sm ) if( sm )
sm->transformWindow( c, data ); sm->transformWindow( c, matrix, data );
if( gm )
gm->transformWindow( c, matrix, data );
} }
void EffectsHandler::transformWorkspace( Workspace* w, EffectData& data ) void EffectsHandler::transformWorkspace( Workspace* w, Matrix& matrix, EffectData& data )
{ {
if( mht ) if( mht )
mht->transformWorkspace( w, data ); mht->transformWorkspace( w, matrix, data );
if( sm ) if( sm )
sm->transformWorkspace( w, data ); sm->transformWorkspace( w, matrix, data );
if( gm )
gm->transformWorkspace( w, matrix, data );
} }
void EffectsHandler::windowDeleted( Toplevel* c ) void EffectsHandler::windowDeleted( Toplevel* c )
@ -260,6 +290,8 @@ void EffectsHandler::windowDeleted( Toplevel* c )
mht->windowDeleted( c ); mht->windowDeleted( c );
if( sm ) if( sm )
sm->windowDeleted( c ); sm->windowDeleted( c );
if( gm )
gm->windowDeleted( c );
} }
EffectsHandler* effects; EffectsHandler* effects;

View file

@ -62,7 +62,6 @@ inline double Matrix::zTranslate() const
class EffectData class EffectData
{ {
public: public:
Matrix matrix;
double opacity; double opacity;
}; };
@ -73,8 +72,8 @@ class Effect
// 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 windowDeleted( Toplevel* c ); virtual void windowDeleted( Toplevel* c );
virtual void transformWindow( Toplevel* c, EffectData& data ); virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
virtual void transformWorkspace( Workspace*, EffectData& data ); virtual void transformWorkspace( Workspace*, Matrix& m, EffectData& data );
}; };
class EffectsHandler class EffectsHandler
@ -83,8 +82,8 @@ class EffectsHandler
EffectsHandler(); EffectsHandler();
void windowUserMovedResized( Toplevel* c, bool first, bool last ); void windowUserMovedResized( Toplevel* c, bool first, bool last );
void windowDeleted( Toplevel* c ); void windowDeleted( Toplevel* c );
void transformWindow( Toplevel* c, EffectData& data ); void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
void transformWorkspace( Workspace*, EffectData& data ); void transformWorkspace( Workspace*, Matrix& m, EffectData& data );
}; };
extern EffectsHandler* effects; extern EffectsHandler* effects;
@ -94,7 +93,7 @@ class MakeHalfTransparent
{ {
public: public:
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last ); virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void transformWindow( Toplevel* c, EffectData& data ); virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
}; };
class ShakyMove class ShakyMove
@ -104,7 +103,7 @@ class ShakyMove
public: public:
ShakyMove(); ShakyMove();
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last ); virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void transformWindow( Toplevel* c, EffectData& data ); virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
virtual void windowDeleted( Toplevel* c ); virtual void windowDeleted( Toplevel* c );
private slots: private slots:
void tick(); void tick();
@ -113,6 +112,13 @@ class ShakyMove
QTimer timer; QTimer timer;
}; };
class GrowMove
: public Effect
{
public:
virtual void windowUserMovedResized( Toplevel* c, bool first, bool last );
virtual void transformWindow( Toplevel* c, Matrix& m, EffectData& data );
};
} // namespace } // namespace

View file

@ -26,11 +26,6 @@ Scene::~Scene()
{ {
} }
void Scene::setWindows( const ToplevelList& list )
{
windows = list;
}
void Scene::windowGeometryShapeChanged( Toplevel* ) void Scene::windowGeometryShapeChanged( Toplevel* )
{ {
} }

View file

@ -23,8 +23,7 @@ class Scene
public: public:
Scene( Workspace* ws ); Scene( Workspace* ws );
virtual ~Scene(); virtual ~Scene();
void setWindows( const ToplevelList& list ); virtual void paint( XserverRegion damage, ToplevelList windows ) = 0;
virtual void paint( XserverRegion damage ) = 0;
virtual void windowGeometryShapeChanged( Toplevel* ); virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* ); virtual void windowOpacityChanged( Toplevel* );
virtual void windowDeleted( Toplevel* ); virtual void windowDeleted( Toplevel* );
@ -32,7 +31,6 @@ class Scene
virtual void updateTransformation( Toplevel* ); virtual void updateTransformation( Toplevel* );
protected: protected:
Workspace* wspace; Workspace* wspace;
ToplevelList windows;
}; };
extern Scene* scene; extern Scene* scene;

View file

@ -29,7 +29,7 @@ SceneBasic::~SceneBasic()
{ {
} }
void SceneBasic::paint( XserverRegion ) void SceneBasic::paint( XserverRegion, ToplevelList windows )
{ {
Pixmap composite_pixmap = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(), QX11Info::appDepth()); Pixmap composite_pixmap = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(), QX11Info::appDepth());
XGCValues val; XGCValues val;

View file

@ -22,7 +22,7 @@ class SceneBasic
public: public:
SceneBasic( Workspace* ws ); SceneBasic( Workspace* ws );
virtual ~SceneBasic(); virtual ~SceneBasic();
virtual void paint( XserverRegion damage ); virtual void paint( XserverRegion damage, ToplevelList windows );
}; };
} // namespace } // namespace

View file

@ -42,9 +42,9 @@ SceneXrender::~SceneXrender()
(*it).free(); (*it).free();
} }
void SceneXrender::paint( XserverRegion damage ) void SceneXrender::paint( XserverRegion damage, ToplevelList windows )
{ {
#if 0 #if 1
XRectangle r; XRectangle r;
r.x = 0; r.x = 0;
r.y = 0; r.y = 0;
@ -54,8 +54,38 @@ void SceneXrender::paint( XserverRegion damage )
#endif #endif
// Use the damage region as the clip region for the root window // Use the damage region as the clip region for the root window
XFixesSetPictureClipRegion( display(), front, 0, 0, damage ); XFixesSetPictureClipRegion( display(), front, 0, 0, damage );
// Client list for clients that are either translucent or have a shadow // Prepare pass for windows
ToplevelList translucents; // Go top to bottom so that clipping is computed properly for phase1
for( int i = windows.count() - 1;
i >= 0;
--i )
{
Toplevel* c = windows[ i ];
resetWindowData( c );
WindowData& data = window_data[ c ];
Picture picture = windowPicture( c );
if( picture == None ) // The render format can be null for GL and/or Xv visuals
{
windows.removeAt( i );
continue;
}
effects->transformWindow( c, data.matrix, data.effect ); // TODO remove, instead add initWindow() to effects
saveWindowClipRegion( c, damage );
if( data.simpleTransformation() && isOpaque( c ))
{ // is opaque, has simple shape, can be clipped, will be painted using simpler faster method
// Subtract the clients shape from the damage region
XserverRegion shape = windowShape( c );
assert( shape != None );
XFixesSubtractRegion( display(), damage, damage, shape );
data.phase = 1;
}
else
data.phase = 2; // will be painted later bottom to top
}
// Fill any areas of the root window not covered by windows
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
// Draw each opaque window top to bottom, subtracting the bounding rect of // Draw each opaque window top to bottom, subtracting the bounding rect of
// each window from the clip region after it's been drawn. // each window from the clip region after it's been drawn.
for( int i = windows.count() - 1; for( int i = windows.count() - 1;
@ -63,59 +93,50 @@ void SceneXrender::paint( XserverRegion damage )
--i ) --i )
{ {
Toplevel* c = windows[ i ]; Toplevel* c = windows[ i ];
checkWindowData( c );
WindowData& data = window_data[ c ]; WindowData& data = window_data[ c ];
effects->transformWindow( c, data.effect ); // TODO remove, instead add initWindow() to effects if( data.phase != 1 )
if( isOpaque( c )) continue;
{ XFixesSetPictureClipRegion( display(), buffer, 0, 0, savedWindowClipRegion( c ));
Picture picture = windowPicture( c ); Picture picture = windowPicture( c );
XserverRegion shape = windowShape( c );
if( picture != None && shape != None )
{
// 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 );
const Matrix& matrix = data.effect.matrix;
if( !matrix.isIdentity())
{
assert( matrix.isOnlyTranslate());
XFixesTranslateRegion( display(), shape, int( matrix.xTranslate()), int( matrix.yTranslate()));
}
XFixesSubtractRegion( display(), damage, damage, shape );
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0, XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
c->x() + int( matrix.xTranslate()), c->y() + int( matrix.yTranslate()), c->width(), c->height()); c->x() + int( data.matrix.xTranslate()), c->y() + int( data.matrix.yTranslate()), c->width(), c->height());
} }
} // Now walk the list bottom to top, drawing translucent and complicated windows.
saveWindowClipRegion( c, damage ); // That we draw bottom to top is important now since we're drawing translucent objects
translucents.prepend( c ); // and also are clipping only by opaque windows.
}
// Fill any areas of the root window not covered by windows
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
// Now walk the list bottom to top, drawing translucent windows and shadows.
// That we draw bottom to top is important now since we're drawing translucent objects.
for( int i = 0; for( int i = 0;
i < translucents.count(); i < windows.count();
++i ) ++i )
{ {
Toplevel* c = translucents[ i ]; Toplevel* c = windows[ i ];
// Restore the previously saved clip region WindowData& data = window_data[ c ];
XserverRegion r = savedWindowClipRegion( c ); if( data.phase != 2 && false)
XFixesSetPictureClipRegion( display(), buffer, 0, 0, r ); continue;
if( !isOpaque( c )) XFixesSetPictureClipRegion( display(), buffer, 0, 0, savedWindowClipRegion( c ));
{
Picture picture = windowPicture( c ); Picture picture = windowPicture( c );
Picture alpha = windowAlphaMask( c ); Picture alpha = windowAlphaMask( c );
if( picture != None ) if( data.simpleTransformation())
{ {
const Matrix& matrix = window_data[ c ].effect.matrix;
// TODO clip also using shape? also above?
XRenderComposite( display(), PictOpOver, picture, alpha, buffer, 0, 0, 0, 0, XRenderComposite( display(), PictOpOver, picture, alpha, buffer, 0, 0, 0, 0,
c->x() + int( matrix.xTranslate()), c->y() + int( matrix.yTranslate()), c->width(), c->height()); c->x() + int( data.matrix.xTranslate()), c->y() + int( data.matrix.yTranslate()), c->width(), c->height());
}
else
{
// TODO Okay, I'm at loss here. Whoever wants advanced transformations can implement
// it themselves. If not, they actually don't want it that badly *shrug*.
// setPictureMatrix( picture, data.matrix );
XRenderComposite( display(), PictOpSrc, picture, alpha, buffer, 0, 0, 0, 0,
c->x(), c->y(), c->width(), c->height());
// setPictureMatrix( picture, Matrix());
} }
} }
XFixesDestroyRegion( display(), r ); // cleanup
for( int i = 0;
i < windows.count();
++i )
{
Toplevel* c = windows[ i ];
cleanup( c );
} }
// copy composed buffer to the root window // copy composed buffer to the root window
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None ); XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
@ -127,24 +148,33 @@ void SceneXrender::transformWindowDamage( Toplevel* c, XserverRegion r ) const
{ {
if( !window_data.contains( c )) if( !window_data.contains( c ))
return; return;
const Matrix& matrix = window_data[ c ].effect.matrix; const Matrix& matrix = window_data[ c ].matrix;
if( matrix.isIdentity()) if( matrix.isIdentity())
return; return;
assert( matrix.isOnlyTranslate()); if( matrix.isOnlyTranslate())
// TODO the matrix here is not valid after it changes but before it's first painted
// (i.e. a changes to state where it should be translated but the matrix is not yet updated)
XFixesTranslateRegion( display(), r, int( matrix.xTranslate()), int( matrix.yTranslate())); XFixesTranslateRegion( display(), r, int( matrix.xTranslate()), int( matrix.yTranslate()));
else
{
// The region here should be translated using the matrix, but that's not possible
// (well, maybe fetch the region and transform manually - TODO check). So simply
// mark whole screen as damaged.
XRectangle s;
s.x = s.y = 0;
s.width = displayWidth();
s.height = displayHeight();
XFixesSetRegion( display(), r, &s, 1 );
}
} }
void SceneXrender::updateTransformation( Toplevel* c ) void SceneXrender::updateTransformation( Toplevel* c )
{ {
// TODO maybe only mark as invalid and update on-demand // TODO maybe only mark as invalid and update on-demand
checkWindowData( c ); resetWindowData( c );
WindowData& data = window_data[ c ]; WindowData& data = window_data[ c ];
effects->transformWindow( c, data.effect ); effects->transformWindow( c, data.matrix, data.effect );
} }
void SceneXrender::checkWindowData( Toplevel* c ) void SceneXrender::resetWindowData( Toplevel* c )
{ {
if( !window_data.contains( c )) if( !window_data.contains( c ))
{ {
@ -152,7 +182,7 @@ void SceneXrender::checkWindowData( Toplevel* c )
window_data[ c ].format = XRenderFindVisualFormat( display(), c->visual()); window_data[ c ].format = XRenderFindVisualFormat( display(), c->visual());
} }
WindowData& data = window_data[ c ]; WindowData& data = window_data[ c ];
data.effect.matrix = Matrix(); data.matrix = Matrix();
data.effect.opacity = c->opacity(); data.effect.opacity = c->opacity();
} }
@ -206,11 +236,15 @@ void SceneXrender::saveWindowClipRegion( Toplevel* c, XserverRegion r )
} }
XserverRegion SceneXrender::savedWindowClipRegion( Toplevel* c ) XserverRegion SceneXrender::savedWindowClipRegion( Toplevel* c )
{ // always called after saveWindowClipRegion(), also resets {
return window_data[ c ].saved_clip_region;
}
void SceneXrender::cleanup( Toplevel* c )
{
WindowData& data = window_data[ c ]; WindowData& data = window_data[ c ];
XserverRegion r = data.saved_clip_region; XFixesDestroyRegion( display(), data.saved_clip_region );
data.saved_clip_region = None; data.saved_clip_region = None;
return r;
} }
bool SceneXrender::isOpaque( Toplevel* c ) const bool SceneXrender::isOpaque( Toplevel* c ) const
@ -249,10 +283,11 @@ Picture SceneXrender::windowAlphaMask( Toplevel* c )
return data.alpha; return data.alpha;
} }
XserverRegion SceneXrender::windowShape( Toplevel* c ) XserverRegion SceneXrender::windowShape( Toplevel* c )
{ {
#if 0 // it probably doesn't make sense to cache this, and perhaps some others - they aren't roundtrips
WindowData& data = window_data[ c ]; WindowData& data = window_data[ c ];
#if 0 // it probably doesn't make sense to cache this, and perhaps some others - they aren't roundtrips
if( data.shape == None ) if( data.shape == None )
{ {
data.shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding ); data.shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
@ -260,8 +295,15 @@ XserverRegion SceneXrender::windowShape( Toplevel* c )
} }
return data.shape; return data.shape;
#else #else
if( !data.simpleTransformation())
{
// The region here should be translated using the matrix, but that's not possible
// (well, maybe fetch the region and transform manually - TODO check).
return None;
}
XserverRegion shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding ); XserverRegion shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
XFixesTranslateRegion( display(), shape, c->x(), c->y()); XFixesTranslateRegion( display(), shape,
c->x() + int( data.matrix.xTranslate()), c->y() + int( data.matrix.yTranslate()));
return shape; return shape;
#endif #endif
} }
@ -281,19 +323,28 @@ void SceneXrender::setPictureMatrix( Picture pic, const Matrix& m )
{ {
if( pic == None ) if( pic == None )
return; return;
#if 0
XTransform t; XTransform t;
// ignore z axis // ignore z axis
t.matrix[ 0 ][ 0 ] = XDoubleToFixed( m.m[ 0 ][ 0 ] ); t.matrix[ 0 ][ 0 ] = XDoubleToFixed( 1 / m.m[ 0 ][ 0 ] );
t.matrix[ 0 ][ 1 ] = XDoubleToFixed( m.m[ 0 ][ 1 ] ); t.matrix[ 0 ][ 1 ] = XDoubleToFixed( m.m[ 0 ][ 1 ] );
t.matrix[ 0 ][ 2 ] = -XDoubleToFixed( m.m[ 0 ][ 3 ] ); // translation seems to be inverted t.matrix[ 0 ][ 2 ] = -XDoubleToFixed( m.m[ 0 ][ 3 ] ); // translation seems to be inverted
t.matrix[ 1 ][ 0 ] = XDoubleToFixed( m.m[ 1 ][ 0 ] ); t.matrix[ 1 ][ 0 ] = XDoubleToFixed( m.m[ 1 ][ 0 ] );
t.matrix[ 1 ][ 1 ] = XDoubleToFixed( m.m[ 1 ][ 1 ] ); t.matrix[ 1 ][ 1 ] = XDoubleToFixed( 1 / m.m[ 1 ][ 1 ] );
t.matrix[ 1 ][ 2 ] = -XDoubleToFixed( m.m[ 1 ][ 3 ] ); t.matrix[ 1 ][ 2 ] = -XDoubleToFixed( m.m[ 1 ][ 3 ] );
t.matrix[ 2 ][ 0 ] = XDoubleToFixed( m.m[ 3 ][ 0 ] ); t.matrix[ 2 ][ 0 ] = XDoubleToFixed( m.m[ 3 ][ 0 ] );
t.matrix[ 2 ][ 1 ] = XDoubleToFixed( m.m[ 3 ][ 1 ] ); t.matrix[ 2 ][ 1 ] = XDoubleToFixed( m.m[ 3 ][ 1 ] );
t.matrix[ 2 ][ 2 ] = XDoubleToFixed( m.m[ 3 ][ 3 ] ); t.matrix[ 2 ][ 2 ] = XDoubleToFixed( m.m[ 3 ][ 3 ] );
// and scaling seems to be wrong too
// or maybe I just don't get it, but anyway, for now
if( m.m[ 3 ][ 3 ] != 1 )
{
t.matrix[ 0 ][ 0 ] = XDoubleToFixed( 1 / m.m[ 0 ][ 0 ] * m.m[ 3 ][ 3 ] );
t.matrix[ 1 ][ 1 ] = XDoubleToFixed( 1 / m.m[ 1 ][ 1 ] * m.m[ 3 ][ 3 ] );
t.matrix[ 2 ][ 2 ] = XDoubleToFixed( 1 );
}
XRenderSetPictureTransform( display(), pic, &t ); XRenderSetPictureTransform( display(), pic, &t );
if( t.matrix[ 0 ][ 0 ] != XDoubleToFixed( 1 ) // fast filter for identity or translation if( t.matrix[ 0 ][ 0 ] != XDoubleToFixed( 1 )
|| t.matrix[ 1 ][ 1 ] != XDoubleToFixed( 1 ) || t.matrix[ 1 ][ 1 ] != XDoubleToFixed( 1 )
|| t.matrix[ 2 ][ 2 ] != XDoubleToFixed( 1 ) || t.matrix[ 2 ][ 2 ] != XDoubleToFixed( 1 )
|| t.matrix[ 0 ][ 1 ] != XDoubleToFixed( 0 ) || t.matrix[ 0 ][ 1 ] != XDoubleToFixed( 0 )
@ -301,10 +352,11 @@ void SceneXrender::setPictureMatrix( Picture pic, const Matrix& m )
{ {
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterGood ), 0, 0 ); XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterGood ), 0, 0 );
} }
else else // fast filter for identity or translation
{ {
XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterFast ), 0, 0 ); XRenderSetPictureFilter( display(), pic, const_cast< char* >( FilterFast ), 0, 0 );
} }
#endif
} }
SceneXrender::WindowData::WindowData() SceneXrender::WindowData::WindowData()
@ -326,5 +378,10 @@ void SceneXrender::WindowData::free()
XRenderFreePicture( display(), shape ); XRenderFreePicture( display(), shape );
} }
bool SceneXrender::WindowData::simpleTransformation() const
{
return ( matrix.isIdentity() || matrix.isOnlyTranslate());
}
} // namespace } // namespace
#endif #endif

View file

@ -30,7 +30,7 @@ class SceneXrender
public: public:
SceneXrender( Workspace* ws ); SceneXrender( Workspace* ws );
virtual ~SceneXrender(); virtual ~SceneXrender();
virtual void paint( XserverRegion damage ); virtual void paint( XserverRegion damage, ToplevelList windows );
virtual void windowGeometryShapeChanged( Toplevel* ); virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* ); virtual void windowOpacityChanged( Toplevel* );
virtual void windowDeleted( Toplevel* ); virtual void windowDeleted( Toplevel* );
@ -38,7 +38,7 @@ class SceneXrender
virtual void updateTransformation( Toplevel* ); virtual void updateTransformation( Toplevel* );
private: private:
void createBuffer(); void createBuffer();
void checkWindowData( Toplevel* c ); void resetWindowData( Toplevel* c );
Picture windowPicture( Toplevel* c ); Picture windowPicture( Toplevel* c );
void saveWindowClipRegion( Toplevel* c, XserverRegion r ); void saveWindowClipRegion( Toplevel* c, XserverRegion r );
XserverRegion savedWindowClipRegion( Toplevel* c ); XserverRegion savedWindowClipRegion( Toplevel* c );
@ -46,6 +46,7 @@ class SceneXrender
Picture windowAlphaMask( Toplevel* c ); Picture windowAlphaMask( Toplevel* c );
XserverRegion windowShape( Toplevel* c ); XserverRegion windowShape( Toplevel* c );
static void setPictureMatrix( Picture pic, const Matrix& m ); static void setPictureMatrix( Picture pic, const Matrix& m );
void cleanup( Toplevel* c );
XRenderPictFormat* format; XRenderPictFormat* format;
Picture front; Picture front;
Picture buffer; Picture buffer;
@ -53,13 +54,16 @@ class SceneXrender
{ {
WindowData(); WindowData();
void free(); void free();
bool simpleTransformation() const;
Picture picture; Picture picture;
XRenderPictFormat* format; XRenderPictFormat* format;
XserverRegion saved_clip_region; XserverRegion saved_clip_region;
Picture alpha; Picture alpha;
double alpha_cached_opacity; double alpha_cached_opacity;
XserverRegion shape; XserverRegion shape;
Matrix matrix;
EffectData effect; EffectData effect;
int phase;
}; };
QMap< Toplevel*, WindowData > window_data; QMap< Toplevel*, WindowData > window_data;
}; };