00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "compositingprefs.h"
00022
00023 #include "kwinglobals.h"
00024
00025 #include <kdebug.h>
00026 #include <kxerrorhandler.h>
00027 #include <klocale.h>
00028 #include <kdeversion.h>
00029
00030
00031 namespace KWin
00032 {
00033
00034 CompositingPrefs::CompositingPrefs()
00035 : mXgl( false )
00036 , mEnableCompositing( false )
00037 , mEnableVSync( true )
00038 , mEnableDirectRendering( true )
00039 , mStrictBinding( true )
00040 {
00041 }
00042
00043 CompositingPrefs::~CompositingPrefs()
00044 {
00045 }
00046
00047 bool CompositingPrefs::enableCompositing() const
00048 {
00049 return false;
00050 return mEnableCompositing;
00051 }
00052
00053 bool CompositingPrefs::compositingPossible()
00054 {
00055 #ifdef KWIN_HAVE_COMPOSITING
00056 Extensions::init();
00057 if( !Extensions::compositeAvailable())
00058 {
00059 kDebug( 1212 ) << "No composite extension available";
00060 return false;
00061 }
00062 if( !Extensions::damageAvailable())
00063 {
00064 kDebug( 1212 ) << "No damage extension available";
00065 return false;
00066 }
00067 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00068 if( Extensions::glxAvailable())
00069 return true;
00070 #endif
00071 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00072 if( Extensions::renderAvailable() && Extensions::fixesAvailable())
00073 return true;
00074 #endif
00075 kDebug( 1212 ) << "No OpenGL or XRender/XFixes support";
00076 return false;
00077 #else
00078 return false;
00079 #endif
00080 }
00081
00082 QString CompositingPrefs::compositingNotPossibleReason()
00083 {
00084 #ifdef KWIN_HAVE_COMPOSITING
00085 Extensions::init();
00086 if( !Extensions::compositeAvailable() || !Extensions::damageAvailable())
00087 {
00088 return i18n("Required X extensions (XComposite and XDamage) are not available.");
00089 }
00090 #if defined( KWIN_HAVE_OPENGL_COMPOSITING ) && !defined( KWIN_HAVE_XRENDER_COMPOSITING )
00091 if( !Extensions::glxAvailable())
00092 return i18n( "GLX/OpenGL are not available and only OpenGL support is compiled." );
00093 #elif !defined( KWIN_HAVE_OPENGL_COMPOSITING ) && defined( KWIN_HAVE_XRENDER_COMPOSITING )
00094 if( !( Extensions::renderAvailable() && Extensions::fixesAvailable()))
00095 return i18n( "XRender/XFixes extensions are not available and only XRender support"
00096 " is compiled." );
00097 #else
00098 if( !( Extensions::glxAvailable()
00099 || ( Extensions::renderAvailable() && Extensions::fixesAvailable())))
00100 {
00101 return i18n( "GLX/OpenGL and XRender/XFixes are not available." );
00102 }
00103 #endif
00104 return QString();
00105 #else
00106 return i18n("Compositing was disabled at compile time.\n"
00107 "It is likely Xorg development headers were not installed.");
00108 #endif
00109 }
00110
00111 void CompositingPrefs::detect()
00112 {
00113 if( !compositingPossible())
00114 {
00115 return;
00116 }
00117
00118 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00119 if( !Extensions::glxAvailable())
00120 {
00121 kDebug( 1212 ) << "No GLX available";
00122 return;
00123 }
00124 int glxmajor, glxminor;
00125 glXQueryVersion( display(), &glxmajor, &glxminor );
00126 kDebug( 1212 ) << "glx version is " << glxmajor << "." << glxminor;
00127 bool hasglx13 = ( glxmajor > 1 || ( glxmajor == 1 && glxminor >= 3 ));
00128
00129
00130 GLXContext oldcontext = glXGetCurrentContext();
00131 GLXDrawable olddrawable = glXGetCurrentDrawable();
00132 GLXDrawable oldreaddrawable = None;
00133 if( hasglx13 )
00134 oldreaddrawable = glXGetCurrentReadDrawable();
00135
00136 if( initGLXContext() )
00137 {
00138 detectDriverAndVersion();
00139 applyDriverSpecificOptions();
00140 }
00141 if( hasglx13 )
00142 glXMakeContextCurrent( display(), olddrawable, oldreaddrawable, oldcontext );
00143 else
00144 glXMakeCurrent( display(), olddrawable, oldcontext );
00145 deleteGLXContext();
00146 #endif
00147 }
00148
00149 bool CompositingPrefs::initGLXContext()
00150 {
00151 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00152 mGLContext = NULL;
00153 KXErrorHandler handler;
00154
00155 QVector<int> attribs;
00156 attribs << GLX_RGBA;
00157 attribs << GLX_RED_SIZE << 1;
00158 attribs << GLX_GREEN_SIZE << 1;
00159 attribs << GLX_BLUE_SIZE << 1;
00160 attribs << None;
00161
00162 XVisualInfo* visinfo = glXChooseVisual( display(), DefaultScreen( display()), attribs.data() );
00163 if( !visinfo )
00164 {
00165 attribs.last() = GLX_DOUBLEBUFFER;
00166 attribs << None;
00167 visinfo = glXChooseVisual( display(), DefaultScreen( display()), attribs.data() );
00168 if (!visinfo)
00169 {
00170 kDebug( 1212 ) << "Error: couldn't find RGB GLX visual";
00171 return false;
00172 }
00173 }
00174
00175 mGLContext = glXCreateContext( display(), visinfo, NULL, True );
00176 if ( !mGLContext )
00177 {
00178 kDebug( 1212 ) << "glXCreateContext failed";
00179 XDestroyWindow( display(), mGLWindow );
00180 return false;
00181 }
00182
00183 XSetWindowAttributes attr;
00184 attr.background_pixel = 0;
00185 attr.border_pixel = 0;
00186 attr.colormap = XCreateColormap( display(), rootWindow(), visinfo->visual, AllocNone );
00187 attr.event_mask = StructureNotifyMask | ExposureMask;
00188 unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00189 int width = 100, height = 100;
00190 mGLWindow = XCreateWindow( display(), rootWindow(), 0, 0, width, height,
00191 0, visinfo->depth, InputOutput,
00192 visinfo->visual, mask, &attr );
00193
00194 return glXMakeCurrent( display(), mGLWindow, mGLContext ) && !handler.error( true );
00195 #else
00196 return false;
00197 #endif
00198 }
00199
00200 void CompositingPrefs::deleteGLXContext()
00201 {
00202 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00203 if( mGLContext == NULL )
00204 return;
00205 glXDestroyContext( display(), mGLContext );
00206 XDestroyWindow( display(), mGLWindow );
00207 #endif
00208 }
00209
00210 void CompositingPrefs::detectDriverAndVersion()
00211 {
00212 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00213 mGLVendor = QString((const char*)glGetString( GL_VENDOR ));
00214 mGLRenderer = QString((const char*)glGetString( GL_RENDERER ));
00215 mGLVersion = QString((const char*)glGetString( GL_VERSION ));
00216 mXgl = detectXgl();
00217 kDebug( 1212 ) << "GL vendor is" << mGLVendor;
00218 kDebug( 1212 ) << "GL renderer is" << mGLRenderer;
00219 kDebug( 1212 ) << "GL version is" << mGLVersion;
00220 kDebug( 1212 ) << "XGL:" << ( mXgl ? "yes" : "no" );
00221
00222 if( mGLRenderer.contains( "Intel" ))
00223 {
00224 mDriver = "intel";
00225 QStringList words = mGLRenderer.split(" ");
00226 mVersion = Version( words[ words.count() - 2 ] );
00227 }
00228 else if( mGLVendor.contains( "NVIDIA" ))
00229 {
00230 mDriver = "nvidia";
00231 QStringList words = mGLVersion.split(" ");
00232 mVersion = Version( words[ words.count() - 1 ] );
00233 }
00234 else
00235 {
00236 mDriver = "unknown";
00237 }
00238
00239 kDebug( 1212 ) << "Detected driver" << mDriver << ", version" << mVersion.join(".");
00240 #endif
00241 }
00242
00243 void CompositingPrefs::applyDriverSpecificOptions()
00244 {
00245 if( mXgl )
00246 {
00247 kDebug( 1212 ) << "xgl, enabling";
00248 mEnableCompositing = true;
00249 mStrictBinding = false;
00250 }
00251 else if( mDriver == "intel" )
00252 {
00253 kDebug( 1212 ) << "intel driver, disabling vsync, enabling direct";
00254 mEnableVSync = false;
00255 mEnableDirectRendering = true;
00256
00257 if( mVersion >= Version( "20061017" ) && mGLRenderer.contains( "Intel(R) 9" ))
00258 {
00259 kDebug( 1212 ) << "intel >= 20061017 and 900-series card, enabling compositing";
00260 mEnableCompositing = true;
00261 }
00262 }
00263 else if( mDriver == "nvidia" )
00264 {
00265 mStrictBinding = false;
00266 if( mVersion <= Version( "100.14.23" ))
00267 {
00268 kDebug( 1212 ) << "nvidia <= 100.14.23, disabling vsync";
00269 mEnableVSync = false;
00270 }
00271 if( mVersion >= Version( "96.39" ))
00272 {
00273 kDebug( 1212 ) << "nvidia >= 96.39, enabling compositing";
00274 mEnableCompositing = true;
00275 }
00276 }
00277 }
00278
00279
00280 bool CompositingPrefs::detectXgl()
00281 {
00282 return VendorRelease(display()) == 70000001;
00283 }
00284
00285 CompositingPrefs::Version::Version( const QString& str ) :
00286 QStringList()
00287 {
00288 QRegExp numrx( "(\\d+)|(\\D+)" );
00289 int pos = 0;
00290 while(( pos = numrx.indexIn( str, pos )) != -1 )
00291 {
00292 pos += numrx.matchedLength();
00293
00294 QString part = numrx.cap();
00295 if( part == "." )
00296 continue;
00297
00298 append( part );
00299 }
00300 }
00301
00302 int CompositingPrefs::Version::compare( const Version& v ) const
00303 {
00304 for( int i = 0; i < qMin( count(), v.count() ); i++ )
00305 {
00306 if( at( i )[ 0 ].isDigit() )
00307 {
00308
00309 int num = at( i ).toInt();
00310 int vnum = v.at( i ).toInt();
00311 if( num > vnum )
00312 return 1;
00313 else if( num < vnum )
00314 return -1;
00315 }
00316 else
00317 {
00318
00319 if( at( i ) > v.at( i ))
00320 return 1;
00321 else if( at( i ) < v.at( i ))
00322 return -1;
00323 }
00324 }
00325
00326 if( count() > v.count() )
00327 return 1;
00328 else if( count() < v.count() )
00329 return -1;
00330 else
00331 return 0;
00332 }
00333
00334 }
00335