Move functionality to the base Scene class.

svn path=/branches/work/kwin_composite/; revision=596186
This commit is contained in:
Luboš Luňák 2006-10-16 21:06:34 +00:00
parent caed149f40
commit ddab4e0d2c
9 changed files with 152 additions and 205 deletions

View file

@ -133,6 +133,20 @@ class ShiftWorkspaceUp
};
#endif
// a special effect that is last in the order that'll actually call the painting functions
// TODO this should actually be in scene.h
class Scene::WrapperEffect
: public Effect
{
public:
virtual ~WrapperEffect();
virtual void prePaintScreen( int* mask, QRegion* region );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
};
inline
WindowPaintData::WindowPaintData()
: opacity( 1.0 )

View file

@ -13,9 +13,19 @@ License. See the file "COPYING" for the exact licensing terms.
#include <X11/extensions/shape.h>
#include "effects.h"
namespace KWinInternal
{
//****************************************
// Scene::WrapperEffect
//****************************************
Scene::WrapperEffect::~WrapperEffect()
{
}
//****************************************
// Scene
//****************************************
@ -31,6 +41,90 @@ Scene::~Scene()
{
}
void Scene::WrapperEffect::prePaintScreen( int*, QRegion* )
{
// nothing, no changes
}
// the function that'll be eventually called by paintScreen() above
void Scene::WrapperEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( mask & PAINT_SCREEN_REGION )
scene->paintSimpleScreen( region );
else
scene->paintGenericScreen();
}
// the generic painting code that should eventually handle even
// transformations
void Scene::paintGenericScreen()
{
paintBackground( infiniteRegion());
foreach( Window* w, stacking_order ) // bottom to top
{
if( !w->isVisible())
continue;
paintWindow( w, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT, infiniteRegion());
}
}
// the optimized case without any transformations at all
void Scene::paintSimpleScreen( QRegion region )
{
QList< Phase2Data > phase2;
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
region = QRegion( 0, 0, displayWidth(), displayHeight());
// Draw each opaque window top to bottom, subtracting the bounding rect of
// each window from the clip region after it's been drawn.
for( int i = stacking_order.count() - 1; // top to bottom
i >= 0;
--i )
{
Window* w = stacking_order[ i ];
if( !w->isVisible())
continue;
if( region.isEmpty()) // completely clipped
continue;
if( !w->isOpaque())
{
phase2.prepend( Phase2Data( w, region ));
continue;
}
paintWindow( w, PAINT_WINDOW_OPAQUE, region );
// window is opaque, clip windows below
region -= w->shape().translated( w->x(), w->y());
}
// Fill any areas of the root window not covered by windows
paintBackground( region );
// Now walk the list bottom to top, drawing translucent windows.
// That we draw bottom to top is important now since we're drawing translucent objects
// and also are clipping only by opaque windows.
foreach( Phase2Data d, phase2 )
{
Window* w = d.window;
paintWindow( w, PAINT_WINDOW_TRANSLUCENT, d.region );
}
}
void Scene::WrapperEffect::prePaintWindow( Scene::Window* , int*, QRegion* )
{
// nothing, no changes
}
void Scene::paintWindow( Window* w, int mask, QRegion region )
{
WindowPaintData data;
// data.opacity = w->opacity();
WrapperEffect wrapper;
effects->paintWindow( w, mask, region, data, &wrapper );
}
// the function that'll be eventually called by paintWindow() above
void Scene::WrapperEffect::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data )
{
w->performPaint( region, mask );
}
void Scene::windowGeometryShapeChanged( Toplevel* )
{
}
@ -61,6 +155,10 @@ Scene::Window::~Window()
{
}
void Scene::Window::free()
{
}
void Scene::Window::discardShape()
{
shape_valid = false;

15
scene.h
View file

@ -11,8 +11,8 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_SCENE_H
#define KWIN_SCENE_H
#include "utils.h"
#include "toplevel.h"
#include "utils.h"
namespace KWinInternal
{
@ -48,15 +48,20 @@ class Scene
PAINT_SCREEN_REGION = 1 << 0,
PAINT_SCREEN_ALL = 1 << 1
};
virtual void paintGenericScreen();
virtual void paintSimpleScreen( QRegion region );
virtual void paintBackground( QRegion region ) = 0;
virtual void paintWindow( Window* w, int mask, QRegion region );
static QRegion infiniteRegion();
template< typename T >
struct Phase2Data
{
Phase2Data( T* w, QRegion r ) : window( w ), region( r ) {}
T* window;
Phase2Data( Window* w, QRegion r ) : window( w ), region( r ) {}
Window* window;
QRegion region;
};
QVector< Window* > stacking_order;
Workspace* wspace;
class WrapperEffect;
};
class Scene::Window
@ -64,6 +69,8 @@ class Scene::Window
public:
Window( Toplevel* c );
virtual ~Window();
virtual void free(); // is often copied by value, use manually instead of dtor
virtual void performPaint( QRegion region, int mask ) = 0;
int x() const;
int y() const;
int width() const;

