Sun, 02/20/2022 - 17:32
I'm trying to build an application using Qt 6.2.3 with QML and OpenCascade 7.6. I encountered a problem of program crashing just after the start. After several debugging sessions I found that the problem is related with OpenGL as attempts to get current OpenGL context and device weren't succesful (wglCurrentContext() and wglCurrentDC() both returned nothing as I got from memory inspection). I referred to Anton Shabalin's example and AndroidQt sample in code writing process, also tried to build and run the first, with the same result. I tried to build and run my program with Qt 5.15 toolkit, I had semi-success - the program just didn't draw anything (in Application Output I saw "TKOpenGL.WinSystem error - wglMakeCurrent() has failed"). I'm not really proficient in OpenGL so I would really appreciate a help on this issue.
The code where error occurs is at the slot for synchronization, particularly the function for a viewer initialization. I request device and render contexts with aforementioned functions, set up display driver, viewer, context and try to initialize a window through Handle(WNT_Window) window = new WNT_Window(drawable, render_context); - that's where I get an exception.
Sun, 02/20/2022 - 18:06
Qt 6 implements several new backends for QtQuick, and OpenGL is not default one on Windows platform. You might want explicitly asking Qt to load OpenGL backend (something like QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL)) or build Qt with OpenGL backend (configure -opengl desktop). The same applies to Qt 5, though there OpenGL implementation is usually selected by default, save some exceptions where Qt decides that OpenGL drivers are not good enough (have no idea by what criteria). Just as starting point.
Sat, 02/26/2022 - 01:27
So, after some research I found the solution. The key is to be aware of where you are working at - at GUI thread or rendering thread as they are separated in QtQuick Qt6 by default. Indeed, setting explicitly the usage of OpenGl as a rendering backend should be done and it's done for the rendering thread, but classes derived from QQuickItem are considered by Qt as being at GUI thread so when the called slots for synchronization and rendering are from QQuickItem there is no any existing OpenGl context. So, the solution is to separate classes for rendering and for GUI.
More detailed explanations can be found at
https://doc.qt.io/qt-6/qtquick-scenegraph-openglunderqml-example.html (also a practical example - the reason why I don't provide my own code)
https://doc.qt.io/qt-6/qtquick-visualcanvas-scenegraph.html
Sat, 02/26/2022 - 01:29
Also you can set the usage of a single thread for both GUI and rendering but it's not recommended due to portability issues.
Sat, 02/26/2022 - 11:16
Ekaterina Evdokimova wrote:
In contrary - dedicated rendering OpenGL thread used by Qt5 / QtQuick by default is a non-portable way. The only platform that I known that might have problems with single-threaded implementations is Android, where the key class GLSurfaceView is always expected to perform rendering in non-GUI thread. So I guess yes, if you are targeting Android platform as well, then you would certainly want debugging multi-threading issues in a desktop build - for portability and convenience reasons.
For instance, new macOS versions suddenly decided to "deprecate" usage of OpenGL from non-GUI threads, making existing multi-threaded OpenGL applications (including Qt5) broken just by upgrade of macOS SDK. And for this reason Qt 5.14 changed this default behavior to single-threaded on macOS platform:
The main drawback of a single-threaded implementation is potentially slower performance / larger GUI lag.