Vertex redesign - redo the way windows are split into smaller parts

for use in effects (and not only). Now a list of window quads (=window areas)
is created at the beginning of the paint pass, prepaint calls can modify
the split itself (i.e. divide it into more parts). The actual paint calls
can then modify these quads (i.e. transform their geometry). This will allow
better control of how the split is done and also allow painting e.g. only
the decoration differently. Still work in progress, but it works.
Also pass data to prepaint functions in a struct, as there is
already quite a number of them.


svn path=/trunk/KDE/kdebase/workspace/; revision=684893
This commit is contained in:
Luboš Luňák 2007-07-07 14:01:32 +00:00
parent d265b34760
commit 5faa397849
65 changed files with 715 additions and 494 deletions

View file

@ -96,7 +96,7 @@ KDE 4.0 TODO
- correct ordering for effects [rivo]
would be nice if isn't too strict
- vertex redesign [Seli]
/ vertex redesign [Seli]
affects alpha clear hack
- support applying opacity only to decoration
- not using ARGB visuals
@ -234,7 +234,7 @@ OpenGL TODO
% with current nvidia glXCreatePixmap in tfp mode fails with pixmaps 32x32 and smaller
+ vertices list (and possibly more things) should not be part of SceneOpenGL::Window
/ vertices list (and possibly more things) should not be part of SceneOpenGL::Window
- otherwise drawWindow() used for thumbnails would use them too
- they should be probably part of WindowPaintData

View file

@ -74,11 +74,11 @@ void EffectsHandlerImpl::reconfigure()
}
// the idea is that effects call this function again which calls the next one
void EffectsHandlerImpl::prePaintScreen( int* mask, QRegion* region, int time )
void EffectsHandlerImpl::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( current_paint_screen < loaded_effects.size())
{
loaded_effects[current_paint_screen++].second->prePaintScreen( mask, region, time );
loaded_effects[current_paint_screen++].second->prePaintScreen( data, time );
--current_paint_screen;
}
// no special final code
@ -105,11 +105,11 @@ void EffectsHandlerImpl::postPaintScreen()
// no special final code
}
void EffectsHandlerImpl::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void EffectsHandlerImpl::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( current_paint_window < loaded_effects.size())
{
loaded_effects[current_paint_window++].second->prePaintWindow( w, mask, paint, clip, time );
loaded_effects[current_paint_window++].second->prePaintWindow( w, data, time );
--current_paint_window;
}
// no special final code
@ -1057,33 +1057,6 @@ EffectWindowList EffectWindowImpl::mainWindows() const
return EffectWindowList();
}
QVector<Vertex>& EffectWindowImpl::vertices()
{
#ifdef HAVE_OPENGL
if( SceneOpenGL::Window* w = dynamic_cast< SceneOpenGL::Window* >( sceneWindow()))
return w->vertices();
#endif
abort(); // TODO
}
void EffectWindowImpl::requestVertexGrid(int maxquadsize)
{
#ifdef HAVE_OPENGL
if( SceneOpenGL::Window* w = dynamic_cast< SceneOpenGL::Window* >( sceneWindow()))
return w->requestVertexGrid( maxquadsize );
#endif
abort(); // TODO
}
void EffectWindowImpl::markVerticesDirty()
{
#ifdef HAVE_OPENGL
if( SceneOpenGL::Window* w = dynamic_cast< SceneOpenGL::Window* >( sceneWindow()))
return w->markVerticesDirty();
#endif
abort(); // TODO
}
void EffectWindowImpl::setShader(GLShader* shader)
{
#ifdef HAVE_OPENGL

View file

@ -30,10 +30,10 @@ class EffectsHandlerImpl : public EffectsHandler
public:
EffectsHandlerImpl(CompositingType type);
virtual ~EffectsHandlerImpl();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
@ -189,9 +189,6 @@ class EffectWindowImpl : public EffectWindow
virtual EffectWindow* findModal();
virtual EffectWindowList mainWindows() const;
virtual QVector<Vertex>& vertices();
virtual void requestVertexGrid(int maxquadsize);
virtual void markVerticesDirty();
virtual void setShader(GLShader* shader);
const Toplevel* window() const;

View file

@ -132,19 +132,19 @@ bool BlurEffect::supported()
}
void BlurEffect::prePaintScreen( int* mask, QRegion* region, int time )
void BlurEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
mTransparentWindows = 0;
mTime += time;
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void BlurEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void BlurEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
if( w->isPaintingEnabled() && ( *mask & PAINT_WINDOW_TRANSLUCENT ))
if( w->isPaintingEnabled() && ( data.mask & PAINT_WINDOW_TRANSLUCENT ))
mTransparentWindows++;
}

View file

@ -33,9 +33,9 @@ class BlurEffect : public Effect
BlurEffect();
~BlurEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
static bool supported();

View file

@ -43,12 +43,12 @@ BoxSwitchEffect::~BoxSwitchEffect()
{
}
void BoxSwitchEffect::prePaintScreen( int* mask, QRegion* region, int time )
void BoxSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
effects->prePaintScreen( mask, region, time );
effects->prePaintScreen( data, time );
}
void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void BoxSwitchEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( mActivated )
{
@ -56,8 +56,8 @@ void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint
{
if( windows.contains( w ) && w != selected_window )
{
*mask |= PAINT_WINDOW_TRANSLUCENT;
*mask &= ~PAINT_WINDOW_OPAQUE;
data.mask |= PAINT_WINDOW_TRANSLUCENT;
data.mask &= ~PAINT_WINDOW_OPAQUE;
}
}
else
@ -71,7 +71,7 @@ void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint
}
}
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -35,9 +35,9 @@ class BoxSwitchEffect
BoxSwitchEffect();
~BoxSwitchEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowInputMouseEvent( Window w, QEvent* e );

View file

@ -95,17 +95,17 @@ bool LiquidEffect::supported()
}
void LiquidEffect::prePaintScreen( int* mask, QRegion* region, int time )
void LiquidEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
mTime += time / 1000.0f;
if(mValid)
{
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
// Start rendering to texture
effects->pushRenderTarget(mRenderTarget);
}
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void LiquidEffect::postPaintScreen()

View file

@ -30,7 +30,7 @@ class LiquidEffect : public Effect
LiquidEffect();
~LiquidEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void postPaintScreen();
static bool supported();

View file

@ -23,18 +23,18 @@ ShakyMoveEffect::ShakyMoveEffect()
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 ] );
void ShakyMoveEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ShakyMoveEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( !windows.isEmpty())
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( mask, region, time );
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( data, time );
}
void ShakyMoveEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void ShakyMoveEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ))
*mask |= PAINT_WINDOW_TRANSFORMED;
effects->prePaintWindow( w, mask, paint, clip, time );
data.mask |= PAINT_WINDOW_TRANSFORMED;
effects->prePaintWindow( w, data, time );
}
void ShakyMoveEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -24,8 +24,8 @@ class ShakyMoveEffect
Q_OBJECT
public:
ShakyMoveEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void windowClosed( EffectWindow* c );

View file

@ -23,15 +23,15 @@ ShiftWorkspaceUpEffect::ShiftWorkspaceUpEffect()
timer.start( 2000 );
}
void ShiftWorkspaceUpEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ShiftWorkspaceUpEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( up && diff < 1000 )
diff = qBound( 0, diff + time, 1000 ); // KDE3: note this differs from KCLAMP
if( !up && diff > 0 )
diff = qBound( 0, diff - time, 1000 );
if( diff != 0 )
*mask |= PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( mask, region, time );
data.mask |= PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( data, time );
}
void ShiftWorkspaceUpEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -24,7 +24,7 @@ class ShiftWorkspaceUpEffect
Q_OBJECT
public:
ShiftWorkspaceUpEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
private slots:

View file

