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
|
/ 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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue