The simplest approach is to concurrently distribute the drawing across several images, then composite the images (also concurrently), and then finally submit them for painting on the gui.
This can be done using QtConcurrent::map
on the sequence of images. The map functor draws into an image that's specific to the current thread - e.g. via QThreadStorage
. The reference to that image can also be stored, upon allocation, in a list within the functor. The functor of course has to outlive the call to QtConcurrent::map
. Once map
returns, the images from the list within the functor can be asynchronously combined pair-wise, until only one image remains. That image is then submitted to the display widget.
If the full-size image compositing is to be avoided, then a similar approach will work, but the lines have to grouped into spatial groups, i.e. those intersecting some rectangles that cover the area to be drawn. To fully utilized all cores, you'd want say 2-3x as many rectangular areas as QThread::idealThreadCount()
. Then treat the painting of each of those groups onto its sub-image to be a concurrent task, to be submitted to QtConcurrent::run
. When all tasks are done, the images get submitted to the display widget, which paints them on its backing store, in sequence.
The painting of the images on the backing store can also be multi-threaded, see this answer for a complete example. Generally speaking, the images need to have a width the multiple of (CPU cacheline size/4 since we use 32-bit pixels). The painting of those images on the backing store is fully parallelizable.