Qt: Alternative to BitBlt in Qt5 Windows
Asked Answered
V

1

7

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 ?

Vibratory answered 26/6, 2015 at 8:4 Comment(2)
why was the intermediate bitmap blit step necessary? To provide transparency?Fayalite
@Fayalite This always stores the Pixmap of the last layer in order to have in memory the whole screen content. This avoids the solution to only keep the element of the screen that changed. If this solution was used, there could be some display and refresh problems between the layers (e.g. display the layer 1 after the layer 2 and loosing precious information). Keeping always the entire layer allows us to be sure that what is being drawn is correct.Vibratory
V
4

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.

Vibratory answered 1/7, 2015 at 9:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.