Opengl transparency.

svn path=/branches/work/kwin_composite/; revision=590751
icc-effect-5.14.5
Luboš Luňák 2006-09-30 18:09:41 +00:00
parent ace6b4ad8a
commit d65ebbcb5f
5 changed files with 93 additions and 25 deletions

View File

@ -54,6 +54,7 @@ bool Client::manage( Window w, bool isMapped )
embedClient( w, attr );
vis = attr.visual;
depth = attr.depth;
setupCompositing();

View File

@ -28,6 +28,7 @@ namespace KWinInternal
GLXFBConfig SceneOpenGL::fbcdrawable;
GLXContext SceneOpenGL::context;
GLXPixmap SceneOpenGL::glxroot;
const int root_attrs[] =
{
@ -88,7 +89,7 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, displayWidth(), 0, displayHeight(), 0, 65535 );
// TODO glEnable( GL_DEPTH_TEST );
glEnable( GL_DEPTH_TEST );
checkGLError( "Init" );
}
@ -122,30 +123,39 @@ void SceneOpenGL::paint( QRegion, ToplevelList windows )
grabXServer();
glXWaitX();
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT /* TODO| GL_DEPTH_BUFFER_BIT*/ );
for( ToplevelList::ConstIterator it = windows.begin();
it != windows.end();
++it )
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
int depth = 0;
for( int i = windows.count() - 1; // top to bottom
i >= 0;
--i )
{
QRect r = (*it)->geometry().intersect( QRect( 0, 0, displayWidth(), displayHeight()));
if( !r.isEmpty())
{
assert( this->windows.contains( *it ));
Window& w = this->windows[ *it ];
w.bindTexture();
// TODO for double-buffered root glDrawBuffer( GL_BACK );
glXMakeContextCurrent( display(), glxroot, glxroot, context );
glPushMatrix();
glTranslatef( w.glX(), w.glY(), 0 );
glEnable( GL_TEXTURE_RECTANGLE_ARB );
glBegin( GL_QUADS );
foreach( QRect r, w.shape().rects())
quadDraw( r.x(), w.height() - r.y() - r.height(), r.width(), r.height());
glEnd();
glPopMatrix();
glDisable( GL_TEXTURE_RECTANGLE_ARB );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 );
}
Toplevel* c = windows[ i ];
assert( this->windows.contains( c ));
Window& w = this->windows[ c ];
w.setDepth( --depth );
if( !w.isVisible())
continue;
if( !w.isOpaque())
continue;
w.bindTexture();
w.draw();
}
for( int i = 0;
i < windows.count();
++i )
{
Toplevel* c = windows[ i ];
assert( this->windows.contains( c ));
Window& w = this->windows[ c ];
if( !w.isVisible())
continue;
if( w.isOpaque())
continue;
w.bindTexture();
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
w.draw();
glDisable( GL_BLEND );
}
glFlush();
glXWaitGL();
@ -183,6 +193,7 @@ SceneOpenGL::Window::Window( Toplevel* c )
, glxpixmap( None )
, texture( None )
, shape_valid( false )
, depth( 0 )
{
}
@ -204,12 +215,26 @@ GLXPixmap SceneOpenGL::Window::glxPixmap() const
return glxpixmap;
}
// for relative window positioning
void SceneOpenGL::Window::setDepth( int d )
{
depth = d;
}
void SceneOpenGL::Window::bindTexture()
{
GLXDrawable pixmap = glxPixmap();
glXMakeContextCurrent( display(), pixmap, pixmap, context );
glReadBuffer( GL_FRONT );
glDrawBuffer( GL_FRONT );
if( !toplevel->hasAlpha() && toplevel->opacity() != 1.0 )
{
// TODO this doesn't quite work with the decoration
glColorMask( 0, 0, 0, 1 );
glClearColor( 0, 0, 0, toplevel->opacity());
glClear( GL_COLOR_BUFFER_BIT );
glColorMask( 1, 1, 1, 1 );
}
if( texture == None )
{
glGenTextures( 1, &texture );
@ -266,4 +291,33 @@ QRegion SceneOpenGL::Window::shape() const
return shape_region;
}
void SceneOpenGL::Window::draw()
{
// TODO for double-buffered root glDrawBuffer( GL_BACK );
glXMakeContextCurrent( display(), glxroot, glxroot, context );
glPushMatrix();
glTranslatef( glX(), glY(), depth );
glEnable( GL_TEXTURE_RECTANGLE_ARB );
glBegin( GL_QUADS );
foreach( QRect r, shape().rects())
quadDraw( r.x(), height() - r.y() - r.height(), r.width(), r.height());
glEnd();
glPopMatrix();
glDisable( GL_TEXTURE_RECTANGLE_ARB );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, 0 );
}
bool SceneOpenGL::Window::isVisible() const
{
// TODO mapping state?
return !toplevel->geometry()
.intersect( QRect( 0, 0, displayWidth(), displayHeight()))
.isEmpty();
}
bool SceneOpenGL::Window::isOpaque() const
{
return toplevel->opacity() == 1.0 && !toplevel->hasAlpha();
}
} // namespace

View File

@ -36,7 +36,7 @@ class SceneOpenGL
Pixmap buffer;
GLXFBConfig fbcroot;
static GLXFBConfig fbcdrawable;
GLXPixmap glxroot;
static GLXPixmap glxroot;
static GLXContext context;
class Window;
QMap< Toplevel*, Window > windows;
@ -52,6 +52,10 @@ class SceneOpenGL::Window
int glY() const;
int width() const;
int height() const;
void setDepth( int depth );
void draw();
bool isVisible() const;
bool isOpaque() const;
GLXPixmap glxPixmap() const;
void bindTexture();
QRegion shape() const;
@ -65,6 +69,7 @@ class SceneOpenGL::Window
Texture texture;
mutable QRegion shape_region;
mutable bool shape_valid;
int depth;
};
inline

View File

@ -57,6 +57,7 @@ class Toplevel
Visual* visual() const;
bool shape() const;
virtual double opacity() const = 0;
bool hasAlpha() const;
void setupCompositing();
void finishCompositing();
void addDamage( const QRect& r );
@ -70,6 +71,7 @@ class Toplevel
void damageNotifyEvent( XDamageNotifyEvent* e );
QRect geom;
Visual* vis;
int depth;
virtual void debug( kdbgstream& stream ) const = 0;
friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* );
private:
@ -197,6 +199,11 @@ inline bool Toplevel::shape() const
return is_shape;
}
inline bool Toplevel::hasAlpha() const
{
return depth == 32;
}
#ifdef NDEBUG
inline
kndbgstream& operator<<( kndbgstream& stream, const Toplevel* ) { return stream; }

View File

@ -39,6 +39,7 @@ bool Unmanaged::track( Window w )
setHandle( w );
geom = QRect( attr.x, attr.y, attr.width, attr.height );
vis = attr.visual;
depth = attr.depth;
unsigned long properties[ 2 ];
properties[ NETWinInfo::PROTOCOLS ] =
NET::WMWindowType |