2010-11-21 13:01:39 +00:00
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project .
Copyright ( C ) 2006 Lubos Lunak < l . lunak @ kde . org >
Based on glcompmgr code by Felix Bellaby .
Using code from Compiz and Beryl .
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// This file is included in scene_opengl.cpp
// the configs used for the destination
GLXFBConfig SceneOpenGL : : fbcbuffer_db ;
GLXFBConfig SceneOpenGL : : fbcbuffer_nondb ;
// the configs used for windows
SceneOpenGL : : FBConfigInfo SceneOpenGL : : fbcdrawableinfo [ 32 + 1 ] ;
// GLX content
GLXContext SceneOpenGL : : ctxbuffer ;
GLXContext SceneOpenGL : : ctxdrawable ;
// the destination drawable where the compositing is done
GLXDrawable SceneOpenGL : : glxbuffer = None ;
GLXDrawable SceneOpenGL : : last_pixmap = None ;
2011-01-30 14:34:42 +00:00
SceneOpenGL : : SceneOpenGL ( Workspace * ws )
: Scene ( ws )
, init_ok ( false )
2011-11-26 15:15:46 +00:00
, m_resetModelViewProjectionMatrix ( true )
2011-01-30 14:34:42 +00:00
{
2010-11-21 13:01:39 +00:00
initGLX ( ) ;
// check for FBConfig support
2011-01-30 14:34:42 +00:00
if ( ! hasGLExtension ( " GLX_SGIX_fbconfig " ) | | ! glXGetFBConfigAttrib | | ! glXGetFBConfigs | |
2010-11-21 13:01:39 +00:00
! glXGetVisualFromFBConfig | | ! glXCreatePixmap | | ! glXDestroyPixmap | |
2011-01-30 14:34:42 +00:00
! glXCreateWindow | | ! glXDestroyWindow ) {
kError ( 1212 ) < < " GLX_SGIX_fbconfig or required GLX functions missing " ;
2010-11-21 13:01:39 +00:00
return ; // error
2011-01-30 14:34:42 +00:00
}
if ( ! selectMode ( ) )
2010-11-21 13:01:39 +00:00
return ; // error
2011-01-30 14:34:42 +00:00
if ( ! initBuffer ( ) ) // create destination buffer
2010-11-21 13:01:39 +00:00
return ; // error
2011-01-30 14:34:42 +00:00
if ( ! initRenderingContext ( ) )
2010-11-21 13:01:39 +00:00
return ; // error
// Initialize OpenGL
initGL ( ) ;
2011-07-18 15:55:39 +00:00
2011-04-30 08:29:09 +00:00
GLPlatform * glPlatform = GLPlatform : : instance ( ) ;
2011-05-06 16:13:54 +00:00
if ( glPlatform - > isSoftwareEmulation ( ) ) {
2011-01-30 14:34:42 +00:00
kError ( 1212 ) < < " OpenGL Software Rasterizer detected. Falling back to XRender. " ;
QTimer : : singleShot ( 0 , Workspace : : self ( ) , SLOT ( fallbackToXRenderCompositing ( ) ) ) ;
2010-11-21 13:01:39 +00:00
return ;
2011-01-30 14:34:42 +00:00
}
if ( ! hasGLExtension ( " GL_ARB_texture_non_power_of_two " )
& & ! hasGLExtension ( " GL_ARB_texture_rectangle " ) ) {
kError ( 1212 ) < < " GL_ARB_texture_non_power_of_two and GL_ARB_texture_rectangle missing " ;
2010-11-21 13:01:39 +00:00
return ; // error
2011-01-30 14:34:42 +00:00
}
2011-04-30 08:29:09 +00:00
if ( glPlatform - > isMesaDriver ( ) & & glPlatform - > mesaVersion ( ) < kVersionNumber ( 7 , 10 ) ) {
2011-04-28 20:06:21 +00:00
kError ( 1212 ) < < " KWin requires at least Mesa 7.10 for OpenGL compositing. " ;
return ;
}
2011-01-30 14:34:42 +00:00
if ( db )
glDrawBuffer ( GL_BACK ) ;
2010-11-21 13:01:39 +00:00
// Check whether certain features are supported
has_waitSync = false ;
2011-01-30 14:34:42 +00:00
if ( glXGetVideoSync & & glXIsDirect ( display ( ) , ctxbuffer ) & & options - > glVSync ) {
2010-11-21 13:01:39 +00:00
unsigned int sync ;
2011-01-30 14:34:42 +00:00
if ( glXGetVideoSync ( & sync ) = = 0 ) {
if ( glXWaitVideoSync ( 1 , 0 , & sync ) = = 0 )
2010-11-21 13:01:39 +00:00
has_waitSync = true ;
else
2011-01-30 14:34:42 +00:00
qWarning ( ) < < " NO VSYNC! glXWaitVideoSync(1,0,&uint) isn't 0 but " < < glXWaitVideoSync ( 1 , 0 , & sync ) ;
} else
qWarning ( ) < < " NO VSYNC! glXGetVideoSync(&uint) isn't 0 but " < < glXGetVideoSync ( & sync ) ;
}
2010-11-21 13:01:39 +00:00
2011-01-30 14:34:42 +00:00
debug = qstrcmp ( qgetenv ( " KWIN_GL_DEBUG " ) , " 1 " ) = = 0 ;
2010-11-21 13:01:39 +00:00
// scene shader setup
2011-01-30 14:34:42 +00:00
if ( GLPlatform : : instance ( ) - > supports ( GLSL ) ) {
2010-12-11 09:57:29 +00:00
if ( ! ShaderManager : : instance ( ) - > isValid ( ) ) {
kDebug ( 1212 ) < < " No Scene Shaders available " ;
2011-10-15 07:47:56 +00:00
} else {
// push one shader on the stack so that one is always bound
// consistency with GLES
ShaderManager : : instance ( ) - > pushShader ( ShaderManager : : SimpleShader ) ;
2010-12-11 09:57:29 +00:00
}
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
// OpenGL scene setup
2011-11-26 15:15:46 +00:00
setupModelViewProjectionMatrix ( ) ;
2011-01-30 14:34:42 +00:00
if ( checkGLError ( " Init " ) ) {
kError ( 1212 ) < < " OpenGL compositing setup failed " ;
2010-11-21 13:01:39 +00:00
return ; // error
2011-01-30 14:34:42 +00:00
}
kDebug ( 1212 ) < < " DB: " < < db < < " , Direct: " < < bool ( glXIsDirect ( display ( ) , ctxbuffer ) ) < < endl ;
2010-11-21 13:01:39 +00:00
init_ok = true ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
SceneOpenGL : : ~ SceneOpenGL ( )
2011-01-30 14:34:42 +00:00
{
if ( ! init_ok ) {
2010-11-21 13:01:39 +00:00
// TODO this probably needs to clean up whatever has been created until the failure
2011-07-06 09:58:23 +00:00
m_overlayWindow - > destroy ( ) ;
2010-11-21 13:01:39 +00:00
return ;
2011-01-30 14:34:42 +00:00
}
foreach ( Window * w , windows )
delete w ;
2010-11-21 13:01:39 +00:00
// do cleanup after initBuffer()
2011-04-27 12:51:36 +00:00
cleanupGL ( ) ;
2011-01-30 14:34:42 +00:00
glXMakeCurrent ( display ( ) , None , NULL ) ;
glXDestroyContext ( display ( ) , ctxbuffer ) ;
2011-07-06 09:58:23 +00:00
if ( m_overlayWindow - > window ( ) ) {
2011-01-30 14:34:42 +00:00
if ( hasGLXVersion ( 1 , 3 ) )
glXDestroyWindow ( display ( ) , glxbuffer ) ;
XDestroyWindow ( display ( ) , buffer ) ;
2011-07-06 09:58:23 +00:00
m_overlayWindow - > destroy ( ) ;
2011-01-30 14:34:42 +00:00
} else {
glXDestroyPixmap ( display ( ) , glxbuffer ) ;
XFreeGC ( display ( ) , gcroot ) ;
XFreePixmap ( display ( ) , buffer ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
SceneOpenGL : : EffectFrame : : cleanup ( ) ;
checkGLError ( " Cleanup " ) ;
}
2010-11-21 13:01:39 +00:00
2011-11-26 15:15:46 +00:00
void SceneOpenGL : : setupModelViewProjectionMatrix ( )
{
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
float fovy = 60.0f ;
float aspect = 1.0f ;
float zNear = 0.1f ;
float zFar = 100.0f ;
float ymax = zNear * tan ( fovy * M_PI / 360.0f ) ;
float ymin = - ymax ;
float xmin = ymin * aspect ;
float xmax = ymax * aspect ;
// swap top and bottom to have OpenGL coordinate system match X system
glFrustum ( xmin , xmax , ymin , ymax , zNear , zFar ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
float scaleFactor = 1.1 * tan ( fovy * M_PI / 360.0f ) / ymax ;
glTranslatef ( xmin * scaleFactor , ymax * scaleFactor , - 1.1 ) ;
glScalef ( ( xmax - xmin ) * scaleFactor / displayWidth ( ) , - ( ymax - ymin ) * scaleFactor / displayHeight ( ) , 0.001 ) ;
m_resetModelViewProjectionMatrix = false ;
}
2010-11-21 13:01:39 +00:00
bool SceneOpenGL : : initTfp ( )
2011-01-30 14:34:42 +00:00
{
if ( glXBindTexImageEXT = = NULL | | glXReleaseTexImageEXT = = NULL )
2010-11-21 13:01:39 +00:00
return false ;
return true ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
bool SceneOpenGL : : initRenderingContext ( )
2011-01-30 14:34:42 +00:00
{
2010-11-21 13:01:39 +00:00
bool direct_rendering = options - > glDirect ;
KXErrorHandler errs1 ;
2011-01-30 14:34:42 +00:00
ctxbuffer = glXCreateNewContext ( display ( ) , fbcbuffer , GLX_RGBA_TYPE , NULL ,
direct_rendering ? GL_TRUE : GL_FALSE ) ;
bool failed = ( ctxbuffer = = NULL | | ! glXMakeCurrent ( display ( ) , glxbuffer , ctxbuffer ) ) ;
if ( errs1 . error ( true ) ) // always check for error( having it all in one if () could skip
2010-11-21 13:01:39 +00:00
failed = true ; // it due to evaluation short-circuiting
2011-01-30 14:34:42 +00:00
if ( failed ) {
if ( ! direct_rendering ) {
kDebug ( 1212 ) . nospace ( ) < < " Couldn't initialize rendering context ( "
< < KXErrorHandler : : errorMessage ( errs1 . errorEvent ( ) ) < < " ) " ;
2010-11-21 13:01:39 +00:00
return false ;
2011-01-30 14:34:42 +00:00
}
glXMakeCurrent ( display ( ) , None , NULL ) ;
if ( ctxbuffer ! = NULL )
glXDestroyContext ( display ( ) , ctxbuffer ) ;
2010-11-21 13:01:39 +00:00
direct_rendering = false ; // try again
KXErrorHandler errs2 ;
2011-01-30 14:34:42 +00:00
ctxbuffer = glXCreateNewContext ( display ( ) , fbcbuffer , GLX_RGBA_TYPE , NULL , GL_FALSE ) ;
bool failed = ( ctxbuffer = = NULL | | ! glXMakeCurrent ( display ( ) , glxbuffer , ctxbuffer ) ) ;
if ( errs2 . error ( true ) )
2010-11-21 13:01:39 +00:00
failed = true ;
2011-01-30 14:34:42 +00:00
if ( failed ) {
kDebug ( 1212 ) . nospace ( ) < < " Couldn't initialize rendering context ( "
< < KXErrorHandler : : errorMessage ( errs2 . errorEvent ( ) ) < < " ) " ;
2010-11-21 13:01:39 +00:00
return false ;
}
}
2011-01-30 14:34:42 +00:00
return true ;
}
2010-11-21 13:01:39 +00:00
// create destination buffer
bool SceneOpenGL : : initBuffer ( )
2011-01-30 14:34:42 +00:00
{
if ( ! initBufferConfigs ( ) )
2010-11-21 13:01:39 +00:00
return false ;
2011-07-06 09:58:23 +00:00
if ( fbcbuffer_db ! = NULL & & m_overlayWindow - > create ( ) ) {
2011-01-30 14:34:42 +00:00
// we have overlay, try to create double-buffered window in it
2010-11-21 13:01:39 +00:00
fbcbuffer = fbcbuffer_db ;
2011-01-30 14:34:42 +00:00
XVisualInfo * visual = glXGetVisualFromFBConfig ( display ( ) , fbcbuffer ) ;
2010-11-21 13:01:39 +00:00
XSetWindowAttributes attrs ;
2011-01-30 14:34:42 +00:00
attrs . colormap = XCreateColormap ( display ( ) , rootWindow ( ) , visual - > visual , AllocNone ) ;
2011-07-06 09:58:23 +00:00
buffer = XCreateWindow ( display ( ) , m_overlayWindow - > window ( ) , 0 , 0 , displayWidth ( ) , displayHeight ( ) ,
2011-01-30 14:34:42 +00:00
0 , visual - > depth , InputOutput , visual - > visual , CWColormap , & attrs ) ;
if ( hasGLXVersion ( 1 , 3 ) )
glxbuffer = glXCreateWindow ( display ( ) , fbcbuffer , buffer , NULL ) ;
2010-11-21 13:01:39 +00:00
else
glxbuffer = buffer ;
2011-07-06 09:58:23 +00:00
m_overlayWindow - > setup ( buffer ) ;
2010-11-21 13:01:39 +00:00
db = true ;
2011-01-30 14:34:42 +00:00
XFree ( visual ) ;
} else if ( fbcbuffer_nondb ! = NULL ) {
// cannot get any double-buffered drawable, will double-buffer using a pixmap
2010-11-21 13:01:39 +00:00
fbcbuffer = fbcbuffer_nondb ;
2011-01-30 14:34:42 +00:00
XVisualInfo * visual = glXGetVisualFromFBConfig ( display ( ) , fbcbuffer ) ;
2010-11-21 13:01:39 +00:00
XGCValues gcattr ;
gcattr . subwindow_mode = IncludeInferiors ;
2011-01-30 14:34:42 +00:00
gcroot = XCreateGC ( display ( ) , rootWindow ( ) , GCSubwindowMode , & gcattr ) ;
buffer = XCreatePixmap ( display ( ) , rootWindow ( ) , displayWidth ( ) , displayHeight ( ) ,
visual - > depth ) ;
glxbuffer = glXCreatePixmap ( display ( ) , fbcbuffer , buffer , NULL ) ;
2010-11-21 13:01:39 +00:00
db = false ;
2011-01-30 14:34:42 +00:00
XFree ( visual ) ;
} else {
kError ( 1212 ) < < " Couldn't create output buffer (failed to create overlay window?) ! " ;
2010-11-21 13:01:39 +00:00
return false ; // error
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
int vis_buffer ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbcbuffer , GLX_VISUAL_ID , & vis_buffer ) ;
XVisualInfo * visinfo_buffer = glXGetVisualFromFBConfig ( display ( ) , fbcbuffer ) ;
kDebug ( 1212 ) < < " Buffer visual (depth " < < visinfo_buffer - > depth < < " ): 0x " < < QString : : number ( vis_buffer , 16 ) ;
XFree ( visinfo_buffer ) ;
2010-11-21 13:01:39 +00:00
return true ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
// choose the best configs for the destination buffer
bool SceneOpenGL : : initBufferConfigs ( )
2011-01-30 14:34:42 +00:00
{
2010-11-21 13:01:39 +00:00
int cnt ;
2011-01-30 14:34:42 +00:00
GLXFBConfig * fbconfigs = glXGetFBConfigs ( display ( ) , DefaultScreen ( display ( ) ) , & cnt ) ;
2010-11-21 13:01:39 +00:00
fbcbuffer_db = NULL ;
fbcbuffer_nondb = NULL ;
2011-01-30 14:34:42 +00:00
for ( int i = 0 ; i < 2 ; i + + ) {
2010-11-21 13:01:39 +00:00
int back , stencil , depth , caveat , alpha ;
back = i > 0 ? INT_MAX : 1 ;
stencil = INT_MAX ;
depth = INT_MAX ;
caveat = INT_MAX ;
alpha = 0 ;
2011-01-30 14:34:42 +00:00
for ( int j = 0 ; j < cnt ; j + + ) {
2010-11-21 13:01:39 +00:00
XVisualInfo * vi ;
int visual_depth ;
2011-01-30 14:34:42 +00:00
vi = glXGetVisualFromFBConfig ( display ( ) , fbconfigs [ j ] ) ;
if ( vi = = NULL )
2010-11-21 13:01:39 +00:00
continue ;
visual_depth = vi - > depth ;
2011-01-30 14:34:42 +00:00
XFree ( vi ) ;
if ( visual_depth ! = DefaultDepth ( display ( ) , DefaultScreen ( display ( ) ) ) )
2010-11-21 13:01:39 +00:00
continue ;
int value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_ALPHA_SIZE , & alpha ) ;
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_BUFFER_SIZE , & value ) ;
if ( value ! = visual_depth & & ( value - alpha ) ! = visual_depth )
2010-11-21 13:01:39 +00:00
continue ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_RENDER_TYPE , & value ) ;
if ( ! ( value & GLX_RGBA_BIT ) )
2010-11-21 13:01:39 +00:00
continue ;
int back_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_DOUBLEBUFFER , & back_value ) ;
if ( i > 0 ) {
if ( back_value > back )
2010-11-21 13:01:39 +00:00
continue ;
2011-01-30 14:34:42 +00:00
} else {
if ( back_value < back )
2010-11-21 13:01:39 +00:00
continue ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
int stencil_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_STENCIL_SIZE , & stencil_value ) ;
if ( stencil_value > stencil )
2010-11-21 13:01:39 +00:00
continue ;
int depth_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_DEPTH_SIZE , & depth_value ) ;
if ( depth_value > depth )
2010-11-21 13:01:39 +00:00
continue ;
int caveat_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_CONFIG_CAVEAT , & caveat_value ) ;
if ( caveat_value > caveat )
2010-11-21 13:01:39 +00:00
continue ;
back = back_value ;
stencil = stencil_value ;
depth = depth_value ;
caveat = caveat_value ;
2011-01-30 14:34:42 +00:00
if ( i > 0 )
2010-11-21 13:01:39 +00:00
fbcbuffer_nondb = fbconfigs [ j ] ;
else
fbcbuffer_db = fbconfigs [ j ] ;
}
2011-01-30 14:34:42 +00:00
}
if ( cnt )
XFree ( fbconfigs ) ;
if ( fbcbuffer_db = = NULL & & fbcbuffer_nondb = = NULL ) {
kError ( 1212 ) < < " Couldn't find framebuffer configuration for buffer! " ;
2010-11-21 13:01:39 +00:00
return false ;
2011-01-30 14:34:42 +00:00
}
for ( int i = 0 ; i < = 32 ; i + + ) {
if ( fbcdrawableinfo [ i ] . fbconfig = = NULL )
2010-11-21 13:01:39 +00:00
continue ;
int vis_drawable = 0 ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbcdrawableinfo [ i ] . fbconfig , GLX_VISUAL_ID , & vis_drawable ) ;
kDebug ( 1212 ) < < " Drawable visual (depth " < < i < < " ): 0x " < < QString : : number ( vis_drawable , 16 ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
return true ;
}
2010-11-21 13:01:39 +00:00
// make a list of the best configs for windows by depth
bool SceneOpenGL : : initDrawableConfigs ( )
2011-01-30 14:34:42 +00:00
{
2010-11-21 13:01:39 +00:00
int cnt ;
2011-01-30 14:34:42 +00:00
GLXFBConfig * fbconfigs = glXGetFBConfigs ( display ( ) , DefaultScreen ( display ( ) ) , & cnt ) ;
2010-11-21 13:01:39 +00:00
2011-01-30 14:34:42 +00:00
for ( int i = 0 ; i < = 32 ; i + + ) {
2010-11-21 13:01:39 +00:00
int back , stencil , depth , caveat , alpha , mipmap , rgba ;
back = INT_MAX ;
stencil = INT_MAX ;
depth = INT_MAX ;
caveat = INT_MAX ;
mipmap = 0 ;
rgba = 0 ;
fbcdrawableinfo [ i ] . fbconfig = NULL ;
fbcdrawableinfo [ i ] . bind_texture_format = 0 ;
fbcdrawableinfo [ i ] . texture_targets = 0 ;
fbcdrawableinfo [ i ] . y_inverted = 0 ;
fbcdrawableinfo [ i ] . mipmap = 0 ;
2011-01-30 14:34:42 +00:00
for ( int j = 0 ; j < cnt ; j + + ) {
2010-11-21 13:01:39 +00:00
XVisualInfo * vi ;
int visual_depth ;
2011-01-30 14:34:42 +00:00
vi = glXGetVisualFromFBConfig ( display ( ) , fbconfigs [ j ] ) ;
if ( vi = = NULL )
2010-11-21 13:01:39 +00:00
continue ;
visual_depth = vi - > depth ;
2011-01-30 14:34:42 +00:00
XFree ( vi ) ;
if ( visual_depth ! = i )
2010-11-21 13:01:39 +00:00
continue ;
int value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_ALPHA_SIZE , & alpha ) ;
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_BUFFER_SIZE , & value ) ;
if ( value ! = i & & ( value - alpha ) ! = i )
2010-11-21 13:01:39 +00:00
continue ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_RENDER_TYPE , & value ) ;
if ( ! ( value & GLX_RGBA_BIT ) )
2010-11-21 13:01:39 +00:00
continue ;
2011-01-30 10:55:27 +00:00
value = 0 ;
2011-01-30 14:34:42 +00:00
if ( i = = 32 ) {
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_BIND_TO_TEXTURE_RGBA_EXT , & value ) ;
if ( value ) {
2011-01-30 10:55:27 +00:00
// TODO I think this should be set only after the config passes all tests
rgba = 1 ;
fbcdrawableinfo [ i ] . bind_texture_format = GLX_TEXTURE_FORMAT_RGBA_EXT ;
}
2011-01-30 14:34:42 +00:00
}
if ( ! value ) {
if ( rgba )
2011-01-30 10:55:27 +00:00
continue ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_BIND_TO_TEXTURE_RGB_EXT , & value ) ;
if ( ! value )
2011-01-30 10:55:27 +00:00
continue ;
fbcdrawableinfo [ i ] . bind_texture_format = GLX_TEXTURE_FORMAT_RGB_EXT ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
int back_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_DOUBLEBUFFER , & back_value ) ;
if ( back_value > back )
2010-11-21 13:01:39 +00:00
continue ;
int stencil_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_STENCIL_SIZE , & stencil_value ) ;
if ( stencil_value > stencil )
2010-11-21 13:01:39 +00:00
continue ;
int depth_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_DEPTH_SIZE , & depth_value ) ;
if ( depth_value > depth )
2010-11-21 13:01:39 +00:00
continue ;
int mipmap_value = - 1 ;
2011-01-30 14:34:42 +00:00
if ( GLTexture : : framebufferObjectSupported ( ) ) {
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_BIND_TO_MIPMAP_TEXTURE_EXT , & mipmap_value ) ;
if ( mipmap_value < mipmap )
2010-11-21 13:01:39 +00:00
continue ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
int caveat_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_CONFIG_CAVEAT , & caveat_value ) ;
if ( caveat_value > caveat )
2010-11-21 13:01:39 +00:00
continue ;
// ok, config passed all tests, it's the best one so far
fbcdrawableinfo [ i ] . fbconfig = fbconfigs [ j ] ;
caveat = caveat_value ;
back = back_value ;
stencil = stencil_value ;
depth = depth_value ;
mipmap = mipmap_value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_BIND_TO_TEXTURE_TARGETS_EXT , & value ) ;
2011-01-30 10:55:27 +00:00
fbcdrawableinfo [ i ] . texture_targets = value ;
2011-01-30 14:34:42 +00:00
glXGetFBConfigAttrib ( display ( ) , fbconfigs [ j ] ,
GLX_Y_INVERTED_EXT , & value ) ;
2010-11-21 13:01:39 +00:00
fbcdrawableinfo [ i ] . y_inverted = value ;
fbcdrawableinfo [ i ] . mipmap = mipmap ;
}
2011-01-30 14:34:42 +00:00
}
if ( cnt )
XFree ( fbconfigs ) ;
if ( fbcdrawableinfo [ DefaultDepth ( display ( ) , DefaultScreen ( display ( ) ) ) ] . fbconfig = = NULL ) {
kError ( 1212 ) < < " Couldn't find framebuffer configuration for default depth! " ;
2010-11-21 13:01:39 +00:00
return false ;
2011-01-30 14:34:42 +00:00
}
if ( fbcdrawableinfo [ 32 ] . fbconfig = = NULL ) {
kError ( 1212 ) < < " Couldn't find framebuffer configuration for depth 32 (no ARGB GLX visual)! " ;
2010-11-21 13:01:39 +00:00
return false ;
}
2011-01-30 14:34:42 +00:00
return true ;
}
2010-11-21 13:01:39 +00:00
// the entry function for painting
2011-01-30 14:34:42 +00:00
void SceneOpenGL : : paint ( QRegion damage , ToplevelList toplevels )
{
2011-10-29 15:09:26 +00:00
QElapsedTimer renderTimer ;
renderTimer . start ( ) ;
2011-01-30 14:34:42 +00:00
foreach ( Toplevel * c , toplevels ) {
assert ( windows . contains ( c ) ) ;
stacking_order . append ( windows [ c ] ) ;
}
2011-10-29 15:09:26 +00:00
2010-11-21 13:01:39 +00:00
grabXServer ( ) ;
glXWaitX ( ) ;
2011-11-26 15:15:46 +00:00
if ( m_resetModelViewProjectionMatrix ) {
// reset model view projection matrix if required
setupModelViewProjectionMatrix ( ) ;
}
2010-11-21 13:01:39 +00:00
glPushMatrix ( ) ;
int mask = 0 ;
# ifdef CHECK_GL_ERROR
2011-01-30 14:34:42 +00:00
checkGLError ( " Paint1 " ) ;
2010-11-21 13:01:39 +00:00
# endif
2011-01-30 14:34:42 +00:00
paintScreen ( & mask , & damage ) ; // call generic implementation
2010-11-21 13:01:39 +00:00
# ifdef CHECK_GL_ERROR
2011-01-30 14:34:42 +00:00
checkGLError ( " Paint2 " ) ;
2010-11-21 13:01:39 +00:00
# endif
glPopMatrix ( ) ;
ungrabXServer ( ) ; // ungrab before flushBuffer(), it may wait for vsync
2011-07-06 09:58:23 +00:00
if ( m_overlayWindow - > window ( ) ) // show the window only after the first pass, since
m_overlayWindow - > show ( ) ; // that pass may take long
2011-10-29 15:09:26 +00:00
lastRenderTime = renderTimer . elapsed ( ) ;
2012-01-12 20:01:56 +00:00
if ( ! damage . isEmpty ( ) ) {
flushBuffer ( mask , damage ) ;
}
2010-11-21 13:01:39 +00:00
// do cleanup
stacking_order . clear ( ) ;
2011-01-30 14:34:42 +00:00
checkGLError ( " PostPaint " ) ;
}
2010-11-21 13:01:39 +00:00
// wait for vblank signal before painting
void SceneOpenGL : : waitSync ( )
2011-01-30 14:34:42 +00:00
{
// NOTE that vsync has no effect with indirect rendering
if ( waitSyncAvailable ( ) ) {
2010-11-21 13:01:39 +00:00
uint sync ;
glFlush ( ) ;
2011-01-30 14:34:42 +00:00
glXGetVideoSync ( & sync ) ;
glXWaitVideoSync ( 2 , ( sync + 1 ) % 2 , & sync ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
// actually paint to the screen (double-buffer swap or copy from pixmap buffer)
2011-01-30 14:34:42 +00:00
void SceneOpenGL : : flushBuffer ( int mask , QRegion damage )
{
if ( db ) {
if ( mask & PAINT_SCREEN_REGION ) {
2010-11-21 13:01:39 +00:00
waitSync ( ) ;
2011-01-30 14:34:42 +00:00
if ( glXCopySubBuffer ) {
foreach ( const QRect & r , damage . rects ( ) ) {
2010-11-21 13:01:39 +00:00
// convert to OpenGL coordinates
int y = displayHeight ( ) - r . y ( ) - r . height ( ) ;
2011-01-30 14:34:42 +00:00
glXCopySubBuffer ( display ( ) , glxbuffer , r . x ( ) , y , r . width ( ) , r . height ( ) ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
} else {
2011-08-25 08:29:23 +00:00
// if a shader is bound or the texture unit is enabled, copy pixels results in a black screen
2011-02-06 08:27:30 +00:00
// therefore unbind the shader and restore after copying the pixels
GLint shader = 0 ;
if ( ShaderManager : : instance ( ) - > isShaderBound ( ) ) {
2011-08-25 08:29:23 +00:00
glGetIntegerv ( GL_CURRENT_PROGRAM , & shader ) ;
glUseProgram ( 0 ) ;
}
bool reenableTexUnit = false ;
if ( glIsEnabled ( GL_TEXTURE_2D ) ) {
glDisable ( GL_TEXTURE_2D ) ;
reenableTexUnit = true ;
2011-02-06 08:27:30 +00:00
}
2011-01-30 14:34:42 +00:00
// no idea why glScissor() is used, but Compiz has it and it doesn't seem to hurt
glEnable ( GL_SCISSOR_TEST ) ;
glDrawBuffer ( GL_FRONT ) ;
2010-11-21 13:01:39 +00:00
int xpos = 0 ;
int ypos = 0 ;
2011-01-30 14:34:42 +00:00
foreach ( const QRect & r , damage . rects ( ) ) {
2010-11-21 13:01:39 +00:00
// convert to OpenGL coordinates
int y = displayHeight ( ) - r . y ( ) - r . height ( ) ;
// Move raster position relatively using glBitmap() rather
// than using glRasterPos2f() - the latter causes drawing
// artefacts at the bottom screen edge with some gfx cards
// glRasterPos2f( r.x(), r.y() + r.height());
2011-01-30 14:34:42 +00:00
glBitmap ( 0 , 0 , 0 , 0 , r . x ( ) - xpos , y - ypos , NULL ) ;
2010-11-21 13:01:39 +00:00
xpos = r . x ( ) ;
ypos = y ;
2011-01-30 14:34:42 +00:00
glScissor ( r . x ( ) , y , r . width ( ) , r . height ( ) ) ;
glCopyPixels ( r . x ( ) , y , r . width ( ) , r . height ( ) , GL_COLOR ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
glBitmap ( 0 , 0 , 0 , 0 , - xpos , - ypos , NULL ) ; // move position back to 0,0
glDrawBuffer ( GL_BACK ) ;
glDisable ( GL_SCISSOR_TEST ) ;
2011-08-25 08:29:23 +00:00
if ( reenableTexUnit ) {
glEnable ( GL_TEXTURE_2D ) ;
}
2011-02-06 08:27:30 +00:00
// rebind previously bound shader
if ( ShaderManager : : instance ( ) - > isShaderBound ( ) ) {
2011-08-25 08:29:23 +00:00
glUseProgram ( shader ) ;
2011-02-06 08:27:30 +00:00
}
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
} else {
2010-11-21 13:01:39 +00:00
waitSync ( ) ;
2011-01-30 14:34:42 +00:00
glXSwapBuffers ( display ( ) , glxbuffer ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
glXWaitGL ( ) ;
XFlush ( display ( ) ) ;
} else {
2010-11-21 13:01:39 +00:00
glFlush ( ) ;
glXWaitGL ( ) ;
waitSync ( ) ;
2011-01-30 14:34:42 +00:00
if ( mask & PAINT_SCREEN_REGION )
foreach ( const QRect & r , damage . rects ( ) )
XCopyArea ( display ( ) , buffer , rootWindow ( ) , gcroot , r . x ( ) , r . y ( ) , r . width ( ) , r . height ( ) , r . x ( ) , r . y ( ) ) ;
2010-11-21 13:01:39 +00:00
else
2011-01-30 14:34:42 +00:00
XCopyArea ( display ( ) , buffer , rootWindow ( ) , gcroot , 0 , 0 , displayWidth ( ) , displayHeight ( ) , 0 , 0 ) ;
XFlush ( display ( ) ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-11-26 15:15:46 +00:00
void SceneOpenGL : : screenGeometryChanged ( const QSize & size )
{
Scene : : screenGeometryChanged ( size ) ;
glViewport ( 0 , 0 , size . width ( ) , size . height ( ) ) ;
if ( m_overlayWindow - > window ( ) = = None ) {
glXMakeCurrent ( display ( ) , None , NULL ) ;
glXDestroyPixmap ( display ( ) , glxbuffer ) ;
XFreePixmap ( display ( ) , buffer ) ;
XVisualInfo * visual = glXGetVisualFromFBConfig ( display ( ) , fbcbuffer ) ;
buffer = XCreatePixmap ( display ( ) , rootWindow ( ) , size . width ( ) , size . height ( ) , visual - > depth ) ;
XFree ( visual ) ;
glxbuffer = glXCreatePixmap ( display ( ) , fbcbuffer , buffer , NULL ) ;
glXMakeCurrent ( display ( ) , glxbuffer , ctxbuffer ) ;
// TODO: there seems some bug, some clients become black until an eg. un/remap - could be a general pixmap buffer issue, though
}
else {
glXMakeCurrent ( display ( ) , None , NULL ) ; // deactivate context ////
XMoveResizeWindow ( display ( ) , buffer , 0 , 0 , size . width ( ) , size . height ( ) ) ;
m_overlayWindow - > setup ( buffer ) ;
XSync ( display ( ) , false ) ; // ensure X11 stuff has applied ////
glXMakeCurrent ( display ( ) , glxbuffer , ctxbuffer ) ; // reactivate context ////
glViewport ( 0 , 0 , size . width ( ) , size . height ( ) ) ; // adjust viewport last - should btw. be superflous on the Pixmap buffer - iirc glXCreatePixmap sets the context anyway. ////
}
ShaderManager : : instance ( ) - > resetAllShaders ( ) ;
m_resetModelViewProjectionMatrix = true ;
}
2010-11-21 13:01:39 +00:00
//****************************************
// SceneOpenGL::Texture
//****************************************
2011-07-18 15:55:39 +00:00
SceneOpenGL : : TexturePrivate : : TexturePrivate ( )
2011-01-30 14:34:42 +00:00
{
2011-07-18 15:55:39 +00:00
m_glxpixmap = None ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-07-18 15:55:39 +00:00
SceneOpenGL : : TexturePrivate : : ~ TexturePrivate ( )
2011-01-30 14:34:42 +00:00
{
2011-07-18 15:55:39 +00:00
release ( ) ;
}
void SceneOpenGL : : TexturePrivate : : release ( )
{
if ( m_glxpixmap ! = None ) {
2011-02-05 10:55:10 +00:00
if ( ! options - > glStrictBinding ) {
2011-07-18 15:55:39 +00:00
glXReleaseTexImageEXT ( display ( ) , m_glxpixmap , GLX_FRONT_LEFT_EXT ) ;
2011-02-05 10:55:10 +00:00
}
2011-07-18 15:55:39 +00:00
glXDestroyPixmap ( display ( ) , m_glxpixmap ) ;
2011-08-25 08:29:23 +00:00
m_glxpixmap = None ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
void SceneOpenGL : : Texture : : findTarget ( )
2011-01-30 14:34:42 +00:00
{
2011-07-18 15:55:39 +00:00
Q_D ( Texture ) ;
2010-11-21 13:01:39 +00:00
unsigned int new_target = 0 ;
2011-07-18 15:55:39 +00:00
if ( glXQueryDrawable & & d - > m_glxpixmap ! = None )
glXQueryDrawable ( display ( ) , d - > m_glxpixmap , GLX_TEXTURE_TARGET_EXT , & new_target ) ;
2011-02-05 10:56:48 +00:00
// HACK: this used to be a hack for Xgl.
// without this hack the NVIDIA blob aborts when trying to bind a texture from
// a pixmap icon
if ( new_target = = 0 ) {
if ( NPOTTextureSupported ( ) | |
2011-07-18 15:55:39 +00:00
( isPowerOfTwo ( d - > m_size . width ( ) ) & & isPowerOfTwo ( d - > m_size . height ( ) ) ) ) {
2011-02-05 10:56:48 +00:00
new_target = GLX_TEXTURE_2D_EXT ;
} else {
new_target = GLX_TEXTURE_RECTANGLE_EXT ;
}
}
2011-01-30 14:34:42 +00:00
switch ( new_target ) {
case GLX_TEXTURE_2D_EXT :
2011-07-18 15:55:39 +00:00
d - > m_target = GL_TEXTURE_2D ;
d - > m_scale . setWidth ( 1.0f / d - > m_size . width ( ) ) ;
d - > m_scale . setHeight ( 1.0f / d - > m_size . height ( ) ) ;
2011-01-30 14:34:42 +00:00
break ;
case GLX_TEXTURE_RECTANGLE_EXT :
2011-07-18 15:55:39 +00:00
d - > m_target = GL_TEXTURE_RECTANGLE_ARB ;
d - > m_scale . setWidth ( 1.0f ) ;
d - > m_scale . setHeight ( 1.0f ) ;
2011-01-30 14:34:42 +00:00
break ;
default :
abort ( ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-01-30 14:34:42 +00:00
bool SceneOpenGL : : Texture : : load ( const Pixmap & pix , const QSize & size ,
int depth , QRegion region )
{
2011-12-31 14:04:14 +00:00
Q_UNUSED ( region )
2011-07-18 15:55:39 +00:00
// decrease the reference counter for the old texture
d_ptr = new TexturePrivate ( ) ;
Q_D ( Texture ) ;
2010-11-21 13:01:39 +00:00
# ifdef CHECK_GL_ERROR
2011-01-30 14:34:42 +00:00
checkGLError ( " TextureLoad1 " ) ;
2010-11-21 13:01:39 +00:00
# endif
2011-01-30 14:34:42 +00:00
if ( pix = = None | | size . isEmpty ( ) | | depth < 1 )
2010-11-21 13:01:39 +00:00
return false ;
2011-01-30 14:34:42 +00:00
if ( fbcdrawableinfo [ depth ] . fbconfig = = NULL ) {
kDebug ( 1212 ) < < " No framebuffer configuration for depth " < < depth
< < " ; not binding pixmap " < < endl ;
2011-01-30 10:55:27 +00:00
return false ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-07-18 15:55:39 +00:00
d - > m_size = size ;
// new texture, or texture contents changed; mipmaps now invalid
setDirty ( ) ;
2010-11-21 13:01:39 +00:00
# ifdef CHECK_GL_ERROR
2011-01-30 14:34:42 +00:00
checkGLError ( " TextureLoad2 " ) ;
2010-11-21 13:01:39 +00:00
# endif
2011-01-30 10:55:27 +00:00
// tfp mode, simply bind the pixmap to texture
2011-07-18 15:55:39 +00:00
glGenTextures ( 1 , & d - > m_texture ) ;
2011-01-30 10:55:27 +00:00
// The GLX pixmap references the contents of the original pixmap, so it doesn't
// need to be recreated when the contents change.
// The texture may or may not use the same storage depending on the EXT_tfp
// implementation. When options->glStrictBinding is true, the texture uses
// a different storage and needs to be updated with a call to
// glXBindTexImageEXT() when the contents of the pixmap has changed.
2011-07-18 15:55:39 +00:00
int attrs [ ] = {
GLX_TEXTURE_FORMAT_EXT , fbcdrawableinfo [ depth ] . bind_texture_format ,
GLX_MIPMAP_TEXTURE_EXT , fbcdrawableinfo [ depth ] . mipmap ,
None , None , None
} ;
// Specifying the texture target explicitly is reported to cause a performance
// regression with R300G (see bug #256654).
if ( GLPlatform : : instance ( ) - > driver ( ) ! = Driver_R300G ) {
if ( ( fbcdrawableinfo [ depth ] . texture_targets & GLX_TEXTURE_2D_BIT_EXT ) & &
( GLTexture : : NPOTTextureSupported ( ) | |
( isPowerOfTwo ( size . width ( ) ) & & isPowerOfTwo ( size . height ( ) ) ) ) ) {
attrs [ 4 ] = GLX_TEXTURE_TARGET_EXT ;
attrs [ 5 ] = GLX_TEXTURE_2D_EXT ;
} else if ( fbcdrawableinfo [ depth ] . texture_targets & GLX_TEXTURE_RECTANGLE_BIT_EXT ) {
attrs [ 4 ] = GLX_TEXTURE_TARGET_EXT ;
attrs [ 5 ] = GLX_TEXTURE_RECTANGLE_EXT ;
2011-01-30 14:34:42 +00:00
}
2011-07-18 15:55:39 +00:00
}
d - > m_glxpixmap = glXCreatePixmap ( display ( ) , fbcdrawableinfo [ depth ] . fbconfig , pix , attrs ) ;
2010-11-21 13:01:39 +00:00
# ifdef CHECK_GL_ERROR
2011-07-18 15:55:39 +00:00
checkGLError ( " TextureLoadTFP1 " ) ;
2010-11-21 13:01:39 +00:00
# endif
2011-07-18 15:55:39 +00:00
findTarget ( ) ;
d - > m_yInverted = fbcdrawableinfo [ depth ] . y_inverted ? true : false ;
d - > m_canUseMipmaps = fbcdrawableinfo [ depth ] . mipmap ? true : false ;
glBindTexture ( d - > m_target , d - > m_texture ) ;
2011-01-30 10:55:27 +00:00
# ifdef CHECK_GL_ERROR
2011-07-18 15:55:39 +00:00
checkGLError ( " TextureLoadTFP2 " ) ;
2011-01-30 10:55:27 +00:00
# endif
2011-07-18 15:55:39 +00:00
glXBindTexImageEXT ( display ( ) , d - > m_glxpixmap , GLX_FRONT_LEFT_EXT , NULL ) ;
2010-11-21 13:01:39 +00:00
# ifdef CHECK_GL_ERROR
2011-01-30 14:34:42 +00:00
checkGLError ( " TextureLoad0 " ) ;
2010-11-21 13:01:39 +00:00
# endif
return true ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-07-18 15:55:39 +00:00
void SceneOpenGL : : TexturePrivate : : bind ( )
2011-01-30 14:34:42 +00:00
{
2011-07-18 15:55:39 +00:00
GLTexturePrivate : : bind ( ) ;
if ( options - > glStrictBinding & & m_glxpixmap ) {
glXReleaseTexImageEXT ( display ( ) , m_glxpixmap , GLX_FRONT_LEFT_EXT ) ;
glXBindTexImageEXT ( display ( ) , m_glxpixmap , GLX_FRONT_LEFT_EXT , NULL ) ;
m_hasValidMipmaps = false ; // Mipmaps have to be regenerated after updating the texture
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
enableFilter ( ) ;
2011-01-30 14:34:42 +00:00
if ( hasGLVersion ( 1 , 4 , 0 ) ) {
2010-11-21 13:01:39 +00:00
// Lod bias makes the trilinear-filtered texture look a bit sharper
2011-01-30 14:34:42 +00:00
glTexEnvf ( GL_TEXTURE_FILTER_CONTROL , GL_TEXTURE_LOD_BIAS , - 1.0f ) ;
2010-11-21 13:01:39 +00:00
}
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-07-18 15:55:39 +00:00
void SceneOpenGL : : TexturePrivate : : unbind ( )
2011-01-30 14:34:42 +00:00
{
if ( hasGLVersion ( 1 , 4 , 0 ) ) {
glTexEnvf ( GL_TEXTURE_FILTER_CONTROL , GL_TEXTURE_LOD_BIAS , 0.0f ) ;
}
2011-07-18 15:55:39 +00:00
if ( options - > glStrictBinding & & m_glxpixmap ) {
glBindTexture ( m_target , m_texture ) ;
glXReleaseTexImageEXT ( display ( ) , m_glxpixmap , GLX_FRONT_LEFT_EXT ) ;
2011-01-30 14:34:42 +00:00
}
2010-11-21 13:01:39 +00:00
2011-07-18 15:55:39 +00:00
GLTexturePrivate : : unbind ( ) ;
2011-01-30 14:34:42 +00:00
}
2011-07-18 15:55:39 +00:00