Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Qt5GraphicsOverview
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine. Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean. |
Overview of painting in Qt 5
Painting in Qt 5 is primarily done either through the imperative QPainter API, or through Qt's declarative UI language, QML, and its scene graph back-end.
QPainter
The QPainter provides API for drawing shapes, text and images onto many different surfaces, or QPaintDevices, in Qt, such as QImage, QOpenGLPaintDevice, QWidget, and QPrinter. It supports brushes and pens to define how the interior of shapes are filled and how the outlines are stroked. The QPainter uses different back-ends, or QPaintEngines, depending on what kind of surface you are drawing on. The two most important ones are the software rasterizer and OpenGL back-ends.
The raster paint engine is Qt's software rasterizer, and is used when drawing on a QImage or QWidget. Its strength over the OpenGL paint engine is its high quality when antialiasing is enabled, and a complete feature set.
The OpenGL paint engine is used when drawing on a QOpenGLPaintDevice. It is almost always hardware accelerated and has the potential of being much faster than the raster paint engine. However, it is more sensitive to state changes, and therefore requires the drawing commands to be carefully ordered to achieve optimal performance. Antialiasing with OpenGL needs multisampling, which consumes much more memory than antialiasing with the raster paint engine. The OpenGL paint engine requires OpenGL 2.0 or OpenGL ES 2.0 or later.
To use the OpenGL paint engine on a window, you need to create a QOpenGLContext and a QWindow with an OpenGL surface. You then make the OpenGL context current with the window as the target surface, create a QOpenGLPaintDevice and open a QPainter on it.
QML scene graph
The QML scene graph is a new back-end for QML in Qt 5, and is based on OpenGL. It generally improves the performance of QML significantly over the QPainter-based back-end used in Qt 4. It achieves better performance in a number of ways:
- The scene graph uses OpenGL directly instead of going though a QPainter which could be using either the raster or OpenGL paint engine. This means that all the resources, like geometry, textures and shaders can be stored in a format suitable for OpenGL rather than using classes such as QPainterPath, QPixmap, QBrush, or QPen, which the QPainter would need to translate into OpenGL primitives and possibly cache.
- QML, being a declarative language, defines how the end result should look like, but it doesn't define how and in which order each individual element is drawn. The drawing can therefore be reordered to reduce the number of state changes, or merged to reduce the number of draw calls.
- The scene graph uses a separate render thread, and synchronizes the animations with the vertical retrace on platforms where this can be supported. The render thread allows the preparation of the next frame to be done at the same time the current frame is being rendered. This has a positive effect also on single-core systems, since the render thread might block on OpenGL commands. The synchronization with the vertical retrace improves the perceived smoothness of the animations.
To use the new QML scene graph, you need to import QtQuick 2.0 in your QML file, and use QQuickView to run it.
Custom QML elements can be implemented by inheriting QQuickItem and reimplementing QQuickItem::updatePaintNode(). The QQuickItem is managed by the QQmlEngine, and lives in the main thread. When the QQuickItem is updated, the corresponding QSGNode in the QML scene graph needs to be synchronized with it. The render thread will block the main thread and call QQuickItem::updatePaintNode(). The custom reimplementation of this method can then update the QSGNode with the properties of the QQuickItem. QQuickItem::updatePaintNode() is also responsible for creating a QSGNode if one does not already exist. It can use any sub-class of QSGNode, for instance QSGGeometryNode. The QML scene graph is responsible for managing the QSGNode and will delete it shortly after the corresponding QQuickItem is destroyed.
QML can be mixed with raw OpenGL rendering by connecting to the QQuickView/QQuickWindow signals beforeRendering() or afterRendering() which are emitted before and after the QML scene graph is rendered, respectively. There signals are emitted from the render thread, and the connections need to be direct.