Dynamic OpenGL implementation loading in Qt 5.4

Qt Weekly #21: Dynamic OpenGL implementation loading in Qt 5.4

Published Thursday November 27th, 2014
15 Comments on Qt Weekly #21: Dynamic OpenGL implementation loading in Qt 5.4
Posted in Graphics, OpenGL, Qt Quick, Windows

In Qt 5.4 there is a new configure option on Windows: -opengl dynamic. This, in addition to -opengl desktop and -opengl es2, changes the OpenGL implementation (and implicitly the window system interface API) that Qt is built against. However, unlike the previously existing flags, dynamic is something different. Enabling it ensures that neither the Qt libraries nor the applications link directly to an OpenGL implementation, meaning that neither opengl32.lib nor libEGL.lib + libGLESv2.lib are passed to the linker. Instead, Qt will, upon application startup, choose the implementation to load.

Starting with the Qt 5.4 release candidate the previously ANGLE-only pre-built packages are changed to be dynamic builds. It is therefore time to take a closer look at this feature.

Up until Qt 5.4 the binary packages of Qt have been offered in two variants: desktop OpenGL (meaning opengl32.dll) and ANGLE. ANGLE provides an EGL and OpenGL ES 2.0 (soon 3.0) implementation by translating calls and shaders to Direct3D9 or 11. This is very handy for systems that have a lacking OpenGL implementation, for example due to not having the necessary graphics drivers or installed or due to using remote desktop. In addition, Direct3D 11 supports WARP, a software rasterizer.

The ability to work on a wider range of systems made ANGLE a promising prospect for providing OpenGL support for Qt and Qt Quick 2 on Windows, and so it became the default configuration setting. This is true in 5.4 too: configure defaults to ANGLE when no -opengl setting is specified.

However, the results were not always pretty. Offering multiple versions of the binaries causes confusion when getting started (which package to download?) and when deploying (which Qt libraries to ship with my application?). Relying exclusively on ANGLE is not an option in practice. Many desktop applications want OpenGL 3.x and 4.x features. On systems where a proper graphics driver is known to be available, the translation to Direct3D is unnecessary. Advanced modes of operation, like rendering from multiple threads have issues with ANGLE. Therefore the “desktop” OpenGL packages, meaning binaries linked against opengl32, had to be made available.

To eliminate the confusion, Qt 5.4 introduces the concept of dynamic OpenGL implementation selection. The binaries built in this mode are capable of operating with opengl32 (using WGL as the windowing system interface and regular OpenGL), ANGLE (using EGL and Open GL ES) or with a custom opengl32 variant (for exampleMesa llvmpipe). As expected, Qt will perform some additional steps during application startup to decide which library to load. After that, all OpenGL calls (for example from Qt Quick) will be routed to this library, via QOpenGLFunctions.

The selection algorithm in Qt 5.4 is simple:

  1. Try opengl32 and check if OpenGL 2.0 functions are available.
  2. If this fails, try ANGLE.
  3. If initialization fails either due to missing ANGLE libraries or some other reason, try opengl32sw.dll. In practice this will be a software rasterizer based implementation. To make it easy to get started, a pre-built version of Mesa llvmpipe is bundled with the binary packages of Qt 5.4.

Pro tip: The debug output printed from the platform plugin can be very helpful to check which implementation gets loaded. To enable these prints, set the environment variable QT_LOGGING_RULES to qt.qpa.gl=true.

Why is this logic useful? Consider the following use cases:

  • When running on a modern system with the necessary graphics drivers installed, the first step will succeed so OpenGL is used normally.
  • When running the same application over remote desktop, the first step will fail and the fallback to ANGLE will be used instead. This functions better with remoting, so the application runs, just like locally.
  • Similarly, on a locked-down Windows 7 PC with no vendor-provided drivers installed, opengl32 will often turn out to be useless, providing only OpenGL 1.x. Direct3D and thus ANGLE may still be functional however.
  • In a virtual machine with limited or no accelerated graphics capabilities both step 1 & 2 may fail. In this case a build of Mesa llvmpipe can be utilized automatically, transparently to the application.

