Rendering in QOpenGLWindow embedded in QMdiArea fails



  • Hi there,
    I'm in the process of porting an application from Qt4 to Qt5 (currently working
    on Debian 9 with Qt 5.7.1).
    The application used a QGLWidget embedded as QMdiSubwindow in a QMdiArea.
    As the QGLWidget is deprecated, I first tried to use the QOpenGLWidget instead.
    This worked fine except for stereo rendering. But stereo rendering is an absolute
    must for the application. QTBUG-59636 (https://bugreports.qt.io/browse/QTBUG-59636)
    discusses a similar issue and one of the suggestions in the thread was to use
    QOpenGLWindow instead of QOpenGLWidget and use QWidget::createWindowContainer
    to add it to the Widget hierarchy.
    This works, including stereo rendering, when I show the plain widget.
    However, if I add such a widget to the QMdiArea, rendering fails.
    I could not find any obvious hint in the documentation of what goes wrong here
    but can provide code including pro file that reproduces the issue (on my machine).
    Would be great if anybody can confirm that the problem exists on other setups or,
    even better, suggest a solution.

    Thanks a lot,

    Gabriel

    The code depends on OpenGL headers. If all dependencies are at their default
    locations you should be able to compile with:

    qmake
    make

    Theres a preprocessor define statement that allows to compile in four modes.
    For all of them I would expect a red triangle to appear in a window.
    This is not the case for the last one.

    • QOpenGLWidgetMode => The renderer is a simple QWidget that inherits
      from QOpenGLWidget
    • QOpenGLWindowMode => The renderer inherits from QOpenGLWindow and is
      wrapped using QWidget::createWindowContainer
    • QOpenGLWidgetInQMdiAreaMode => Same as QOpenGLWidgetMode, but resulting widget
      is added as QMdiSubWindow to a QMdiArea
    • QOpenGLWindowInQMdiAreaMode => Same as QOpenGLWindowMode, but resulting widget
      is added as QMdiSubWindow to a QMdiArea
      THIS DOES NOT RENDER ON MY MACHINE

    pro file:

    ######################################################################
    # Automatically generated by qmake (3.0) Thu Jan 24 22:18:34 2019
    ######################################################################
    
    TEMPLATE = app
    TARGET = gl_bug_report
    INCLUDEPATH += .
    QT += widgets
    LIBS += -lGL -lGLU
    
    # Input
    SOURCES += test.cc
    

    source file:

    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <QApplication>
    #include <QOpenGLWidget>
    #include <QOpenGLWindow>
    #include <QDebug>
    #include <QMdiArea>
    #include <QMdiSubWindow>
    
    template <typename T>
    class GLRenderer : public T {
      
    protected:
      virtual void initializeGL() {
        qDebug() << "Enter initializeGL";  
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_COLOR_MATERIAL);
        glEnable(GL_BLEND);
        glEnable(GL_POLYGON_SMOOTH);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glClearColor(0, 0, 0, 0);
      }
    
      virtual void resizeGL(int w, int h) {
        qDebug() << "Enter resizeGL";
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0, w, 0, h);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
      }
    
      virtual void paintGL() {
        qDebug() << "Enter paintGL";
        glClear(GL_COLOR_BUFFER_BIT);
        glColor3f(1, 0, 0);
        glBegin(GL_POLYGON);
        glVertex2f(0, 0);
        glVertex2f(100, 500);
        glVertex2f(500, 100);
        glEnd();
      }
    };
    
    /*
    The define below controls how we use the GLRenderer defined above
    
    QOpenGLWidgetMode           => The renderer is a simple QWidget that inherits 
                                   from QOpenGLWidget
    QOpenGLWindowMode           => The renderer inherits from QOpenGLWindow and is 
                                   wrapped using QWidget::createWindowContainer
    QOpenGLWidgetInQMdiAreaMode => Same as QOpenGLWidgetMode, but resulting widget 
                                   is added as QMdiSubWindow to a QMdiArea
    QOpenGLWindowInQMdiAreaMode => Same as QOpenGLWindowMode, but resulting widget 
                                   is added as QMdiSubWindow to a QMdiArea
                                   THIS DOES NOT RENDER ON MY MACHINE
    */
    
    #define QOpenGLWidgetMode
    
    int main(int argc, char** argv) {
      
      QApplication app(argc, argv);
      QWidget* widget;
      
      #ifdef QOpenGLWidgetMode
      qDebug() << "Create widget using QOpenGLWidget";  
      qDebug() << "This renders a nice triangle on my machine";    
      widget = new GLRenderer<QOpenGLWidget>;
      #endif
    
      #ifdef QOpenGLWindowMode
      qDebug() << "Create widget using QOpenGLWindow and QWidget::createWindowContainer";
      qDebug() << "This renders a nice triangle on my machine";  
      QWindow* window = new GLRenderer<QOpenGLWindow>;
      widget = QWidget::createWindowContainer(window);
      #endif
      
      #ifdef QOpenGLWidgetInQMdiAreaMode
      qDebug() << "Create widget using QOpenGLWidget as subwindow in QMdiArea";  
      qDebug() << "This renders a nice triangle on my machine";    
      QMdiArea* area = new QMdiArea;
      QMdiSubWindow* sub_window = area->addSubWindow(new GLRenderer<QOpenGLWidget>);
      sub_window->setWindowState(Qt::WindowMaximized);
      widget = dynamic_cast<QWidget*>(area);
      #endif
     
      #ifdef QOpenGLWindowInQMdiAreaMode
      qDebug() << "Create widget using QOpenGLWidget as subwindow in QMdiArea";  
      qDebug() << "Rendering fails on my machine";    
      QMdiArea* area = new QMdiArea;
      QWindow* window = new GLRenderer<QOpenGLWindow>;  
      QMdiSubWindow* sub_window = area->addSubWindow(QWidget::createWindowContainer(window));
      sub_window->setWindowState(Qt::WindowMaximized);
      widget = dynamic_cast<QWidget*>(area);
      #endif
      
      widget->show();
      return app.exec();
    }
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    The first thing I would try is to build and run your application with a more recent Qt version. The current version (and LTS) is 5.12.0.



  • Hey,

    Thanks, I fetched Qt 5.12 and indeed, I got the expected behaviour for all four
    modes (red triangle on a black background).
    However, I also fetched 5.7.1 (same version as the system default) and it
    also worked. Puzzling...

    So it's not an issue with the version but rather with the local setup.

    I even found another way to make things work:
    compile with system default but switch from KDE to GNOME...
    Even more puzzled... I need to further dig into it. I'll leave this thread open
    for one or two more days, maybe somebody has a comment on that. If not, I'll resolve
    as this seems to be not an issue with QT itself.

    Thanks again,
    Gabriel


  • Lifetime Qt Champion

    Since you switched desktop, different window manager ?



  • Exactly. Same binary, just ran in GNOME instead KDE. In fact, further
    digging revealed that I don't even need to go that far. The
    "QOpenGLWindowInQMdiAreaMode" also works in KDE with Qt from the system.
    I just need to switch the widget style of the whole KDE desktop settings
    (e.g. from "Breeze" to "Fusion").

    Further observations in malfunctioning case:
    The subwindow is not only not rendered, but the decorators (maximize etc.) in
    the titlebar are not reactive: It just adapts the size of the main window but
    no way to minimize/maximize/close the subwindow. Maybe some initialization issue.
    The interesting point is that I don't observe that behaviour in
    "QOpenGLWidgetInQMdiAreaMode".

    Following Debug output might be relevant (Same binary, linked and compiled
    against Qt system default, define statement is "QOpenGLWindowInQMdiAreaMode"):

    "Breeze" widget style in KDE (has the described problematic behaviour):

    schdaude@schdaudoputer:~/workspace/gl_bug_report$ ./gl_bug_report                                                                    
    Create widget using QOpenGLWidget as subwindow in QMdiArea                                                                           
    Rendering fails on my machine                                                                                                        
    Enter initializeGL                                                                                                                   
    Enter resizeGL                                                                                                                       
    Enter paintGL
    

    "Fusion" Widget style in KDE (fantastic triangle):

    schdaude@schdaudoputer:~/workspace/gl_bug_report$ ./gl_bug_report 
    Create widget using QOpenGLWidget as subwindow in QMdiArea
    Rendering fails on my machine
    Enter initializeGL
    Enter resizeGL
    Enter paintGL
    Enter paintGL
    

    There's one more call to paintGL in the latter.

    In the second round I increased the debug output from the QT side using
    "export QT_LOGGING_RULES="*.debug=true""

    "Breeze" widget style in KDE (has the described problematic behaviour):

    Lots of stuff
    ...
    Enter initializeGL
    Enter resizeGL
    Enter paintGL
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QResizeEvent(1280, 800)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QExposeEvent(QRegion(0,0 1280x800))
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QResizeEvent(1280, 800)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QExposeEvent(QRegion(0,0 1280x800))
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffcfc7e0760)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffcfc7e0760)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffcfc7e0760)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffcfc7e0760)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QFocusEvent(FocusIn, ActiveWindowFocusReason)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QInputMethodQueryEvent(queries=0x101, {})
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QInputMethodQueryEvent(queries=0x101, {})
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QFocusEvent(FocusAboutToChange, ActiveWindowFocusReason)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowDeactivate, 0x7ffcfc7e03b0)
    ...
    Lots of more stuff
    ...
    

    "Fusion" widget style in KDE (fantastic triangle):

    ...
    Lots of stuff
    ...
    Enter initializeGL
    Enter resizeGL
    Enter paintGL
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QExposeEvent(QRegion(size=8, bounds=(0,0 1280x5) - [(0,0 5x1), (1275,0 5x1), (0,1 3x1), (1277,1 3x1), (0,2 2x1), (1278,2 2x1), (0,3 1x2), (1279,3 1x2)]))
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffef19f8080)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffef19f8080)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowActivate, 0x7ffef19f8080)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QFocusEvent(FocusIn, ActiveWindowFocusReason)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QInputMethodQueryEvent(queries=0x101, {})
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QInputMethodQueryEvent(queries=0x101, {})
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QExposeEvent(QRegion(size=8, bounds=(0,0 1280x800) - [(5,0 1270x1), (3,1 1274x1), (2,2 1276x1), (1,3 1278x2), (0,5 1280x19), (0,24 4x772), (1276,24 4x772), (0,796 1280x4)]))
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QExposeEvent(QRegion(size=2, bounds=(0,0 1272x772) - [(0,0 1272x24), (0,24 4x748)]))
    Enter paintGL
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QFocusEvent(FocusAboutToChange, ActiveWindowFocusReason)
    qt.widgets.gestures: QGestureManager:Recognizer: ignored the event:  QPanGesture(state=NoGesture,lastOffset=0,0QPointF(0,0),offset=0,0,acceleration=0,delta=0,0) QEvent(WindowDeactivate, 0x7ffef19f7cd0)
    ...
    Lots of more stuff
    ...
    

    The QExposeEvents clearly differ and theres the additional call to paintGL.

    => local setup problem that gets triggered by some subtle difference in how the
    QMdiSubwindow is created?


  • Lifetime Qt Champion

    Interesting...

    Is KWin used in both cases ?
    What Linux flavour are you running ?



  • Interesting indeed ;)
    Yes, KWin is used in both cases.
    It's Debian 9.6. Rather fresh install coming with KDE (and now additionally GNOME for the described "digging")


  • Lifetime Qt Champion

    Then there might be a bug with the Debian version... Especially since the same version downloaded through the installer does work correctly.



  • Jap, might be the case. As you said, the same version downloaded through the installer works as expected... I close this topic as it seems to be a local setup problem (weird one though). Thanks for the help!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.