diff --git a/effects.h b/effects.h index 1769d6667d..b9bc6b056c 100644 --- a/effects.h +++ b/effects.h @@ -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 ) diff --git a/scene.cpp b/scene.cpp index a4c9ec7ae7..c9ed1c96ea 100644 --- a/scene.cpp +++ b/scene.cpp @@ -13,9 +13,19 @@ License. See the file "COPYING" for the exact licensing terms. #include +#include "effects.h" + namespace KWinInternal { +//**************************************** +// Scene::WrapperEffect +//**************************************** + +Scene::WrapperEffect::~WrapperEffect() + { + } + //**************************************** // Scene //**************************************** @@ -30,7 +40,91 @@ Scene::Scene( Workspace* ws ) 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; diff --git a/scene.h b/scene.h index b933aa7f64..c1d5f8df47 100644 --- a/scene.h +++ b/scene.h @@ -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; diff --git a/scene_basic.cpp b/scene_basic.cpp index c237074d85..91846e6dbd 100644 --- a/scene_basic.cpp +++ b/scene_basic.cpp @@ -56,4 +56,9 @@ void SceneBasic::paint( QRegion, ToplevelList windows ) XFlush( display()); } +void SceneBasic::paintBackground( QRegion ) + { + // empty, not using inherited functionality + } + } // namespace diff --git a/scene_basic.h b/scene_basic.h index 8c5756b64e..d972fe05a6 100644 --- a/scene_basic.h +++ b/scene_basic.h @@ -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 diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 8d9ccc9a76..6919d86009 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -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 ) diff --git a/scene_opengl.h b/scene_opengl.h index f9a4148d4c..b865363cd8 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -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 #include @@ -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 diff --git a/scene_xrender.cpp b/scene_xrender.cpp index a1327aba40..b346791ab1 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -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 ) diff --git a/scene_xrender.h b/scene_xrender.h index 2ca70a4f58..be1ed873a7 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -13,12 +13,11 @@ License. See the file "COPYING" for the exact licensing terms. #include "config.h" +#include "scene.h" + #ifdef HAVE_XRENDER #include -#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