Fast painting from QPixmap into QWidget

  • Hi,

    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

    1. QPainter painter(this);

      painter.scale(sx, sy); // so that the image is rescaled to the current size of the widget

    2. 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

    1. paint 1:1 on a offscreen pixmap and draw it at once with scaling. This is always slower
    2. 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.

    Thank you

Log in to reply