/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2007 Rivo Laks 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 "compositingprefs.h" #include "xcbutils.h" #include "kwinglplatform.h" #include #include #include #include #include #include #include #include namespace KWin { extern int screen_number; // main.cpp extern bool is_multihead; CompositingPrefs::CompositingPrefs() : mEnableDirectRendering(true) { } CompositingPrefs::~CompositingPrefs() { } bool CompositingPrefs::openGlIsBroken() { const QString unsafeKey(QStringLiteral("OpenGLIsUnsafe") + (is_multihead ? QString::number(screen_number) : QString())); return KConfigGroup(KGlobal::config(), "Compositing").readEntry(unsafeKey, false); } bool CompositingPrefs::compositingPossible() { // first off, check whether we figured that we'll crash on detection because of a buggy driver KConfigGroup gl_workaround_group(KGlobal::config(), "Compositing"); const QString unsafeKey(QStringLiteral("OpenGLIsUnsafe") + (is_multihead ? QString::number(screen_number) : QString())); if (gl_workaround_group.readEntry("Backend", "OpenGL") == QStringLiteral("OpenGL") && gl_workaround_group.readEntry(unsafeKey, false)) return false; if (!Xcb::Extensions::self()->isCompositeAvailable()) { kDebug(1212) << "No composite extension available"; return false; } if (!Xcb::Extensions::self()->isDamageAvailable()) { kDebug(1212) << "No damage extension available"; return false; } if (hasGlx()) return true; #ifdef KWIN_HAVE_XRENDER_COMPOSITING if (Xcb::Extensions::self()->isRenderAvailable() && Xcb::Extensions::self()->isFixesAvailable()) return true; #endif #ifdef KWIN_HAVE_OPENGLES return true; #endif kDebug(1212) << "No OpenGL or XRender/XFixes support"; return false; } QString CompositingPrefs::compositingNotPossibleReason() { // first off, check whether we figured that we'll crash on detection because of a buggy driver KConfigGroup gl_workaround_group(KGlobal::config(), "Compositing"); const QString unsafeKey(QStringLiteral("OpenGLIsUnsafe") + (is_multihead ? QString::number(screen_number) : QString())); if (gl_workaround_group.readEntry("Backend", "OpenGL") == QStringLiteral("OpenGL") && gl_workaround_group.readEntry(unsafeKey, false)) return i18n("OpenGL compositing (the default) has crashed KWin in the past.
" "This was most likely due to a driver bug." "

If you think that you have meanwhile upgraded to a stable driver,
" "you can reset this protection but be aware that this might result in an immediate crash!

" "

Alternatively, you might want to use the XRender backend instead.

"); if (!Xcb::Extensions::self()->isCompositeAvailable() || !Xcb::Extensions::self()->isDamageAvailable()) { return i18n("Required X extensions (XComposite and XDamage) are not available."); } #if !defined( KWIN_HAVE_XRENDER_COMPOSITING ) if (!hasGlx()) return i18n("GLX/OpenGL are not available and only OpenGL support is compiled."); #else if (!(hasGlx() || (Xcb::Extensions::self()->isRenderAvailable() && Xcb::Extensions::self()->isFixesAvailable()))) { return i18n("GLX/OpenGL and XRender/XFixes are not available."); } #endif return QString(); } static bool s_glxDetected = false; static bool s_hasGlx = false; bool CompositingPrefs::hasGlx() { if (s_glxDetected) { return s_hasGlx; } #ifndef KWIN_HAVE_OPENGLES int event_base, error_base; s_hasGlx = glXQueryExtension(display(), &event_base, &error_base); #endif s_glxDetected = true; return s_hasGlx; } void CompositingPrefs::detect() { if (!compositingPossible() || openGlIsBroken()) { return; } #ifndef KWIN_HAVE_OPENGLES // HACK: This is needed for AIGLX const bool forceIndirect = qstrcmp(qgetenv("LIBGL_ALWAYS_INDIRECT"), "1") == 0; const bool forceEgl = qstrcmp(qgetenv("KWIN_OPENGL_INTERFACE"), "egl") == 0 || qstrcmp(qgetenv("KWIN_OPENGL_INTERFACE"), "egl_wayland") == 0; if (!forceIndirect && !forceEgl && 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(QStringLiteral("kwin_opengl_test")); if (QProcess::execute(opengl_test) != 0) { mEnableDirectRendering = false; setenv("LIBGL_ALWAYS_INDIRECT", "1", true); } else { mEnableDirectRendering = true; } } else { mEnableDirectRendering = !forceIndirect; } #endif } } // namespace