Windows: Add infrastructure to be able to a GL renderer based on GPU.

Introduce flags for the renderer type and move code to
qwindowsopengltester. Introduce
QWindowsOpenGLTester::supportedGlesRenderers() where type-dependent
checking can be added.

Change-Id: I4bbffaf861cb0fdbea0919e081e3626fb5a872de
Task-number: QTBUG-43263
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
bb10
Friedemann Kleint 2015-01-12 15:59:36 +01:00
parent 0fa092cbae
commit 97a82f62c4
6 changed files with 168 additions and 48 deletions

View File

@ -340,7 +340,7 @@ QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int versi
{
}
QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType)
{
const HDC dc = QWindowsContext::instance()->displayContext();
if (!dc){
@ -359,27 +359,26 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
EGLDisplay display = EGL_NO_DISPLAY;
#ifdef EGL_ANGLE_platform_angle_opengl
if (libEGL.eglGetPlatformDisplayEXT && qEnvironmentVariableIsSet("QT_ANGLE_PLATFORM")) {
if (libEGL.eglGetPlatformDisplayEXT
&& (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
const EGLint anglePlatformAttributes[][5] = {
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE },
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE },
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, EGL_NONE }
};
const EGLint *attributes = 0;
const QByteArray anglePlatform = qgetenv("QT_ANGLE_PLATFORM");
if (anglePlatform == "d3d11")
if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)
attributes = anglePlatformAttributes[0];
else if (anglePlatform == "d3d9")
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9)
attributes = anglePlatformAttributes[1];
else if (anglePlatform == "warp")
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp)
attributes = anglePlatformAttributes[2];
else
qCWarning(lcQpaGl) << "Invalid value set for QT_ANGLE_PLATFORM:" << anglePlatform;
if (attributes)
display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
}
#endif // EGL_ANGLE_platform_angle_opengl
#else // EGL_ANGLE_platform_angle_opengl
Q_UNUSED(preferredType)
#endif
if (display == EGL_NO_DISPLAY)
display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {

View File

@ -35,6 +35,7 @@
#define QWINDOWSEGLCONTEXT_H
#include "qwindowsopenglcontext.h"
#include "qwindowsopengltester.h"
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@ -249,7 +250,7 @@ class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
Q_DISABLE_COPY(QWindowsEGLStaticContext)
public:
static QWindowsEGLStaticContext *create();
static QWindowsEGLStaticContext *create(QWindowsOpenGLTester::Renderers preferredType);
~QWindowsEGLStaticContext();
EGLDisplay display() const { return m_display; }

View File

@ -328,47 +328,61 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
}
#ifndef QT_NO_OPENGL
QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
{
#if defined(QT_OPENGL_DYNAMIC)
QWindowsOpenGLTester::Renderer requestedRenderer = QWindowsOpenGLTester::requestedRenderer();
switch (requestedRenderer) {
case QWindowsOpenGLTester::DesktopGl:
if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create())
return glCtx;
qCWarning(lcQpaGl, "System OpenGL failed. Falling back to Software OpenGL.");
return QOpenGLStaticContext::create(true);
// If ANGLE is requested, use it, don't try anything else.
case QWindowsOpenGLTester::AngleRendererD3d9:
case QWindowsOpenGLTester::AngleRendererD3d11:
case QWindowsOpenGLTester::AngleRendererD3d11Warp:
return QWindowsEGLStaticContext::create(requestedRenderer);
case QWindowsOpenGLTester::Gles:
return QWindowsEGLStaticContext::create(QWindowsOpenGLTester::supportedGlesRenderers());
case QWindowsOpenGLTester::SoftwareRasterizer:
if (QWindowsStaticOpenGLContext *swCtx = QOpenGLStaticContext::create(true))
return swCtx;
qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL.");
if (QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DesktopGl)
return QOpenGLStaticContext::create();
return Q_NULLPTR;
default:
break;
}
const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers();
if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) {
if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create())
return glCtx;
}
if (QWindowsOpenGLTester::Renderers glesRenderers = supportedRenderers & QWindowsOpenGLTester::GlesMask) {
if (QWindowsEGLStaticContext *eglCtx = QWindowsEGLStaticContext::create(glesRenderers))
return eglCtx;
}
return QOpenGLStaticContext::create(true);
#elif defined(QT_OPENGL_ES_2)
QWindowsOpenGLTester::Renderers glesRenderers = QWindowsOpenGLTester::requestedGlesRenderer();
if (glesRenderers == QWindowsOpenGLTester::InvalidRenderer)
glesRenderers = QWindowsOpenGLTester::supportedGlesRenderers();
return QWindowsEGLStaticContext::create(glesRenderers);
#elif !defined(QT_NO_OPENGL)
return QOpenGLStaticContext::create();
#endif
}
static QWindowsStaticOpenGLContext *q_staticOpenGLContext = 0;
QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create()
{
QWindowsStaticOpenGLContext *ctx = 0;
#if defined(QT_OPENGL_DYNAMIC)
const QByteArray requested = qgetenv("QT_OPENGL"); // angle, desktop, software
const bool angleRequested = QCoreApplication::testAttribute(Qt::AA_UseOpenGLES) || requested == "angle";
const bool desktopRequested = QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL) || requested == "desktop";
const bool softwareRequested = QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL) || requested == "software";
// If ANGLE is requested, use it, don't try anything else.
if (angleRequested) {
ctx = QWindowsEGLStaticContext::create();
} else {
// If opengl32.dll seems to be OpenGL 2.x capable, or desktop OpenGL is requested, use it.
if (!softwareRequested && (desktopRequested || QWindowsOpenGLTester::testDesktopGL()))
ctx = QOpenGLStaticContext::create();
// If failed and desktop OpenGL is not explicitly requested, try ANGLE.
if (!ctx && !desktopRequested && !softwareRequested)
ctx = QWindowsEGLStaticContext::create();
// Try software.
if (!ctx) {
ctx = QOpenGLStaticContext::create(true);
// If software was explicitly requested but failed, try the regular one.
if (!ctx && softwareRequested && QWindowsOpenGLTester::testDesktopGL()) {
qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL.");
ctx = QOpenGLStaticContext::create();
}
}
}
#elif defined(QT_OPENGL_ES_2)
ctx = QWindowsEGLStaticContext::create();
#elif !defined(QT_NO_OPENGL)
ctx = QOpenGLStaticContext::create();
#endif
q_staticOpenGLContext = ctx;
return ctx;
q_staticOpenGLContext = QWindowsStaticOpenGLContext::doCreate();
return q_staticOpenGLContext;
}
bool QWindowsIntegrationPrivate::ensureStaticOpenGLContext()

