Fast painting from QPixmap into QWidget
I am writing the frontend of an emulator and I have some performance problems when I need to output the video frames to the QWidget.
The FPS is 60, and the video size is 560x384 (=215040 pixels)
I inherit from QWidget and each time a frame is ready an update() is issued and in the following call to paintEvent() I do
painter.scale(sx, sy); // so that the image is rescaled to the current size of the widget
loop over rows and columns and draw part of precomputed pixmaps with
painter.drawPixmap(xpixel, ypixel, lores, sx, sy, 14, 2 "or" 16);
There are always 40 columns, but the number of rows can be either 24 in text mode or 24*8 in HiRes
So the number of calls to drawPixmap is either 960 or 7680 each frame.
Problem is that CPU utilisation is super high. 15-100% according to size of widget and graphics mode.
As a comparison there are 2 other versions of this emulator running in Wine or native in Linux with SDL and they take respectively 10% or 5% in the worst case.
I tried to
- paint 1:1 on a offscreen pixmap and draw it at once with scaling. This is always slower
- use a QOpenGLWidget. A bit faster for big sizes, slower for small window
This is a 64 bit machine, Haswell i5. When I watch a video fullscreen (25FPS normally) CPU usage is <2%.
For this reason I think a lot more can be achieved.
Is a QPainter + QPixmap the best way to deal with this?
I was thinking to chip into the multimedia framework and simply code a producer of QVideoFrame and use a VideoPlayer to display, but I have not found where to start.