Problem with QTest, QGlWidget, and Qt5



  • Hi,
    I have a a huge application initially developped under Qt4.8.4., so using QGlWidget. This application comes with millions of lines to test all parts from low-level (basic functions) to high-level. Now I have to migrate this application to a Qt5. As QGlWidget still exists, event if it is deprecated, I'm still using this class. So migration of the application was quite simple and works well. Unfortunately, for regulatory reasons I have to prove this, by running the associated tests. And all tests based on QGLWidget fail. I already spent two days to try to understand the problem. It seems that there is somewhere a QWindow, with a default size of 160*160, that is the origin of my problem.

    An example of test that fails is the following:

    • Create a QGlWidget of size 290*290 (this is the size of the widget in the application)
    • Place some objects in the widget,
    • Explicitely call paintGL to force the drawing,
    • Read the image using glReadPixels
    • Check the value of some particular pixels.

    The failure is on the glReadPixels. It only reads pixels in the area limited by the QWindow. To be sure of this I forced a call to processEvents() to have the display in the QWidget (and not only in the OpenGL frame buffer). Ans I show the image reduced to the QWindow. I have tried to force the size of the QWindow. In this case the display takes the whole QWidget (that is what I want). But glReadPixels performed after still only capture a 160*160 part of the image.

    Any idea of how quickly resolve this stupide problem? If I have to move to QOpenGLWidget, this will take months of developments, that will be an unacceptable cost for my boss.


  • Moderators

    @Alain38-0 Can you show:

    1. Your test code from Qt 4?
    2. Your test code from Qt 5?


  • Hi @JKSH ,
    test code is quit simple. The active part (other part contains confidential elements) is:

        unsigned char image[290*290 * 4];
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->makeCurrent();
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->paintGL();
        glReadPixels(0, 0, 290, 290, GL_RGBA, GL_UNSIGNED_BYTE, image);
    
    

    AxialView is a QGraphicView that contains a QGLWidget as background.


  • Moderators

    @Alain38-0 said in Problem with QTest, QGlWidget, and Qt5:

        unsigned char image[290*290 * 4];
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->makeCurrent();
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->paintGL();
        glReadPixels(0, 0, 290, 290, GL_RGBA, GL_UNSIGNED_BYTE, image);
    
    

    AxialView is a QGraphicView that contains a QGLWidget as background.

    It's not clear: Where is this code being called from? I know that makeCurrent() and paintGL() can only be called by QGLWidget/QOpenGLWidget... Are you using a widget to update a different widget?

    Please provide a Short, Self Contained, Correct (Compilable), Example (http://www.sscce.org/ ). Remove the confidential and unnecessary elements, and give us a compilable example (including a main() function, a simple class, and an output display) that demonstrates the problem. Otherwise, it's difficult to understand the problem.



  • In addition to my current problem, few new elements. First I found a partial workaround. Doing

        qApp->processEvents();
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->resize(290, 290);
        qApp->processEvents();
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->makeCurrent();
        dynamic_cast<Display2DScene*>(axialView.scene())->getBackground()->paintGL();
        qApp->processEvents();
    
    

    Before glReadPixels seems to solve the problem, but only the first time glReadPixels is called. In the same test function I have a second glReadPixels from the same view. For this second read I have an incoherency between what is displayed on the screen (that is right), and what is read by glReadPixels (that is the previous image).



  • Hi,
    I have found a similar problem in my application (so, this time this is not with QTest). I'm calling the below function:

    ///---------------------------------------------------------------------------------------
    unsigned char* AbstractDisplay2DPlanning::getImageBuffer(int& p_width, int& p_height)
    ///---------------------------------------------------------------------------------------
    {
        // getImageBuffer(int &p_width, int &p_height)
        this->m_scene->getBackground()->makeCurrent();
    
        glDrawBuffer(GL_BACK);  // Drawing on the back buffer (invisible)
    
        this->m_scene->getBackground()->paintGL();
        m_scene->getBackground()->resize(this->size());
        this->extPaintGL();
    
        // Retrieve pixels
        int     viewport[4];
        glReadBuffer(GL_BACK);
        glGetIntegerv(GL_VIEWPORT, viewport);
        UChar*  pixelBuffer = new (std::nothrow) UChar[4 * viewport[2] * viewport[3]];
    
        if (pixelBuffer != NULL)
        {
            // Read pixels
            // Get the image in BGR mode just to ensure a right display in the design report (somewhere image is inverted from BGR to RGB
            glReadPixels(0, 0, viewport[2], viewport[3], GL_BGRA, GL_UNSIGNED_BYTE, pixelBuffer);
        }// Read pixels
    
        else
        {
            // Memory problem
            viewport[2] = viewport[3] = 0;
            INCAS_CRITICAL() << "Cannot allocate the buffer";
        }// Memory problem
    
    #ifdef _DEBUG
        QImage(pixelBuffer, viewport[2], viewport[3], QImage::Format_ARGB32).save("C:/Temp/ReadImage.png");
    #endif
    
        glDrawBuffer(GL_FRONT_AND_BACK); // Restore normal drawing mode
    
        p_width = viewport[2];
        p_height= viewport[3];
    
        return pixelBuffer;
    }// getImageBuffer(int &p_width, int &p_height)
    

    AbstractDisplay2DPlanning inherits from QGraphicsView. m_scene->background() is a QGLWidget that displays a lot of stuff. And extPaintGL() is a member of AbstractDisplay2DPlanning that is specific to each derived class. Its goal is to display additional elements using native OpenGL commands (i.e. not using the QOpenGLFunctions). Notice that, as all the code is based on QGLWidget, only native OpenGL commands are used.

    Below, the result image:
    0_1532353710484_ReadImage.png
    As you can see on it, only a 160x160 part of the OpenGL buffer has been read, instead of the 290x290 drawn part.


  • Moderators

    @Alain38-0 said in Problem with QTest, QGlWidget, and Qt5:

    I have found a similar problem in my application

    Please provide a Short, Self Contained, Correct (Compilable), Example (http://www.sscce.org/ ). Remove the confidential and unnecessary elements, and give us a compilable example (including a main() function, a simple class, and an output display) that demonstrates the problem. Otherwise, it's difficult to understand the problem.