Doing `headless’ OpenGL on a remote machine with embedded Tomcat

A current project of mine involves a slightly involved client/server architecture to generate OpenGL imagery for a standard client-side web application. We knew for this project that we could not rely on WebGL as:

  • It would not well-supported for all users
  • If it was supported, some features may be disabled (e.g. antialiasing, vertex texture fetch, etc)
  • It would not allow us to scale the rendering for complex scenes

By using a remote server to generate an image to be inserted in-place as requested based on a set of query parameters, we could eliminate these problems at the expense of increased difficulty of interacting with the generated imagery and the additional lag imposed on the request and response.

Our chosen architecture was Java and its JoGL bindings, using an embedded Tomcat servlet to respond to client requests. Running both client and server on my development machine was simple enough as the localhost passthrough ensured no firewall issues and also I knew that there would be no issues with rendering to offscreen OpenGL buffers as I’d had lots of experience with pixel buffer and framebuffer objects previously for some GPGPU stuff on my PhD.

I was provided access to a remote machine in order to test the imagery server application. My issue (which took an embarrassing amount of time to figure out) was that JOGL was failing to provide a valid OpenGL context, on account of there being no active DISPLAY set by the X server on the machine. I have to admit, I’d had little experiences with X11 previously and had really no idea where to go from here: I required an active DISPLAY to be set that would provide an OpenGL context, but the machine was headless.

My first test then was obvious:

ssh me@myserver -X

This confirmed that having my local machine perform the OpenGL commands on behalf of the remote server (based on a request from my local machine… convoluted, no?) worked just fine. So, the application was working just fine on the server, and I knew that there were no further ports to open as the server was attempting to set up an OpenGL context upon receipt of the client request.

Eventually, I found out based on some StackExchange searches about Xvfb, which did exactly what I required: providing a virtual framebuffer to which I could render to without having a physical display attached. Starting it was simple:

Now all I had to do was instruct JoGL to use screen 12 rather than whatever the default display was (in this case, it was the null display), and it worked perfectly. So there you go!

Leave a Reply