diff --git a/ui/gl/gl_detection.cpp b/ui/gl/gl_detection.cpp index 7ee5767..8adfe4e 100644 --- a/ui/gl/gl_detection.cpp +++ b/ui/gl/gl_detection.cpp @@ -10,6 +10,7 @@ #include "base/debug_log.h" #include +#include #include #include #include @@ -22,6 +23,16 @@ namespace { bool ForceDisabled/* = false*/; +ANGLE ResolvedANGLE = ANGLE::Auto; + +void CrashCheckStart() { + auto f = QFile(Integration::Instance().openglCheckFilePath()); + if (f.open(QIODevice::WriteOnly)) { + f.write("1", 1); + f.close(); + } +} + } // namespace Capabilities CheckCapabilities(QWidget *widget) { @@ -47,9 +58,9 @@ Capabilities CheckCapabilities(QWidget *widget) { auto tester = QOpenGLWidget(widget); tester.setFormat(format); - Ui::Integration::Instance().openglCheckStart(); + CrashCheckStart(); tester.grabFramebuffer(); // Force initialize(). - Ui::Integration::Instance().openglCheckFinish(); + CrashCheckFinish(); if (!tester.window()->windowHandle()) { tester.window()->createWinId(); @@ -123,8 +134,71 @@ Capabilities CheckCapabilities(QWidget *widget) { return result; } +bool LastCrashCheckFailed() { + return QFile::exists(Integration::Instance().openglCheckFilePath()); +} + +void CrashCheckFinish() { + QFile::remove(Integration::Instance().openglCheckFilePath()); +} + void ForceDisable(bool disable) { ForceDisabled = disable; } +#ifdef Q_OS_WIN + +void ConfigureANGLE() { + qunsetenv("DESKTOP_APP_QT_ANGLE_PLATFORM"); + const auto path = Ui::Integration::Instance().angleBackendFilePath(); + if (path.isEmpty()) { + return; + } + auto f = QFile(path); + if (!f.open(QIODevice::ReadOnly)) { + return; + } + auto bytes = f.read(32); + const auto check = [&](const char *backend, ANGLE angle) { + if (bytes.startsWith(backend)) { + ResolvedANGLE = angle; + qputenv("DESKTOP_APP_QT_ANGLE_PLATFORM", backend); + } + }; + check("d3d11on12", ANGLE::D3D11on12); + check("d3d11", ANGLE::D3D11); + check("d3d9", ANGLE::D3D9); + check("gl", ANGLE::OpenGL); + if (ResolvedANGLE == ANGLE::Auto) { + LOG(("ANGLE Warning: Unknown backend: %1" + ).arg(QString::fromUtf8(bytes))); + } +} + +void ChangeANGLE(ANGLE backend) { + const auto path = Ui::Integration::Instance().angleBackendFilePath(); + const auto write = [&](QByteArray backend) { + auto f = QFile(path); + if (!f.open(QIODevice::WriteOnly)) { + LOG(("ANGLE Warning: Could not write to %1.").arg(path)); + return; + } + f.write(backend); + }; + switch (backend) { + case ANGLE::Auto: QFile(path).remove(); break; + case ANGLE::D3D9: write("d3d9"); break; + case ANGLE::D3D11: write("d3d11"); break; + case ANGLE::D3D11on12: write("d3d11on12"); break; + case ANGLE::OpenGL: write("gl"); break; + default: Unexpected("ANGLE backend value."); + } +} + +ANGLE CurrentANGLE() { + return ResolvedANGLE; +} + +#endif // Q_OS_WIN + } // namespace Ui::GL diff --git a/ui/gl/gl_detection.h b/ui/gl/gl_detection.h index 9641fad..c50cab7 100644 --- a/ui/gl/gl_detection.h +++ b/ui/gl/gl_detection.h @@ -24,4 +24,20 @@ struct Capabilities { void ForceDisable(bool disable); +[[nodiscard]] bool LastCrashCheckFailed(); +void CrashCheckFinish(); + +// Windows only. +enum class ANGLE { + Auto, + D3D9, + D3D11, + D3D11on12, + OpenGL, +}; + +void ConfigureANGLE(); // Requires Ui::Integration being set. +void ChangeANGLE(ANGLE backend); +[[nodiscard]] ANGLE CurrentANGLE(); + } // namespace Ui::GL diff --git a/ui/integration.cpp b/ui/integration.cpp index f7879f0..999140b 100644 --- a/ui/integration.cpp +++ b/ui/integration.cpp @@ -6,8 +6,10 @@ // #include "ui/integration.h" +#include "ui/gl/gl_detection.h" #include "ui/text/text_entity.h" #include "ui/basic_click_handlers.h" +#include "base/platform/base_platform_info.h" namespace Ui { namespace { @@ -18,6 +20,10 @@ Integration *IntegrationInstance = nullptr; void Integration::Set(not_null instance) { IntegrationInstance = instance; + + if constexpr (Platform::IsWindows()) { + GL::ConfigureANGLE(); + } } Integration &Integration::Instance() { @@ -30,16 +36,6 @@ bool Integration::Exists() { return (IntegrationInstance != nullptr); } -void Integration::openglCheckStart() { -} - -void Integration::openglCheckFinish() { -} - -bool Integration::openglLastCheckFailed() { - return false; -} - void Integration::textActionsUpdated() { } diff --git a/ui/integration.h b/ui/integration.h index 955ea72..cd7704b 100644 --- a/ui/integration.h +++ b/ui/integration.h @@ -35,11 +35,9 @@ public: virtual void registerLeaveSubscription(not_null widget) = 0; virtual void unregisterLeaveSubscription(not_null widget) = 0; - virtual void openglCheckStart(); - virtual void openglCheckFinish(); - [[nodiscard]] virtual bool openglLastCheckFailed(); - [[nodiscard]] virtual QString emojiCacheFolder() = 0; + [[nodiscard]] virtual QString openglCheckFilePath() = 0; + [[nodiscard]] virtual QString angleBackendFilePath() = 0; virtual void textActionsUpdated(); virtual void activationFromTopPanel();