add more spacing
[personal-kdebase.git] / workspace / kwin / compositingprefs.cpp
blob5c4c377d3e3f8b4e56743a3cd63b8701eb9acb07
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
21 #include "compositingprefs.h"
23 #include "kwinglobals.h"
25 #include <kdebug.h>
26 #include <kxerrorhandler.h>
27 #include <klocale.h>
28 #include <kdeversion.h>
31 namespace KWin
34 CompositingPrefs::CompositingPrefs()
35 : mXgl( false )
36 , mEnableCompositing( false )
37 , mEnableVSync( true )
38 , mEnableDirectRendering( true )
39 , mStrictBinding( true )
43 CompositingPrefs::~CompositingPrefs()
47 bool CompositingPrefs::enableCompositing() const
49 return mEnableCompositing;
52 bool CompositingPrefs::compositingPossible()
54 #ifdef KWIN_HAVE_COMPOSITING
55 Extensions::init();
56 if( !Extensions::compositeAvailable())
58 kDebug( 1212 ) << "No composite extension available";
59 return false;
61 if( !Extensions::damageAvailable())
63 kDebug( 1212 ) << "No damage extension available";
64 return false;
66 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
67 if( Extensions::glxAvailable())
68 return true;
69 #endif
70 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
71 if( Extensions::renderAvailable() && Extensions::fixesAvailable())
72 return true;
73 #endif
74 kDebug( 1212 ) << "No OpenGL or XRender/XFixes support";
75 return false;
76 #else
77 return false;
78 #endif
81 QString CompositingPrefs::compositingNotPossibleReason()
83 #ifdef KWIN_HAVE_COMPOSITING
84 Extensions::init();
85 if( !Extensions::compositeAvailable() || !Extensions::damageAvailable())
87 return i18n("Required X extensions (XComposite and XDamage) are not available.");
89 #if defined( KWIN_HAVE_OPENGL_COMPOSITING ) && !defined( KWIN_HAVE_XRENDER_COMPOSITING )
90 if( !Extensions::glxAvailable())
91 return i18n( "GLX/OpenGL are not available and only OpenGL support is compiled." );
92 #elif !defined( KWIN_HAVE_OPENGL_COMPOSITING ) && defined( KWIN_HAVE_XRENDER_COMPOSITING )
93 if( !( Extensions::renderAvailable() && Extensions::fixesAvailable()))
94 return i18n( "XRender/XFixes extensions are not available and only XRender support"
95 " is compiled." );
96 #else
97 if( !( Extensions::glxAvailable()
98 || ( Extensions::renderAvailable() && Extensions::fixesAvailable())))
100 return i18n( "GLX/OpenGL and XRender/XFixes are not available." );
102 #endif
103 return QString();
104 #else
105 return i18n("Compositing was disabled at compile time.\n"
106 "It is likely Xorg development headers were not installed.");
107 #endif
110 // This function checks selected compositing setup and returns false if it should not
111 // be used even if explicitly configured (unless checks are overridden).
112 // More checks like broken XRender setups etc. should be added here.
113 bool CompositingPrefs::validateSetup( CompositingType compositingType ) const
115 switch( compositingType )
117 case NoCompositing:
118 return false;
119 case OpenGLCompositing:
120 if( mDriver == "software" )
122 kDebug( 1212 ) << "Software GL renderer detected, forcing compositing off.";
123 return false;
125 return true; // allow
126 case XRenderCompositing:
127 return true; // xrender - always allow?
129 abort();
132 void CompositingPrefs::detect()
134 if( !compositingPossible())
136 return;
139 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
140 if( !Extensions::glxAvailable())
142 kDebug( 1212 ) << "No GLX available";
143 return;
145 int glxmajor, glxminor;
146 glXQueryVersion( display(), &glxmajor, &glxminor );
147 kDebug( 1212 ) << "glx version is " << glxmajor << "." << glxminor;
148 bool hasglx13 = ( glxmajor > 1 || ( glxmajor == 1 && glxminor >= 3 ));
150 // remember and later restore active context
151 GLXContext oldcontext = glXGetCurrentContext();
152 GLXDrawable olddrawable = glXGetCurrentDrawable();
153 GLXDrawable oldreaddrawable = None;
154 if( hasglx13 )
155 oldreaddrawable = glXGetCurrentReadDrawable();
157 if( initGLXContext() )
159 detectDriverAndVersion();
160 applyDriverSpecificOptions();
162 if( hasglx13 )
163 glXMakeContextCurrent( display(), olddrawable, oldreaddrawable, oldcontext );
164 else
165 glXMakeCurrent( display(), olddrawable, oldcontext );
166 deleteGLXContext();
167 #endif
170 bool CompositingPrefs::initGLXContext()
172 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
173 mGLContext = NULL;
174 KXErrorHandler handler;
175 // Most of this code has been taken from glxinfo.c
176 QVector<int> attribs;
177 attribs << GLX_RGBA;
178 attribs << GLX_RED_SIZE << 1;
179 attribs << GLX_GREEN_SIZE << 1;
180 attribs << GLX_BLUE_SIZE << 1;
181 attribs << None;
183 XVisualInfo* visinfo = glXChooseVisual( display(), DefaultScreen( display()), attribs.data() );
184 if( !visinfo )
186 attribs.last() = GLX_DOUBLEBUFFER;
187 attribs << None;
188 visinfo = glXChooseVisual( display(), DefaultScreen( display()), attribs.data() );
189 if (!visinfo)
191 kDebug( 1212 ) << "Error: couldn't find RGB GLX visual";
192 return false;
196 mGLContext = glXCreateContext( display(), visinfo, NULL, True );
197 if ( !mGLContext )
199 kDebug( 1212 ) << "glXCreateContext failed";
200 XDestroyWindow( display(), mGLWindow );
201 return false;
204 XSetWindowAttributes attr;
205 attr.background_pixel = 0;
206 attr.border_pixel = 0;
207 attr.colormap = XCreateColormap( display(), rootWindow(), visinfo->visual, AllocNone );
208 attr.event_mask = StructureNotifyMask | ExposureMask;
209 unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
210 int width = 100, height = 100;
211 mGLWindow = XCreateWindow( display(), rootWindow(), 0, 0, width, height,
212 0, visinfo->depth, InputOutput,
213 visinfo->visual, mask, &attr );
215 return glXMakeCurrent( display(), mGLWindow, mGLContext ) && !handler.error( true );
216 #else
217 return false;
218 #endif
221 void CompositingPrefs::deleteGLXContext()
223 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
224 if( mGLContext == NULL )
225 return;
226 glXDestroyContext( display(), mGLContext );
227 XDestroyWindow( display(), mGLWindow );
228 #endif
231 void CompositingPrefs::detectDriverAndVersion()
233 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
234 mGLVendor = QString((const char*)glGetString( GL_VENDOR ));
235 mGLRenderer = QString((const char*)glGetString( GL_RENDERER ));
236 mGLVersion = QString((const char*)glGetString( GL_VERSION ));
237 mXgl = detectXgl();
238 kDebug( 1212 ) << "GL vendor is" << mGLVendor;
239 kDebug( 1212 ) << "GL renderer is" << mGLRenderer;
240 kDebug( 1212 ) << "GL version is" << mGLVersion;
241 kDebug( 1212 ) << "XGL:" << ( mXgl ? "yes" : "no" );
243 if( mGLRenderer.startsWith( "Mesa DRI Intel" ))
245 mDriver = "intel";
246 QStringList words = mGLRenderer.split(" ");
247 mVersion = Version( words[ words.count() - 2 ] );
249 else if( mGLVendor == "NVIDIA Corporation" )
251 mDriver = "nvidia";
252 QStringList words = mGLVersion.split(" ");
253 mVersion = Version( words[ words.count() - 1 ] );
255 else if( mGLVendor == "ATI Technologies Inc." )
257 mDriver = "fglrx";
258 mVersion = Version( mGLVersion.split(" ").first());
260 else if( mGLRenderer.startsWith( "Mesa DRI" ))
262 mDriver = "radeon";
263 mVersion = Version( mGLRenderer.split(" ")[ 3 ] );
265 else if( mGLRenderer == "Software Rasterizer" )
267 mDriver = "software";
268 QStringList words = mGLVersion.split(" ");
269 mVersion = Version( words[ words.count() - 1 ] );
271 else
273 mDriver = "unknown";
276 kDebug( 1212 ) << "Detected driver" << mDriver << ", version" << mVersion.join(".");
277 #endif
280 // See http://techbase.kde.org/Projects/KWin/HW for a list of some cards that are known to work.
281 void CompositingPrefs::applyDriverSpecificOptions()
283 if( mXgl )
285 kDebug( 1212 ) << "xgl, enabling";
286 mEnableCompositing = true;
287 mStrictBinding = false;
289 else if( mDriver == "intel" )
291 kDebug( 1212 ) << "intel driver, disabling vsync, enabling direct";
292 mEnableVSync = false;
293 mEnableDirectRendering = true;
294 if( mVersion >= Version( "20061017" ))
296 if( mGLRenderer.contains( "Intel(R) 9" ))
297 { // Enable compositing by default on 900-series cards
298 kDebug( 1212 ) << "intel >= 20061017 and 900-series card, enabling compositing";
299 mEnableCompositing = true;
301 if( mGLRenderer.contains( "Mesa DRI Intel(R) G" ))
302 { // e.g. G43 chipset
303 kDebug( 1212 ) << "intel >= 20061017 and Gxx-series card, enabling compositing";
304 mEnableCompositing = true;
308 else if( mDriver == "nvidia" )
310 mStrictBinding = false;
311 if( mVersion >= Version( "173.14.12" ))
313 kDebug( 1212 ) << "nvidia >= 173.14.12, enabling compositing";
314 mEnableCompositing = true;
317 else if( mDriver == "radeon" )
318 { // radeon r200 only ?
319 if( mGLRenderer.startsWith( "Mesa DRI R200" ) && mVersion >= Version( "20060602" ))
321 kDebug( 1212 ) << "radeon r200 >= 20060602, enabling compositing";
322 mEnableCompositing = true;
325 else if( mDriver == "fglrx" )
326 { // radeon r200 only ?
327 if( mVersion >= Version( "2.1.7412" ))
329 kDebug( 1212 ) << "fglrx >= 2.1.7412, enabling compositing";
330 mEnableCompositing = true;
336 bool CompositingPrefs::detectXgl()
337 { // Xgl apparently uses only this specific X version
338 return VendorRelease(display()) == 70000001;
341 CompositingPrefs::Version::Version( const QString& str ) :
342 QStringList()
344 QRegExp numrx( "(\\d+)|(\\D+)" );
345 int pos = 0;
346 while(( pos = numrx.indexIn( str, pos )) != -1 )
348 pos += numrx.matchedLength();
350 QString part = numrx.cap();
351 if( part == "." )
352 continue;
354 append( part );
358 int CompositingPrefs::Version::compare( const Version& v ) const
360 for( int i = 0; i < qMin( count(), v.count() ); i++ )
362 if( at( i )[ 0 ].isDigit() )
364 // This part of version string is numeric - compare numbers
365 int num = at( i ).toInt();
366 int vnum = v.at( i ).toInt();
367 if( num > vnum )
368 return 1;
369 else if( num < vnum )
370 return -1;
372 else
374 // This part is string
375 if( at( i ) > v.at( i ))
376 return 1;
377 else if( at( i ) < v.at( i ))
378 return -1;
382 if( count() > v.count() )
383 return 1;
384 else if( count() < v.count() )
385 return -1;
386 else
387 return 0;
390 } // namespace