View file

@ -56,4 +56,9 @@ void SceneBasic::paint( QRegion, ToplevelList windows )
XFlush( display());
}
void SceneBasic::paintBackground( QRegion )
{
// empty, not using inherited functionality
}
} // namespace

View file

@ -23,6 +23,8 @@ class SceneBasic
SceneBasic( Workspace* ws );
virtual ~SceneBasic();
virtual void paint( QRegion damage, ToplevelList windows );
protected:
virtual void paintBackground( QRegion region );
};
} // namespace

View file

@ -10,8 +10,6 @@ License. See the file "COPYING" for the exact licensing terms.
Based on glcompmgr code by Felix Bellaby.
******************************************************************/
#include "scene_opengl.h"
#include "utils.h"
@ -263,6 +261,11 @@ bool SceneOpenGL::findConfig( const int* attrs, GLXFBConfig& config, VisualID vi
void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
{
foreach( Toplevel* c, toplevels )
{
assert( windows.contains( c ));
stacking_order.append( &windows[ c ] );
}
grabXServer();
glXWaitX();
glPushMatrix();
@ -270,11 +273,6 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
glClear( GL_COLOR_BUFFER_BIT );
glScalef( 1, -1, 1 );
glTranslatef( 0, -displayHeight(), 0 );
foreach( Toplevel* c, toplevels )
{
assert( windows.contains( c ));
stacking_order.append( &windows[ c ] );
}
int mask = ( damage == QRegion( 0, 0, displayWidth(), displayHeight()))
? PAINT_SCREEN_ALL : PAINT_SCREEN_REGION;
WrapperEffect wrapper;
@ -283,6 +281,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
// TODO call also prePaintWindow() for all windows
ScreenPaintData data;
effects->paintScreen( mask, damage, data, &wrapper );
stacking_order.clear();
glPopMatrix();
// TODO only partial repaint for mask & PAINT_SCREEN_REGION
if( root_db )
@ -296,85 +295,14 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
}
ungrabXServer();
checkGLError( "PostPaint" );
stacking_order.clear();
}
void SceneOpenGL::WrapperEffect::prePaintScreen( int*, QRegion* )
{
// nothing, no changes
}
// the function that'll be eventually called by wrapper.peformPaintScreen() above
void SceneOpenGL::WrapperEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( mask & PAINT_SCREEN_REGION )
static_cast< SceneOpenGL* >( scene )->paintSimpleScreen( region );
else
static_cast< SceneOpenGL* >( scene )->paintGenericScreen();
}
// the generic painting code that should eventually handle even
// transformations
void SceneOpenGL::paintGenericScreen()
{
paintBackground( infiniteRegion());
foreach( Window* w, stacking_order ) // bottom to top
{
if( !w->isVisible())
continue;
paintWindow( w, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT, infiniteRegion());
}
}
// the optimized case without any transformations at all
void SceneOpenGL::paintSimpleScreen( QRegion region )
{
QList< Phase2Data > phase2;
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
region = QRegion( 0, 0, displayWidth(), displayHeight());
for( int i = stacking_order.count() - 1; // top to bottom
i >= 0;
--i )
{
Window* w = stacking_order[ i ];
if( !w->isVisible())
continue;
if( region.isEmpty()) // completely clipped
continue;
if( !w->isOpaque())
{
phase2.prepend( Phase2Data( w, region ));
continue;
}
paintWindow( w, PAINT_WINDOW_OPAQUE, region );
// window is opaque, clip windows below
region -= w->shape().translated( w->x(), w->y());
}
paintBackground( region );
foreach( Phase2Data d, phase2 )
{
Window* w = d.window;
paintWindow( w, PAINT_WINDOW_TRANSLUCENT, d.region );
}
}
void SceneOpenGL::WrapperEffect::prePaintWindow( Scene::Window* , int*, QRegion* )
{
// nothing, no changes
}
void SceneOpenGL::paintWindow( Window* w, int mask, QRegion region )
{
WindowPaintData data;
// data.opacity = w->opacity();
WrapperEffect wrapper;
effects->paintWindow( w, mask, region, data, &wrapper );
}
// the function that'll be eventually called by paintWindow() above
void SceneOpenGL::WrapperEffect::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data )
{
static_cast< Window* >( w )->performPaint( region, mask );
Scene::paintSimpleScreen( region );
}
void SceneOpenGL::paintBackground( QRegion )

