File indexing completed on 2024-05-05 17:42:26

0001 /*
0002     SPDX-FileCopyrightText: 2016 David Edmundson <davidedmundson@kde.org>
0003     SPDX-FileCopyrightText: 2020 Piotr Henryk Dabrowski <phd@phd.re>
0004     SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "renderersettings.h"
0010 
0011 #include <QGuiApplication>
0012 #include <QLibraryInfo>
0013 #include <QOffscreenSurface>
0014 #include <QOpenGLContext>
0015 #include <QOpenGLFunctions>
0016 #include <QQuickWindow>
0017 #include <QSurfaceFormat>
0018 #include <QVersionNumber>
0019 
0020 /**
0021  * If QtQuick is configured (QQuickWindow::sceneGraphBackend()) to use the OpenGL backend,
0022  * check if it is supported or otherwise reconfigure QtQuick to fallback to software mode.
0023  * This function is called by init().
0024  *
0025  * @returns true if the selected backend is supported, false on fallback to software mode.
0026  */
0027 static bool checkBackend(QOpenGLContext &checkContext)
0028 {
0029     if (!QQuickWindow::sceneGraphBackend().isEmpty()) {
0030         return true; // QtQuick is not configured to use the OpenGL backend
0031     }
0032 
0033     // kwin wayland has it's own QPA, it is unable to create a GL context at this point.
0034     // KF6 TODO, drop this . The issue will be resolved in future kwin releases.
0035     QString platformName = qApp->platformName();
0036     if (platformName == QLatin1String("wayland-org.kde.kwin.qpa")) {
0037         return true;
0038     }
0039 
0040 #ifdef QT_NO_OPENGL
0041     bool ok = false;
0042 #else
0043     bool ok = checkContext.create();
0044 #endif
0045     if (!ok) {
0046         qWarning("Warning: fallback to QtQuick software backend.");
0047         QQuickWindow::setSceneGraphBackend(QStringLiteral("software"));
0048     }
0049     return ok;
0050 }
0051 
0052 void initializeRendererSessions()
0053 {
0054     // This is loaded via Q_COREAPP_STARTUP_FUNCTION
0055 
0056     // Due to a quirk this gets called twice, see QTBUG-54479
0057 
0058     // The order of events is:
0059     // Q*Application constructor starts
0060     // We load the QPA
0061     // We load the QPT (The first arguably incorrect invocation triggers)
0062     // QPA gets initalised
0063     // QCoreApplication constructor ends
0064     // Second (correct) invocation
0065     // it's important that we run after the QPA is initalised'
0066 
0067     static bool firstCall = true;
0068     if (firstCall) {
0069         firstCall = false;
0070         return;
0071     }
0072 
0073     PlasmaQtQuickSettings::RendererSettings s;
0074     QOpenGLContext checkContext;
0075     if (!s.sceneGraphBackend().isEmpty()) {
0076         QQuickWindow::setSceneGraphBackend(s.sceneGraphBackend());
0077     } else {
0078         QQuickWindow::setSceneGraphBackend(QStringLiteral(""));
0079         checkBackend(checkContext);
0080     }
0081 
0082     if (!qEnvironmentVariableIsSet("QSG_RENDER_LOOP")) {
0083         if (!s.renderLoop().isEmpty()) {
0084             qputenv("QSG_RENDER_LOOP", s.renderLoop().toLatin1());
0085         } else if (QGuiApplication::platformName() == QLatin1String("wayland")) {
0086 #if QT_CONFIG(opengl)
0087             // Workaround for Bug 432062 / QTBUG-95817
0088             QOffscreenSurface surface;
0089             surface.create();
0090             if (checkContext.makeCurrent(&surface)) {
0091                 const char *vendor = reinterpret_cast<const char *>(checkContext.functions()->glGetString(GL_VENDOR));
0092                 if (qstrcmp(vendor, "NVIDIA Corporation") == 0) {
0093                     // Otherwise Qt Quick Windows break when resized
0094                     qputenv("QSG_RENDER_LOOP", "basic");
0095                 }
0096             }
0097 #endif
0098         }
0099     }
0100 }
0101 
0102 // Because this file gets loaded in the platform plugin, the QGuiApplication already exists
0103 Q_COREAPP_STARTUP_FUNCTION(initializeRendererSessions)