@ -24,28 +24,28 @@ TaskbarThumbnailEffect::TaskbarThumbnailEffect()
}
void TaskbarThumbnailEffect::prePaintScreen( int* mask, QRegion* region, int time )
void TaskbarThumbnailEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
// We might need to paint thumbnails if cursor has moved since last
// painting or some thumbnails were painted the last time
QPoint cpos = cursorPos();
if(cpos != mLastCursorPos || mThumbnails.count() > 0)
{
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
mThumbnails.clear();
mLastCursorPos = cpos;
}
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void TaskbarThumbnailEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void TaskbarThumbnailEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
QRect iconGeo = w->iconGeometry();
if(iconGeo.contains( mLastCursorPos ))
mThumbnails.append( w );
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void TaskbarThumbnailEffect::postPaintScreen()

View file

@ -31,8 +31,8 @@ class TaskbarThumbnailEffect
public:
TaskbarThumbnailEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void postPaintScreen();
virtual void mouseChanged( const QPoint& pos, const QPoint& old,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers );

View file

@ -25,27 +25,27 @@ WavyWindowsEffect::WavyWindowsEffect()
}
void WavyWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time )
void WavyWindowsEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
// Adjust elapsed time
mTimeElapsed += (time / 1000.0f);
// We need to mark the screen windows as transformed. Otherwise the whole
// screen won't be repainted, resulting in artefacts
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void WavyWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void WavyWindowsEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
// This window will be transformed by the effect
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
// Check if OpenGL compositing is used
// Request the window to be divided into cells which are at most 30x30
// pixels big
w->requestVertexGrid(30);
data.quads = data.quads.makeGrid( 30 );
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void WavyWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
@ -58,15 +58,17 @@ void WavyWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region,
// We have OpenGL compositing and the window has been subdivided
// because of our request (in pre-paint pass)
// Transform all the vertices to create wavy effect
QVector< Vertex >& vertices = w->vertices();
for(int i = 0; i < vertices.count(); i++)
{
vertices[i].pos[0] += sin(mTimeElapsed + vertices[i].texcoord[1] / 60 + 0.5f) * 10;
vertices[i].pos[1] += sin(mTimeElapsed + vertices[i].texcoord[0] / 80) * 10;
for( int i = 0;
i < data.quads.count();
++i )
for( int j = 0;
j < 4;
++j )
{
WindowVertex& v = data.quads[ i ][ j ];
v.move( v.x() + sin(mTimeElapsed + v.textureY() / 60 + 0.5f) * 10,
v.y() + sin(mTimeElapsed + v.textureX() / 80) * 10 );
}
// We have changed the vertices, so they will have to be reset before
// the next paint pass
w->markVerticesDirty();
}
// Call the next effect.

View file

@ -27,8 +27,8 @@ class WavyWindowsEffect
public:
WavyWindowsEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -42,7 +42,7 @@ DesktopGridEffect::DesktopGridEffect()
slideEnabled = conf.readEntry( "Slide", true );
}
void DesktopGridEffect::prePaintScreen( int* mask, QRegion* region, int time )
void DesktopGridEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( slide )
{
@ -50,7 +50,7 @@ void DesktopGridEffect::prePaintScreen( int* mask, QRegion* region, int time )
// PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
// so with normal screen painting second screen paint would erase parts of the first paint
if( progress != 1 )
*mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
else
{
slide = false;
@ -66,28 +66,28 @@ void DesktopGridEffect::prePaintScreen( int* mask, QRegion* region, int time )
// PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
// so with normal screen painting second screen paint would erase parts of the first paint
if( progress != 0 )
*mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
if( !activated && progress == 0 )
finish();
int d = posToDesktop( cursorPos());
if( d != hover_desktop )
{
*region |= desktopRect( hover_desktop, true );
data.paint |= desktopRect( hover_desktop, true );
hover_desktop = d;
*region |= desktopRect( hover_desktop, true );
data.paint |= desktopRect( hover_desktop, true );
}
}
effects->prePaintScreen( mask, region, time );
effects->prePaintScreen( data, time );
}
void DesktopGridEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void DesktopGridEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( slide )
{
if( w->isOnAllDesktops())
{
if( slide_painting_sticky )
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
else
w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
}
@ -104,12 +104,12 @@ void DesktopGridEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* pai
w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
if( w == window_move )
{
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
if( w->isOnAllDesktops() && painting_desktop != posToDesktop( window_move_pos - window_move_diff ))
w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
}
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -23,10 +23,10 @@ class DesktopGridEffect
Q_OBJECT
public:
DesktopGridEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowClosed( EffectWindow* w );
virtual void desktopChanged( int old );

View file

@ -15,7 +15,7 @@ namespace KWin
KWIN_EFFECT( dialogparent, DialogParentEffect )
void DialogParentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void DialogParentEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
// How long does it take for the effect to get it's full strength (in ms)
const float changeTime = 200;
@ -34,7 +34,7 @@ void DialogParentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* pa
}
// Call the next effect
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void DialogParentEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -28,7 +28,7 @@ class DialogParentEffect
: public Effect
{
public:
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );

View file

