Qt: Alternative to BitBlt in Qt5 Windows

2.8k views Asked by At

I am currently porting an open-source solution (Albatross ATM solution http://www.albatross.aero/) from Qt3 to Qt5. Albatross is an air traffic viewer which requires very good performances. There are various issues that I have been able to manage but not the display part.

The display architecture rests on a bitblt command which firstly copies one pixmap into another and finally copies the pixmap to the screen.

Here is the Qt3 display code (working and performant):

void CAsdView::paintEvent ( QPaintEvent * Event)
{
    QRect   rcBounds=Event->rect();

    QPainter tmp;

    for (int lay=0;lay<(int)m_RectTable.size();lay++) //For each drawing layer (there are 3) 
    {

        if (!m_RectTable[lay].isEmpty())
        {
            if (lay!=0)
                bitBlt(m_BitmapTable[lay],m_RectTable[lay].left(),m_RectTable[lay].top(),m_BitmapTable[lay-1],m_RectTable[lay].left(),m_RectTable[lay].top(),m_RectTable[lay].width(),m_RectTable[lay].height(),CopyROP); //m_BitmapTable is a QVector< QPixmap* >, m_RectTable is a QVector<QRect>

            tmp.begin(m_BitmapTable[lay]);

            if (lay==0)
                tmp.fillRect(m_RectTable[lay], *m_pBrush);

            OnDraw(&tmp,lay);
            tmp.end();
            m_RectTable[lay].setRect(0,0,-1,-1);
        }
    }
    bitBlt(this, rcBounds.left(), rcBounds.top(),m_BitmapTable[m_LayerNb-1],rcBounds.left(), rcBounds.top(),rcBounds.width(), rcBounds.height(), CopyROP);  
}

I have tried replacing bitblt by drawPixmap but the performance are very bad since I have to display very often the screen.

Here is the new Qt5 code :

void CAsdView::paintEvent ( QPaintEvent * Event)
{
    QRect   rcBounds=Event->rect();
    QPainter tmp;

    for (int lay=0;lay<(int)m_RectTable.size();lay++)
    {
        if (!m_RectTable.at(lay).isEmpty())
        {       
            tmp2.begin(m_BitmapTable[lay]);

            if (lay != 0)
            {
                tmp.drawPixmap(m_RectTable[lay].left(), m_RectTable[lay].top(), *m_BitmapTable.at(lay - 1), m_RectTable[lay].left(), m_RectTable[lay].top(), m_RectTable[lay].width(), m_RectTable[lay].height());//TOCHECK
                m_BitmapTable[lay] = m_BitmapTable[lay - 1].copy(m_RectTable[lay]);
            }

            if (lay==0)
                tmp.fillRect(m_RectTable.at(lay), *m_pBrush);

            OnDraw(&tmp, lay);
            tmp.end();
            m_RectTable[lay].setRect(0, 0, -1, -1);
        }
    }
    tmp.begin(this);
    tmp.drawPixmap(rcBounds.left(), rcBounds.top(), m_BitmapTable.at(m_LayerNb - 1), rcBounds.left(), rcBounds.top(), rcBounds.width(), rcBounds.height()); 
    tmp.end();
}
  • For the layers, there are 3 layers. The layer 0 is the deepest (background), the layer 2 is the highest. This configuration is used in order to be sure that the air traffic is always displayed on top of the screen.

  • The OnDraw method draws, depending on the layer, the elements that have changed since the last paintEvent

Q: Do you have any idea on how I could improve this paintEvent method in order to geta good behaviour back and have good performances again with Qt5 ?

1

There are 1 answers

0
Robert Jones On

I found the problem here.

drawPixmap/drawImage is cleary the best alternative to bitblt in Qt4/Qt5. Unfortunately I had some issues with the scaled() method of QPixmap (used in another piece of code not shown here...)which returned me bad results. I had to go from pixmap.resize() to pixmap.scaled() and I made a mistake here.

I changed it and now I clearly have a pretty good result. So for those like me who are still wondering, the best alternative in Qt for Bitblt is drawPixmap with a QPainter.