Applications that require desktop OpenGL and are not functional with OpenGL ES can use the QT_OPENGL environment variable or the Qt::AA_UseDesktopOpenGLapplication attribute before instantiating Q(Gui)Application. ANGLE can also be forced, if needed. For example, when playing video with Qt Multimedia, the best, accelerated path relies on Direct3D – ANGLE interop. Using a non-ANGLE implementation will still work, but possibly with reduced performance. Finally, in some scenarios (e.g. when targetting Windows XP) the robust solution is to deploy a software rasterizer (i.e. opengl32sw.dll) and force that withQt::AA_UseSoftwareOpenGL in order to ensure a uniform experience across all the target systems. For the relevant settings, see the Windows-specific pages in the Qt documentation.

So how do you take this into use? It is easy: with Qt 5.4 the binary packages that previously were using ANGLE are now built with -opengl dynamic instead. This means that the “suffixless” packages that do not have opengl in the name (for instance, qt-enterprise-windows-x86-msvc2013_64-5.4.0.exe) are now capable of operating both with regular, desktop OpenGL, ANGLE and the software fallbacks, if needed. For the time being the “opengl” packages (built with -opengl desktop) are still being offered. However, these may disappear in Qt 5.5.

There is an important consequence of not linking directly to the OpenGL implementation: no OpenGL functions like glClear() are callable directly anymore. Applications that want to be dynamically switchable must always use QOpenGLFunctions and be prepared to function both on OpenGL and OpenGL ES 2.0. For Qt itself, this is not a problem. All the standard Qt modules, including Qt Quick 2 (qtdeclarative), have been updated to make sure they function as expected in all configurations. For examples, see the documentation and our earlier post about QOpenGLWidget.

Note that this dynamic mode of operation and in particular the software rasterizer fallback are targeted towards general GUI applications based on Qt Quick 2. Applications with heavy OpenGL graphics, for example visualization or games, are obviously not in scope here. Such applications are expected to continue to rely exclusively on modern OpenGL and dedicated graphics hardware. They should enforce a given implementation via QT_OPENGL or the application attributes, so they can continue to use direct OpenGL function calls and other features, like theversioned OpenGL function wrappers. Just add LIBS += -lopengl32 to the application’s.pro file. The migration of an application that today uses and requires the desktop OpenGL builds of Qt is as simple as adding a line to its main() function and a line to the .pro project file. This is naturally not always an option, and this is the reason why Qt 5.4 continues to offer some of the desktop OpenGL packages. The future however lies in the dynamic builds, so applications are expected to gradually migrate to it.

Do you like this? Share it

Posted in Graphics, OpenGL, Qt Quick, Windows


15 comments

Dynamic OpenGL implementation loading in Qt 5.4_第1张图片 TomasL

Great news! Our support team has been quite busy helping customers upgrade their graphics card drivers after we moved from Qt 4.8 to 5.x.
I find the qt-enterprise-windows-x86-msvc2013-5.4.0-rc1.exe download, but can’t find the VS2012 equivalent without OpenGL. Will the dynamic version be built for VS2012 as well, or do I have to upgrade to VS2013?
Thanks, TomasL

Dynamic OpenGL implementation loading in Qt 5.4_第2张图片 Laszlo Agocs

For the time being the previously ANGLE-only packages (like the msvc2013 one you mentioned) are switched to dynamic. All the others are same as in previous releases. This was done to reduce the chance of potentially drastic changes in 5.4. If everything goes as expected, Qt 5.5 can drop the desktop OpenGL-only packages and provide only the dynamic variants. We will then have dynamic packages for all the VS versions.

With 5.4 you can either change to VS2013 or build from source for VS2012.

Dynamic OpenGL implementation loading in Qt 5.4_第3张图片 HGH

I want to make my own renderer (independant of Qt) but use Qt Quick for GUI. Does the dynamic implemenation support this scenario?

What about adopting native context too?

Dynamic OpenGL implementation loading in Qt 5.4_第4张图片 Laszlo Agocs

That’s fine, as long as you limit yourself to OpenGL ES 2.0 level and use QOpenGLFunctions.

Native contexts can be tricky since sometimes you will use WGL, sometimes ANGLE’s EGL emulation. You can use http://doc-snapshot.qt-project.org/qt5-5.4/qopenglcontext.html#openGLModuleType to decide at runtime which one is appropriate.

