diff --git a/glutils.cpp b/glutils.cpp index 8e5375099f..9e00283933 100644 --- a/glutils.cpp +++ b/glutils.cpp @@ -31,6 +31,8 @@ glXReleaseTexImageEXT_func glXReleaseTexImageEXT; glXBindTexImageEXT_func glXBindTexImageEXT; // glActiveTexture glActiveTexture_func glActiveTexture; +// glXCopySubBufferMESA +glXCopySubBuffer_func glXCopySubBuffer; // Functions @@ -52,7 +54,7 @@ void initGLX() glXGetProcAddress = (glXGetProcAddress_func) getProcAddress( "glxGetProcAddressARB" ); glXBindTexImageEXT = (glXBindTexImageEXT_func) getProcAddress( "glXBindTexImageEXT" ); glXReleaseTexImageEXT = (glXReleaseTexImageEXT_func) getProcAddress( "glXReleaseTexImageEXT" ); - + glXCopySubBuffer = (glXCopySubBuffer_func) getProcAddress( "glXCopySubBufferMESA" ); // Get GLX version int major, minor; @@ -70,7 +72,6 @@ void initGL() if( !glActiveTexture ) glActiveTexture = (glActiveTexture_func) getProcAddress( "glActiveTextureARB" ); - // Get OpenGL version QString glversionstring = QString((const char*)glGetString(GL_VERSION)); QStringList glversioninfo = glversionstring.left(glversionstring.indexOf(' ')).split('.'); diff --git a/glutils.h b/glutils.h index 93886aea22..cc537f1170 100644 --- a/glutils.h +++ b/glutils.h @@ -82,6 +82,9 @@ extern glXBindTexImageEXT_func glXBindTexImageEXT; // glActiveTexture typedef void (*glActiveTexture_func)(GLenum); extern glActiveTexture_func glActiveTexture; +// glXCopySubBufferMESA +typedef void (*glXCopySubBuffer_func) ( Display* , GLXDrawable, int, int, int, int ); +extern glXCopySubBuffer_func glXCopySubBuffer; } // namespace diff --git a/scene_opengl.cpp b/scene_opengl.cpp index e17b7a59da..ccd902446b 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -446,10 +446,40 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels ) int mask = 0; paintScreen( &mask, &damage ); // call generic implementation glPopMatrix(); - // TODO only partial repaint for mask & PAINT_SCREEN_REGION + flushBuffer( mask, damage ); + ungrabXServer(); + } + +// actually paint to the screen (double-buffer swap or copy from pixmap buffer) +void SceneOpenGL::flushBuffer( int mask, const QRegion& damage ) + { if( db ) { - glXSwapBuffers( display(), glxbuffer ); + if( mask & PAINT_SCREEN_REGION ) + { + if( glXCopySubBuffer ) + { + foreach( QRect r, damage.rects()) + glXCopySubBuffer( display(), glxbuffer, r.x(), r.y(), r.width(), r.height()); + } + else + { // no idea why glScissor() is used, but Compiz has it and it doesn't seem to hurt + glEnable( GL_SCISSOR_TEST ); + glDrawBuffer( GL_FRONT ); + foreach( QRect r, damage.rects()) + { + // convert to OpenGL coordinates + int y = displayHeight() - r.y() - r.height(); + glRasterPos2f( r.x(), r.y() + r.height()); + glScissor( r.x(), y, r.width(), r.height()); + glCopyPixels( r.x(), y, r.width(), r.height(), GL_COLOR ); + } + glDrawBuffer( GL_BACK ); + glDisable( GL_SCISSOR_TEST ); + } + } + else + glXSwapBuffers( display(), glxbuffer ); glXWaitGL(); XFlush( display()); } @@ -457,10 +487,13 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels ) { glFlush(); glXWaitGL(); - XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, displayWidth(), displayHeight(), 0, 0 ); + if( mask & PAINT_SCREEN_REGION ) + foreach( QRect r, damage.rects()) + XCopyArea( display(), buffer, rootWindow(), gcroot, r.x(), r.y(), r.width(), r.height(), r.x(), r.y()); + else + XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, displayWidth(), displayHeight(), 0, 0 ); XFlush( display()); } - ungrabXServer(); } void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data ) @@ -475,15 +508,6 @@ void SceneOpenGL::paintGenericScreen( int mask, ScreenPaintData data ) glPopMatrix(); } -// the optimized case without any transformations at all -void SceneOpenGL::paintSimpleScreen( int mask, QRegion region ) - { - // TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar) - // For now always force redrawing of the whole area. - region = QRegion( 0, 0, displayWidth(), displayHeight()); - Scene::paintSimpleScreen( mask, region ); - } - void SceneOpenGL::paintBackground( QRegion ) { // TODO? diff --git a/scene_opengl.h b/scene_opengl.h index fd20b8e8e7..b55a58fe10 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -35,7 +35,6 @@ class SceneOpenGL virtual void windowDeleted( Toplevel* ); protected: virtual void paintGenericScreen( int mask, ScreenPaintData data ); - virtual void paintSimpleScreen( int mask, QRegion region ); virtual void paintBackground( QRegion region ); private: void selectMode(); @@ -45,6 +44,7 @@ class SceneOpenGL void initBuffer(); void initRenderingContext(); bool findConfig( const int* attrs, GLXFBConfig* config, VisualID visual = None ); + void flushBuffer( int mask, const QRegion& damage ); typedef GLuint Texture; GC gcroot; Drawable buffer;