@ -17,24 +17,24 @@ namespace KWin
KWIN_EFFECT( drunken, DrunkenEffect )
void DrunkenEffect::prePaintScreen( int* mask, QRegion* region, int time )
void DrunkenEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( !windows.isEmpty())
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( mask, region, time );
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( data, time );
}
void DrunkenEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void DrunkenEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ))
{
windows[ w ] += time / 1000.;
if( windows[ w ] < 1 )
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
else
windows.remove( w );
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void DrunkenEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -20,8 +20,8 @@ class DrunkenEffect
: public Effect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
virtual void windowAdded( EffectWindow* w );

View file

@ -100,17 +100,17 @@ bool ExplosionEffect::loadData()
return true;
}
void ExplosionEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ExplosionEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( mActiveAnimations > 0 )
// We need to mark the screen as transformed. Otherwise the whole screen
// won't be repainted, resulting in artefacts
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void ExplosionEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( mWindows.contains( w ))
{
@ -121,8 +121,8 @@ void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint
mWindows[ w ] += time / 700.0; // complete change in 700ms
if( mWindows[ w ] < 1 )
{
*mask |= PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED;
*mask &= ~PAINT_WINDOW_OPAQUE;
data.mask |= PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED;
data.mask &= ~PAINT_WINDOW_OPAQUE;
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
}
else
@ -134,7 +134,7 @@ void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint
}
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void ExplosionEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -32,8 +32,8 @@ class ExplosionEffect
ExplosionEffect();
~ExplosionEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -25,17 +25,17 @@ FadeEffect::FadeEffect()
fadeWindows = conf.readEntry( "FadeWindows", true );
}
void FadeEffect::prePaintScreen( int* mask, QRegion* region, int time )
void FadeEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( !windows.isEmpty())
{
fadeInStep = time / double( fadeInTime );
fadeOutStep = time / double( fadeOutTime );
}
effects->prePaintScreen( mask, region, time );
effects->prePaintScreen( data, time );
}
void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void FadeEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ))
{
@ -43,8 +43,8 @@ void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRe
windows[ w ].fadeOutStep += fadeOutStep;
if( windows[ w ].opacity < 1.0 )
{
*mask &= ~PAINT_WINDOW_OPAQUE;
*mask |= PAINT_WINDOW_TRANSLUCENT;
data.mask &= ~PAINT_WINDOW_OPAQUE;
data.mask |= PAINT_WINDOW_TRANSLUCENT;
}
if( windows[ w ].deleted )
{
@ -57,7 +57,7 @@ void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRe
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
}
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
if( windows.contains( w ) && !w->isPaintingEnabled())
{ // if the window isn't to be painted, then let's make sure
// to track its progress

View file

@ -21,8 +21,8 @@ class FadeEffect
{
public:
FadeEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
// TODO react also on virtual desktop changes

View file

@ -18,24 +18,24 @@ namespace KWin
KWIN_EFFECT( fallapart, FallApartEffect )
void FallApartEffect::prePaintScreen( int* mask, QRegion* region, int time )
void FallApartEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( !windows.isEmpty())
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(data, time);
}
void FallApartEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void FallApartEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ))
{
if( windows[ w ] < 1 )
{
windows[ w ] += time / 1000.;
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
// Request the window to be divided into cells
w->requestVertexGrid( 40 );
data.quads = data.quads.makeGrid( 40 );
}
else
{
@ -43,22 +43,20 @@ void FallApartEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint
w->unrefWindow();
}
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void FallApartEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( windows.contains( w ))
{
QVector< Vertex >& vertices = w->vertices();
assert( vertices.count() % 4 == 0 );
for( int i = 0;
i < vertices.count();
i += 4 )
WindowQuadList new_quads;
int cnt = 0;
foreach( WindowQuad quad, data.quads )
{
// make fragments move in various directions, based on where
// they are (left pieces generally move to the left, etc.)
QPointF p1( vertices[ i ].pos[ 0 ], vertices[ i ].pos[ 1 ] );
QPointF p1( quad[ 0 ].x(), quad[ 0 ].y());
double xdiff = 0;
if( p1.x() < w->width() / 2 )
xdiff = -( w->width() / 2 - p1.x()) / w->width() * 100;
@ -70,38 +68,36 @@ void FallApartEffect::paintWindow( EffectWindow* w, int mask, QRegion region, Wi
if( p1.y() > w->height() / 2 )
ydiff = ( p1.y() - w->height() / 2 ) / w->height() * 100;
double modif = windows[ w ] * windows[ w ] * 64;
srandom( i ); // change direction randomly but consistently
srandom( cnt ); // change direction randomly but consistently
xdiff += ( rand() % 21 - 10 );
ydiff += ( rand() % 21 - 10 );
for( int j = 0;
j < 4;
++j )
{
vertices[ i + j ].pos[ 0 ] += xdiff * modif;
vertices[ i + j ].pos[ 1 ] += ydiff * modif;
quad[ j ].move( quad[ j ].x() + xdiff * modif, quad[ j ].y() + ydiff * modif );
}
// also make the fragments rotate around their center
QPointF center(( vertices[ i ].pos[ 0 ] + vertices[ i + 1 ].pos[ 0 ]
+ vertices[ i + 2 ].pos[ 0 ] + vertices[ i + 3 ].pos[ 0 ] ) / 4,
( vertices[ i ].pos[ 1 ] + vertices[ i + 1 ].pos[ 1 ]
+ vertices[ i + 2 ].pos[ 1 ] + vertices[ i + 3 ].pos[ 1 ] ) / 4 );
QPointF center(( quad[ 0 ].x() + quad[ 1 ].x() + quad[ 2 ].x() + quad[ 3 ].x()) / 4,
( quad[ 0 ].y() + quad[ 1 ].y() + quad[ 2 ].y() + quad[ 3 ].y()) / 4 );
double adiff = ( rand() % 720 - 360 ) / 360. * 2 * M_PI; // spin randomly
for( int j = 0;
j < 4;
++j )
{
double x = vertices[ i + j ].pos[ 0 ] - center.x();
double y = vertices[ i + j ].pos[ 1 ] - center.y();
double x = quad[ j ].x() - center.x();
double y = quad[ j ].y() - center.y();
double angle = atan2( y, x );
angle += windows[ w ] * adiff;
double dist = sqrt( x * x + y * y );
x = dist * cos( angle );
y = dist * sin( angle );
vertices[ i + j ].pos[ 0 ] = center.x() + x;
vertices[ i + j ].pos[ 1 ] = center.y() + y;
quad[ j ].move( center.x() + x, center.y() + y );
}
w->markVerticesDirty();
new_quads.append( quad );
++cnt;
}
data.quads = new_quads;
}
effects->paintWindow( w, mask, region, data );
}

View file

@ -20,8 +20,8 @@ class FallApartEffect
: public Effect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();
virtual void windowClosed( EffectWindow* c );

View file

@ -11,30 +11,30 @@ License. See the file "COPYING" for the exact licensing terms.
#include "flame.h"
#include <assert.h>
#include <kdebug.h>
namespace KWin
{
KWIN_EFFECT( flame, FlameEffect )
void FlameEffect::prePaintScreen( int* mask, QRegion* region, int time )
void FlameEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( !windows.isEmpty())
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(data, time);
}
void FlameEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void FlameEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ))
{
if( windows[ w ] < 1 )
{
windows[ w ] += time / 500.;
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
// Request the window to be divided into cells
w->requestVertexGrid( qMax( w->height() / 50, 5 ));
data.quads = data.quads.splitAtY( windows[ w ] * w->height());
}
else
{
@ -42,41 +42,24 @@ void FlameEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QR
w->unrefWindow();
}
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void FlameEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( windows.contains( w ))
{
QVector< Vertex >& vertices = w->vertices();
QVector< Vertex > new_vertices;
double ylimit = windows[ w ] * w->height(); // parts above this are already away
assert( vertices.count() % 4 == 0 );
for( int i = 0;
i < vertices.count();
i += 4 )
WindowQuadList new_quads;
float ylimit = windows[ w ] * w->height(); // parts above this are already away
foreach( WindowQuad quad, data.quads )
{
bool is_in = false;
for( int j = 0;
j < 4;
++j )
if( vertices[ i + j ].pos[ 1 ] >= ylimit )
is_in = true;
if( !is_in )
if( quad.bottom() <= ylimit )
continue;
for( int j = 0;
j < 4;
++j )
{
Vertex vertex = vertices[ i + j ];
new_vertices.append( vertex );
}
new_quads.append( quad );
}
if( new_vertices.isEmpty())
if( new_quads.isEmpty())
return; // nothing to paint
w->vertices() = new_vertices;
w->markVerticesDirty();
data.quads = new_quads;
}
effects->paintWindow( w, mask, region, data );
}

View file

@ -20,8 +20,8 @@ class FlameEffect
: public Effect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
virtual void windowClosed( EffectWindow* c );

View file

@ -36,7 +36,7 @@ KWIN_EFFECT( howto, HowtoEffect )
// region - the region of the screen that needs to be painted, support for modifying it
// is not fully implemented yet, do not use
// time - time in milliseconds since the last paint, useful for animations
void HowtoEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void HowtoEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
// Is this window the one that is going to be faded out and in again?
if( w == fade_window )
@ -49,8 +49,8 @@ void HowtoEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QR
{
// Since the effect will make the window translucent, explicitly change
// the flags so that the window will be painted only as translucent.
*mask |= PAINT_WINDOW_TRANSLUCENT;
*mask &= ~PAINT_WINDOW_OPAQUE;
data.mask |= PAINT_WINDOW_TRANSLUCENT;
data.mask &= ~PAINT_WINDOW_OPAQUE;
}
else
{
@ -61,7 +61,7 @@ void HowtoEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QR
}
// Call the next effect (or the actual window painting code if this is the last effect).
// Effects are chained and they all modify something if needed and then call the next one.
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
// The function that handles the actual painting. Some simple modifications are possible

View file

@ -38,7 +38,7 @@ class HowtoEffect
// A pre-paint function. It tells the compositing code how the painting will
// be affected by this effect.
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
// A paint function. It actually performs the modifications to the painting.
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );

View file

