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_VERSION=3.3 (Compatibility Profile) Mesa 20.2.6
    GL_RENDERER=llvmpipe (LLVM 11.0.0, 256 bits)

    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

    It's outside my normal zone but Im wondering
    if approach 3 is just missing
    with a

    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();
    QOpenGLFunctions *gl = context->functions(); // <-- Shows the same warning

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

  • Lifetime Qt Champion

    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;
    assert(context.isValid());  // <----- fails here
    QOffscreenSurface 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