View file

@ -12,7 +12,6 @@ License. See the file "COPYING" for the exact licensing terms.
#define KWIN_SCENE_OPENGL_H
#include "scene.h"
#include "effects.h"
#include <GL/gl.h>
#include <GL/glx.h>
@ -31,14 +30,12 @@ class SceneOpenGL
virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
protected:
virtual void paintSimpleScreen( QRegion region );
virtual void paintBackground( QRegion region );
private:
void initBuffer();
bool findConfig( const int* attrs, GLXFBConfig& config, VisualID visual = None );
void paintGenericScreen();
void paintSimpleScreen( QRegion region );
void paintBackground( QRegion region );
class Window;
void paintWindow( Window* w, int mask, QRegion region );
typedef GLuint Texture;
GC gcroot;
Drawable buffer;
@ -48,10 +45,8 @@ class SceneOpenGL
static GLXDrawable glxroot;
static GLXContext context;
static bool tfp_mode;
class Window;
QMap< Toplevel*, Window > windows;
QVector< Window* > stacking_order;
typedef Scene::Phase2Data< Window > Phase2Data;
class WrapperEffect;
};
class SceneOpenGL::Window
@ -59,8 +54,8 @@ class SceneOpenGL::Window
{
public:
Window( Toplevel* c );
void free(); // is often copied by value, use manually instead of dtor
void performPaint( QRegion region, int mask );
virtual void free();
virtual void performPaint( QRegion region, int mask );
void bindTexture();
void discardTexture();
Window() {} // QMap sucks even in Qt4
@ -71,17 +66,6 @@ class SceneOpenGL::Window
GLXPixmap bound_glxpixmap; // only for tfp_mode
};
// a special effect that is last in the order that'll actually call the painting functions
class SceneOpenGL::WrapperEffect
: public Effect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
};
} // namespace
#endif

View file

