Commit 743e2bc9 authored by David Edmundson's avatar David Edmundson
Browse files

If GL context creation fails fall back to the software renderer

Summary:
If we cannot create a GL context, instead of showing an error and
quitting, switch to using the QtQuick software renderer and restart.

If software mode is already set, then show the error as before. This
could happen in the case of the software renderer not being installed.

Test Plan:
After doing some driver changing, I ended up with the annoying "plasma can't start"
message.

Without the entry in kdeglobals I now start plasma and it seamlessly comes up
working.

Reviewers: #plasma

Subscribers: mart, broulik, graesslin, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D11722
parent 21f66974
......@@ -66,14 +66,14 @@ DesktopView::DesktopView(Plasma::Corona *corona, QScreen *targetScreen)
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);
}
......
......@@ -23,6 +23,7 @@
#include <QQuickWindow>
#include <QSessionManager>
#include <QDebug>
#include <QProcess>
#include <QMessageBox>
#include <QDBusConnection>
#include <QDBusMessage>
......@@ -182,6 +183,29 @@ int main(int argc, char *argv[])
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();
......
......@@ -1191,7 +1191,10 @@ void ShellCorona::addOutput(QScreen* screen)
}
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 @@ void ShellCorona::createWaitingPanels()
//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::insertContainment(const QString &activity, int screenNum, Plas
}
}
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()) {
......
......@@ -113,6 +113,9 @@ public:
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 @@ private Q_SLOTS:
void primaryOutputChanged();
void panelContainmentDestroyed(QObject* cont);
void showOpenGLNotCompatibleWarning();
void interactiveConsoleVisibilityChanged(bool visible);
void handleScreenRemoved(QScreen* screen);
......
......@@ -91,6 +91,8 @@ void ShellManager::loadHandlers()
Q_ASSERT(!d->corona);
d->corona = new ShellCorona(this);
connect(d->corona, &ShellCorona::glInitialisationFailed,
this, &ShellManager::glInitialisationFailed);
connect(
this, &ShellManager::shellChanged,
......
......@@ -58,6 +58,7 @@ public Q_SLOTS:
Q_SIGNALS:
void shellChanged(const QString & shell);
void glInitialisationFailed();
private Q_SLOTS:
void loadHandlers();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment