For simple paint, clip by above windows. A missing todo is to still

update only changed areas instead of doing full glXSwapBuffers()
when possible.


svn path=/branches/work/kwin_composite/; revision=595357
This commit is contained in:
Luboš Luňák 2006-10-14 07:15:23 +00:00
parent b60b847e25
commit 004d781e32
3 changed files with 53 additions and 19 deletions

View file

@ -73,7 +73,8 @@ TODO:
/ design framework for graphical effects / design framework for graphical effects
- modelling it after compiz seems to make a lot of sense - modelling it after compiz seems to make a lot of sense
* make paintSimpleScreen() clip non-visible parts * update only those parts of the screen that have been changed
- clip parts of lower windows by parts of windows above them, so that those parts - for paintSimpleScreen() - it currently sets region to the whole screen
don't need to be painted - instead of using glXSwapBuffers() or XCopyArea() that update the whole screen,
- similarly like in scene_xrender.cpp there should be glCopyPixels() used
- compiz has such code in evenLoop() in the if() block for COMP_SCREEN_DAMAGE_REGION_MASK

View file

@ -267,7 +267,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList windows )
glClear( GL_COLOR_BUFFER_BIT ); glClear( GL_COLOR_BUFFER_BIT );
glScalef( 1, -1, 1 ); glScalef( 1, -1, 1 );
glTranslatef( 0, -displayHeight(), 0 ); glTranslatef( 0, -displayHeight(), 0 );
if( /*generic case*/true ) if( /*generic case*/false )
paintGenericScreen( windows ); paintGenericScreen( windows );
else else
paintSimpleScreen( damage, windows ); paintSimpleScreen( damage, windows );
@ -285,7 +285,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList windows )
checkGLError( "PostPaint" ); checkGLError( "PostPaint" );
} }
// the generic drawing code that should eventually handle even // the generic painting code that should eventually handle even
// transformations // transformations
void SceneOpenGL::paintGenericScreen( ToplevelList windows ) void SceneOpenGL::paintGenericScreen( ToplevelList windows )
{ {
@ -301,15 +301,18 @@ void SceneOpenGL::paintGenericScreen( ToplevelList windows )
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
} }
w.draw(); w.paint( infiniteRegion());
glDisable( GL_BLEND ); glDisable( GL_BLEND );
} }
} }
// the optimized case without any transformations at all // the optimized case without any transformations at all
void SceneOpenGL::paintSimpleScreen( QRegion, ToplevelList windows ) void SceneOpenGL::paintSimpleScreen( QRegion damage, ToplevelList windows )
{ {
QList< Window* > phase2; QList< Phase2Data > phase2;
QRegion region = damage;
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
region = QRegion( 0, 0, displayWidth(), displayHeight());
for( int i = windows.count() - 1; // top to bottom for( int i = windows.count() - 1; // top to bottom
i >= 0; i >= 0;
--i ) --i )
@ -319,25 +322,35 @@ void SceneOpenGL::paintSimpleScreen( QRegion, ToplevelList windows )
Window& w = this->windows[ c ]; Window& w = this->windows[ c ];
if( !w.isVisible()) if( !w.isVisible())
continue; continue;
if( region.isEmpty()) // completely clipped
continue;
if( !w.isOpaque()) if( !w.isOpaque())
{ {
phase2.prepend( &w ); phase2.prepend( Phase2Data( &w, region ));
continue; continue;
} }
w.bindTexture(); w.bindTexture();
w.draw(); w.paint( region );
// window is opaque, clip windows below
region -= w.shape().translated( w.x(), w.y());
} }
foreach( Window* w2, phase2 ) paintBackground( region );
foreach( Phase2Data d, phase2 )
{ {
Window& w = *w2; Window& w = *d.window;
w.bindTexture(); w.bindTexture();
glEnable( GL_BLEND ); glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
w.draw(); w.paint( d.region );
glDisable( GL_BLEND ); glDisable( GL_BLEND );
} }
} }
void SceneOpenGL::paintBackground( QRegion )
{
// TODO?
}
void SceneOpenGL::windowAdded( Toplevel* c ) void SceneOpenGL::windowAdded( Toplevel* c )
{ {
assert( !windows.contains( c )); assert( !windows.contains( c ));
@ -562,7 +575,7 @@ QRegion SceneOpenGL::Window::shape() const
return shape_region; return shape_region;
} }
static void quadDraw( int x1, int y1, int x2, int y2, bool invert_y ) static void quadPaint( int x1, int y1, int x2, int y2, bool invert_y )
{ {
glTexCoord2i( x1, invert_y ? y2 : y1 ); glTexCoord2i( x1, invert_y ? y2 : y1 );
glVertex2i( x1, y1 ); glVertex2i( x1, y1 );
@ -574,8 +587,14 @@ static void quadDraw( int x1, int y1, int x2, int y2, bool invert_y )
glVertex2i( x1, y2 ); glVertex2i( x1, y2 );
} }
void SceneOpenGL::Window::draw() void SceneOpenGL::Window::paint( QRegion region )
{ {
// paint only requested areas
if( region != infiniteRegion()) // avoid integer overflow
region.translate( -x(), -y());
region &= shape();
if( region.isEmpty())
return;
// TODO for double-buffered root glDrawBuffer( GL_BACK ); // TODO for double-buffered root glDrawBuffer( GL_BACK );
glXMakeContextCurrent( display(), glxroot, glxroot, context ); glXMakeContextCurrent( display(), glxroot, glxroot, context );
glPushMatrix(); glPushMatrix();
@ -602,9 +621,9 @@ void SceneOpenGL::Window::draw()
} }
glEnable( GL_TEXTURE_RECTANGLE_ARB ); glEnable( GL_TEXTURE_RECTANGLE_ARB );
glBegin( GL_QUADS ); glBegin( GL_QUADS );
foreach( QRect r, shape().rects()) foreach( QRect r, region.rects())
{ {
quadDraw( r.x(), r.y(), r.x() + r.width(), r.y() + r.height(), quadPaint( r.x(), r.y(), r.x() + r.width(), r.y() + r.height(),
texture_y_inverted ); texture_y_inverted );
} }
glEnd(); glEnd();

