File indexing completed on 2024-11-24 05:00:56

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     return ok;
0046 }
0047 
0048 void initializeRendererSessions()
0049 {
0050     // This is loaded via Q_COREAPP_STARTUP_FUNCTION
0051 
0052     // Due to a quirk this gets called twice, see QTBUG-54479
0053 
0054     // The order of events is:
0055     // Q*Application constructor starts
0056     // We load the QPA
0057     // We load the QPT (The first arguably incorrect invocation triggers)
0058     // QPA gets initalised
0059     // QCoreApplication constructor ends
0060     // Second (correct) invocation
0061     // it's important that we run after the QPA is initalised'
0062 
0063     static bool firstCall = true;
0064     if (firstCall) {
0065         firstCall = false;
0066         return;
0067     }
0068 
0069     PlasmaQtQuickSettings::RendererSettings s;
0070     QOpenGLContext checkContext;
0071 
0072     QSGRendererInterface::GraphicsApi graphicsApi = QSGRendererInterface::Unknown;
0073 
0074     switch (s.sceneGraphBackend()) {
0075     case PlasmaQtQuickSettings::RendererSettings::software:
0076         graphicsApi = QSGRendererInterface::Software;
0077         break;
0078     case PlasmaQtQuickSettings::RendererSettings::opengl:
0079         graphicsApi = QSGRendererInterface::OpenGL;
0080         break;
0081     default:
0082         if (!checkBackend(checkContext)) {
0083             qWarning("Warning: fallback to QtQuick software backend.");
0084             graphicsApi = QSGRendererInterface::Software;
0085         }
0086     }
0087 
0088     if (graphicsApi != QSGRendererInterface::Unknown) {
0089         QQuickWindow::setSceneGraphBackend(graphicsApi);
0090     }
0091 
0092     if (!qEnvironmentVariableIsSet("QSG_RENDER_LOOP")) {
0093         if (s.renderLoop() == PlasmaQtQuickSettings::RendererSettings::basic) {
0094             qputenv("QSG_RENDER_LOOP", "basic");
0095         } else if (QGuiApplication::platformName() == QLatin1String("wayland")) {
0096 #if QT_CONFIG(opengl)
0097             // Workaround for Bug 432062 / QTBUG-95817
0098             QOffscreenSurface surface;
0099             surface.create();
0100             if (checkContext.makeCurrent(&surface)) {
0101                 const char *vendor = reinterpret_cast<const char *>(checkContext.functions()->glGetString(GL_VENDOR));
0102                 if (qstrcmp(vendor, "NVIDIA Corporation") == 0) {
0103                     // Otherwise Qt Quick Windows break when resized
0104                     qputenv("QSG_RENDER_LOOP", "basic");
0105                 }
0106             }
0107 #endif
0108         }
0109     }
0110 }
0111 
0112 // Because this file gets loaded in the platform plugin, the QGuiApplication already exists
0113 Q_COREAPP_STARTUP_FUNCTION(initializeRendererSessions)