OpenGL Core Profile Context support in QPainter

As many of you may know, QPainter has a multi-backend architecture and has two main paint engine implementations under the hood in Qt 5: the raster paint engine and the OpenGL2 paint engine, designed for OpenGL ES 2.0.

The GL Paint Engine

While in many ways the raster paint engine can be considered one of Qt's crown jewels, let's now talk about the other half: the GL paint engine that is used when opening a QPainter on

The Problem

What about modern OpenGL, though?

That is where the problems started appearing: around Qt 5.0 those who were in need of a core profile context due to doing custom OpenGL rendering that needed this ended up running into roadblocks quite often. Components like Qt Quick were initially unable to function with such contexts due to relying on deprecated/removed functionality (for example, client-side pointers), lacking a vertex array object, and supplying GLSL shaders of a version the support for which is not mandated in such contexts.

In some cases opting for a compatibility profile was a viable workaround. However, Mac OS X / macOS famously lacks support for this: there the choice has been either OpenGL 2.1 or a 3.2+ core profile context. Attempts to work this around by for instance rendering into textures in one context and then using the texture in another context via resource sharing were often futile too, since some platforms tend to reject resource sharing between contexts of different version/profile.


Fortunately, during the lifetime of Qt 5 things have improved a lot: first Qt Quick, and then other, less user-facing GL-based components got fixed up to be able to function both with core and compatibility contexts.

As of Qt 5.8 there is one big exception: the GL paint engine for QPainter.

The Last Missing Piece

The good news is, this will soon no longer be the case. Thanks to a contribution started by Krita, see here for some interesting background information, QPainter is becoming able to function in core profile contexts as well. Functionality-wise this will not bring any changes, rendering still happens using the same techniques like before.

In addition to fixing up the original patch, we also integrated it with our internal QPainter regression testing system called Lancelot. This means that in addition to raster (with various QImage formats) and OpenGL 2, there will also be a run with a core profile context from now on, to ensure the output from QPainter does not regress between Qt releases.

All in all this means that a snippet like the following is now going to function as expected.

  class Window : public QOpenGLWindow {
    void initializeGL() override {
      QSurfaceFormat fmt;
      fmt.setVersion(4, 5); // or anything >= 3.2
    void paintGL() override {
      QPainter p(this);
      p.fillRect(10, 10, 50, 50, Qt::red);


Qt 5.9.

The patch has now been merged to qtbase in the 'dev' branch. This will soon branch out to '5.9', which, as the name suggests, will provide the content for Qt 5.9. Those who are in urgent need of this can most likely apply the patch (see QTBUG-33535) on top of an earlier version - the number of conflicts are expected to be low (or even zero).

That's all for now, have fun with QPainter in core profile contexts!

Blog Topics: