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

OpenGL rendering to QQuickFrameBufferObject not working when deployed



  • I have a Qt/QML application with some QML elements containing QQuickFrameBufferObject to which I render using my own OpenGL code.
    I have created an application bundle, but when I launch the application bundle the QQuickFrameBufferObjects are never instantiated.
    Using gdb I verified that the QQuickFrameBufferObject::createRenderer() method was never called. This obviously results in no rendering happening.

    If I run the bundle on the machine where it was compiled, it works. As soon as I transfer it to a different machine (not platform) it ceases to render to the framebuffer.

    I have tried compiling Qt with -qt-qpa and -qt-xcb which was suggested to reduce platform dependence.
    Both machines support the same version of OpenGL.

    Since there is no error message, it is very hard to figure out why the createRenderer() method is never called.

    Does anyone know why the renderer would not be created and what I can do to solve it?


  • Lifetime Qt Champion

    Hi,

    What Linux distribution are you running ?

    How did you deploy your application ?



  • I have tried compiling and distributing to/from Debian, Ubuntu 18, Fedora, and Arch Linux.

    The problem is reproducable using the Qt example from quick/scenegraph/textureinsgnode.

    I create a directory structure as follows

    application/
        textureinsgnode.bin (the actual executable)
        textureinsgnode (my launch script)
        lib/
        platforms/
        qml/
    

    Using qmake -query I find the QT_INSTALL_PLUGINS path and copy QT_INSTALL_PLUGINS/libqxcb.so into my bundle platforms directory. Then I $ ldd libqxcb.so and copy all the dependencies to my application bundle's lib/ directory.

    Then I do the same for the executable textureinsgnode.bin, copying all dependencies to lib/.

    After copying all dependencies I delete dependencies such as libGL.so which should always use the system version.

    I then find the QT_INSTALL_QML path and copy over QT_INSTALL_QML/{QtQml,QtQuick,QtQuick.2} directories to the application bundle qml/ directory.

    I launch the application with the launcher script which sets the LD_LIBRARY_PATH and QML2_IMPORT_PATH. It looks like this:

    #!/bin/sh
    
    DIR=$(dirname "$0")
    
    LD_LIBRARY_PATH="$DIR"/lib:"$LD_LIBRARY_PATH"
    export LD_LIBRARY_PATH
    QML2_IMPORT_PATH="$DIR"/qml
    export QML2_IMPORT_PATH
    
    exec "$0".bin "$@"
    

    When launched on the machine where it was compiled, the bundle executes correctly and displays everything. When moved to a different machine (which is also able to compile and execute the application using the same Qt version), the textured node is not created because the QQuickFrameBufferObject::createRenderer() method is never called, and the texture is obviously not displayed. However, the non QQuickFrameBufferObject QML components ARE rendered, which is what is so weird. In the textureinsgnode example there are some controls to control the rotation of the texture, and these are visible when the bundle is executed on a different machine.

    If I delete the libQt5Core library from the lib/ directory of my bundle, forcing the bundle to use my system version, the bundle executes correctly. But this defeats the purpose of bundling Qt...



  • Turns out that the xcbglintegrations directory was missing and Qt fell back to the software renderer when creating the scene graph. As the software renderer does not provide an OpenGL context the QQuickFramebufferObject::Renderer would never get instantiated due to a silent if statement check in the scene graph core. The rest of the graphical elements would render fine because they are supported by the software renderer.


  • Lifetime Qt Champion

    Glad you found out and thanks for sharing !

    Did you consider using the linuxdeployqt project ?


Log in to reply