@ -42,7 +42,7 @@ MagnifierEffect::MagnifierEffect()
magnifier_size = QSize( 200, 200 ); // TODO config option
}
void MagnifierEffect::prePaintScreen( int* mask, QRegion* region, int time )
void MagnifierEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( zoom != target_zoom )
{
@ -52,8 +52,8 @@ void MagnifierEffect::prePaintScreen( int* mask, QRegion* region, int time )
else
zoom = qMax( zoom * qMin( 1 - diff, 0.8 ), target_zoom );
}
effects->prePaintScreen( mask, region, time );
*region |= magnifierArea().adjusted( -FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH );
effects->prePaintScreen( data, time );
data.paint |= magnifierArea().adjusted( -FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH );
}
void MagnifierEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -22,7 +22,7 @@ class MagnifierEffect
Q_OBJECT
public:
MagnifierEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void mouseChanged( const QPoint& pos, const QPoint& old,

View file

@ -15,14 +15,14 @@ namespace KWin
KWIN_EFFECT( maketransparent, MakeTransparentEffect )
void MakeTransparentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void MakeTransparentEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if(( w->isUserMove() || w->isUserResize()) || w->isDialog())
{
*mask |= PAINT_WINDOW_TRANSLUCENT;
*mask &= ~PAINT_WINDOW_OPAQUE;
data.mask |= PAINT_WINDOW_TRANSLUCENT;
data.mask &= ~PAINT_WINDOW_OPAQUE;
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void MakeTransparentEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class MakeTransparentEffect
{
public:
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
};

View file

@ -22,17 +22,17 @@ MinimizeAnimationEffect::MinimizeAnimationEffect()
}
void MinimizeAnimationEffect::prePaintScreen( int* mask, QRegion* region, int time )
void MinimizeAnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( mActiveAnimations > 0 )
// We need to mark the screen windows as transformed. Otherwise the
// whole screen won't be repainted, resulting in artefacts
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
const float changeTime = 500;
if( mAnimationProgress.contains( w ))
@ -55,7 +55,7 @@ void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegio
if( mAnimationProgress.contains( w ))
{
// We'll transform this window
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_MINIMIZE );
}
else
@ -63,7 +63,7 @@ void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegio
mActiveAnimations--;
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void MinimizeAnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -27,8 +27,8 @@ class MinimizeAnimationEffect
public:
MinimizeAnimationEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -69,7 +69,7 @@ PresentWindowsEffect::~PresentWindowsEffect()
}
void PresentWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time )
void PresentWindowsEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
// How long does it take for the effect to get it's full strength (in ms)
const float changeTime = 300;
@ -89,25 +89,25 @@ void PresentWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time
// We need to mark the screen windows as transformed. Otherwise the whole
// screen won't be repainted, resulting in artefacts
if( mActiveness > 0.0f )
*mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void PresentWindowsEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( mActiveness > 0.0f )
{
if( mWindowData.contains(w) )
{
// This window will be transformed by the effect
*mask |= Effect::PAINT_WINDOW_TRANSFORMED;
data.mask |= Effect::PAINT_WINDOW_TRANSFORMED;
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_MINIMIZE );
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
// If it's minimized window or on another desktop and effect is not
// fully active, then apply some transparency
if( mActiveness < 1.0f && (w->isMinimized() || !w->isOnCurrentDesktop() ))
*mask |= Effect::PAINT_WINDOW_TRANSLUCENT;
data.mask |= Effect::PAINT_WINDOW_TRANSLUCENT;
// Change window's hover according to cursor pos
WindowData& windata = mWindowData[w];
const float hoverchangetime = 200;
@ -119,7 +119,7 @@ void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion*
else if( !w->isDesktop())
w->disablePainting( EffectWindow::PAINT_DISABLED );
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void PresentWindowsEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -36,8 +36,8 @@ class PresentWindowsEffect
PresentWindowsEffect();
virtual ~PresentWindowsEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -15,24 +15,24 @@ namespace KWin
KWIN_EFFECT( scalein, ScaleInEffect )
void ScaleInEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ScaleInEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( !windows.isEmpty())
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( mask, region, time );
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( data, time );
}
void ScaleInEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void ScaleInEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ))
{
windows[ w ] += time / 500.; // complete change in 500ms
if( windows[ w ] < 1 )
*mask |= PAINT_WINDOW_TRANSFORMED;
data.mask |= PAINT_WINDOW_TRANSFORMED;
else
windows.remove( w );
}
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void ScaleInEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -20,8 +20,8 @@ class ScaleInEffect
: public Effect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
// TODO react also on virtual desktop changes

View file

@ -37,11 +37,11 @@ QRect ShadowEffect::shadowRectangle(const QRect& windowRectangle) const
return windowRectangle.adjusted( shadowXOffset - shadowFuzzyness - 20, shadowYOffset - shadowFuzzyness - 20,
shadowXOffset + shadowFuzzyness + 20, shadowYOffset + shadowFuzzyness + 20);
}
void ShadowEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void ShadowEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
*mask |= PAINT_WINDOW_TRANSLUCENT;
*paint |= QRegion( shadowRectangle( ( QRegion( w->geometry()) & *paint ).boundingRect() ));
effects->prePaintWindow( w, mask, paint, clip, time );
data.mask |= PAINT_WINDOW_TRANSLUCENT;
data.paint |= QRegion( shadowRectangle( ( QRegion( w->geometry()) & data.paint ).boundingRect() ));
effects->prePaintWindow( w, data, time );
}
void ShadowEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -24,7 +24,7 @@ class ShadowEffect
{
public:
ShadowEffect();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );

View file

@ -57,7 +57,7 @@ ShowFpsEffect::ShowFpsEffect()
y = displayHeight() - MAX_TIME - y;
}
void ShowFpsEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ShowFpsEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( time == 0 ) {
// TODO optimized away
@ -66,8 +66,8 @@ void ShowFpsEffect::prePaintScreen( int* mask, QRegion* region, int time )
frames[ frames_pos ] = t.minute() * 60000 + t.second() * 1000 + t.msec();
if( ++frames_pos == MAX_FPS )
frames_pos = 0;
effects->prePaintScreen( mask, region, time );
*region += QRect( x, y, FPS_WIDTH + NUM_PAINTS, MAX_TIME );
effects->prePaintScreen( data, time );
data.paint += QRect( x, y, FPS_WIDTH + NUM_PAINTS, MAX_TIME );
}
void ShowFpsEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -23,7 +23,7 @@ class ShowFpsEffect
{
public:
ShowFpsEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
private:

View file

@ -48,16 +48,16 @@ bool TestFBOEffect::supported()
}
void TestFBOEffect::prePaintScreen( int* mask, QRegion* region, int time )
void TestFBOEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if(mValid)
{
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
// Start rendering to texture
effects->pushRenderTarget(mRenderTarget);
}
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void TestFBOEffect::postPaintScreen()

View file

@ -31,7 +31,7 @@ class TestFBOEffect : public Effect
TestFBOEffect();
~TestFBOEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void postPaintScreen();
static bool supported();

View file

@ -41,10 +41,10 @@ TestInputEffect::~TestInputEffect()
effects->destroyInputWindow( input );
}
void TestInputEffect::prePaintScreen( int* mask, QRegion* region, int time )
void TestInputEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
*mask |= PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( mask, region, time );
data.mask |= PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( data, time );
}
void TestInputEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -28,7 +28,7 @@ class TestInputEffect
public:
TestInputEffect();
virtual ~TestInputEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void windowInputMouseEvent( Window w, QEvent* e );
private:

View file

