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

QOpenGLFunctions in Docker (headless OpenGL)



  • We have a QT-based application and we would like to run it in Docker without xvfb and without showing GUI. We want to create a headless mode, but if possible, we want to avoid dependency on xvfb.

    Approach #1: First, we tried simply by setting the QT_QPA_PLATFORM environment variable to offscreen. Although this hides the GUI on my PC it fails to create QOpenGLFunctions in Docker.

    QOpenGLContext *context = new QOpenGLContext();
    QOpenGLFunctions *gl = context->functions(); // Shows warning: "QOpenGLFunctions created with non-current context"
    

    Approach #2: Then, we tried to initialize OpenGL context (without QT) according to the following two articles:

    And it works! It works in Docker and on my machine. We are able to use gl* functions without the display in Docker. Here are some details:

    GL_VENDOR=Mesa/X.org
    GL_VERSION=3.3 (Compatibility Profile) Mesa 20.2.6
    GL_RENDERER=llvmpipe (LLVM 11.0.0, 256 bits)
    GL_SHADING_LANGUAGE_VERSION=4.50
    

    Approach #3: Therefore, we tried to use our working EGL context to create QOpenGLContext:

    QOpenGLContext *context = new QOpenGLContext;
    context->setNativeHandle(QVariant::fromValue(QEGLNativeContext(ourEglContext, ourEglDisplay)));
    QOpenGLFunctions *gl = context->functions(); // Shows warning: "QOpenGLFunctions created with non-current context"
    

    But again, although it works fine on my PC I get the same warning in Docker.

    Do you have any suggestions? Does it make sense that we create a custom platform similar to the offscreen, or there is a simpler solution?


  • Lifetime Qt Champion

    Hi
    It's outside my normal zone but Im wondering
    if approach 3 is just missing
    https://doc.qt.io/qt-5/qopenglcontext.html#makeCurrent
    with a
    https://doc.qt.io/qt-5/qoffscreensurface.html

    Again, its not something i have much experience with but i used Qt to render
    openGL mesh to images as a command line tool. Not exactly headless nor in docker
    but no harm in mentioning it.



  • Hi, thank you for the suggestion. You mean something like this:

    QOpenGLContext *context = new QOpenGLContext;
    context->setNativeHandle(QVariant::fromValue(QEGLNativeContext(eglCtx, eglDpy)));
    
    QOffscreenSurface *surface = new QOffscreenSurface();
    surface->setFormat(context->format());
    context->makeCurrent(surface);
    
    context->create();
    QOpenGLFunctions *gl = context->functions(); // <-- Shows the same warning
    

    But I am getting the same warning. Maybe I am missing something?


  • Lifetime Qt Champion

    @lukicdarkoo
    Yes exactly.
    But can you check if makeCurrent returns true or false ?



  • @mrjj Oh, it returns false. I will need some time to figure out why it returns false.



  • @mrjj I was calling the makeCurrent function before create. Here is the fixed version:

    QGuiApplication a(argc, argv);
    
    QOpenGLContext context;
    context.create();
    assert(context.isValid());  // <----- fails here
    
    QOffscreenSurface surface;
    surface.create();
    assert(surface.isValid());
    
    context.makeCurrent(&surface);
    
    QOpenGLFunctions *gl = context.functions();
    qDebug() << "Version: " << QString::fromLatin1((const char *)gl->glGetString(GL_VERSION));
    qDebug() << "Renderer: " << QString::fromLatin1((const char *)gl->glGetString(GL_RENDERER));
    

    But it also fails to create the OpenGL context in Docker. With xvfb-run and on my PC it works fine though.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Did you try to use the eglfs backend ? Since the Nvdia documentation mentions egl as system to use so you do not need an X server running.


Log in to reply