View File

@ -58,6 +58,9 @@ public:
// reimplement these.
virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; }
virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
private:
static QWindowsStaticOpenGLContext *doCreate();
};
class QWindowsOpenGLContext : public QPlatformOpenGLContext

View File

@ -37,6 +37,7 @@
#include <QtCore/QVariantMap>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
#ifndef Q_OS_WINCE
# include <QtCore/qt_windows.h>
@ -171,6 +172,87 @@ QVariant GpuDescription::toVariant() const
return result;
}
QWindowsOpenGLTester::Renderer QWindowsOpenGLTester::requestedGlesRenderer()
{
#ifndef Q_OS_WINCE
const char platformVar[] = "QT_ANGLE_PLATFORM";
if (qEnvironmentVariableIsSet(platformVar)) {
const QByteArray anglePlatform = qgetenv(platformVar);
if (anglePlatform == "d3d11")
return QWindowsOpenGLTester::AngleRendererD3d11;
if (anglePlatform == "d3d9")
return QWindowsOpenGLTester::AngleRendererD3d9;
if (anglePlatform == "warp")
return QWindowsOpenGLTester::AngleRendererD3d11Warp;
qCWarning(lcQpaGl) << "Invalid value set for " << platformVar << ": " << anglePlatform;
}
#endif // !Q_OS_WINCE
return QWindowsOpenGLTester::InvalidRenderer;
}
QWindowsOpenGLTester::Renderer QWindowsOpenGLTester::requestedRenderer()
{
#ifndef Q_OS_WINCE
const char openGlVar[] = "QT_OPENGL";
if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES)) {
const Renderer glesRenderer = QWindowsOpenGLTester::requestedGlesRenderer();
return glesRenderer != InvalidRenderer ? glesRenderer : Gles;
}
if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL))
return QWindowsOpenGLTester::DesktopGl;
if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL))
return QWindowsOpenGLTester::SoftwareRasterizer;
if (qEnvironmentVariableIsSet(openGlVar)) {
const QByteArray requested = qgetenv(openGlVar);
if (requested == "angle") {
const Renderer glesRenderer = QWindowsOpenGLTester::requestedGlesRenderer();
return glesRenderer != InvalidRenderer ? glesRenderer : Gles;
}
if (requested == "desktop")
return QWindowsOpenGLTester::DesktopGl;
if (requested == "software")
return QWindowsOpenGLTester::SoftwareRasterizer;
qCWarning(lcQpaGl) << "Invalid value set for " << openGlVar << ": " << requested;
}
#endif // !Q_OS_WINCE
return QWindowsOpenGLTester::InvalidRenderer;
}
static inline QWindowsOpenGLTester::Renderers
detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly)
{
Q_UNUSED(gpu)
#ifndef Q_OS_WINCE
// Add checks for card types with known issues here.
QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11
| QWindowsOpenGLTester::AngleRendererD3d9
| QWindowsOpenGLTester::AngleRendererD3d11Warp
| QWindowsOpenGLTester::SoftwareRasterizer);
if (!glesOnly && QWindowsOpenGLTester::testDesktopGL())
result |= QWindowsOpenGLTester::DesktopGl;
return result;
#else // !Q_OS_WINCE
return QWindowsOpenGLTester::Gles;
#endif
}
QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers()
{
const GpuDescription gpu = GpuDescription::detect();
const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true);
qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
return result;
}
QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers()
{
const GpuDescription gpu = GpuDescription::detect();
const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false);
qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
return result;
}
bool QWindowsOpenGLTester::testDesktopGL()
{
#ifndef Q_OS_WINCE

View File

@ -37,6 +37,7 @@
#include <qtwindowsglobal.h>
#include <QtCore/QByteArray>
#include <QtCore/QFlags>
QT_BEGIN_NAMESPACE
@ -92,9 +93,29 @@ QDebug operator<<(QDebug d, const GpuDescription &gd);
class QWindowsOpenGLTester
{
public:
enum Renderer {
InvalidRenderer = 0x0000,
DesktopGl = 0x0001,
AngleRendererD3d11 = 0x0002,
AngleRendererD3d9 = 0x0004,
AngleRendererD3d11Warp = 0x0008, // "Windows Advanced Rasterization Platform"
AngleBackendMask = AngleRendererD3d11 | AngleRendererD3d9 | AngleRendererD3d11Warp,
Gles = 0x0010, // ANGLE/unspecified or Generic GLES for Windows CE.
GlesMask = Gles | AngleBackendMask,
SoftwareRasterizer = 0x0020
};
Q_DECLARE_FLAGS(Renderers, Renderer)
static Renderer requestedGlesRenderer();
static Renderer requestedRenderer();
static Renderers supportedGlesRenderers();
static Renderers supportedRenderers();
static bool testDesktopGL();
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsOpenGLTester::Renderers)
QT_END_NAMESPACE
#endif // QWINDOWSOPENGLTESTER_H