View file

@ -36,6 +36,8 @@ class SceneOpenGL
bool findConfig( const int* attrs, GLXFBConfig& config, VisualID visual = None ); bool findConfig( const int* attrs, GLXFBConfig& config, VisualID visual = None );
void paintGenericScreen( ToplevelList windows ); void paintGenericScreen( ToplevelList windows );
void paintSimpleScreen( QRegion damage, ToplevelList windows ); void paintSimpleScreen( QRegion damage, ToplevelList windows );
void paintBackground( QRegion damage );
static QRegion infiniteRegion();
typedef GLuint Texture; typedef GLuint Texture;
GC gcroot; GC gcroot;
Drawable buffer; Drawable buffer;
@ -47,6 +49,12 @@ class SceneOpenGL
static bool tfp_mode; static bool tfp_mode;
class Window; class Window;
QMap< Toplevel*, Window > windows; QMap< Toplevel*, Window > windows;
struct Phase2Data
{
Phase2Data( Window* w, QRegion r ) : window( w ), region( r ) {}
Window* window;
QRegion region;
};
}; };
class SceneOpenGL::Window class SceneOpenGL::Window
@ -59,7 +67,7 @@ class SceneOpenGL::Window
int y() const; int y() const;
int width() const; int width() const;
int height() const; int height() const;
void draw(); void paint( QRegion region );
bool isVisible() const; bool isVisible() const;
bool isOpaque() const; bool isOpaque() const;
void bindTexture(); void bindTexture();
@ -77,6 +85,12 @@ class SceneOpenGL::Window
mutable bool shape_valid; mutable bool shape_valid;
}; };
inline
QRegion SceneOpenGL::infiniteRegion()
{ // INT_MIN / 2 because it's width/height (INT_MIN+INT_MAX==-1)
return QRegion( INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX );
}
inline inline
int SceneOpenGL::Window::x() const int SceneOpenGL::Window::x() const
{ {