@ -43,11 +43,11 @@ TrackMouseEffect::~TrackMouseEffect()
delete texture;
}
void TrackMouseEffect::prePaintScreen( int* mask, QRegion* region, int time )
void TrackMouseEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( active )
angle = ( angle + time / 10 ) % 360;
effects->prePaintScreen( mask, region, time );
effects->prePaintScreen( data, time );
}
void TrackMouseEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -23,7 +23,7 @@ class TrackMouseEffect
public:
TrackMouseEffect();
virtual ~TrackMouseEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void mouseChanged( const QPoint& pos, const QPoint& old,

View file

@ -33,7 +33,7 @@ ZoomEffect::ZoomEffect()
a->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_0));
}
void ZoomEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ZoomEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( zoom != target_zoom )
{
@ -44,8 +44,8 @@ void ZoomEffect::prePaintScreen( int* mask, QRegion* region, int time )
zoom = qMax( zoom * qMin( 1 - diff, 0.8 ), target_zoom );
}
if( zoom != 1.0 )
*mask |= PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( mask, region, time );
data.mask |= PAINT_SCREEN_TRANSFORMED;
effects->prePaintScreen( data, time );
}
void ZoomEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -22,7 +22,7 @@ class ZoomEffect
Q_OBJECT
public:
ZoomEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void mouseChanged( const QPoint& pos, const QPoint& old,

View file

@ -125,9 +125,9 @@ void Effect::mouseChanged( const QPoint&, const QPoint&, Qt::MouseButtons, Qt::K
{
}
void Effect::prePaintScreen( int* mask, QRegion* region, int time )
void Effect::prePaintScreen( ScreenPrePaintData& data, int time )
{
effects->prePaintScreen( mask, region, time );
effects->prePaintScreen( data, time );
}
void Effect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
@ -140,9 +140,9 @@ void Effect::postPaintScreen()
effects->postPaintScreen();
}
void Effect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void Effect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
effects->prePaintWindow( w, mask, paint, clip, time );
effects->prePaintWindow( w, data, time );
}
void Effect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
@ -289,5 +289,157 @@ EffectWindowGroup::~EffectWindowGroup()
{
}
/***************************************************************
WindowQuad
***************************************************************/
WindowQuad WindowQuad::makeSubQuad( float x1, float y1, float x2, float y2 ) const
{
assert( x1 < x2 && y1 < y2 && x1 >= left() && x2 <= right() && y1 >= top() && y2 <= bottom());
WindowQuad ret( *this );
ret.verts[ 0 ].px = x1;
ret.verts[ 3 ].px = x1;
ret.verts[ 1 ].px = x2;
ret.verts[ 2 ].px = x2;
ret.verts[ 0 ].py = y1;
ret.verts[ 1 ].py = y1;
ret.verts[ 2 ].py = y2;
ret.verts[ 3 ].py = y2;
float tleft = ( x1 - left()) / ( right() - left()) * ( textureRight() - textureLeft()) + textureLeft();
float tright = ( x2 - left()) / ( right() - left()) * ( textureRight() - textureLeft()) + textureLeft();
float ttop = ( y1 - top()) / ( bottom() - top()) * ( textureBottom() - textureTop()) + textureTop();
float tbottom = ( y2 - top()) / ( bottom() - top()) * ( textureBottom() - textureTop()) + textureTop();
ret.verts[ 0 ].tx = tleft;
ret.verts[ 3 ].tx = tleft;
ret.verts[ 1 ].tx = tright;
ret.verts[ 2 ].tx = tright;
ret.verts[ 0 ].ty = ttop;
ret.verts[ 1 ].ty = ttop;
ret.verts[ 2 ].ty = tbottom;
ret.verts[ 3 ].ty = tbottom;
return ret;
}
/***************************************************************
WindowQuadList
***************************************************************/
WindowQuadList WindowQuadList::splitAtX( float x ) const
{
WindowQuadList ret;
foreach( WindowQuad quad, *this )
{
bool wholeleft = true;
bool wholeright = true;
for( int i = 0;
i < 4;
++i )
{
if( quad[ i ].x() < x )
wholeright = false;
if( quad[ i ].x() >= x )
wholeleft = false;
}
if( wholeleft || wholeright ) // is whole in one split part
{
ret.append( quad );
continue;
}
ret.append( quad.makeSubQuad( quad.left(), quad.top(), x, quad.bottom()));
ret.append( quad.makeSubQuad( x, quad.top(), quad.right(), quad.bottom()));
}
return ret;
}
WindowQuadList WindowQuadList::splitAtY( float y ) const
{
WindowQuadList ret;
foreach( WindowQuad quad, *this )
{
bool wholetop = true;
bool wholebottom = true;
for( int i = 0;
i < 4;
++i )
{
if( quad[ i ].y() < y )
wholebottom = false;
if( quad[ i ].y() >= y )
wholetop = false;
}
if( wholetop || wholebottom ) // is whole in one split part
{
ret.append( quad );
continue;
}
ret.append( quad.makeSubQuad( quad.left(), quad.top(), quad.right(), y ));
ret.append( quad.makeSubQuad( quad.left(), y, quad.right(), quad.bottom()));
}
return ret;
}
WindowQuadList WindowQuadList::makeGrid( int maxquadsize ) const
{
if( empty())
return *this;
// find the bounding rectangle
float left = first().left();
float right = first().right();
float top = first().top();
float bottom = first().bottom();
foreach( WindowQuad quad, *this )
{
left = qMin( left, quad.left());
right = qMax( right, quad.right());
top = qMin( top, quad.top());
bottom = qMax( bottom, quad.bottom());
}
WindowQuadList ret;
for( float x = left;
x < right;
x += maxquadsize )
{
for( float y = top;
y < bottom;
y += maxquadsize )
{
foreach( WindowQuad quad, *this )
{
if( QRectF( QPointF( quad.left(), quad.top()), QPointF( quad.right(), quad.bottom()))
.intersects( QRectF( x, y, maxquadsize, maxquadsize )))
{
ret.append( quad.makeSubQuad( qMax( x, quad.left()), qMax( y, quad.top()),
qMin( quad.right(), x + maxquadsize ), qMin( quad.bottom(), y + maxquadsize )));
}
}
}
}
return ret;
}
void WindowQuadList::makeArrays( float** vertices, float** texcoords )
{
*vertices = new float[ count() * 4 * 2 ];
*texcoords = new float[ count() * 4 * 2 ];
float* vpos = *vertices;
float* tpos = *texcoords;
for( int i = 0;
i < count();
++i )
for( int j = 0;
j < 4;
++j )
{
*vpos++ = at( i )[ j ].x();
*vpos++ = at( i )[ j ].y();
*tpos++ = at( i )[ j ].textureX();
*tpos++ = at( i )[ j ].textureY();
}
}
bool WindowQuadList::smoothNeeded() const
{
return false; // TODO
}
} // namespace

View file

