At ArrayFire, we constantly encounter projects that require OpenGL and run on a remote server that does not have a display.
In this blog, we have compiled a list of steps that users can use to run OpenGL full profile applications over SSH on remote systems without a display.

A few notes before we get started.
<ul>
	<li>The first part of the blog that shows the configuration of the xorg.conf file it limited to NVIDIA Quadro and Tesla cards (with display).</li>
	<li>NVIDIA GeForce cards do not support this functionality.</li>
	<li>AMD cards support this capability without the modification of xorg.conf file.</li>
</ul>

<strong>Requirements</strong>:
To run the tool, you will need libGL.so, libX11.so. Another tool I would recommend strongly is glewinfo. Most linux distributions ship this with the glew-utils package. An alternate to glewinfo is glxinfo which is present on all systems with X. You can substitute glewinfo with glxinfo in all the commands below if needed.

<strong>Part 1: Setting up X (NVIDIA Only)</strong>
To get X to run on NVIDIA cards, we need to make a small change to the xorg.conf file. Before making the change, make sure you create a back up of the current version on your system.
Open xorg.conf (located in /etc/X11/xorg.conf). Look for "Section Device". You NVIDIA card should be listed here. Add this line before the end of the section: <code>Option         "UseDisplayDevice" "none"</code>. If you have more than one NVIDIA card listed, add this line to all the cards. Save and close the file and restart the system.

<strong>Part 2: Login and Initial Diagnosis</strong>
Login to the remote system using the -X flag. That is, <code>ssh -X user@remote</code>.
Once logged in, run <code>echo $DISPLAY</code>. It is very likely that the output of this will be <strong>localhost:10.0</strong>. This specifies the display device is the client computer. If you have glewinfo installed, run it using <code>glewinfo | less</code>. You should see the graphics card from you local machine listed there, and perhaps OpenGL 2.x.

If you have glewinfo installed, run the following command:
<code>env DISPLAY=:0 glewinfo | less</code>.
The goal of this command is to run glewinfo having temporarily set DISPLAY to :0 (remote system). If this command run's successfully, you should be able to see the graphics card on the remote system along with the full OpenGL profile. And now you are ready to deploy applications using X.
If you want to set DISPLAY for the entire session, run <code>export DISPLAY=:0</code>

<strong>Part 3: Deploying Off-Screen Rendering Applications on Remote System</strong>
This is where X becomes crucial. Tools like GLFW may or may not work on remote systems because of dependence on Xrandr and other software. The trick is use X to create an OpenGL context, and the run everything using off-screen rendering using framebuffers and renderbuffers. I took the source to create an OpenGL context using X from <a href="http://www.opengl.org/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)" title="OpenGL Context Creation Page" target="_blank"></a> and modified it slighly. Thanks to the folks at OpenGL.org for providing this. The source code with the changes I made can be found here: <a href="https://github.com/arrayfire/glContext/blob/master/glContext.hpp" target="_blank">glContext.hpp</a>.

Include this in your source code. To create context run createGLContext() and to delete the context run deleteGLContext().

I have specified that the minimum OpenGL version should be 4.4 with forward context enabled. You can modify this version by changing the values at lines 26 and 27.
The forward compatibility can be disabled at line 241 by changing line 241 to None.
If the application fails to create the specified version of the context, the application will exit.

At line 189, we create the window. The API description can be found <a href="http://tronche.com/gui/x/xlib/window/XCreateWindow.html" title="link" target="_blank"></a>. "0, 0, 10, 10" specifies the top-left corner (0,0) and the width and height of the window (10, 10). Since the goal of this is to be used for off-screen rendering, the size of the window has no effect on the rendering.
Line 202 specifies the window title.

If everything goes successfully, you should see an output like this:
<pre>
glContext.hpp:307: GL Version  = 4.4.0 NVIDIA 331.75
glContext.hpp:308: GL Vendor   = NVIDIA Corporation
glContext.hpp:309: GL Renderer = Quadro K5000/PCIe/SSE2
glContext.hpp:310: GL Shader   = 4.40 NVIDIA via Cg compiler
</pre>

If you wish to use a lower minimum version, say 3.0, then the version provided by the output will reflect 3.0 since GL fetches version from the context.

To test the context creation as a stand alone, create a cpp file with the following contents (<a href="https://github.com/arrayfire/glContext/blob/master/glContext.cpp" title="glContext.cpp" target="_blank">glContext.cpp</a>):
<pre>
#include "glContext.hpp"

int main(int argc, char* argv[])
{
    createGLContext();
    deleteGLContext();
    return 0;
}
</pre>

Compile this with <strong>g++ -o gl glContext.cpp -lGL -lX11</strong> and run with <strong>./gl</strong> (make sure DISPLAY is :0). If this works successfully, any off-screen rendering code will work perfectly with this.
<strong>Note:</strong> If you use GLEW, make sure you include glew.h before including gl.h.

If you wish to know about remote OpenGL further or work with us on remote rendering, contact us at technical@arrayfire.com.