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:
parent
b60b847e25
commit
004d781e32
3 changed files with 53 additions and 19 deletions
|
@ -73,7 +73,8 @@ TODO:
|
|||
/ design framework for graphical effects
|
||||
- modelling it after compiz seems to make a lot of sense
|
||||
|
||||
* make paintSimpleScreen() clip non-visible parts
|
||||
- clip parts of lower windows by parts of windows above them, so that those parts
|
||||
don't need to be painted
|
||||
- similarly like in scene_xrender.cpp
|
||||
* update only those parts of the screen that have been changed
|
||||
- for paintSimpleScreen() - it currently sets region to the whole screen
|
||||
- instead of using glXSwapBuffers() or XCopyArea() that update the whole screen,
|
||||
there should be glCopyPixels() used
|
||||
- compiz has such code in evenLoop() in the if() block for COMP_SCREEN_DAMAGE_REGION_MASK
|
||||
|
|
|
@ -267,7 +267,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList windows )
|
|||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
glScalef( 1, -1, 1 );
|
||||
glTranslatef( 0, -displayHeight(), 0 );
|
||||
if( /*generic case*/true )
|
||||
if( /*generic case*/false )
|
||||
paintGenericScreen( windows );
|
||||
else
|
||||
paintSimpleScreen( damage, windows );
|
||||
|
@ -285,7 +285,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList windows )
|
|||
checkGLError( "PostPaint" );
|
||||
}
|
||||
|
||||
// the generic drawing code that should eventually handle even
|
||||
// the generic painting code that should eventually handle even
|
||||
// transformations
|
||||
void SceneOpenGL::paintGenericScreen( ToplevelList windows )
|
||||
{
|
||||
|
@ -301,15 +301,18 @@ void SceneOpenGL::paintGenericScreen( ToplevelList windows )
|
|||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
w.draw();
|
||||
w.paint( infiniteRegion());
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
i >= 0;
|
||||
--i )
|
||||
|
@ -319,25 +322,35 @@ void SceneOpenGL::paintSimpleScreen( QRegion, ToplevelList windows )
|
|||
Window& w = this->windows[ c ];
|
||||
if( !w.isVisible())
|
||||
continue;
|
||||
if( region.isEmpty()) // completely clipped
|
||||
continue;
|
||||
if( !w.isOpaque())
|
||||
{
|
||||
phase2.prepend( &w );
|
||||
phase2.prepend( Phase2Data( &w, region ));
|
||||
continue;
|
||||
}
|
||||
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();
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
w.draw();
|
||||
w.paint( d.region );
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
}
|
||||
|
||||
void SceneOpenGL::paintBackground( QRegion )
|
||||
{
|
||||
// TODO?
|
||||
}
|
||||
|
||||
void SceneOpenGL::windowAdded( Toplevel* c )
|
||||
{
|
||||
assert( !windows.contains( c ));
|
||||
|
@ -562,7 +575,7 @@ QRegion SceneOpenGL::Window::shape() const
|
|||
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 );
|
||||
glVertex2i( x1, y1 );
|
||||
|
@ -574,8 +587,14 @@ static void quadDraw( int x1, int y1, int x2, int y2, bool invert_y )
|
|||
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 );
|
||||
glXMakeContextCurrent( display(), glxroot, glxroot, context );
|
||||
glPushMatrix();
|
||||
|
@ -602,9 +621,9 @@ void SceneOpenGL::Window::draw()
|
|||
}
|
||||
glEnable( GL_TEXTURE_RECTANGLE_ARB );
|
||||
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 );
|
||||
}
|
||||
glEnd();
|
||||
|
|
|
@ -36,6 +36,8 @@ class SceneOpenGL
|
|||
bool findConfig( const int* attrs, GLXFBConfig& config, VisualID visual = None );
|
||||
void paintGenericScreen( ToplevelList windows );
|
||||
void paintSimpleScreen( QRegion damage, ToplevelList windows );
|
||||
void paintBackground( QRegion damage );
|
||||
static QRegion infiniteRegion();
|
||||
typedef GLuint Texture;
|
||||
GC gcroot;
|
||||
Drawable buffer;
|
||||
|
@ -47,6 +49,12 @@ class SceneOpenGL
|
|||
static bool tfp_mode;
|
||||
class Window;
|
||||
QMap< Toplevel*, Window > windows;
|
||||
struct Phase2Data
|
||||
{
|
||||
Phase2Data( Window* w, QRegion r ) : window( w ), region( r ) {}
|
||||
Window* window;
|
||||
QRegion region;
|
||||
};
|
||||
};
|
||||
|
||||
class SceneOpenGL::Window
|
||||
|
@ -59,7 +67,7 @@ class SceneOpenGL::Window
|
|||
int y() const;
|
||||
int width() const;
|
||||
int height() const;
|
||||
void draw();
|
||||
void paint( QRegion region );
|
||||
bool isVisible() const;
|
||||
bool isOpaque() const;
|
||||
void bindTexture();
|
||||
|
@ -77,6 +85,12 @@ class SceneOpenGL::Window
|
|||
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
|
||||
int SceneOpenGL::Window::x() const
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue