diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5dc485f516..b0fa7bdbbd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -112,6 +112,7 @@ kde4_add_kdeinit_executable( kwin ${kwin_KDEINIT_SRCS})
target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTXML_LIBRARY} kephal kdecorations kwineffects ${X11_LIBRARIES})
if(OPENGL_FOUND)
+ add_subdirectory(opengltest)
target_link_libraries(kdeinit_kwin ${OPENGL_gl_LIBRARY})
# -ldl used by OpenGL code
find_library(DL_LIBRARY dl)
diff --git a/compositingprefs.cpp b/compositingprefs.cpp
index f38185db78..2aac0e9999 100644
--- a/compositingprefs.cpp
+++ b/compositingprefs.cpp
@@ -26,6 +26,9 @@ along with this program. If not, see .
#include
#include
#include
+#include
+
+#include
namespace KWin
@@ -115,6 +118,20 @@ void CompositingPrefs::detect()
}
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+ // HACK: This is needed for AIGLX
+ if( qstrcmp( qgetenv( "KWIN_DIRECT_GL" ), "1" ) != 0 )
+ {
+ // Start an external helper program that initializes GLX and returns
+ // 0 if we can use direct rendering, and 1 otherwise.
+ // The reason we have to use an external program is that after GLX
+ // has been initialized, it's too late to set the LIBGL_ALWAYS_INDIRECT
+ // environment variable.
+ // Direct rendering is preferred, since not all OpenGL extensions are
+ // available with indirect rendering.
+ const QString opengl_test = KStandardDirs::findExe( "kwin_opengl_test" );
+ if ( QProcess::execute( opengl_test ) != 0 )
+ setenv( "LIBGL_ALWAYS_INDIRECT", "1", true );
+ }
if( !Extensions::glxAvailable())
{
kDebug( 1212 ) << "No GLX available";
diff --git a/main.cpp b/main.cpp
index c5346a9518..d97dbcf7e5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -496,10 +496,6 @@ KDE_EXPORT int kdemain( int argc, char * argv[] )
if( KDE_signal( SIGHUP, KWin::sighandler ) == SIG_IGN )
KDE_signal( SIGHUP, SIG_IGN );
- // HACK: This is needed for AIGLX
- if( qstrcmp( qgetenv( "KWIN_DIRECT_GL" ), "1" ) != 0 )
- setenv( "LIBGL_ALWAYS_INDIRECT","1", true );
-
// HACK: this is needed to work around a Qt4.4.0RC1 bug (#157659)
setenv( "QT_SLOW_TOPLEVEL_RESIZE", "1", true );
diff --git a/opengltest/CMakeLists.txt b/opengltest/CMakeLists.txt
new file mode 100644
index 0000000000..49607c8213
--- /dev/null
+++ b/opengltest/CMakeLists.txt
@@ -0,0 +1,10 @@
+########### next target ###############
+
+set(kwin_opengl_test_SRCS opengltest.cpp )
+
+kde4_add_executable(kwin_opengl_test ${kwin_opengl_test_SRCS})
+
+target_link_libraries(kwin_opengl_test ${X11_LIBRARIES} ${OPENGL_gl_LIBRARY})
+
+install(TARGETS kwin_opengl_test ${INSTALL_TARGETS_DEFAULT_ARGS} )
+
diff --git a/opengltest/opengltest.cpp b/opengltest/opengltest.cpp
new file mode 100644
index 0000000000..dd2273b9d7
--- /dev/null
+++ b/opengltest/opengltest.cpp
@@ -0,0 +1,89 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2010 Fredrik Höglund
+
+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 .
+*********************************************************************/
+
+#include
+#include
+#include
+#include
+
+
+// Return 0 if we can use a direct context, 1 otherwise
+int main(int argc, char *argv[])
+{
+ Display *dpy = XOpenDisplay(0);
+
+ int error_base, event_base;
+ if (!glXQueryExtension(dpy, &error_base, &event_base))
+ return 1;
+
+ int major, minor;
+ if (!glXQueryVersion(dpy, &major, &minor))
+ return 1;
+
+ // glXCreatePixmap() is a GLX 1.3+ function.
+ // It is also provided by EXT_texture_from_pixmap, but only for indirect contexts.
+ if (major == 1 && minor < 3)
+ return 1;
+
+ int attribs[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None,
+ None
+ };
+
+ // Try to find an RGBA visual
+ XVisualInfo *xvi = glXChooseVisual(dpy, DefaultScreen(dpy), attribs);
+ if (!xvi) {
+ // Try again for a doubled buffered visual
+ attribs[sizeof(attribs) / sizeof(int) - 2] = GLX_DOUBLEBUFFER;
+ xvi = glXChooseVisual(dpy, DefaultScreen(dpy), attribs);
+ }
+
+ if (!xvi)
+ return 1;
+
+ GLXContext ctx = glXCreateContext(dpy, xvi, NULL, True);
+
+ // Create a window using the visual.
+ // We only need it to make the context current
+ XSetWindowAttributes attr;
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), xvi->visual, AllocNone);
+ Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0,
+ xvi->depth, InputOutput, xvi->visual,
+ CWBackPixel | CWBorderPixel | CWColormap, &attr);
+ glXMakeCurrent(dpy, win, ctx);
+
+ // Assume that glXCreatePixmap() works with DRI2 drivers, and the NVidia driver
+ const GLubyte *renderer = glGetString(GL_RENDERER);
+ if (strstr((const char *)renderer, "DRI2"))
+ return 0;
+
+ const GLubyte *vendor = glGetString(GL_VENDOR);
+ if (strstr((const char *)vendor, "NVIDIA"))
+ return 0;
+
+ return 1;
+}
+