Solved 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
makeTheres 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(); }
- QOpenGLWidgetMode => The renderer is a simple QWidget that inherits
-
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 -
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? -
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") -
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!