Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

MacOS : QOpenGLWindow + QOpenGLWidget in MainWindow + QPainter causes repaint bug



  • I have made a simple program that shows the following bug :

    In MacOS only,
    When one uses a QPainter in a QOpenOpenGLWindow + a QPainter in a QOpenOpenGLWidget,
    And when both are rendered (not hidden),
    The QOpenGLWindow becomes blank.

    To reproduce :

    • Download the project
    • Compile and run -> the MainWindow that contains the QOpenGLWidget appears
    • Click the show button -> the QOpenGLWindow appears fine (because it uses OpenGL only internally)
    • Click the change QPainter use button -> the QOpenGLWindow goes blank (it now uses a QPainter)
    • Resize the QOpenGLWindow so it updates -> it flickers
    • Minimize the MainWindow
    • Resize the QOpenGLWindow so it updates -> it displays correctly again

    Download link :
    https://drive.google.com/file/d/1nCEjL1GiurQhULbIXI6pbIZ2b11FovBf/view?usp=sharing

    Should I send an issue to Qt ?

    MacOS 10.15.7
    Qt 5.15.1
    Xcode 12.2

    Have a nice day


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    You need to add which version of Qt you are using as well as macOS and XCode version.



  • @SGaist updated my post



  • Bug seems to disappear if i don't explicitly request a 3.3 Core OpenGL profile : 2.1 OpenGL profile is given and things seems to work fine.
    QPainter must behave in a different way whether it has the possibility to use VAOs and stuff or not


  • Lifetime Qt Champion

    QPainter does not use OpenGL.

    As for the Profile, Apple's implementation of OpenGL is known to lag behind in comparison to other OS like Linux and Windows.



  • @SGaist

    QPainter does not use OpenGL.

    Are you 100% sure about that ?
    Documentation seems to say the oposite :
    a5e10e1a-ca99-45f7-87af-4c64d4c19459-image.png

    Moreover, i have observed the effective QPainter OpenGL draw calls with RenderDoc on Windows

    Anyway, i have a workaround for this issue right now so this is not much of a concern for me anymore.
    I still think this is a real issue and that it should be reported. It may be related to https://bugreports.qt.io/browse/QTBUG-69644


  • Lifetime Qt Champion

    You are correct, it's an evolution I have missed a bit.

    Thanks for the link !

    Can you share your workaround ?



  • @SGaist

    Can you share your workaround ?

    I use the QPainter to create a texture instead :

    void AQOpenGLWindowSubclass::paintGL()
    {
    #ifdef __WIN32
        QPainter painter(this);
        
        painter.beginNativePainting();
        // Use OpenGL API
        // glSomething(...)
        // [...]
        painter.endNativePainting();
        // Use QPainter to paint directly on the window surface
        // painter.drawSomething(...);
        // [...]
    
    #elif defined (__APPLE__)
        // Use OpenGL API
        // glSomething(...)
        // [...]
    
        // Create a QImage to use QPainter on
        QImage paintedImage(width, height, QImage::Format_ARGB32_Premultiplied);
        QPainter painter(&paintedImage);
        // Clear image (not always done per default it seems)
        paintedImage.fill(QColor::fromRgbF(0,0,0,0));
        // Use QPainter to paint on the image
        // painter.drawSomething(...);
        // [...]
    
        // Convert QImage into QTexture
        QOpenGLTexture paintedTexture(QOpenGLTexture::Target2D);
        paintedTexture.setMinMagFilters(QOpenGLTexture::Filter::Linear, QOpenGLTexture::Linear);
        paintedTexture.setData(paintedImage.mirrored(), QOpenGLTexture::DontGenerateMipMaps);
    
        // Use OpenGL to draw the texture on the window surface
        // But set a decent blending function before if you want to use it 
        // (It was set to something troubling like glBlendFunc(GL_ONE, GL_ZERO) or something)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
        // Draw the painted texture the way you want
        // glUseProgram(...)
        // glActiveTexture(GL_TEXTURE0);
        // glBindTexture(GL_TEXTURE_2D, paintedTexture.textureId());
        // ...
    #endif
    

  • Lifetime Qt Champion

    Thanks for the code !

    You can use the Q_OS_XXX macros to ifdef your code.