• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWin

compositingprefs.cpp

Go to the documentation of this file.
00001 /********************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program.  If not, see <http://www.gnu.org/licenses/>.
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 mEnableCompositing;
00050     }
00051 
00052 bool CompositingPrefs::compositingPossible()
00053     {
00054 #ifdef KWIN_HAVE_COMPOSITING
00055     Extensions::init();
00056     if( !Extensions::compositeAvailable())
00057         {
00058         kDebug( 1212 ) << "No composite extension available";
00059         return false;
00060         }
00061     if( !Extensions::damageAvailable())
00062         {
00063         kDebug( 1212 ) << "No damage extension available";
00064         return false;
00065         }
00066 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00067     if( Extensions::glxAvailable())
00068         return true;
00069 #endif
00070 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00071     if( Extensions::renderAvailable() && Extensions::fixesAvailable())
00072         return true;
00073 #endif
00074     kDebug( 1212 ) << "No OpenGL or XRender/XFixes support";
00075     return false;
00076 #else
00077     return false;
00078 #endif
00079     }
00080 
00081 QString CompositingPrefs::compositingNotPossibleReason()
00082     {
00083 #ifdef KWIN_HAVE_COMPOSITING
00084     Extensions::init();
00085     if( !Extensions::compositeAvailable() || !Extensions::damageAvailable())
00086         {
00087         return i18n("Required X extensions (XComposite and XDamage) are not available.");
00088         }
00089 #if defined( KWIN_HAVE_OPENGL_COMPOSITING ) && !defined( KWIN_HAVE_XRENDER_COMPOSITING )
00090     if( !Extensions::glxAvailable())
00091         return i18n( "GLX/OpenGL are not available and only OpenGL support is compiled." );
00092 #elif !defined( KWIN_HAVE_OPENGL_COMPOSITING ) && defined( KWIN_HAVE_XRENDER_COMPOSITING )
00093     if( !( Extensions::renderAvailable() && Extensions::fixesAvailable()))
00094         return i18n( "XRender/XFixes extensions are not available and only XRender support"
00095             " is compiled." );
00096 #else
00097     if( !( Extensions::glxAvailable()
00098             || ( Extensions::renderAvailable() && Extensions::fixesAvailable())))
00099         {
00100         return i18n( "GLX/OpenGL and XRender/XFixes are not available." );
00101         }
00102 #endif
00103     return QString();
00104 #else
00105     return i18n("Compositing was disabled at compile time.\n"
00106             "It is likely Xorg development headers were not installed.");
00107 #endif
00108     }
00109 
00110 // This function checks selected compositing setup and returns false if it should not
00111 // be used even if explicitly configured (unless checks are overridden).
00112 // More checks like broken XRender setups etc. should be added here.
00113 bool CompositingPrefs::validateSetup( CompositingType compositingType ) const
00114     {
00115     switch( compositingType )
00116         {
00117         case NoCompositing:
00118             return false;
00119         case OpenGLCompositing:
00120             if( mDriver == "software" )
00121                 {
00122                 kDebug( 1212 ) << "Software GL renderer detected, forcing compositing off.";
00123                 return false;
00124                 }
00125             return true; // allow
00126         case XRenderCompositing:
00127             return true; // xrender - always allow?
00128         }
00129     abort();
00130     }
00131 
00132 void CompositingPrefs::detect()
00133     {
00134     if( !compositingPossible())
00135         {
00136         return;
00137         }
00138 
00139 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00140     if( !Extensions::glxAvailable())
00141         {
00142         kDebug( 1212 ) << "No GLX available";
00143         return;
00144         }
00145     int glxmajor, glxminor;
00146     glXQueryVersion( display(), &glxmajor, &glxminor );
00147     kDebug( 1212 ) << "glx version is " << glxmajor << "." << glxminor;
00148     bool hasglx13 = ( glxmajor > 1 || ( glxmajor == 1 && glxminor >= 3 ));
00149 
00150     // remember and later restore active context
00151     GLXContext oldcontext = glXGetCurrentContext();
00152     GLXDrawable olddrawable = glXGetCurrentDrawable();
00153     GLXDrawable oldreaddrawable = None;
00154     if( hasglx13 )
00155         oldreaddrawable = glXGetCurrentReadDrawable();
00156 
00157     if( initGLXContext() )
00158         {
00159         detectDriverAndVersion();
00160         applyDriverSpecificOptions();
00161         }
00162     if( hasglx13 )
00163         glXMakeContextCurrent( display(), olddrawable, oldreaddrawable, oldcontext );
00164     else
00165         glXMakeCurrent( display(), olddrawable, oldcontext );
00166     deleteGLXContext();
00167 #endif
00168     }
00169 
00170 bool CompositingPrefs::initGLXContext()
00171 {
00172 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00173     mGLContext = NULL;
00174     KXErrorHandler handler;
00175     // Most of this code has been taken from glxinfo.c
00176     QVector<int> attribs;
00177     attribs << GLX_RGBA;
00178     attribs << GLX_RED_SIZE << 1;
00179     attribs << GLX_GREEN_SIZE << 1;
00180     attribs << GLX_BLUE_SIZE << 1;
00181     attribs << None;
00182 
00183     XVisualInfo* visinfo = glXChooseVisual( display(), DefaultScreen( display()), attribs.data() );
00184     if( !visinfo )
00185         {
00186         attribs.last() = GLX_DOUBLEBUFFER;
00187         attribs << None;
00188         visinfo = glXChooseVisual( display(), DefaultScreen( display()), attribs.data() );
00189         if (!visinfo)
00190             {
00191             kDebug( 1212 ) << "Error: couldn't find RGB GLX visual";
00192             return false;
00193             }
00194         }
00195 
00196     mGLContext = glXCreateContext( display(), visinfo, NULL, True );
00197     if ( !mGLContext )
00198     {
00199         kDebug( 1212 ) << "glXCreateContext failed";
00200         XDestroyWindow( display(), mGLWindow );
00201         return false;
00202     }
00203 
00204     XSetWindowAttributes attr;
00205     attr.background_pixel = 0;
00206     attr.border_pixel = 0;
00207     attr.colormap = XCreateColormap( display(), rootWindow(), visinfo->visual, AllocNone );
00208     attr.event_mask = StructureNotifyMask | ExposureMask;
00209     unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00210     int width = 100, height = 100;
00211     mGLWindow = XCreateWindow( display(), rootWindow(), 0, 0, width, height,
00212                        0, visinfo->depth, InputOutput,
00213                        visinfo->visual, mask, &attr );
00214 
00215     return glXMakeCurrent( display(), mGLWindow, mGLContext ) && !handler.error( true );
00216 #else
00217    return false;
00218 #endif
00219 }
00220 
00221 void CompositingPrefs::deleteGLXContext()
00222 {
00223 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00224     if( mGLContext == NULL )
00225         return;
00226     glXDestroyContext( display(), mGLContext );
00227     XDestroyWindow( display(), mGLWindow );
00228 #endif
00229 }
00230 
00231 void CompositingPrefs::detectDriverAndVersion()
00232     {
00233 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00234     mGLVendor = QString((const char*)glGetString( GL_VENDOR ));
00235     mGLRenderer = QString((const char*)glGetString( GL_RENDERER ));
00236     mGLVersion = QString((const char*)glGetString( GL_VERSION ));
00237     mXgl = detectXgl();
00238     kDebug( 1212 ) << "GL vendor is" << mGLVendor;
00239     kDebug( 1212 ) << "GL renderer is" << mGLRenderer;
00240     kDebug( 1212 ) << "GL version is" << mGLVersion;
00241     kDebug( 1212 ) << "XGL:" << ( mXgl ? "yes" : "no" );
00242 
00243     if( mGLRenderer.startsWith( "Mesa DRI Intel" ))
00244         {
00245         mDriver = "intel";
00246         QStringList words = mGLRenderer.split(" ");
00247         mVersion = Version( words[ words.count() - 2 ] );
00248         }
00249     else if( mGLVendor == "NVIDIA Corporation" )
00250         {
00251         mDriver = "nvidia";
00252         QStringList words = mGLVersion.split(" ");
00253         mVersion = Version( words[ words.count() - 1 ] );
00254         }
00255     else if( mGLVendor == "ATI Technologies Inc." )
00256         {
00257         mDriver = "fglrx";
00258         mVersion = Version( mGLVersion.split(" ").first());
00259         }
00260     else if( mGLRenderer.startsWith( "Mesa DRI" ))
00261         {
00262         mDriver = "radeon";
00263         mVersion = Version( mGLRenderer.split(" ")[ 3 ] );
00264         }
00265     else if( mGLRenderer == "Software Rasterizer" )
00266         {
00267         mDriver = "software";
00268         QStringList words = mGLVersion.split(" ");
00269         mVersion = Version( words[ words.count() - 1 ] );
00270         }
00271     else
00272         {
00273         mDriver = "unknown";
00274         }
00275 
00276     kDebug( 1212 ) << "Detected driver" << mDriver << ", version" << mVersion.join(".");
00277 #endif
00278     }
00279 
00280 // See http://techbase.kde.org/Projects/KWin/HW for a list of some cards that are known to work.
00281 void CompositingPrefs::applyDriverSpecificOptions()
00282     {
00283     if( mXgl )
00284         {
00285         kDebug( 1212 ) << "xgl, enabling";
00286         mEnableCompositing = true;
00287         mStrictBinding = false;
00288         }
00289     else if( mDriver == "intel" )
00290         {
00291         kDebug( 1212 ) << "intel driver, disabling vsync, enabling direct";
00292         mEnableVSync = false;
00293         mEnableDirectRendering = true;
00294         if( mVersion >= Version( "20061017" ))
00295             { 
00296             if( mGLRenderer.contains( "Intel(R) 9" ))
00297                 { // Enable compositing by default on 900-series cards
00298                 kDebug( 1212 ) << "intel >= 20061017 and 900-series card, enabling compositing";
00299                 mEnableCompositing = true;
00300                 }
00301             if( mGLRenderer.contains( "Mesa DRI Intel(R) G" ))
00302                 { // e.g. G43 chipset
00303                 kDebug( 1212 ) << "intel >= 20061017 and Gxx-series card, enabling compositing";
00304                 mEnableCompositing = true;
00305                 }
00306             }
00307         }
00308     else if( mDriver == "nvidia" )
00309         {
00310         mStrictBinding = false;
00311         if( mVersion >= Version( "173.14.12" ))
00312             {
00313             kDebug( 1212 ) << "nvidia >= 173.14.12, enabling compositing";
00314             mEnableCompositing = true;
00315             }
00316         }
00317     else if( mDriver == "radeon" )
00318         { // radeon r200 only ?
00319         if( mGLRenderer.startsWith( "Mesa DRI R200" ) && mVersion >= Version( "20060602" ))
00320             {
00321             kDebug( 1212 ) << "radeon r200 >= 20060602, enabling compositing";
00322             mEnableCompositing = true;
00323             }
00324         }
00325     else if( mDriver == "fglrx" )
00326         { // radeon r200 only ?
00327         if( mVersion >= Version( "2.1.7412" ))
00328             {
00329             kDebug( 1212 ) << "fglrx >= 2.1.7412, enabling compositing";
00330             mEnableCompositing = true;
00331             }
00332         }
00333     }
00334 
00335 
00336 bool CompositingPrefs::detectXgl()
00337     { // Xgl apparently uses only this specific X version
00338     return VendorRelease(display()) == 70000001;
00339     }
00340 
00341 CompositingPrefs::Version::Version( const QString& str ) :
00342         QStringList()
00343     {
00344     QRegExp numrx( "(\\d+)|(\\D+)" );
00345     int pos = 0;
00346     while(( pos = numrx.indexIn( str, pos )) != -1 )
00347         {
00348         pos += numrx.matchedLength();
00349 
00350         QString part = numrx.cap();
00351         if( part == "." )
00352             continue;
00353 
00354         append( part );
00355         }
00356     }
00357 
00358 int CompositingPrefs::Version::compare( const Version& v ) const
00359     {
00360     for( int i = 0; i < qMin( count(), v.count() ); i++ )
00361         {
00362         if( at( i )[ 0 ].isDigit() )
00363             {
00364             // This part of version string is numeric - compare numbers
00365             int num = at( i ).toInt();
00366             int vnum = v.at( i ).toInt();
00367             if( num > vnum )
00368                 return 1;
00369             else if( num < vnum )
00370                 return -1;
00371             }
00372         else
00373             {
00374             // This part is string
00375             if( at( i ) > v.at( i ))
00376                 return 1;
00377             else if( at( i ) < v.at( i ))
00378                 return -1;
00379             }
00380         }
00381 
00382     if( count() > v.count() )
00383         return 1;
00384     else if( count() < v.count() )
00385         return -1;
00386     else
00387         return 0;
00388     }
00389 
00390 } // namespace
00391 

KWin

Skip menu "KWin"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal