From 364ce6fbfc2a938626f6ce5acc5718564d862ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Sun, 3 Apr 2011 21:59:57 +0200 Subject: [PATCH] Allow the user to rearm OpenGLIsUnsafe KWIn autocrash protection Also add a usable "doesn't work why" info and WARN! the user about clicking the rearm button. Merge "OpenGLIsUnsafe" and "CheckIsSafe" config keys Move the entire checking into CompositingPrefs BUG:250865 FIXED-IN:4.7 --- composite.cpp | 3 +- compositingprefs.cpp | 41 +++++- compositingprefs.h | 1 + kcmkwin/kwincompositing/main.cpp | 92 ++++++++---- kcmkwin/kwincompositing/main.h | 2 + kcmkwin/kwincompositing/main.ui | 241 +++++++++++++++++++++++++++++-- kcmkwin/kwinscreenedges/main.cpp | 11 +- 7 files changed, 339 insertions(+), 52 deletions(-) diff --git a/composite.cpp b/composite.cpp index 598db03636..8d7fd84551 100644 --- a/composite.cpp +++ b/composite.cpp @@ -120,8 +120,7 @@ void Workspace::setupCompositing() KSharedConfigPtr unsafeConfigPtr(KSharedConfig::openConfig("kwinrc")); KConfigGroup unsafeConfig(unsafeConfigPtr, "Compositing"); if (unsafeConfig.readEntry("OpenGLIsUnsafe", false)) - kWarning(1212) << "KWin has detected that your OpenGL library is unsafe to use, " - "falling back to XRender."; + kWarning(1212) << "KWin has detected that your OpenGL library is unsafe to use"; else { unsafeConfig.writeEntry("OpenGLIsUnsafe", true); unsafeConfig.sync(); diff --git a/compositingprefs.cpp b/compositingprefs.cpp index 360238478b..025048e70d 100644 --- a/compositingprefs.cpp +++ b/compositingprefs.cpp @@ -23,10 +23,12 @@ along with this program. If not, see . #include "kwinglobals.h" #include "kwinglplatform.h" +#include #include #include #include #include +#include #include #include @@ -52,8 +54,21 @@ bool CompositingPrefs::recommendCompositing() const return mRecommendCompositing; } +bool CompositingPrefs::openGlIsBroken() +{ + KSharedConfigPtr config = KSharedConfig::openConfig("kwinrc"); + return KConfigGroup(config, "Compositing").readEntry("OpenGLIsUnsafe", false); +} + bool CompositingPrefs::compositingPossible() { + // first off, check whether we figured that we'll crash on detection because of a buggy driver + KSharedConfigPtr config = KSharedConfig::openConfig("kwinrc"); + KConfigGroup gl_workaround_group(config, "Compositing"); + if (gl_workaround_group.readEntry("Backend", "OpenGL") == "OpenGL" && + gl_workaround_group.readEntry("OpenGLIsUnsafe", false)) + return false; + #ifdef KWIN_HAVE_COMPOSITING Extensions::init(); if (!Extensions::compositeAvailable()) { @@ -85,6 +100,17 @@ bool CompositingPrefs::compositingPossible() QString CompositingPrefs::compositingNotPossibleReason() { #ifdef KWIN_HAVE_COMPOSITING + // first off, check whether we figured that we'll crash on detection because of a buggy driver + KSharedConfigPtr config = KSharedConfig::openConfig("kwinrc"); + KConfigGroup gl_workaround_group(config, "Compositing"); + if (gl_workaround_group.readEntry("Backend", "OpenGL") == "OpenGL" && + gl_workaround_group.readEntry("OpenGLIsUnsafe", 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.

"); + Extensions::init(); if (!Extensions::compositeAvailable() || !Extensions::damageAvailable()) { return i18n("Required X extensions (XComposite and XDamage) are not available."); @@ -111,10 +137,19 @@ QString CompositingPrefs::compositingNotPossibleReason() void CompositingPrefs::detect() { - if (!compositingPossible()) { + if (!compositingPossible() || openGlIsBroken()) { return; } + // NOTICE: this is intended to workaround broken GL implementations that successfully segfault + // on glXQuery :-( + // we tag GL as unsafe. It *must* be reset before every return, and in case we "unexpectedly" + // end (aka "segfaulted") we know that we shall not try again + KSharedConfigPtr config = KSharedConfig::openConfig("kwinrc"); + KConfigGroup gl_workaround_config = KConfigGroup(config, "Compositing"); + gl_workaround_config.writeEntry("OpenGLIsUnsafe", true); + gl_workaround_config.sync(); + #ifdef KWIN_HAVE_OPENGL_COMPOSITING #ifdef KWIN_HAVE_OPENGLES bool haveContext = false; @@ -153,6 +188,8 @@ void CompositingPrefs::detect() } if (!Extensions::glxAvailable()) { kDebug(1212) << "No GLX available"; + gl_workaround_config.writeEntry("OpenGLIsUnsafe", false); + gl_workaround_config.sync(); return; } int glxmajor, glxminor; @@ -177,6 +214,8 @@ void CompositingPrefs::detect() glXMakeCurrent(display(), olddrawable, oldcontext); deleteGLXContext(); #endif + gl_workaround_config.writeEntry("OpenGLIsUnsafe", false); + gl_workaround_config.sync(); #endif } diff --git a/compositingprefs.h b/compositingprefs.h index 89c97a7d5f..4cfc0095ef 100644 --- a/compositingprefs.h +++ b/compositingprefs.h @@ -39,6 +39,7 @@ public: static bool compositingPossible(); static QString compositingNotPossibleReason(); + static bool openGlIsBroken(); bool recommendCompositing() const; bool enableVSync() const { return mEnableVSync; diff --git a/kcmkwin/kwincompositing/main.cpp b/kcmkwin/kwincompositing/main.cpp index 8b447253c6..a2bba83ad8 100644 --- a/kcmkwin/kwincompositing/main.cpp +++ b/kcmkwin/kwincompositing/main.cpp @@ -82,6 +82,7 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList layout()->setMargin(0); ui.tabWidget->setCurrentIndex(0); ui.statusTitleWidget->hide(); + ui.rearmGlSupport->hide(); // For future use (void) I18N_NOOP("Use GLSL shaders"); @@ -102,6 +103,7 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); + connect(ui.rearmGlSupportButton, SIGNAL(clicked()), this, SLOT(rearmGlSupport())); connect(ui.useCompositing, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectWinManagement, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.effectAnimations, SIGNAL(toggled(bool)), this, SLOT(changed())); @@ -143,34 +145,8 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList a->setGlobalShortcut( KShortcut( Qt::ALT + Qt::SHIFT + Qt::Key_F12 )); connect(ui.toggleEffectsShortcut, SIGNAL(keySequenceChanged(const QKeySequence&)), this, SLOT(toggleEffectShortcutChanged(const QKeySequence&))); - // NOTICE: this is intended to workaround broken GL implementations that successfully segfault on glXQuery :-( - KConfigGroup unsafeConfig(mKWinConfig, "Compositing"); - const bool glUnsafe = unsafeConfig.readEntry("OpenGLIsUnsafe", false); - if (!glUnsafe && CompositingPrefs::compositingPossible()) { - unsafeConfig.writeEntry("OpenGLIsUnsafe", true); - unsafeConfig.sync(); - - // Driver-specific config detection - mDefaultPrefs.detect(); - initEffectSelector(); - // Initialize the user interface with the config loaded from kwinrc. - load(); - - unsafeConfig.writeEntry("OpenGLIsUnsafe", false); - unsafeConfig.sync(); - } else { - // TODO: Add a "force recheck" button that removes the "OpenGLInUnsafe" flag - - ui.useCompositing->setEnabled(false); - ui.useCompositing->setChecked(false); - - QString text = i18n("Desktop effects are not available on this system due to the following technical issues:"); - text += "
"; - text += CompositingPrefs::compositingNotPossibleReason(); - ui.statusTitleWidget->setText(text); - ui.statusTitleWidget->setPixmap(KTitleWidget::InfoMessage, KTitleWidget::ImageLeft); - ui.statusTitleWidget->show(); - } + // Initialize the user interface with the config loaded from kwinrc. + load(); KAboutData *about = new KAboutData(I18N_NOOP("kcmkwincompositing"), 0, ki18n("KWin Desktop Effects Configuration Module"), @@ -357,12 +333,27 @@ void KWinCompositingConfig::loadGeneralTab() ui.desktopSwitchingCombo->setCurrentIndex(3); } +void KWinCompositingConfig::rearmGlSupport() +{ + // rearm config + KConfigGroup gl_workaround_config = KConfigGroup(mKWinConfig, "Compositing"); + gl_workaround_config.writeEntry("OpenGLIsUnsafe", false); + gl_workaround_config.sync(); + + // save last changes + save(); + + // Initialize the user interface with the config loaded from kwinrc. + load(); +} + void KWinCompositingConfig::toogleSmoothScaleUi(int compositingType) { ui.glScaleFilter->setVisible(compositingType == OPENGL_INDEX); ui.xrScaleFilter->setVisible(compositingType == XRENDER_INDEX); ui.scaleMethodLabel->setBuddy(compositingType == XRENDER_INDEX ? ui.xrScaleFilter : ui.glScaleFilter); + ui.glGroup->setEnabled(compositingType == OPENGL_INDEX); } void KWinCompositingConfig::toggleEffectShortcutChanged(const QKeySequence &seq) @@ -413,9 +404,33 @@ void KWinCompositingConfig::loadAdvancedTab() toogleSmoothScaleUi(ui.compositingType->currentIndex()); } +void KWinCompositingConfig::updateStatusUI(bool compositingIsPossible) +{ + if (compositingIsPossible) { + ui.compositingOptionsContainer->show(); + ui.statusTitleWidget->hide(); + ui.rearmGlSupport->hide(); + + // Driver-specific config detection + mDefaultPrefs.detect(); + } + else { + ui.compositingOptionsContainer->hide(); + QString text = i18n("Desktop effects are not available on this system due to the following technical issues:"); + text += "
"; + text += CompositingPrefs::compositingNotPossibleReason(); + ui.statusTitleWidget->setText(text); + ui.statusTitleWidget->setPixmap(KTitleWidget::InfoMessage, KTitleWidget::ImageLeft); + ui.statusTitleWidget->show(); + ui.rearmGlSupport->setVisible(CompositingPrefs::openGlIsBroken()); + } +} + void KWinCompositingConfig::load() { + initEffectSelector(); mKWinConfig->reparseConfiguration(); + updateStatusUI(CompositingPrefs::compositingPossible()); // Copy Plugins group to temp config file QMap entries = mKWinConfig->entryMap("Plugins"); @@ -537,7 +552,7 @@ bool KWinCompositingConfig::saveAdvancedTab() KConfigGroup config(mKWinConfig, "Compositing"); if (config.readEntry("Backend", "OpenGL") - != ((ui.compositingType->currentIndex() == 0) ? "OpenGL" : "XRender") + != ((ui.compositingType->currentIndex() == OPENGL_INDEX) ? "OpenGL" : "XRender") || config.readEntry("GLDirect", mDefaultPrefs.enableDirectRendering()) != ui.glDirect->isChecked() || config.readEntry("GLVSync", mDefaultPrefs.enableVSync()) != ui.glVSync->isChecked() @@ -568,6 +583,20 @@ bool KWinCompositingConfig::saveAdvancedTab() void KWinCompositingConfig::save() { + if (ui.compositingType->currentIndex() == OPENGL_INDEX && + CompositingPrefs::openGlIsBroken() && !ui.rearmGlSupport->isVisible()) + { + KConfigGroup config(mKWinConfig, "Compositing"); + QString oldBackend = config.readEntry("Backend", "OpenGL"); + config.writeEntry("Backend", "OpenGL"); + config.sync(); + updateStatusUI(false); + config.writeEntry("Backend", oldBackend); + config.sync(); + ui.tabWidget->setCurrentIndex(0); + return; + } + // Save current config. We'll use this for restoring in case something goes wrong. KConfigGroup config(mKWinConfig, "Compositing"); mPreviousConfig = config.entryMap(); @@ -659,11 +688,16 @@ void KWinCompositingConfig::configChanged(bool reinitCompositing) { // Send signal to kwin mKWinConfig->sync(); + // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", reinitCompositing ? "reinitCompositing" : "reloadConfig"); QDBusConnection::sessionBus().send(message); + // maybe it's ok now? + if (reinitCompositing && !ui.compositingOptionsContainer->isVisible()) + load(); + // HACK: We can't just do this here, due to the asynchronous nature of signals. // We also can't change reinitCompositing into a message (which would allow // callWithCallbac() to do this neater) due to multiple kwin instances. diff --git a/kcmkwin/kwincompositing/main.h b/kcmkwin/kwincompositing/main.h index 84742b701f..d9937759cc 100644 --- a/kcmkwin/kwincompositing/main.h +++ b/kcmkwin/kwincompositing/main.h @@ -76,11 +76,13 @@ public slots: void initEffectSelector(); private slots: + void rearmGlSupport(); void toogleSmoothScaleUi(int compositingType); void toggleEffectShortcutChanged(const QKeySequence &seq); private: bool effectEnabled(const QString& effect, const KConfigGroup& cfg) const; + void updateStatusUI(bool compositingIsPossible); KSharedConfigPtr mKWinConfig; Ui::KWinCompositingConfig ui; diff --git a/kcmkwin/kwincompositing/main.ui b/kcmkwin/kwincompositing/main.ui index 2e4218f76b..a96896062d 100644 --- a/kcmkwin/kwincompositing/main.ui +++ b/kcmkwin/kwincompositing/main.ui @@ -6,8 +6,8 @@ 0 0 - 560 - 472 + 544 + 523 @@ -20,9 +20,117 @@ General - + - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 75 + true + + + + Pressing this button can crash the desktop. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 125 + 71 + + + + + + + + I have saved my data. + + + + + + + Qt::Horizontal + + + + 125 + 71 + + + + + + + + false + + + Re-enable OpenGL detection + + + + + @@ -376,6 +484,9 @@ 0 + + Qt::WheelFocus + @@ -384,8 +495,24 @@ Advanced - - + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 8 + + + + + @@ -435,8 +562,27 @@ - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + 0 + + General Options @@ -591,8 +737,40 @@ p, li { white-space: pre-wrap; } - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + 0 + + OpenGL Options @@ -634,7 +812,7 @@ On legacy hardware disabling Shaders can improve the performance. - + Qt::Vertical @@ -647,6 +825,32 @@ On legacy hardware disabling Shaders can improve the performance. + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -686,5 +890,22 @@ On legacy hardware disabling Shaders can improve the performance. animationSpeedCombo - + + + rearmSafetyCheck + toggled(bool) + rearmGlSupportButton + setEnabled(bool) + + + 161 + 64 + + + 194 + 119 + + + + diff --git a/kcmkwin/kwinscreenedges/main.cpp b/kcmkwin/kwinscreenedges/main.cpp index 1cbbef1cf8..1819459a9b 100644 --- a/kcmkwin/kwinscreenedges/main.cpp +++ b/kcmkwin/kwinscreenedges/main.cpp @@ -64,16 +64,7 @@ KWinScreenEdgesConfig::KWinScreenEdgesConfig(QWidget* parent, const QVariantList connect(m_ui->quickMaximizeBox, SIGNAL(stateChanged(int)), this, SLOT(groupChanged())); connect(m_ui->quickTileBox, SIGNAL(stateChanged(int)), this, SLOT(groupChanged())); - // NOTICE: this is intended to workaround broken GL implementations that successfully segfault on glXQuery :-( - KConfigGroup gl_workaround_config(m_config, "Compositing"); - const bool checkIsSafe = gl_workaround_config.readEntry("CheckIsSafe", true); - if (checkIsSafe && CompositingPrefs::compositingPossible()) { - gl_workaround_config.writeEntry("CheckIsSafe", false); - gl_workaround_config.sync(); - m_defaultPrefs.detect(); // Driver-specific config detection - gl_workaround_config.writeEntry("CheckIsSafe", true); - gl_workaround_config.sync(); - } + m_defaultPrefs.detect(); // Driver-specific config detection load(); }