@ -23,7 +23,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QList>
#include <QHash>
#include <stdio.h>
#include <assert.h>
class KLibrary;
class KConfigGroup;
@ -36,9 +36,14 @@ namespace KWin
class EffectWindow;
class EffectWindowGroup;
class Effect;
class Vertex;
class WindowQuad;
class GLRenderTarget;
class GLShader;
class WindowQuadList;
class WindowPrePaintData;
class WindowPaintData;
class ScreenPrePaintData;
class ScreenPaintData;
typedef QPair< QString, Effect* > EffectPair;
typedef QPair< Effect*, Window > InputWindowPair;
@ -72,10 +77,10 @@ class KWIN_EXPORT Effect
Effect();
virtual ~Effect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
// paintWindow() can do various transformations
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
@ -165,10 +170,10 @@ class KWIN_EXPORT EffectsHandler
EffectsHandler(CompositingType type);
virtual ~EffectsHandler();
// for use by effects
virtual void prePaintScreen( int* mask, QRegion* region, int time ) = 0;
virtual void prePaintScreen( ScreenPrePaintData& data, int time ) = 0;
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ) = 0;
virtual void postPaintScreen() = 0;
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ) = 0;
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) = 0;
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) = 0;
virtual void postPaintWindow( EffectWindow* w ) = 0;
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) = 0;
@ -335,14 +340,6 @@ class KWIN_EXPORT EffectWindow
virtual EffectWindow* findModal() = 0;
virtual EffectWindowList mainWindows() const = 0;
virtual QVector<Vertex>& vertices() = 0;
// Can be called in pre-paint pass. Makes sure that all quads that the
// window consists of are not bigger than maxquadsize x maxquadsize
// (in pixels) in the following paint pass.
virtual void requestVertexGrid(int maxquadsize) = 0;
// Marks vertices of the window as dirty. Call this if you change
// position of the vertices
virtual void markVerticesDirty() = 0;
virtual void setShader(GLShader* shader) = 0;
};
@ -355,28 +352,265 @@ class KWIN_EXPORT EffectWindowGroup
/**
* @short Vertex class
* Vertex has position and texture coordinate which are equal at first,
* however effects can e.g. modify position to move the window or part of it.
* A vertex is one position in a window. WindowQuad consists of four WindowVertex objects
* and represents one part of a window.
**/
class KWIN_EXPORT Vertex
{
class KWIN_EXPORT WindowVertex
{
public:
Vertex() {}
Vertex(float x, float y)
{
pos[0] = texcoord[0] = x; pos[1] = texcoord[1] = y; pos[2] = 0.0f;
}
Vertex(float x, float y, float u, float v)
{
pos[0] = x; pos[1] = y; pos[2] = 0.0f; texcoord[0] = u; texcoord[1] = v;
}
float pos[3];
float texcoord[2];
};
float x() const;
float y() const;
void move( float x, float y );
void setX( float x );
void setY( float y );
float textureX() const;
float textureY() const;
WindowVertex();
WindowVertex( float x, float y, float tx, float ty );
private:
friend class WindowQuad;
float px, py; // position
float tx, ty; // texture coords
};
/**
* @short Class representing one area of a window.
* WindowQuads consists of four WindowVertex objects and represents one part of a window.
*/
class KWIN_EXPORT WindowQuad
{
public:
WindowQuad();
WindowQuad makeSubQuad( float x1, float y1, float x2, float y2 ) const;
WindowVertex& operator[]( int index );
const WindowVertex& operator[]( int index ) const;
// these 8 work only with untransformed quads
float left() const;
float right() const;
float top() const;
float bottom() const;
float textureLeft() const;
float textureRight() const;
float textureTop() const;
float textureBottom() const;
private:
void checkUntransformed() const;
WindowVertex verts[ 4 ];
};
class KWIN_EXPORT WindowQuadList
: public QList< WindowQuad >
{
public:
WindowQuadList splitAtX( float x ) const;
WindowQuadList splitAtY( float y ) const;
WindowQuadList makeGrid( int maxquadsize ) const;
bool smoothNeeded() const;
void makeArrays( float** vertices, float** texcoords );
};
class KWIN_EXPORT WindowPrePaintData
{
public:
int mask;
QRegion paint;
QRegion clip;
WindowQuadList quads;
};
class KWIN_EXPORT WindowPaintData
{
public:
WindowPaintData();
/**
* Window opacity, in range 0 = transparent to 1 = fully opaque
*/
double opacity;
double xScale;
double yScale;
int xTranslate;
int yTranslate;
/**
* Saturation of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* unsaturated (greyscale). 0.5 would make the colors less intense,
* but not completely grey
**/
float saturation;
/**
* Brightness of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* black. 0.5 would make it 50% darker than usual
**/
float brightness;
WindowQuadList quads;
};
class KWIN_EXPORT ScreenPaintData
{
public:
ScreenPaintData();
double xScale;
double yScale;
int xTranslate;
int yTranslate;
};
class KWIN_EXPORT ScreenPrePaintData
{
public:
int mask;
QRegion paint;
};
extern KWIN_EXPORT EffectsHandler* effects;
/***************************************************************
WindowVertex
***************************************************************/
inline
WindowVertex::WindowVertex()
: px( 0 ), py( 0 ), tx( 0 ), ty( 0 )
{
}
inline
WindowVertex::WindowVertex( float _x, float _y, float _tx, float _ty )
: px( _x ), py( _y ), tx( _tx ), ty( _ty )
{
}
inline
float WindowVertex::x() const
{
return px;
}
inline
float WindowVertex::y() const
{
return py;
}
inline
void WindowVertex::move( float x, float y )
{
px = x;
py = y;
}
inline
void WindowVertex::setX( float x )
{
px = x;
}
inline
void WindowVertex::setY( float y )
{
py = y;
}
inline
float WindowVertex::textureX() const
{
return tx;
}
inline
float WindowVertex::textureY() const
{
return ty;
}
/***************************************************************
WindowQuad
***************************************************************/
inline
WindowQuad::WindowQuad()
{
}
inline
WindowVertex& WindowQuad::operator[]( int index )
{
assert( index >= 0 && index < 4 );
return verts[ index ];
}
inline
const WindowVertex& WindowQuad::operator[]( int index ) const
{
assert( index >= 0 && index < 4 );
return verts[ index ];
}
inline
void WindowQuad::checkUntransformed() const
{
assert( verts[ 0 ].py == verts[ 1 ].py && verts[ 2 ].py == verts[ 3 ].py
&& verts[ 0 ].px == verts[ 3 ].px && verts[ 1 ].px == verts[ 2 ].px );
assert( verts[ 0 ].ty == verts[ 1 ].ty && verts[ 2 ].ty == verts[ 3 ].ty
&& verts[ 0 ].tx == verts[ 3 ].tx && verts[ 1 ].tx == verts[ 2 ].tx );
}
inline
float WindowQuad::left() const
{
checkUntransformed();
return verts[ 0 ].px;
}
inline
float WindowQuad::right() const
{
checkUntransformed();
return verts[ 2 ].px;
}
inline
float WindowQuad::top() const
{
checkUntransformed();
return verts[ 0 ].py;
}
inline
float WindowQuad::bottom() const
{
checkUntransformed();
return verts[ 2 ].py;
}
inline
float WindowQuad::textureLeft() const
{
checkUntransformed();
return verts[ 0 ].tx;
}
inline
float WindowQuad::textureRight() const
{
checkUntransformed();
return verts[ 2 ].tx;
}
inline
float WindowQuad::textureTop() const
{
checkUntransformed();
return verts[ 0 ].ty;
}
inline
float WindowQuad::textureBottom() const
{
checkUntransformed();
return verts[ 2 ].ty;
}
} // namespace

View file

@ -13,6 +13,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QX11Info>
#include <QPoint>
#include <qregion.h>
#include <kdemacros.h>
@ -64,43 +65,6 @@ enum ElectricBorder
// DesktopListMode lists them in the order created.
enum TabBoxMode { TabBoxDesktopMode, TabBoxDesktopListMode, TabBoxWindowsMode };
class KWIN_EXPORT WindowPaintData
{
public:
WindowPaintData();
/**
* Window opacity, in range 0 = transparent to 1 = fully opaque
*/
double opacity;
double xScale;
double yScale;
int xTranslate;
int yTranslate;
/**
* Saturation of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* unsaturated (greyscale). 0.5 would make the colors less intense,
* but not completely grey
**/
float saturation;
/**
* Brightness of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* black. 0.5 would make it 50% darker than usual
**/
float brightness;
};
class KWIN_EXPORT ScreenPaintData
{
public:
ScreenPaintData();
double xScale;
double yScale;
int xTranslate;
int yTranslate;
};
inline
KWIN_EXPORT Display* display()
{

View file

@ -116,19 +116,19 @@ GLShader* ShaderEffect::shader() const
return mShader;
}
void ShaderEffect::prePaintScreen( int* mask, QRegion* region, int time )
void ShaderEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
mTime += time / 1000.0f;
#ifdef HAVE_OPENGL
if( mValid && mEnabled )
{
*mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
// Start rendering to texture
effects->pushRenderTarget(mRenderTarget);
}
#endif
effects->prePaintScreen(mask, region, time);
effects->prePaintScreen(data, time);
}
void ShaderEffect::postPaintScreen()

View file

@ -27,7 +27,7 @@ class KWIN_EXPORT ShaderEffect : public Effect
ShaderEffect(const QString& shadername);
virtual ~ShaderEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void postPaintScreen();
static bool supported();

View file