@ -88,8 +88,10 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
WrapperEffect wrapper;
// preparation step
effects->prePaintScreen( &mask, &damage, &wrapper );
// TODO call also prePaintWindow() for all windows
ScreenPaintData data;
effects->paintScreen( mask, damage, data, &wrapper );
stacking_order.clear();
if( mask & PAINT_SCREEN_REGION )
{
// Use the damage region as the clip region for the root window
@ -107,82 +109,6 @@ void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
XFlush( display());
}
stacking_order.clear();
}
void SceneXrender::WrapperEffect::prePaintScreen( int*, QRegion* )
{
// nothing, no changes
}
void SceneXrender::WrapperEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( mask & PAINT_SCREEN_REGION )
static_cast< SceneXrender* >( scene )->paintSimpleScreen( region );
else
static_cast< SceneXrender* >( scene )->paintGenericScreen();
}
void SceneXrender::paintGenericScreen()
{
paintBackground( infiniteRegion());
foreach( Window* w, stacking_order ) // bottom to top
{
if( !w->isVisible())
continue;
paintWindow( w, PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSLUCENT, infiniteRegion());
}
}
void SceneXrender::paintSimpleScreen( QRegion region )
{
QList< Phase2Data > phase2;
// Draw each opaque window top to bottom, subtracting the bounding rect of
// each window from the clip region after it's been drawn.
for( int i = stacking_order.count() - 1;
i >= 0;
--i )
{
Window* w = stacking_order[ i ];
if( !w->isVisible())
continue;
if( !w->isOpaque())
{
phase2.prepend( Phase2Data( w, region ));
continue;
}
paintWindow( w, PAINT_WINDOW_OPAQUE, region );
// window is opaque, clip windows below
region -= w->shape().translated( w->x(), w->y());
}
// Fill any areas of the root window not covered by windows
paintBackground( region );
// Now walk the list bottom to top, drawing translucent windows.
// That we draw bottom to top is important now since we're drawing translucent objects
// and also are clipping only by opaque windows.
foreach( Phase2Data d, phase2 )
{
Window* w = d.window;
paintWindow( w, PAINT_WINDOW_TRANSLUCENT, d.region );
}
}
void SceneXrender::WrapperEffect::prePaintWindow( Scene::Window* , int*, QRegion* )
{
// nothing, no changes
}
void SceneXrender::paintWindow( Window* w, int mask, QRegion region )
{
WindowPaintData data;
// data.opacity = w->opacity();
WrapperEffect wrapper;
effects->paintWindow( w, mask, region, data, &wrapper );
}
void SceneXrender::WrapperEffect::paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data )
{
static_cast< Window* >( w )->performPaint( region, mask );
}
void SceneXrender::paintBackground( QRegion region )

View file

@ -13,12 +13,11 @@ License. See the file "COPYING" for the exact licensing terms.
#include "config.h"
#include "scene.h"
#ifdef HAVE_XRENDER
#include <X11/extensions/Xrender.h>
#include "scene.h"
#include "effects.h"
namespace KWinInternal
{
@ -35,21 +34,16 @@ class SceneXrender
virtual void windowOpacityChanged( Toplevel* );
virtual void windowAdded( Toplevel* );
virtual void windowDeleted( Toplevel* );
protected:
virtual void paintBackground( QRegion region );
private:
void createBuffer();
void paintGenericScreen();
void paintSimpleScreen( QRegion region );
void paintBackground( QRegion region );
class Window;
void paintWindow( Window* w, int mask, QRegion region );
static XserverRegion toXserverRegion( QRegion region );
XRenderPictFormat* format;
Picture front;
static Picture buffer;
class Window;
QMap< Toplevel*, Window > windows;
QVector< Window* > stacking_order;
typedef Scene::Phase2Data< Window > Phase2Data;
class WrapperEffect;
};
class SceneXrender::Window
@ -57,8 +51,8 @@ class SceneXrender::Window
{
public:
Window( Toplevel* c );
void free(); // is often copied by value, use manually instead of dtor
void performPaint( QRegion region, int mask );
virtual void free();
virtual void performPaint( QRegion region, int mask );
void discardPicture();
void discardAlpha();
Window() {} // QMap sucks even in Qt4
@ -71,17 +65,6 @@ class SceneXrender::Window
double alpha_cached_opacity;
};
// a special effect that is last in the order that'll actually call the painting functions
class SceneXrender::WrapperEffect
: public Effect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void prePaintWindow( Scene::Window* w, int* mask, QRegion* region );
virtual void paintWindow( Scene::Window* w, int mask, QRegion region, WindowPaintData& data );
};
} // namespace
#endif