A really nice trick from Compiz. OpenGL coordinates have Y upside

down ( [0,0] is bottomleft, unlike topleft with X ), so simply
flip the whole scene upside down and move it up -> the coordinates
match, except for when mapping pixmap to textures.


svn path=/branches/work/kwin_composite/; revision=594942
This commit is contained in:
Luboš Luňák 2006-10-12 21:12:51 +00:00
parent 5de53a53e6
commit 392acfb28c
2 changed files with 23 additions and 10 deletions

View file

@ -265,8 +265,11 @@ void SceneOpenGL::paint( QRegion, ToplevelList windows )
{ {
grabXServer(); grabXServer();
glXWaitX(); glXWaitX();
glPushMatrix();
glClearColor( 0, 0, 0, 1 ); glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glScalef( 1, -1, 1 );
glTranslatef( 0, -displayHeight(), 0 );
int depth = 0; int depth = 0;
QList< Window* > phase2; QList< Window* > phase2;
for( int i = windows.count() - 1; // top to bottom for( int i = windows.count() - 1; // top to bottom
@ -296,6 +299,7 @@ void SceneOpenGL::paint( QRegion, ToplevelList windows )
w.draw(); w.draw();
glDisable( GL_BLEND ); glDisable( GL_BLEND );
} }
glPopMatrix();
if( root_db ) if( root_db )
glXSwapBuffers( display(), glxroot ); glXSwapBuffers( display(), glxroot );
else else
@ -437,7 +441,9 @@ void SceneOpenGL::Window::bindTexture()
bound_glxpixmap = glXCreatePixmap( display(), fbcdrawable, pix, attrs ); bound_glxpixmap = glXCreatePixmap( display(), fbcdrawable, pix, attrs );
int value; int value;
glXGetFBConfigAttrib( display(), fbcdrawable, GLX_Y_INVERTED_EXT, &value ); glXGetFBConfigAttrib( display(), fbcdrawable, GLX_Y_INVERTED_EXT, &value );
texture_y_inverted = value ? true : false; // this is swapped in order to get a conversion of OpenGL coordinates
// (binding to a texture is not affected by transforming the OpenGL scene)
texture_y_inverted = value ? false : true;
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture ); glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
glXBindTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT, NULL ); glXBindTexImageEXT( display(), bound_glxpixmap, GLX_FRONT_LEFT_EXT, NULL );
} }
@ -451,6 +457,7 @@ void SceneOpenGL::Window::bindTexture()
{ {
glGenTextures( 1, &texture ); glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture ); glBindTexture( GL_TEXTURE_RECTANGLE_ARB, texture );
texture_y_inverted = true; // conversion to OpenGL coordinates
glCopyTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, glCopyTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0,
toplevel->hasAlpha() ? GL_RGBA : GL_RGB, toplevel->hasAlpha() ? GL_RGBA : GL_RGB,
0, 0, toplevel->width(), toplevel->height(), 0 ); 0, 0, toplevel->width(), toplevel->height(), 0 );
@ -462,7 +469,11 @@ void SceneOpenGL::Window::bindTexture()
{ {
foreach( QRect r, toplevel->damage().rects()) foreach( QRect r, toplevel->damage().rects())
{ {
int gly = height() - r.y() - r.height(); // to opengl coords // convert to OpenGL coordinates (this is mapping
// the pixmap to a texture, this is not affected
// by transforming the OpenGL scene)
int gly = toplevel->height() - r.y() - r.height();
texture_y_inverted = true;
glCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, glCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_ARB, 0,
r.x(), gly, r.x(), gly, r.width(), r.height()); r.x(), gly, r.x(), gly, r.width(), r.height());
} }
@ -550,7 +561,7 @@ void SceneOpenGL::Window::draw()
// 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();
glTranslatef( glX(), glY(), depth ); glTranslatef( x(), y(), depth );
if( toplevel->opacity() != 1.0 ) if( toplevel->opacity() != 1.0 )
{ {
if( toplevel->hasAlpha()) if( toplevel->hasAlpha())
@ -574,8 +585,10 @@ 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, shape().rects())
quadDraw( r.x(), height() - r.y() - r.height(), {
r.x() + r.width(), height() - r.y(), texture_y_inverted ); quadDraw( r.x(), r.y(), r.x() + r.width(), r.y() + r.height(),
texture_y_inverted );
}
glEnd(); glEnd();
glPopMatrix(); glPopMatrix();
if( toplevel->opacity() != 1.0 ) if( toplevel->opacity() != 1.0 )

View file

@ -53,8 +53,8 @@ class SceneOpenGL::Window
Window( Toplevel* c ); Window( Toplevel* c );
~Window(); ~Window();
void free(); // is often copied by value, use manually instead of dtor void free(); // is often copied by value, use manually instead of dtor
int glX() const; // remap to OpenGL coordinates int x() const;
int glY() const; int y() const;
int width() const; int width() const;
int height() const; int height() const;
void setDepth( int depth ); void setDepth( int depth );
@ -78,15 +78,15 @@ class SceneOpenGL::Window
}; };
inline inline
int SceneOpenGL::Window::glX() const int SceneOpenGL::Window::x() const
{ {
return toplevel->x(); return toplevel->x();
} }
inline inline
int SceneOpenGL::Window::glY() const int SceneOpenGL::Window::y() const
{ {
return displayHeight() - toplevel->y() - toplevel->height(); return toplevel->y();
} }
inline inline