@ -94,7 +94,12 @@ void Scene::paintScreen( int* mask, QRegion* region )
updateTimeDiff();
// preparation step
static_cast<EffectsHandlerImpl*>(effects)->startPaint();
effects->prePaintScreen( mask, region, time_diff );
ScreenPrePaintData pdata;
pdata.mask = *mask;
pdata.paint = *region;
effects->prePaintScreen( pdata, time_diff );
*mask = pdata.mask;
*region = pdata.paint;
if( *mask & ( PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS ))
{ // Region painting is not possible with transformations,
// because screen damage doesn't match transformed positions.
@ -165,19 +170,21 @@ void Scene::paintGenericScreen( int orig_mask, ScreenPaintData )
QList< Phase2Data > phase2;
foreach( Window* w, stacking_order ) // bottom to top
{
int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
WindowPrePaintData data;
data.mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
w->resetPaintingEnabled();
QRegion paint = infiniteRegion(); // no clipping, so doesn't really matter
QRegion clip = QRegion();
data.paint = infiniteRegion(); // no clipping, so doesn't really matter
data.clip = QRegion();
data.quads = buildQuads( w );
// preparation step
effects->prePaintWindow( effectWindow( w ), &mask, &paint, &clip, time_diff );
effects->prePaintWindow( effectWindow( w ), data, time_diff );
if( !w->isPaintingEnabled())
continue;
phase2.append( Phase2Data( w, infiniteRegion(), mask ));
phase2.append( Phase2Data( w, infiniteRegion(), data.mask, data.quads ));
}
foreach( Phase2Data d, phase2 )
paintWindow( d.window, d.mask, d.region );
paintWindow( d.window, d.mask, d.region, d.quads );
}
// The optimized case without any transformations at all.
@ -199,38 +206,40 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region )
--i )
{
Window* w = stacking_order[ i ];
int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
WindowPrePaintData data;
data.mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
w->resetPaintingEnabled();
QRegion paint = region;
QRegion clip = w->isOpaque() ? w->shape().translated( w->x(), w->y()) : QRegion();
data.paint = region;
data.clip = w->isOpaque() ? w->shape().translated( w->x(), w->y()) : QRegion();
data.quads = buildQuads( w );
// preparation step
effects->prePaintWindow( effectWindow( w ), &mask, &paint, &clip, time_diff );
effects->prePaintWindow( effectWindow( w ), data, time_diff );
if( !w->isPaintingEnabled())
continue;
paint -= allclips; // make sure to avoid already clipped areas
if( paint.isEmpty()) // completely clipped
data.paint -= allclips; // make sure to avoid already clipped areas
if( data.paint.isEmpty()) // completely clipped
continue;
if( paint != region ) // prepaint added area to draw
if( data.paint != region ) // prepaint added area to draw
{
region |= paint; // make sure other windows in that area get painted too
painted_region |= paint; // make sure it makes it to the screen
region |= data.paint; // make sure other windows in that area get painted too
painted_region |= data.paint; // make sure it makes it to the screen
}
// If the window is transparent, the transparent part will be done
// in the 2nd pass.
if( mask & PAINT_WINDOW_TRANSLUCENT )
phase2translucent.prepend( Phase2Data( w, paint, mask ));
if( mask & PAINT_WINDOW_OPAQUE )
if( data.mask & PAINT_WINDOW_TRANSLUCENT )
phase2translucent.prepend( Phase2Data( w, data.paint, data.mask, data.quads ));
if( data.mask & PAINT_WINDOW_OPAQUE )
{
phase2opaque.append( Phase2Data( w, paint, mask ));
phase2opaque.append( Phase2Data( w, data.paint, data.mask, data.quads ));
// The window can clip by its opaque parts the windows below.
region -= clip;
allclips |= clip;
region -= data.clip;
allclips |= data.clip;
}
}
// Do the actual painting
// First opaque windows, top to bottom
foreach( Phase2Data d, phase2opaque )
paintWindow( d.window, d.mask, d.region );
paintWindow( d.window, d.mask, d.region, d.quads );
if( !( orig_mask & PAINT_SCREEN_BACKGROUND_FIRST ))
paintBackground( region ); // Fill any areas of the root window not covered by windows
// Now walk the list bottom to top, drawing translucent windows.
@ -239,17 +248,18 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region )
QRegion add_paint;
foreach( Phase2Data d, phase2translucent )
{
paintWindow( d.window, d.mask, d.region | add_paint );
paintWindow( d.window, d.mask, d.region | add_paint, d.quads );
// It is necessary to also add paint regions of windows below, because their
// pre-paint's might have extended the paint area, so those areas need to be painted too.
add_paint |= d.region;
}
}
void Scene::paintWindow( Window* w, int mask, QRegion region )
void Scene::paintWindow( Window* w, int mask, QRegion region, WindowQuadList quads )
{
WindowPaintData data;
data.opacity = w->window()->opacity();
data.quads = quads;
w->prepareForPainting();
effects->paintWindow( effectWindow( w ), mask, region, data );
}
@ -266,6 +276,22 @@ void Scene::finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, Wind
w->sceneWindow()->performPaint( mask, region, data );
}
WindowQuadList Scene::buildQuads( const Window* w )
{
WindowQuadList ret;
foreach( QRect r, w->shape().rects())
{
WindowQuad quad;
// TODO asi mam spatne pravy dolni roh - bud tady, nebo v jinych castech
quad[ 0 ] = WindowVertex( r.x(), r.y(), r.x(), r.y());
quad[ 1 ] = WindowVertex( r.x() + r.width(), r.y(), r.x() + r.width(), r.y());
quad[ 2 ] = WindowVertex( r.x() + r.width(), r.y() + r.height(), r.x() + r.width(), r.y() + r.height());
quad[ 3 ] = WindowVertex( r.x(), r.y() + r.height(), r.x(), r.y() + r.height());
ret.append( quad );
}
return ret;
}
//****************************************
// Scene::Window
//****************************************

View file

@ -92,9 +92,11 @@ class Scene
// called after all effects had their paintWindow() called
void finalPaintWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data );
// shared implementation, starts painting the window
virtual void paintWindow( Window* w, int mask, QRegion region );
virtual void paintWindow( Window* w, int mask, QRegion region, WindowQuadList quads );
// called after all effects had their drawWindow() called
void finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data );
// creates initial quad list for a window
virtual WindowQuadList buildQuads( const Window* w );
// infinite region, i.e. everything
static QRegion infiniteRegion();
// compute time since the last repaint
@ -102,10 +104,12 @@ class Scene
// saved data for 2nd pass of optimized screen painting
struct Phase2Data
{
Phase2Data( Window* w, QRegion r, int m ) : window( w ), region( r ), mask( m ) {}
Phase2Data( Window* w, QRegion r, int m, const WindowQuadList& q )
: window( w ), region( r ), mask( m ), quads( q ) {}
Window* window;
QRegion region;
int mask;
WindowQuadList quads;
};
// windows in their stacking order
QVector< Window* > stacking_order;

View file

