Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyOpenGL headless rendering

I'm using PyOpenGL+glfw for rendering.

When trying to do the same on a headless machine (e.g a server) glfw.init() fails:

glfw.GLFWError: (65544) b'X11: The DISPLAY environment variable is missing'
Fatal Python error: Couldn't create autoTLSkey mapping
Aborted (core dumped)

I found some information about headless rendering, but only when using OpenGL directly and not through python

EDIT: I understand that maybe glfw isn't able to support it. A solution without glfw, but with something else might also work...

like image 495
user972014 Avatar asked Feb 01 '19 16:02

user972014


2 Answers

GLFW does not support headless OpenGL at all.

https://www.glfw.org/docs/latest/context.html#context_offscreen

GLFW doesn't support creating contexts without an associated window.

This isn’t an unusual limitation, the problem is that the normal way to create an OpenGL context is by using the X server. There are now alternatives using EGL, which is relatively new. You will need to use an EGL wrapper for Python.

See: OpenGL without X.org in linux

like image 143
Dietrich Epp Avatar answered Sep 26 '22 12:09

Dietrich Epp


The solution is to use xvfb for a virtual framebuffer.

The problem is that the glfw that is installed in Ubuntu using apt-get install libglfw3 libglfw3-dev is old and unfit, so we need to compile it from source.

Here is a full working docker example:

docker run --name headless_test -ti ubuntu /bin/bash

# Inside the ubuntu shell:
apt update && apt install -y python3 python3-pip git python-opengl xvfb xorg-dev cmake
pip3 install pyopengl glfw
mkdir /projects
git clone https://github.com/glfw/glfw.git /projects/glfw
cd /projects/glfw
cmake -DBUILD_SHARED_LIBS=ON .
make
export PYGLFW_LIBRARY=/projects/glfw/src/libglfw.so
xvfb-run python3 some_script_using_pyopengl_and_glfw.py

And here is the base of PyOpenGL code to use it:

from OpenGL.GL import *
from OpenGL.GLU import *
import glfw

glfw.init()
# Set window hint NOT visible
glfw.window_hint(glfw.VISIBLE, False)
# Create a windowed mode window and its OpenGL context
window = glfw.create_window(DISPLAY_WIDTH, DISPLAY_HEIGHT, "hidden window", None, None)
# Make the window's context current
glfw.make_context_current(window)
like image 41
user972014 Avatar answered Sep 26 '22 12:09

user972014