diff --git a/composite.cpp b/composite.cpp index 6f1a2d378f..192e96a0c0 100644 --- a/composite.cpp +++ b/composite.cpp @@ -45,12 +45,20 @@ void Workspace::setupCompositing() c->setupCompositing(); foreach( Unmanaged* c, unmanaged ) c->setupCompositing(); + foreach( Client* c, clients ) + scene->windowAdded( c ); + foreach( Unmanaged* c, unmanaged ) + scene->windowAdded( c ); } void Workspace::finishCompositing() { if( scene == NULL ) return; + foreach( Client* c, clients ) + scene->windowDeleted( c ); + foreach( Unmanaged* c, unmanaged ) + scene->windowDeleted( c ); foreach( Client* c, clients ) c->finishCompositing(); foreach( Unmanaged* c, unmanaged ) diff --git a/scene.cpp b/scene.cpp index 2a7d1af24c..4229fa024a 100644 --- a/scene.cpp +++ b/scene.cpp @@ -34,6 +34,10 @@ void Scene::windowOpacityChanged( Toplevel* ) { } +void Scene::windowAdded( Toplevel* ) + { + } + void Scene::windowDeleted( Toplevel* ) { } diff --git a/scene.h b/scene.h index 1f4e3cea6c..fdc9af563b 100644 --- a/scene.h +++ b/scene.h @@ -26,6 +26,7 @@ class Scene virtual void paint( XserverRegion damage, ToplevelList windows ) = 0; virtual void windowGeometryShapeChanged( Toplevel* ); virtual void windowOpacityChanged( Toplevel* ); + virtual void windowAdded( Toplevel* ); virtual void windowDeleted( Toplevel* ); virtual void transformWindowDamage( Toplevel*, XserverRegion ) const; virtual void updateTransformation( Toplevel* ); diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 2636c89a9e..f08be4b3df 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -24,6 +24,8 @@ namespace KWinInternal // SceneOpenGL //**************************************** +GLXFBConfig SceneOpenGL::fbcdrawable; + const int root_attrs[] = { GLX_DOUBLEBUFFER, False, @@ -81,6 +83,10 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) SceneOpenGL::~SceneOpenGL() { + for( QMap< Toplevel*, Window >::Iterator it = windows.begin(); + it != windows.end(); + ++it ) + (*it).free(); glXDestroyPixmap( display(), glxroot ); XFreeGC( display(), gcroot ); XFreePixmap( display(), buffer ); @@ -99,17 +105,12 @@ static void quadDraw( int x, int y, int w, int h ) glVertex2i( x, y + h ); } -GLuint txts[ 100 ]; -int txts_i = 0; -GLXDrawable drws[ 100 ]; -int drws_i; - void SceneOpenGL::paint( XserverRegion, ToplevelList windows ) { + grabXServer(); + glXWaitX(); glClearColor( 0, 0, 0, 1 ); glClear( GL_COLOR_BUFFER_BIT /* TODO| GL_DEPTH_BUFFER_BIT*/ ); - txts_i = 0; - drws_i = 0; for( ToplevelList::ConstIterator it = windows.begin(); it != windows.end(); ++it ) @@ -117,19 +118,16 @@ void SceneOpenGL::paint( XserverRegion, ToplevelList windows ) QRect r = (*it)->geometry().intersect( QRect( 0, 0, displayWidth(), displayHeight())); if( !r.isEmpty()) { - GLXDrawable gldraw = glXCreatePixmap( display(), fbcdrawable, - (*it)->windowPixmap(), NULL ); - glXMakeContextCurrent( display(), gldraw, gldraw, context ); + assert( this->windows.contains( *it )); + Window& w = this->windows[ *it ]; + GLXDrawable pixmap = w.glxPixmap(); + glXMakeContextCurrent( display(), pixmap, pixmap, context ); glReadBuffer( GL_FRONT ); glDrawBuffer( GL_FRONT ); - // TODO grabXServer(); - glXWaitX(); - GLuint texture; - glGenTextures( 1, &texture ); + Texture texture = w.texture(); glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture ); glCopyTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, (*it)->width(), (*it)->height(), 0 ); - //ungrabXServer(); glXMakeContextCurrent( display(), glxroot, glxroot, context ); glDrawBuffer( GL_BACK ); glPushMatrix(); @@ -143,21 +141,57 @@ void SceneOpenGL::paint( XserverRegion, ToplevelList windows ) glDisable( GL_TEXTURE_RECTANGLE_ARB ); glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 ); glXWaitGL(); - txts[ txts_i++ ] = texture; - drws[ drws_i++ ] = gldraw; } } glFlush(); XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, displayWidth(), displayHeight(), 0, 0 ); + ungrabXServer(); XFlush( display()); - for( int i = 0; - i < txts_i; - ++i ) - glDeleteTextures( 1, &txts[ i ] ); - for( int i = 0; - i < drws_i; - ++i ) - glXDestroyPixmap( display(), drws[ i ] ); + } + +void SceneOpenGL::windowAdded( Toplevel* c ) + { + assert( !windows.contains( c )); + windows[ c ] = Window( c ); + } + +void SceneOpenGL::windowDeleted( Toplevel* c ) + { + assert( windows.contains( c )); + windows[ c ].free(); + windows.remove( c ); + } + +SceneOpenGL::Window::Window( Toplevel* c ) + : toplevel( c ) + , glxpixmap( None ) + , gltexture( None ) + { + } + +SceneOpenGL::Window::~Window() + { + } + +void SceneOpenGL::Window::free() + { + discardPixmap(); + discardTexture(); + } + +GLXPixmap SceneOpenGL::Window::glxPixmap() const + { + if( glxpixmap == None ) + glxpixmap = glXCreatePixmap( display(), fbcdrawable, + toplevel->windowPixmap(), NULL ); + return glxpixmap; + } + +SceneOpenGL::Texture SceneOpenGL::Window::texture() const + { + if( gltexture == None ) + glGenTextures( 1, &gltexture ); + return gltexture; } } // namespace diff --git a/scene_opengl.h b/scene_opengl.h index ad00287558..7d3533ef20 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -26,15 +26,53 @@ class SceneOpenGL SceneOpenGL( Workspace* ws ); virtual ~SceneOpenGL(); virtual void paint( XserverRegion damage, ToplevelList windows ); + virtual void windowAdded( Toplevel* ); + virtual void windowDeleted( Toplevel* ); private: + typedef GLuint Texture; GC gcroot; Pixmap buffer; GLXFBConfig fbcroot; - GLXFBConfig fbcdrawable; + static GLXFBConfig fbcdrawable; GLXPixmap glxroot; GLXContext context; + class Window; + QMap< Toplevel*, Window > windows; }; +class SceneOpenGL::Window + { + public: + Window( Toplevel* c ); + ~Window(); + void free(); // is often copied by value, use manually instead of dtor + GLXPixmap glxPixmap() const; + Texture texture() const; + Window() {} // QMap sucks even in Qt4 + private: + void discardPixmap(); + void discardTexture(); + Toplevel* toplevel; + mutable GLXPixmap glxpixmap; + mutable Texture gltexture; + }; + +inline +void SceneOpenGL::Window::discardPixmap() + { + if( glxpixmap != None ) + glXDestroyPixmap( display(), glxpixmap ); + glxpixmap = None; + } + +inline +void SceneOpenGL::Window::discardTexture() + { + if( gltexture != None ) + glDeleteTextures( 1, &gltexture ); + gltexture = None; + } + } // namespace #endif diff --git a/scene_xrender.cpp b/scene_xrender.cpp index d028e427e4..3c76bca62e 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -202,12 +202,17 @@ void SceneXrender::windowOpacityChanged( Toplevel* c ) void SceneXrender::windowDeleted( Toplevel* c ) { - if( !window_data.contains( c )) - return; + assert( window_data.contains( c )); window_data[ c ].free(); window_data.remove( c ); } +void SceneXrender::windowAdded( Toplevel* c ) + { + assert( !window_data.contains( c )); + resetWindowData( c ); + } + // TODO handle xrandr changes void SceneXrender::createBuffer() diff --git a/scene_xrender.h b/scene_xrender.h index 69425948e1..281db07513 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -33,6 +33,7 @@ class SceneXrender virtual void paint( XserverRegion damage, ToplevelList windows ); virtual void windowGeometryShapeChanged( Toplevel* ); virtual void windowOpacityChanged( Toplevel* ); + virtual void windowAdded( Toplevel* ); virtual void windowDeleted( Toplevel* ); virtual void transformWindowDamage( Toplevel*, XserverRegion ) const; virtual void updateTransformation( Toplevel* ); diff --git a/toplevel.cpp b/toplevel.cpp index 9964dd8eff..da5a69256a 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -10,8 +10,6 @@ License. See the file "COPYING" for the exact licensing terms. #include "toplevel.h" -#include "scene.h" - namespace KWinInternal { @@ -30,8 +28,6 @@ Toplevel::~Toplevel() assert( damage_handle == None ); assert( damage_region == None ); assert( window_pixmap == None ); - if( scene != NULL ) - scene->windowDeleted( this ); } #ifndef NDEBUG diff --git a/workspace.cpp b/workspace.cpp index d89650f3a4..4b65df1ce2 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -43,6 +43,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "rules.h" #include "kwinadaptor.h" #include "unmanaged.h" +#include "scene.h" #include #include @@ -486,6 +487,8 @@ Client* Workspace::createClient( Window w, bool is_mapped ) return NULL; } addClient( c, Allowed ); + if( scene ) + scene->windowAdded( c ); return c; } @@ -498,6 +501,8 @@ Unmanaged* Workspace::createUnmanaged( Window w ) return NULL; } addUnmanaged( c, Allowed ); + if( scene ) + scene->windowAdded( c ); return c; } @@ -564,6 +569,8 @@ void Workspace::removeClient( Client* c, allowed_t ) Notify::raise( Notify::Delete ); Q_ASSERT( clients.contains( c ) || desktops.contains( c )); + if( scene ) + scene->windowDeleted( c ); clients.removeAll( c ); desktops.removeAll( c ); unconstrained_stacking_order.removeAll( c ); @@ -602,6 +609,8 @@ void Workspace::removeClient( Client* c, allowed_t ) void Workspace::removeUnmanaged( Unmanaged* c, allowed_t ) { assert( unmanaged.contains( c )); + if( scene ) + scene->windowDeleted( c ); unmanaged.removeAll( c ); }