Commit b3484aa8 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Implement "Software Renderer" option for OpenGL engine

On old GPUs that support D3D<=10.0 we cannot use Angle for emulating
openGL, therefore we should use some software implementation (or try
using D3D9 with its openGLES 2.0). This patch adds an option to select
software rasterizer WARP, created by Microsoft, which is a part of
DirectX 11 and should be avaailable on all system with Windows 7 and
newer.

CCBUG:408872
parent 70958faf
......@@ -218,26 +218,13 @@ extern "C" int main(int argc, char **argv)
logUsage = kritarc.value("LogUsage", true).toBool();
#ifdef Q_OS_WIN
// Force ANGLE to use Direct3D11. D3D9 doesn't support OpenGL ES 3 and WARP
// might get weird crashes atm.
const QString preferredRendererString = kritarc.value("OpenGLRenderer", "angle").toString();
preferredRenderer = KisOpenGL::convertConfigToOpenGLRenderer(preferredRendererString);
qputenv("QT_ANGLE_PLATFORM", "d3d11");
#else
const QString preferredRendererString = kritarc.value("OpenGLRenderer", "auto").toString();
preferredRenderer = KisOpenGL::convertConfigToOpenGLRenderer(preferredRendererString);
#endif
const QSurfaceFormat format =
KisOpenGL::selectSurfaceFormat(preferredRenderer, rootSurfaceFormat, enableOpenGLDebug);
const KisOpenGL::RendererConfig config =
KisOpenGL::selectSurfaceConfig(preferredRenderer, rootSurfaceFormat, enableOpenGLDebug);
if (format.renderableType() == QSurfaceFormat::OpenGLES) {
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
} else {
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true);
}
KisOpenGL::setDefaultSurfaceFormat(format);
KisOpenGL::setDefaultSurfaceConfig(config);
KisOpenGL::setDebugSynchronous(openGLDebugSynchronous);
#ifdef Q_OS_WIN
......
......@@ -1086,20 +1086,29 @@ DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name)
KisConfig cfg(true);
const QString rendererOpenGLText = i18nc("canvas renderer", "OpenGL");
const QString rendererSoftwareText = i18nc("canvas renderer", "Software Renderer (very slow)");
#ifdef Q_OS_WIN
const QString rendererOpenGLESText = i18nc("canvas renderer", "Direct3D 11 via ANGLE");
#else
const QString rendererOpenGLESText = i18nc("canvas renderer", "OpenGL ES");
#endif
lblCurrentRenderer->setText(KisOpenGL::hasOpenGLES() ? rendererOpenGLESText : rendererOpenGLText);
const KisOpenGL::OpenGLRenderer renderer = KisOpenGL::getCurrentOpenGLRenderer();
lblCurrentRenderer->setText(renderer == KisOpenGL::RendererOpenGLES ? rendererOpenGLESText :
renderer == KisOpenGL::RendererDesktopGL ? rendererOpenGLText :
renderer == KisOpenGL::RendererSoftware ? rendererSoftwareText :
i18nc("canvas renderer", "Unknown"));
cmbPreferredRenderer->clear();
QString qtPreferredRendererText;
if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererOpenGLES) {
qtPreferredRendererText = rendererOpenGLESText;
} else if (KisOpenGL::getQtPreferredOpenGLRenderer() == KisOpenGL::RendererSoftware) {
qtPreferredRendererText = rendererSoftwareText;
} else {
qtPreferredRendererText = rendererOpenGLText;
}
cmbPreferredRenderer->addItem(i18nc("canvas renderer", "Auto (%1)", qtPreferredRendererText), KisOpenGL::RendererAuto);
cmbPreferredRenderer->setCurrentIndex(0);
if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererDesktopGL) {
......@@ -1116,10 +1125,19 @@ DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name)
cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
}
}
if (KisOpenGL::getSupportedOpenGLRenderers() & KisOpenGL::RendererSoftware) {
cmbPreferredRenderer->addItem(rendererSoftwareText, KisOpenGL::RendererSoftware);
if (KisOpenGL::getUserPreferredOpenGLRendererConfig() == KisOpenGL::RendererSoftware) {
cmbPreferredRenderer->setCurrentIndex(cmbPreferredRenderer->count() - 1);
}
}
#endif
if (!(KisOpenGL::getSupportedOpenGLRenderers() &
(KisOpenGL::RendererDesktopGL | KisOpenGL::RendererOpenGLES))) {
(KisOpenGL::RendererDesktopGL |
KisOpenGL::RendererOpenGLES |
KisOpenGL::RendererSoftware))) {
grpOpenGL->setEnabled(false);
grpOpenGL->setChecked(false);
chkUseTextureBuffer->setEnabled(false);
......
......@@ -113,15 +113,48 @@ private:
QSurfaceFormat m_oldFormat;
};
struct EnvironmentSetter
{
EnvironmentSetter(const QLatin1String &env, const QString &value)
: m_env(env)
{
if (qEnvironmentVariableIsEmpty(m_env.latin1())) {
m_oldValue = qEnvironmentVariable(env.latin1());
}
if (!value.isEmpty()) {
qputenv(env.latin1(), value.toLatin1());
} else {
qunsetenv(env.latin1());
}
}
~EnvironmentSetter() {
if (m_oldValue) {
qputenv(m_env.latin1(), (*m_oldValue).toLatin1());
} else {
qunsetenv(m_env.latin1());
}
}
private:
const QLatin1String m_env;
boost::optional<QString> m_oldValue;
};
}
boost::optional<KisOpenGLModeProber::Result>
KisOpenGLModeProber::probeFormat(const QSurfaceFormat &format, bool adjustGlobalState)
KisOpenGLModeProber::probeFormat(const KisOpenGL::RendererConfig &rendererConfig,
bool adjustGlobalState)
{
const QSurfaceFormat &format = rendererConfig.format;
QScopedPointer<AppAttributeSetter> sharedContextSetter;
QScopedPointer<AppAttributeSetter> glSetter;
QScopedPointer<AppAttributeSetter> glesSetter;
QScopedPointer<SurfaceFormatSetter> formatSetter;
QScopedPointer<EnvironmentSetter> rendererSetter;
QScopedPointer<QGuiApplication> application;
int argc = 1;
......@@ -138,6 +171,7 @@ KisOpenGLModeProber::probeFormat(const QSurfaceFormat &format, bool adjustGlobal
glesSetter.reset(new AppAttributeSetter(Qt::AA_UseOpenGLES, format.renderableType() == QSurfaceFormat::OpenGLES));
}
rendererSetter.reset(new EnvironmentSetter(QLatin1String("QT_ANGLE_PLATFORM"), angleRendererToString(rendererConfig.angleRenderer)));
formatSetter.reset(new SurfaceFormatSetter(format));
QGuiApplication::setDesktopSettingsAware(false);
......@@ -253,6 +287,27 @@ bool KisOpenGLModeProber::isFormatHDR(const QSurfaceFormat &format)
#endif
}
QString KisOpenGLModeProber::angleRendererToString(KisOpenGL::AngleRenderer renderer)
{
QString value;
switch (renderer) {
case KisOpenGL::AngleRendererDefault:
break;
case KisOpenGL::AngleRendererD3d9:
value = "d3d9";
break;
case KisOpenGL::AngleRendererD3d11:
value = "d3d11";
break;
case KisOpenGL::AngleRendererD3d11Warp:
value = "warp";
break;
};
return value;
}
KisOpenGLModeProber::Result::Result(QOpenGLContext &context) {
if (!context.isValid()) {
return;
......
......@@ -26,6 +26,7 @@
#include <QSurfaceFormat>
#include "KisSurfaceColorSpace.h"
#include <boost/optional.hpp>
#include "kis_opengl.h"
class KoColorProfile;
......@@ -45,11 +46,12 @@ public:
const KoColorProfile *rootSurfaceColorProfile() const;
boost::optional<Result> probeFormat(const QSurfaceFormat &format,
boost::optional<Result> probeFormat(const KisOpenGL::RendererConfig &rendererConfig,
bool adjustGlobalState = true);
static bool fuzzyCompareColorSpaces(const KisSurfaceColorSpace &lhs,
const KisSurfaceColorSpace &rhs);
static QString angleRendererToString(KisOpenGL::AngleRenderer renderer);
public:
static void initSurfaceFormatFromConfig(KisConfig::RootSurfaceFormat config,
......
This diff is collapsed.
......@@ -46,21 +46,36 @@ public:
TrilinearFilterMode, // LINEAR_MIPMAP_LINEAR
HighQualityFiltering // Mipmaps + custom shader
};
public:
enum OpenGLRenderer {
RendererNone = 0x00,
RendererAuto = 0x01,
RendererDesktopGL = 0x02,
RendererOpenGLES = 0x04,
RendererSoftware = 0x08
};
Q_DECLARE_FLAGS(OpenGLRenderers, OpenGLRenderer)
enum AngleRenderer {
AngleRendererDefault = 0x0000,
AngleRendererD3d11 = 0x0002,
AngleRendererD3d9 = 0x0004,
AngleRendererD3d11Warp = 0x0008, // "Windows Advanced Rasterization Platform"
};
Q_DECLARE_FLAGS(OpenGLRenderers, OpenGLRenderer);
static QSurfaceFormat selectSurfaceFormat(KisOpenGL::OpenGLRenderer preferredRenderer,
struct RendererConfig {
QSurfaceFormat format;
AngleRenderer angleRenderer = AngleRendererDefault;
OpenGLRenderer rendererId() const;
};
public:
static RendererConfig selectSurfaceConfig(KisOpenGL::OpenGLRenderer preferredRenderer,
KisConfig::RootSurfaceFormat preferredRootSurfaceFormat,
bool enableDebug);
static void setDefaultSurfaceFormat(const QSurfaceFormat &format);
static void setDefaultSurfaceConfig(const RendererConfig &config);
static OpenGLRenderer getCurrentOpenGLRenderer();
static OpenGLRenderer getQtPreferredOpenGLRenderer();
......
Markdown is supported
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