@ -709,7 +709,6 @@ void SceneOpenGL::windowGeometryShapeChanged( Toplevel* c )
Window* w = windows[ c ];
w->discardShape();
w->discardTexture();
w->discardVertices();
}
void SceneOpenGL::windowOpacityChanged( Toplevel* )
@ -1015,96 +1014,17 @@ void SceneOpenGL::Texture::unbind()
SceneOpenGL::Window::Window( Toplevel* c )
: Scene::Window( c )
, texture()
, currentXResolution( -1 )
, currentYResolution( -1 )
, requestedXResolution( 0 )
, requestedYResolution( 0 )
, verticesDirty( false )
{
}
SceneOpenGL::Window::~Window()
{
discardTexture();
discardVertices();
}
void SceneOpenGL::Window::requestVertexGrid(int maxquadsize)
{
requestedXResolution = (requestedXResolution <= 0) ? maxquadsize : qMin(maxquadsize, requestedXResolution);
requestedYResolution = (requestedYResolution <= 0) ? maxquadsize : qMin(maxquadsize, requestedYResolution);
}
void SceneOpenGL::Window::createVertexGrid(int xres, int yres)
{
int oldcount = verticeslist.count();
verticeslist.clear();
foreach( QRect r, shape().rects())
{
// First calculate number of columns/rows that this rect will be
// divided into
int cols = (xres <= 0) ? 1 : (int)ceil( r.width() / (float)xres );
int rows = (yres <= 0) ? 1 : (int)ceil( r.height() / (float)yres );
// Now calculate actual size of each cell
int cellw = r.width() / cols;
int cellh = r.height() / rows;
int maxx = r.x() + r.width();
int maxy = r.y() + r.height();
for( int x1 = r.x(); x1 < maxx; x1 += cellw )
{
int x2 = qMin(x1 + cellw, maxx);
for( int y1 = r.y(); y1 < maxy; y1 += cellh )
{
int y2 = qMin(y1 + cellh, maxy);
// Add this quad to vertices' list
verticeslist.append( Vertex( x1, y1 ));
verticeslist.append( Vertex( x1, y2 ));
verticeslist.append( Vertex( x2, y2 ));
verticeslist.append( Vertex( x2, y1 ));
}
}
}
Client* c = qobject_cast<Client *>(window());
kDebug( 1212 ) << k_funcinfo << "'" << (c ? c->caption() : "") << "': Resized vertex grid from " <<
oldcount/4 << " quads (minreso: " << currentXResolution << "x" << currentYResolution <<
") to " << verticeslist.count()/4 << " quads (minreso: " << xres << "x" << yres << ")" << endl;
currentXResolution = xres;
currentYResolution = yres;
verticesDirty = false;
}
void SceneOpenGL::Window::resetVertices()
{
// This assumes that texcoords of the vertices are unchanged. If they are,
// we need to do this in some other way (or maybe the effects should then
// clean things up themselves)
for(int i = 0; i < verticeslist.count(); i++)
{
verticeslist[i].pos[0] = verticeslist[i].texcoord[0];
verticeslist[i].pos[1] = verticeslist[i].texcoord[1];
}
verticesDirty = false;
}
void SceneOpenGL::Window::prepareVertices()
{
if( requestedXResolution != currentXResolution || requestedYResolution != currentYResolution )
createVertexGrid( requestedXResolution, requestedYResolution );
else if( verticesDirty )
resetVertices();
// Reset requests for the next painting
requestedXResolution = 0;
requestedYResolution = 0;
// Reset shader. If effect wants to use shader, it has to set it in paint pass
shader = 0;
}
void SceneOpenGL::Window::prepareForPainting()
{
prepareVertices();
shader = NULL; // TODO
// We should also bind texture here so that effects could access it in the
// paint pass
}
@ -1181,13 +1101,6 @@ void SceneOpenGL::Window::discardTexture()
texture.discard();
}
void SceneOpenGL::Window::discardVertices()
{
// Causes list of vertices to be recreated before next rendering pass
currentXResolution = -1;
currentYResolution = -1;
}
// when the window's composite pixmap is discarded, undo binding it to the texture
void SceneOpenGL::Window::pixmapDiscarded()
{
@ -1240,7 +1153,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
// filtering when it actually makes a difference, that is with
// minification or changed vertices
if( options->smoothScale == 2
&& ( verticesDirty || data.xScale < 1 || data.yScale < 1 ))
&& ( data.quads.smoothNeeded() || data.xScale < 1 || data.yScale < 1 ))
{
texture.setFilter( GL_LINEAR_MIPMAP_LINEAR );
}
@ -1267,12 +1180,15 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
prepareRenderStates( mask, data );
texture.bind();
texture.enableUnnormalizedTexCoords();
// Render geometry
region.translate( toplevel->x(), toplevel->y() ); // Back to screen coords
renderGLGeometry( mask, region, verticeslist.count(),
verticeslist[ 0 ].pos, verticeslist[ 0 ].texcoord, 0, 3, sizeof( Vertex ));
float* vertices;
float* texcoords;
data.quads.makeArrays( &vertices, &texcoords );
renderGLGeometry( mask, region, data.quads.count() * 4,
vertices, texcoords, NULL, 2, 0 );
delete[] vertices;
delete[] texcoords;
texture.disableUnnormalizedTexCoords();
glPopMatrix();

View file

@ -123,27 +123,9 @@ class SceneOpenGL::Window
virtual void pixmapDiscarded();
bool bindTexture();
void discardTexture();
void discardVertices();
// Returns list of vertices
QVector<Vertex>& vertices() { return verticeslist; }
// Can be called in pre-paint pass. Makes sure that all quads that the
// window consists of are not bigger than maxquadsize x maxquadsize
// (in pixels) in the following paint pass.
void requestVertexGrid(int maxquadsize);
// Marks vertices of the window as dirty. Call this if you change
// position of the vertices
void markVerticesDirty() { verticesDirty = true; }
void setShader( GLShader* s ) { shader = s; }
protected:
// Makes sure that vertex grid requests are fulfilled and that vertices
// aren't dirty. Call this before paint pass
void prepareVertices();
void createVertexGrid(int xres, int yres);
void resetVertices(); // Resets positions of vertices
void prepareRenderStates( int mask, WindowPaintData data );
void prepareShaderRenderStates( int mask, WindowPaintData data );
void restoreRenderStates( int mask, WindowPaintData data );
@ -151,16 +133,6 @@ class SceneOpenGL::Window
private:
Texture texture;
QVector<Vertex> verticeslist;
// Maximum size of the biggest quad that window currently has, in pixels
int currentXResolution;
int currentYResolution;
// Requested maximum size of the biggest quad that window would have
// during the next paint pass, in pixels
int requestedXResolution;
int requestedYResolution;
bool verticesDirty; // vertices have been modified in some way
GLShader* shader; // shader to be used for rendering, if any
};

View file

@ -198,31 +198,33 @@ void SceneXrender::paintTransformedScreen( int orig_mask )
--i )
{
Window* w = static_cast< Window* >( stacking_order[ i ] );
int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
WindowPrePaintData data;
data.mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
w->resetPaintingEnabled();
QRegion paint = region;
data.paint = region;
// TODO this is wrong, transformedShape() should be used here, but is not known yet
QRegion clip = w->isOpaque() ? region : QRegion();
data.clip = w->isOpaque() ? region : QRegion();
data.quads = buildQuads( w );
// preparation step
effects->prePaintWindow( effectWindow( w ), &mask, &paint, &clip, time_diff );
effects->prePaintWindow( effectWindow( w ), data, time_diff );
if( !w->isPaintingEnabled())
continue;
paint -= allclips; // make sure to avoid already clipped areas
if( paint.isEmpty()) // completely clipped
data.paint -= allclips; // make sure to avoid already clipped areas
if( data.paint.isEmpty()) // completely clipped
continue;
if( paint != region ) // prepaint added area to draw
if( data.paint != region ) // prepaint added area to draw
{
region |= paint; // make sure other windows in that area get painted too
painted_region |= paint; // make sure it makes it to the screen
region |= data.paint; // make sure other windows in that area get painted too
painted_region |= data.paint; // make sure it makes it to the screen
}
// If the window is transparent, the transparent part will be done
// in the 2nd pass.
if( mask & PAINT_WINDOW_TRANSLUCENT )
phase2.prepend( Phase2Data( w, paint, mask ));
if( mask & PAINT_WINDOW_OPAQUE )
if( data.mask & PAINT_WINDOW_TRANSLUCENT )
phase2.prepend( Phase2Data( w, data.paint, data.mask, data.quads ));
if( data.mask & PAINT_WINDOW_OPAQUE )
{
w->setTransformedShape( QRegion());
paintWindow( w, mask, paint );
paintWindow( w, data.mask, data.paint, data.quads );
// The window can clip by its opaque parts the windows below.
region -= w->transformedShape();
}
@ -236,7 +238,7 @@ void SceneXrender::paintTransformedScreen( int orig_mask )
foreach( Phase2Data d, phase2 )
{
Scene::Window* w = d.window;
paintWindow( w, d.mask, d.region | add_paint );
paintWindow( w, d.mask, d.region | add_paint, d.quads );
// It is necessary to also add paint regions of windows below, because their
// pre-paint's might have extended the paint area, so those areas need to be painted too.
add_paint |= d.region;