diff --git a/modules/gui/qt/qt.cpp b/modules/gui/qt/qt.cpp index 81b5f2e30ff024032a21f439cd233cd4c1ebcbdb..f76deadf2e7647566bf2c1c4d11d3645f1367aa2 100644 --- a/modules/gui/qt/qt.cpp +++ b/modules/gui/qt/qt.cpp @@ -920,45 +920,6 @@ static void *Thread( void *obj ) QApplication app( argc, argv ); app.setProperty("initialStyle", app.style()->objectName()); -#if defined(_WIN32) - // NOTE: Qt Quick does not have a cross-API RHI fallback procedure (as of Qt 6.7.1). - // We have to manually pick a graphics api here, since the default graphics - // api (Direct3D 11.2) may not be supported. - - if (qEnvironmentVariableIsEmpty("QSG_RHI_BACKEND") && - qEnvironmentVariableIsEmpty("QT_QUICK_BACKEND") && - (QT_VERSION < QT_VERSION_CHECK(6, 4, 0) || !uint(qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER")))) - { - // If OS version is lower than Windows 8.1, and Qt version is lower than - // 6.6.0, do not take risk and use OpenGL (since probing is not available). - // If OS version is greater than or equal to Windows 8.1, and Qt version is - // lower than 6.6.0, take risk and do not use the fallback procedure. - // Qt in the contribs is already version 6.7.0, so this should not be a - // concern. - if ((QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1) || - (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0))) - { - // TODO: Probe D3D12 when it becomes the default. - // If probing is not available, use OpenGL as a compromise: - QSGRendererInterface::GraphicsApi graphicsApi = QSGRendererInterface::OpenGL; -#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) - QRhiD3D11InitParams params; - if (QRhi::probe(QRhi::D3D11, ¶ms)) - graphicsApi = QSGRendererInterface::Direct3D11; - else - { - QRhiGles2InitParams params1; - params1.fallbackSurface = QRhiGles2InitParams::newFallbackSurface(); - if (!QRhi::probe(QRhi::OpenGLES2, ¶ms1)) - graphicsApi = QSGRendererInterface::Software; - delete params1.fallbackSurface; - } -#endif - QQuickWindow::setGraphicsApi(graphicsApi); - } - } -#endif - { // Install custom translator: const auto translator = new Translator(&app); @@ -995,6 +956,88 @@ static void *Thread( void *obj ) #endif QSettings::UserScope, "vlc", "vlc-qt-interface" ); +#if defined(_WIN32) + // NOTE: Qt Quick does not have a cross-API RHI fallback procedure (as of Qt 6.7.1). + // We have to manually pick a graphics api here, since the default graphics + // api (Direct3D 11.2) may not be supported. + static const auto probeRhi = []() -> QSGRendererInterface::GraphicsApi { + std::optional<QSGRendererInterface::GraphicsApi> graphicsApi; + // TODO: Probe D3D12 when it becomes the default. + { + // D3D11 + QRhiD3D11InitParams params; + if (QRhi::probe(QRhi::D3D11, ¶ms)) + graphicsApi = QSGRendererInterface::Direct3D11; + } + + if (!graphicsApi) + { + // Vulkan + QVulkanInstance inst; + if (inst.create()) + { + QRhiVulkanInitParams params1; + params1.inst = &inst; + if (QRhi::probe(QRhi::Vulkan, ¶ms1)) + graphicsApi = QSGRendererInterface::Vulkan; + } + } + + if (!graphicsApi) + { + // OpenGL + QRhiGles2InitParams params2; + params2.fallbackSurface = QRhiGles2InitParams::newFallbackSurface(); + if (QRhi::probe(QRhi::OpenGLES2, ¶ms2)) + graphicsApi = QSGRendererInterface::OpenGL; + delete params2.fallbackSurface; + } + + if (!graphicsApi) + graphicsApi = QSGRendererInterface::Software; + + return *graphicsApi; + }; + + if (qEnvironmentVariableIsEmpty("QSG_RHI_BACKEND") && + qEnvironmentVariableIsEmpty("QT_QUICK_BACKEND") && + (QT_VERSION < QT_VERSION_CHECK(6, 4, 0) || !uint(qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER")))) + { + static const char* const graphicsApiKey = "graphics-api"; + const QVariant graphicsApiValue = p_intf->mainSettings->value(graphicsApiKey); + // settings value can be string (ini file), do not use `typeId()`: + if (graphicsApiValue.isValid() && Q_LIKELY(graphicsApiValue.canConvert<int>())) + { + // A cached (by then) valid graphics api is found, use it: + QQuickWindow::setGraphicsApi(static_cast<QSGRendererInterface::GraphicsApi>(graphicsApiValue.value<int>())); + // Asynchronous re-probe to see if the cached graphics api is still applicable. + // If not, QQuickWindow is going to emit scene graph error, and the application is + // likely going to terminate. However, when the user starts the application again + // there will not be an error thanks to this. We can not prevent the error, as + // it is decided to not make compositor initializaation wait to not reduce the startup + // speed. Startup time is defined as the time it takes to start playing the initial + // item. Currently the player waits for the interface, and QQuickWindow initialization + // is therefore not enforced to be synchronous (`QWindow::setVisible(true)` which + // initializes the scene graph thus rhi is asynchronous). + QMetaObject::invokeMethod(&app, [settings = QPointer(p_intf->mainSettings)]() { + // We can not use `QQuickWindow::setGraphicsApi()` here, as QQuickWindow + // may have already tried to initialize the scene graph hence rhi. If the + // cached graphics api is not optimal or not available anymore, the next + // startup will use the refreshed value. That's the best we can do here + // without forcing QQuickWindow to wait (hence delaying startup). + assert(settings); + settings->setValue(graphicsApiKey, static_cast<int>(probeRhi())); + }, Qt::QueuedConnection); // Asynchronous, so probing here does not cause start-up slowdown. + } + else + { + const QSGRendererInterface::GraphicsApi graphicsApi = probeRhi(); + QQuickWindow::setGraphicsApi(graphicsApi); + p_intf->mainSettings->setValue(graphicsApiKey, static_cast<int>(graphicsApi)); + } + } +#endif + app.setApplicationDisplayName( qtr("VLC media player") ); if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )