diff options
author | Laszlo Agocs <laszlo.agocs@digia.com> | 2014-04-24 14:36:49 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-05-22 22:00:59 +0200 |
commit | 39e06078258393f28c3def96326c26c55e450844 (patch) | |
tree | 4cf90468516dc175b44b83c98fa7abc07d140601 /src/plugins/platforms/windows/qwindowsintegration.cpp | |
parent | 09ed9e3eae71efdcc769a83859fcfa976ed40694 (diff) |
Load winsys and gl dynamically in the windows plugin
The dynamic builds (-opengl dynamic) are now functional on Windows.
In such a build no components in Qt link to any OpenGL libraries directly
and qmake will not automatically add any such libraries to the
applications' makefiles. Instead, the libraries are chosen and loaded
during runtime and applications are expected to use QOpenGLFunctions
instead of direct OpenGLfunction calls.
Set the environment variable QT_OPENGL to desktop or angle to skip testing
and force the given implementation. The application attributes (AA_UseOpenGLES
and such) are also taken into account.
The testing logic is same as before: We try to load opengl32 and
resolve a shader related function. If this fails, ANGLE is chosen. This
allows utilizing full desktop OpenGL on systems that have proper drivers,
while a transparent fallback to ANGLE will be done automatically for
systems that don't. The latter includes also remote desktop connections.
Software rendering via Mesa llvmpipe is supported too. The fallback is
automatic on systems where the desktop test fails and ANGLE fails to load
or initialize (e.g. due to missing libs like d3dcompiler), as long as a
suitable patched build of Mesa is available.
[ChangeLog][QtGui] Dynamic OpenGL implementation loading is now supported
on Windows. This requires Qt to be configured with -opengl dynamic.
Task-number: QTBUG-36483
Change-Id: Ie8bb25a6d55b3a1609b00150aeccd909aec27313
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsintegration.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsintegration.cpp | 147 |
1 files changed, 93 insertions, 54 deletions
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index fc59302bf3..529dd75ed5 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch> -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -43,19 +43,7 @@ #include "qwindowsintegration.h" #include "qwindowswindow.h" #include "qwindowscontext.h" - -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) -# include "qwindowseglcontext.h" -# include <QtGui/QOpenGLContext> -#endif - -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) -# include "qwindowsglcontext.h" -#endif - -#if !defined(QT_NO_OPENGL) -# include <QtGui/QOpenGLFunctions> -#endif +#include "qwindowsopenglcontext.h" #include "qwindowsscreen.h" #include "qwindowstheme.h" @@ -91,6 +79,17 @@ #include <limits.h> +#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) +# include "qwindowseglcontext.h" +#endif +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) +# include "qwindowsglcontext.h" +#endif + +#ifndef Q_OS_WINCE +# include "qwindowsopengltester.h" +#endif + QT_BEGIN_NAMESPACE /*! @@ -136,15 +135,9 @@ QT_BEGIN_NAMESPACE struct QWindowsIntegrationPrivate { -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) - typedef QSharedPointer<QWindowsEGLStaticContext> QEGLStaticContextPtr; -#endif -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr; -#endif - explicit QWindowsIntegrationPrivate(const QStringList ¶mList); ~QWindowsIntegrationPrivate(); + bool ensureStaticOpenGLContext(); unsigned m_options; QWindowsContext m_context; @@ -155,12 +148,9 @@ struct QWindowsIntegrationPrivate QWindowsDrag m_drag; # endif #endif -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) - QEGLStaticContextPtr m_staticEGLContext; -#endif -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - QOpenGLStaticContextPtr m_staticOpenGLContext; -#endif +#ifndef QT_NO_OPENGL + QSharedPointer<QWindowsStaticOpenGLContext> m_staticOpenGLContext; +#endif // QT_NO_OPENGL QScopedPointer<QPlatformInputContext> m_inputContext; #ifndef QT_NO_ACCESSIBILITY QWindowsAccessibility m_accessibility; @@ -273,12 +263,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co case OpenGL: return true; case ThreadedOpenGL: -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) - return QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL - ? QWindowsEGLContext::hasThreadedOpenGLCapability() : true; -# else - return true; -# endif // QT_OPENGL_ES_2 + return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->supportsThreadedOpenGL() : false; #endif // !QT_NO_OPENGL case WindowMasks: return true; @@ -288,6 +273,8 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co return true; case RasterGLSurface: return true; + case AllGLFunctionsQueryable: + return true; default: return QPlatformIntegration::hasCapability(cap); } @@ -304,8 +291,7 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const if (customMarginsV.isValid()) requested.customMargins = qvariant_cast<QMargins>(customMarginsV); - const QWindowsWindowData obtained - = QWindowsWindowData::create(window, requested, window->title()); + QWindowsWindowData obtained = QWindowsWindowData::create(window, requested, window->title()); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << '<' << window << "\n Requested: " << requested.geometry << "frame incl.: " @@ -323,6 +309,11 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const QWindowSystemInterface::handleGeometryChange(window, obtained.geometry); } +#ifndef QT_NO_OPENGL + d->ensureStaticOpenGLContext(); + obtained.staticOpenGLContext = d->m_staticOpenGLContext; +#endif // QT_NO_OPENGL + return obtained; } @@ -334,32 +325,80 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons } #ifndef QT_NO_OPENGL -QPlatformOpenGLContext - *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +static QWindowsStaticOpenGLContext *q_staticOpenGLContext = 0; + +QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create() { - qCDebug(lcQpaGl) << __FUNCTION__ << context->format(); -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC) - if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) { - if (d->m_staticEGLContext.isNull()) { - QWindowsEGLStaticContext *staticContext = QWindowsEGLStaticContext::create(); - if (!staticContext) - return 0; - d->m_staticEGLContext = QSharedPointer<QWindowsEGLStaticContext>(staticContext); + 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 == QByteArrayLiteral("angle"); + const bool desktopRequested = QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL) || requested == QByteArrayLiteral("desktop"); + const bool softwareRequested = QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL) || requested == QByteArrayLiteral("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()) + ctx = QOpenGLStaticContext::create(); } - return new QWindowsEGLContext(d->m_staticEGLContext, context->format(), context->shareHandle()); } +#elif defined(QT_OPENGL_ES_2) + ctx = QWindowsEGLStaticContext::create(); +#elif !defined(QT_NO_OPENGL) + ctx = QOpenGLStaticContext::create(); #endif -#if !defined(QT_OPENGL_ES_2) - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { - if (d->m_staticOpenGLContext.isNull()) - d->m_staticOpenGLContext = - QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create()); - QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context)); - return result->isValid() ? result.take() : 0; + + q_staticOpenGLContext = ctx; + + return ctx; +} + +bool QWindowsIntegrationPrivate::ensureStaticOpenGLContext() +{ + if (m_staticOpenGLContext.isNull()) + m_staticOpenGLContext = QSharedPointer<QWindowsStaticOpenGLContext>(QWindowsStaticOpenGLContext::create()); + return !m_staticOpenGLContext.isNull(); +} + +QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + qCDebug(lcQpaGl) << __FUNCTION__ << context->format(); + if (d->ensureStaticOpenGLContext()) { + QScopedPointer<QWindowsOpenGLContext> result(d->m_staticOpenGLContext->createContext(context)); + if (result->isValid()) + return result.take(); } -#endif // !QT_OPENGL_ES_2 return 0; } + +QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType() +{ +#if defined(QT_OPENGL_ES_2) + return QOpenGLContext::LibGLES; +#elif !defined(QT_OPENGL_DYNAMIC) + return QOpenGLContext::LibGL; +#else + return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->moduleType() : QOpenGLContext::LibGL; +#endif +} + +QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext() +{ + return q_staticOpenGLContext; +} #endif // !QT_NO_OPENGL /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for |