Dynamic OpenGL implementation loading in Qt 5.4_第5张图片 HGH

I need to reread the blog post more careful again.

My question was exactly the opposite: if I can use non-QOpenGLFunctions and even import them by using GLEW.
I want to write my renderer that won’t depend on Qt, so it can be used on system without Qt and I’d like to use Qt for context initialization and GUI rendering (incl. Qt Quick).

So I guess it’s not possible then.

Thank you for your posts and answers! I hope to see your presentation from Qt DD on YouTube soon.
There is a nice table when to use the different classes. I hope you’ll put it in the documenation (haven’t seen it yet).

Dynamic OpenGL implementation loading in Qt 5.4_第6张图片 Laszlo Agocs

Yes, that most likely won’t be feasible since GLEW and other similar helpers will not know anything about ANGLE and Qt’s way of resolving OpenGL functions.

You can of course still use the ‘dynamic’ builds, but by enforcing desktop OpenGL so that a fallback to ANGLE never occurs (because the non-Qt code is not able to deal with that).

Dynamic OpenGL implementation loading in Qt 5.4_第7张图片 Heath

Will this functionality also be supported under Linux?

This would provide me the ability to decide at startup whether my application will use the systems installed version of GL, or one I would ship with my application for compatibility purposes (for example a Mesa3D).

However, I would like to be in charge of deciding which shared library is loaded by default, and which is chosen after evaluating the runtime environment.

Dynamic OpenGL implementation loading in Qt 5.4_第8张图片 Laszlo Agocs

Some elements will be present in Qt 5.5 on Linux (when using the xcb platform plugin under X11), namely that the GLX/EGL bits in the platform plugin are moved out to additional plugins that are then dynamically loaded by the platform plugin during runtime, but that solves a different problem and will not help your use case since we will continue to link to libGL.so/libGLESv2.so/libEGL.so and similar.

What future versions may bring is not yet clear.

In the meantime, you could experiment with LD_PRELOAD.

Dynamic OpenGL implementation loading in Qt 5.4_第9张图片 Heath

Yes, you could, But it’s not my preferred approach.

Actually , I have been using my own embedded OpenGL indirection table machinery in Qt for this very purpose, for a very long time (Qt 3/4.X) . You guys added the ability for me to control the GL library loading via qt_set_gl_library_name() probably 10 years ago. Recently in porting our codebase to Qt5 I noticed that you are now doing much of what I was doing myself, building OpenGL function pointer tables, and switching between them. I guess I’m just trying to minimize the amount of work I have been doing in code generating all of these dynamic bindings. Hoping to get you to do it instead 

Dynamic OpenGL implementation loading in Qt 5.4_第10张图片 Laszlo Agocs

Yes, most of the building blocks are in place for Linux too (QOpenGLFunctions). Eventually we will probably get to a solution similar to what we have now on Windows, but the need and urgency is much lower on Linux.

Dynamic OpenGL implementation loading in Qt 5.4_第11张图片 zeecrowddev

Great news !!!
Congratulations tor the Qt Team for this initiative.

Dynamic OpenGL implementation loading in Qt 5.4_第12张图片 Hernan Martinez

Terrific news.
Software rasterizer and HIGH DPI support in Qt 5.4 . I can finally advocate Qt 5 at the office.

The software rasterizer means that I will finally be able to use Qt Quick in Safe Mode ?

Dynamic OpenGL implementation loading in Qt 5.4_第13张图片 Laszlo Agocs

Quick in safe mode: Presumably yes, although I don’t think it has been tried yet.

Dynamic OpenGL implementation loading in Qt 5.4_第14张图片 Hernan Martinez

I’m trying today. I couldn’t yet because I have to compile Qt with ‘target -xp’ to be able to use VS 2013 and target xp o.O

Dynamic OpenGL implementation loading in Qt 5.4_第15张图片 Shantanu Tushar

For our product we have been using the binary mingw package for Qt which is available from the Downloads page. However, I see it has the name “-opengl” in the installer meaning that it won’t have the dynamic GL switching.

Are there mingw binaries built with -opengl dynamic?

Thanks!


你可能感兴趣的:(Dynamic OpenGL implementation loading in Qt 5.4)