Separate more generic and simple screen paint.

svn path=/branches/work/kwin_composite/; revision=595559
This commit is contained in:
Luboš Luňák 2006-10-14 20:46:47 +00:00
parent 1069654076
commit 17e46e32fb
2 changed files with 71 additions and 38 deletions

View file

@ -32,6 +32,7 @@ GLXFBConfig SceneOpenGL::fbcdrawable;
GLXContext SceneOpenGL::context; GLXContext SceneOpenGL::context;
GLXPixmap SceneOpenGL::glxroot; GLXPixmap SceneOpenGL::glxroot;
bool SceneOpenGL::tfp_mode; // using glXBindTexImageEXT (texture_from_pixmap) bool SceneOpenGL::tfp_mode; // using glXBindTexImageEXT (texture_from_pixmap)
bool SceneOpenGL::root_db; // destination drawable is double-buffered
typedef void (*glXBindTexImageEXT_func)( Display* dpy, GLXDrawable drawable, typedef void (*glXBindTexImageEXT_func)( Display* dpy, GLXDrawable drawable,
int buffer, const int* attrib_list ); int buffer, const int* attrib_list );
@ -180,6 +181,7 @@ void SceneOpenGL::initBuffer()
{ {
buffer = rootWindow(); buffer = rootWindow();
glxroot = glXCreateWindow( display(), fbcroot, buffer, NULL ); glxroot = glXCreateWindow( display(), fbcroot, buffer, NULL );
glDrawBuffer( GL_BACK );
} }
else else
{ {
@ -262,15 +264,33 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList windows )
{ {
grabXServer(); grabXServer();
glXWaitX(); glXWaitX();
if( /*generic case*/false )
paintGenericScreen( windows );
else
paintSimpleScreen( damage, windows );
ungrabXServer();
checkGLError( "PostPaint" );
}
// the generic painting code that should eventually handle even
// transformations
void SceneOpenGL::paintGenericScreen( ToplevelList windows )
{
glPushMatrix(); glPushMatrix();
glClearColor( 0, 0, 0, 1 ); glClearColor( 0, 0, 0, 1 );
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*/false ) paintBackground( infiniteRegion());
paintGenericScreen( windows ); foreach( Toplevel* c, windows ) // bottom to top
else {
paintSimpleScreen( damage, windows ); assert( this->windows.contains( c ));
Window& w = this->windows[ c ];
if( !w.isVisible())
continue;
w.bindTexture();
w.paint( infiniteRegion(), PAINT_OPAQUE | PAINT_TRANSLUCENT );
}
glPopMatrix(); glPopMatrix();
if( root_db ) if( root_db )
glXSwapBuffers( display(), glxroot ); glXSwapBuffers( display(), glxroot );
@ -281,34 +301,16 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList windows )
XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, displayWidth(), displayHeight(), 0, 0 ); XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, displayWidth(), displayHeight(), 0, 0 );
XFlush( display()); XFlush( display());
} }
ungrabXServer();
checkGLError( "PostPaint" );
}
// the generic painting code that should eventually handle even
// transformations
void SceneOpenGL::paintGenericScreen( ToplevelList windows )
{
foreach( Toplevel* c, windows ) // bottom to top
{
assert( this->windows.contains( c ));
Window& w = this->windows[ c ];
if( !w.isVisible())
continue;
w.bindTexture();
if( !w.isOpaque())
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
w.paint( infiniteRegion());
glDisable( GL_BLEND );
}
} }
// the optimized case without any transformations at all // the optimized case without any transformations at all
void SceneOpenGL::paintSimpleScreen( QRegion damage, ToplevelList windows ) void SceneOpenGL::paintSimpleScreen( QRegion damage, ToplevelList windows )
{ {
glPushMatrix();
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glScalef( 1, -1, 1 );
glTranslatef( 0, -displayHeight(), 0 );
QList< Phase2Data > phase2; QList< Phase2Data > phase2;
QRegion region = damage; QRegion region = damage;
// TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar) // TODO repaint only damaged areas (means also don't do glXSwapBuffers and similar)
@ -330,7 +332,7 @@ void SceneOpenGL::paintSimpleScreen( QRegion damage, ToplevelList windows )
continue; continue;
} }
w.bindTexture(); w.bindTexture();
w.paint( region ); w.paint( region, PAINT_OPAQUE );
// window is opaque, clip windows below // window is opaque, clip windows below
region -= w.shape().translated( w.x(), w.y()); region -= w.shape().translated( w.x(), w.y());
} }
@ -339,10 +341,17 @@ void SceneOpenGL::paintSimpleScreen( QRegion damage, ToplevelList windows )
{ {
Window& w = *d.window; Window& w = *d.window;
w.bindTexture(); w.bindTexture();
glEnable( GL_BLEND ); w.paint( d.region, PAINT_TRANSLUCENT );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); }
w.paint( d.region ); glPopMatrix();
glDisable( GL_BLEND ); if( root_db )
glXSwapBuffers( display(), glxroot );
else
{
glFlush();
glXWaitGL();
XCopyArea( display(), buffer, rootWindow(), gcroot, 0, 0, displayWidth(), displayHeight(), 0, 0 );
XFlush( display());
} }
} }
@ -515,6 +524,8 @@ void SceneOpenGL::Window::bindTexture()
// the pixmap // the pixmap
glXDestroyPixmap( display(), pixmap ); glXDestroyPixmap( display(), pixmap );
XFreePixmap( display(), pix ); XFreePixmap( display(), pix );
if( root_db )
glDrawBuffer( GL_BACK );
} }
#ifdef ALPHA_CLEAR_COPY #ifdef ALPHA_CLEAR_COPY
if( alpha_clear ) if( alpha_clear )
@ -587,7 +598,7 @@ static void quadPaint( int x1, int y1, int x2, int y2, bool invert_y )
glVertex2i( x1, y2 ); glVertex2i( x1, y2 );
} }
void SceneOpenGL::Window::paint( QRegion region ) void SceneOpenGL::Window::paint( QRegion region, int mask )
{ {
// paint only requested areas // paint only requested areas
if( region != infiniteRegion()) // avoid integer overflow if( region != infiniteRegion()) // avoid integer overflow
@ -595,15 +606,31 @@ void SceneOpenGL::Window::paint( QRegion region )
region &= shape(); region &= shape();
if( region.isEmpty()) if( region.isEmpty())
return; return;
// TODO for double-buffered root glDrawBuffer( GL_BACK );
glXMakeContextCurrent( display(), glxroot, glxroot, context ); glXMakeContextCurrent( display(), glxroot, glxroot, context );
glPushMatrix(); glPushMatrix();
glTranslatef( x(), y(), 0 ); glTranslatef( x(), y(), 0 );
if( mask & ( PAINT_OPAQUE | PAINT_TRANSLUCENT ))
{}
else if( mask & PAINT_OPAQUE )
{
if( !isOpaque())
return;
}
else if( mask & PAINT_TRANSLUCENT )
{
if( isOpaque())
return;
}
bool was_blend = glIsEnabled( GL_BLEND );
if( !isOpaque())
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
if( toplevel->opacity() != 1.0 ) if( toplevel->opacity() != 1.0 )
{ {
if( toplevel->hasAlpha()) if( toplevel->hasAlpha())
{ {
glEnable( GL_BLEND );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glColor4f( toplevel->opacity(), toplevel->opacity(), toplevel->opacity(), glColor4f( toplevel->opacity(), toplevel->opacity(), toplevel->opacity(),
toplevel->opacity()); toplevel->opacity());
@ -632,8 +659,9 @@ void SceneOpenGL::Window::paint( QRegion region )
{ {
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
glColor4f( 0, 0, 0, 0 ); glColor4f( 0, 0, 0, 0 );
glDisable( GL_BLEND );
} }
if( !was_blend )
glDisable( GL_BLEND );
glDisable( GL_TEXTURE_RECTANGLE_ARB ); glDisable( GL_TEXTURE_RECTANGLE_ARB );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 ); glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 );
} }

View file

@ -38,11 +38,16 @@ class SceneOpenGL
void paintSimpleScreen( QRegion damage, ToplevelList windows ); void paintSimpleScreen( QRegion damage, ToplevelList windows );
void paintBackground( QRegion damage ); void paintBackground( QRegion damage );
static QRegion infiniteRegion(); static QRegion infiniteRegion();
enum
{
PAINT_OPAQUE = 1 << 0,
PAINT_TRANSLUCENT = 1 << 1
};
typedef GLuint Texture; typedef GLuint Texture;
GC gcroot; GC gcroot;
Drawable buffer; Drawable buffer;
GLXFBConfig fbcroot; GLXFBConfig fbcroot;
bool root_db; static bool root_db;
static GLXFBConfig fbcdrawable; static GLXFBConfig fbcdrawable;
static GLXDrawable glxroot; static GLXDrawable glxroot;
static GLXContext context; static GLXContext context;
@ -67,7 +72,7 @@ class SceneOpenGL::Window
int y() const; int y() const;
int width() const; int width() const;
int height() const; int height() const;
void paint( QRegion region ); void paint( QRegion region, int mask );
bool isVisible() const; bool isVisible() const;
bool isOpaque() const; bool isOpaque() const;
void bindTexture(); void bindTexture();