From 6e54bae328fe34a2ca900ff1c0a45b18a5a23434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Sun, 19 Nov 2006 20:10:25 +0000 Subject: [PATCH] Try to reduce number of roundtrips in SHM mode by merging region rectangles. svn path=/branches/work/kwin_composite/; revision=606267 --- scene_opengl.cpp | 38 +++++++++++++++++++++++++++----------- scene_opengl.h | 1 + 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 5dff05ffd3..37326fe769 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -603,7 +603,8 @@ void SceneOpenGL::Window::bindTexture() xgcv.graphics_exposures = False; xgcv.subwindow_mode = IncludeInferiors; GC gc = XCreateGC( display(), pix, GCGraphicsExposures | GCSubwindowMode, &xgcv ); - foreach( QRect r, toplevel->damage().rects()) + QRegion damage = optimizeBindDamage( toplevel->damage(), 100 * 100 ); + foreach( QRect r, damage.rects()) { // TODO for small areas it might be faster to not use SHM to avoid the XSync() Pixmap p = XShmCreatePixmap( display(), rootWindow(), shm.shmaddr, &shm, r.width(), r.height(), toplevel->depth()); @@ -670,17 +671,15 @@ void SceneOpenGL::Window::bindTexture() else { glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture ); - if( !toplevel->damage().isEmpty()) + QRegion damage = optimizeBindDamage( toplevel->damage(), 30 * 30 ); + foreach( QRect r, damage.rects()) { - foreach( QRect r, toplevel->damage().rects()) - { - // convert to OpenGL coordinates (this is mapping - // the pixmap to a texture, this is not affected - // by using glOrtho() for the OpenGL scene) - int gly = toplevel->height() - r.y() - r.height(); - glCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, - r.x(), gly, r.x(), gly, r.width(), r.height()); - } + // convert to OpenGL coordinates (this is mapping + // the pixmap to a texture, this is not affected + // by using glOrtho() for the OpenGL scene) + int gly = toplevel->height() - r.y() - r.height(); + glCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, + r.x(), gly, r.x(), gly, r.width(), r.height()); } } glXWaitGL(); @@ -698,6 +697,23 @@ void SceneOpenGL::Window::bindTexture() XFreePixmap( display(), window_pix ); } + +QRegion SceneOpenGL::Window::optimizeBindDamage( const QRegion& reg, int limit ) + { + if( reg.rects().count() <= 1 ) + return reg; + // try to reduce the number of rects, as especially with SHM mode every rect + // causes X roundtrip, even for very small areas - so, when the size difference + // between all the areas and the bounding rectangle is small, simply use + // only the bounding rectangle + int size = 0; + foreach( QRect r, reg.rects()) + size += r.width() * r.height(); + if( reg.boundingRect().width() * reg.boundingRect().height() - size < limit ) + return reg.boundingRect(); + return reg; + } + void SceneOpenGL::Window::enableTexture() { glEnable( GL_TEXTURE_RECTANGLE_ARB ); diff --git a/scene_opengl.h b/scene_opengl.h index 335a2698f4..fc7bf55903 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -76,6 +76,7 @@ class SceneOpenGL::Window void discardTexture(); Window() {} // QMap sucks even in Qt4 private: + QRegion optimizeBindDamage( const QRegion& reg, int limit ); Texture texture; bool texture_y_inverted; // texture has y inverted Pixmap bound_pixmap; // the pixmap the texture is bound to, only for tfp_mode