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 onxvfb
.Approach #1: First, we tried simply by setting the
QT_QPA_PLATFORM
environment variable tooffscreen
. Although this hides the GUI on my PC it fails to createQOpenGLFunctions
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:
- https://developer.nvidia.com/blog/linking-opengl-server-side-rendering/
- https://developer.nvidia.com/blog/egl-eye-opengl-visualization-without-x-server/
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? -
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.htmlAgain, 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?
-
@lukicdarkoo
Yes exactly.
But can you check if makeCurrent returns true or false ? -
@mrjj I was calling the
makeCurrent
function beforecreate
. 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. -
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.