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"
26 #include <kxerrorhandler.h>
28 #include <kdeversion.h>
34 CompositingPrefs::CompositingPrefs()
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
56 if( !Extensions::compositeAvailable())
58 kDebug( 1212 ) << "No composite extension available";
61 if( !Extensions::damageAvailable())
63 kDebug( 1212 ) << "No damage extension available";
66 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
67 if( Extensions::glxAvailable())
70 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
71 if( Extensions::renderAvailable() && Extensions::fixesAvailable())
74 kDebug( 1212 ) << "No OpenGL or XRender/XFixes support";
81 QString
CompositingPrefs::compositingNotPossibleReason()
83 #ifdef KWIN_HAVE_COMPOSITING
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"
97 if( !( Extensions::glxAvailable()
98 || ( Extensions::renderAvailable() && Extensions::fixesAvailable())))
100 return i18n( "GLX/OpenGL and XRender/XFixes are not available." );
105 return i18n("Compositing was disabled at compile time.\n"
106 "It is likely Xorg development headers were not installed.");
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
)
119 case OpenGLCompositing
:
120 if( mDriver
== "software" )
122 kDebug( 1212 ) << "Software GL renderer detected, forcing compositing off.";
125 return true; // allow
126 case XRenderCompositing
:
127 return true; // xrender - always allow?
132 void CompositingPrefs::detect()
134 if( !compositingPossible())
139 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
140 if( !Extensions::glxAvailable())
142 kDebug( 1212 ) << "No GLX available";
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
;
155 oldreaddrawable
= glXGetCurrentReadDrawable();
157 if( initGLXContext() )
159 detectDriverAndVersion();
160 applyDriverSpecificOptions();
163 glXMakeContextCurrent( display(), olddrawable
, oldreaddrawable
, oldcontext
);
165 glXMakeCurrent( display(), olddrawable
, oldcontext
);
170 bool CompositingPrefs::initGLXContext()
172 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
174 KXErrorHandler handler
;
175 // Most of this code has been taken from glxinfo.c
176 QVector
<int> attribs
;
178 attribs
<< GLX_RED_SIZE
<< 1;
179 attribs
<< GLX_GREEN_SIZE
<< 1;
180 attribs
<< GLX_BLUE_SIZE
<< 1;
183 XVisualInfo
* visinfo
= glXChooseVisual( display(), DefaultScreen( display()), attribs
.data() );
186 attribs
.last() = GLX_DOUBLEBUFFER
;
188 visinfo
= glXChooseVisual( display(), DefaultScreen( display()), attribs
.data() );
191 kDebug( 1212 ) << "Error: couldn't find RGB GLX visual";
196 mGLContext
= glXCreateContext( display(), visinfo
, NULL
, True
);
199 kDebug( 1212 ) << "glXCreateContext failed";
200 XDestroyWindow( display(), mGLWindow
);
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 );
221 void CompositingPrefs::deleteGLXContext()
223 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
224 if( mGLContext
== NULL
)
226 glXDestroyContext( display(), mGLContext
);
227 XDestroyWindow( display(), mGLWindow
);
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
));
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" ))
246 QStringList words
= mGLRenderer
.split(" ");
247 mVersion
= Version( words
[ words
.count() - 2 ] );
249 else if( mGLVendor
== "NVIDIA Corporation" )
252 QStringList words
= mGLVersion
.split(" ");
253 mVersion
= Version( words
[ words
.count() - 1 ] );
255 else if( mGLVendor
== "ATI Technologies Inc." )
258 mVersion
= Version( mGLVersion
.split(" ").first());
260 else if( mGLRenderer
.startsWith( "Mesa DRI" ))
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 ] );
276 kDebug( 1212 ) << "Detected driver" << mDriver
<< ", version" << mVersion
.join(".");
280 // See http://techbase.kde.org/Projects/KWin/HW for a list of some cards that are known to work.
281 void CompositingPrefs::applyDriverSpecificOptions()
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
) :
344 QRegExp
numrx( "(\\d+)|(\\D+)" );
346 while(( pos
= numrx
.indexIn( str
, pos
)) != -1 )
348 pos
+= numrx
.matchedLength();
350 QString part
= numrx
.cap();
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();
369 else if( num
< vnum
)
374 // This part is string
375 if( at( i
) > v
.at( i
))
377 else if( at( i
) < v
.at( i
))
382 if( count() > v
.count() )
384 else if( count() < v
.count() )