diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp --- a/shell/desktopview.cpp +++ b/shell/desktopview.cpp @@ -66,14 +66,14 @@ QObject::connect(m_activityController, &KActivities::Controller::activityRemoved, this, &DesktopView::candidateContainmentsChanged); - if (QQuickWindow::sceneGraphBackend() != QLatin1String("software")) { + if (rendererInterface()->graphicsApi() != QSGRendererInterface::Software) { connect(this, &DesktopView::sceneGraphInitialized, this, [this, corona]() { // check whether the GL Context supports OpenGL // Note: hasOpenGLShaderPrograms is broken, see QTBUG--39730 if (!QOpenGLShaderProgram::hasOpenGLShaderPrograms(openglContext())) { qWarning() << "GLSL not available, Plasma won't be functional"; - QMetaObject::invokeMethod(corona, "showOpenGLNotCompatibleWarning", Qt::QueuedConnection); + QMetaObject::invokeMethod(corona, "glInitialisationFailed", Qt::QueuedConnection); } }, Qt::DirectConnection); } diff --git a/shell/main.cpp b/shell/main.cpp --- a/shell/main.cpp +++ b/shell/main.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -182,6 +183,29 @@ KDBusService service(KDBusService::Unique); + + QObject::connect(ShellManager::instance(), &ShellManager::glInitialisationFailed, &app, [&app]() { + //scene graphs errors come from a thread + //even though we process them in the main thread, app.exit could still process these events + static bool s_multipleInvokations = false; + if (s_multipleInvokations) { + return; + } + s_multipleInvokations = true; + + qCritical("Open GL context could not be created"); + auto configGroup = KSharedConfig::openConfig()->group("QtQuickRendererSettings"); + if (configGroup.readEntry("SceneGraphBackend") != QLatin1String("software")) { + configGroup.writeEntry("SceneGraphBackend", "software", KConfigBase::Global | KConfigBase::Persistent); + configGroup.sync(); + QProcess::startDetached("plasmashell", app.arguments()); + } else { + QCoreApplication::setAttribute(Qt::AA_ForceRasterWidgets); + QMessageBox::critical(nullptr, i18n("Plasma Failed To Start"), + i18n("Plasma is unable to start as it could not correctly use OpenGL 2 or software fallback\nPlease check that your graphic drivers are set up correctly.")); + } + app.exit(-1); + }); QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, ShellManager::instance(), &QObject::deleteLater); return app.exec(); diff --git a/shell/shellcorona.h b/shell/shellcorona.h --- a/shell/shellcorona.h +++ b/shell/shellcorona.h @@ -113,6 +113,9 @@ QString defaultContainmentPlugin() const; +Q_SIGNALS: + void glInitialisationFailed(); + public Q_SLOTS: /** * Request saving applicationConfig on disk, it's event compressed, not immediate @@ -200,7 +203,6 @@ void primaryOutputChanged(); void panelContainmentDestroyed(QObject* cont); - void showOpenGLNotCompatibleWarning(); void interactiveConsoleVisibilityChanged(bool visible); void handleScreenRemoved(QScreen* screen); diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -1191,7 +1191,10 @@ } DesktopView *view = new DesktopView(this, screen); - connect(view, &QQuickWindow::sceneGraphError, this, &ShellCorona::showOpenGLNotCompatibleWarning); + + if (view->rendererInterface()->graphicsApi() != QSGRendererInterface::Software) { + connect(view, &QQuickWindow::sceneGraphError, this, &ShellCorona::glInitialisationFailed); + } connect(screen, &QScreen::geometryChanged, this, [=]() { const int id = m_screenPool->id(screen->name()); if (id >= 0) { @@ -1279,7 +1282,9 @@ //Q_ASSERT(qBound(0, requestedScreen, m_screenPool->count() - 1) == requestedScreen); QScreen *screen = m_desktopViewforId.value(requestedScreen)->screenToFollow(); PanelView* panel = new PanelView(this, screen); - connect(panel, &QQuickWindow::sceneGraphError, this, &ShellCorona::showOpenGLNotCompatibleWarning); + if (panel->rendererInterface()->graphicsApi() != QSGRendererInterface::Software) { + connect(panel, &QQuickWindow::sceneGraphError, this, &ShellCorona::glInitialisationFailed); + } connect(panel, &QWindow::visibleChanged, this, &Plasma::Corona::availableScreenRectChanged); connect(panel, &PanelView::locationChanged, this, &Plasma::Corona::availableScreenRectChanged); connect(panel, &PanelView::visibilityModeChanged, this, &Plasma::Corona::availableScreenRectChanged); @@ -1962,23 +1967,6 @@ } } -void ShellCorona::showOpenGLNotCompatibleWarning() -{ - static bool s_multipleInvokations = false; - if (s_multipleInvokations) { - return; - } - s_multipleInvokations = true; - - QCoreApplication::setAttribute(Qt::AA_ForceRasterWidgets); - QMessageBox::critical(nullptr, i18n("Plasma Failed To Start"), - i18n("Plasma is unable to start as it could not correctly use OpenGL 2.\n Please check that your graphic drivers are set up correctly.")); - qCritical("Open GL context could not be created"); - - // this doesn't work and I have no idea why. - QCoreApplication::exit(1); -} - void ShellCorona::setupWaylandIntegration() { if (!KWindowSystem::isPlatformWayland()) { diff --git a/shell/shellmanager.h b/shell/shellmanager.h --- a/shell/shellmanager.h +++ b/shell/shellmanager.h @@ -58,6 +58,7 @@ Q_SIGNALS: void shellChanged(const QString & shell); + void glInitialisationFailed(); private Q_SLOTS: void loadHandlers(); diff --git a/shell/shellmanager.cpp b/shell/shellmanager.cpp --- a/shell/shellmanager.cpp +++ b/shell/shellmanager.cpp @@ -91,6 +91,8 @@ Q_ASSERT(!d->corona); d->corona = new ShellCorona(this); + connect(d->corona, &ShellCorona::glInitialisationFailed, + this, &ShellManager::glInitialisationFailed); connect( this, &ShellManager::shellChanged,