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; +} +