Oculus is discontinuing the support for Linux and Mac with the latest the version of its SDK (0.6.0.0 which is supported by Windows only at this time. The new Compositor Service is one of the major changes after direct to rift mode but is available on Windows only. If you don’t know what I’m talking about, here’s an extract from the documentation about the new service based API:
The compositor service moves distortion rendering from the application process to the OVRServer process using texture sets that are shared between the two processes. A texture set is basically a swap chain, with buffers rotated to allow game rendering to proceed while the current frame is distorted and displayed.
The Linux community is not giving up the challenge. But on Linux configuring the Rift can be a little tricky, there’s no direct to rift mode and using a Multi-head configuration which shares the same Screen with the Rift is not the best option.
Here’s why, the Monitors sharing the same Screen have to run at the same vertical refresh rate. The Rift is seen by Xorg as a normal Monitor so if other Monitors running at 60Hz are attached at the same Screen object, the Rift will be unable to run at its native 75Hz.
Running the Rift Monitor at 60Hz will cause delay and jittering of the image especially when turning your head around fast.
So how to fix this problem, and make the Rift run at 75Hz ?
Configuring X.Org
Googling around I came by an article called Proper Oculus Rift DK2 setup on GNU/Linux where a young Greek developer John Tsiombikas describes the way to hook up the Rift on a second Screen.
I recommend you to read his article before proceed because John is explaining in simple words the terminology needed to understand how an X.Org conf file works, here a quick extract about the terminology:
[…] It goes like this: each X server is called a “Display”, and each Display has one or more Screens. […], an xorg.conf file has:
-
One or more “Device” sections, describing each graphics card, or graphics output in case of multi-head GPUs […].
-
One or more “Monitor” sections, describing each monitor we have connected […].
-
One or more “Screen” sections, binding together a Device and a Monitor by referencing the appropriate section identifiers, to describe available color depths and resolutions for each combination.
-
And a “ServerLayout” section, referencing each Screen we want to use, and specifying their spatial relationships in the real world (such as screen A is on the left side of screen B, which is below screen C, etc).
Here’s my configuration, generated by nvidia-settings:
# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings: version 352.09 (buildmeister@swio-display-x86-rhel47-06) Tue May 12 15:27:42 PDT 2015
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
Screen 1 "Screen1" Below "Screen0"
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
Option "Xinerama" "0"
EndSection
Section "Files"
EndSection
Section "Module"
Load "dbe"
Load "extmod"
Load "type1"
Load "freetype"
Load "glx"
EndSection
Section "InputDevice"
# generated from default
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/psaux"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
# generated from default
Identifier "Keyboard0"
Driver "kbd"
EndSection
Section "Monitor"
# HorizSync source: edid, VertRefresh source: edid
Identifier "Monitor0"
VendorName "Unknown"
ModelName "LG Electronics E2240"
HorizSync 30.0 - 83.0
VertRefresh 56.0 - 75.0
Option "DPMS"
EndSection
Section "Monitor"
# HorizSync source: edid, VertRefresh source: edid
Identifier "Monitor1"
VendorName "Unknown"
ModelName "OVR Rift DK2"
HorizSync 30.0 - 150.0
VertRefresh 56.0 - 77.0
Option "DPMS"
EndSection
Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce GTX 660"
BusID "PCI:1:0:0"
Screen 0
EndSection
Section "Device"
Identifier "Device1"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce GTX 660"
BusID "PCI:1:0:0"
Screen 1
EndSection
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
# Option "Stereo" "0"
# Option "metamodes" "DVI-I-1: nvidia-auto-select +0+0, DVI-D-0: nvidia-auto-select +1920+0"
# Option "SLI" "Off"
# Option "MultiGPU" "Off"
# Option "BaseMosaic" "off"
SubSection "Display"
Depth 24
EndSubSection
EndSection
Section "Screen"
Identifier "Screen1"
Device "Device1"
Monitor "Monitor1"
DefaultDepth 24
Option "Stereo" "0"
Option "metamodes" "HDMI-0: nvidia-auto-select +0+0"
Option "SLI" "Off"
Option "MultiGPU" "Off"
Option "BaseMosaic" "off"
SubSection "Display"
Depth 24
EndSubSection
EndSection
Using nvidia-settings is much more convenient instead of writing the whole configuration by hand, just click on “Save to X Configuration file” to save the xorg.conf file:
As you can see two X Screen are present, one for my normal monitors and one for the Rift, the one for the Rift running at 75Hz of vertical refresh rate.
As you read on the article above from John Tsiombikas, he also created a script based on VNC for spying on the Rift, which if you ask me is a very clever solution to check whats going on the Rift:
#!/bin/sh
x11vnc -display :0.1 -scale 0.5 -rotate +90 \ -localhost -nopw -norc -timeout 1 \
-q -viewonly -once -bg && \ vncviewer localhost
For my little contribute a wrote a simple XRandr bash script for putting the screen on the Rift in sleep mode:
#!/bin/bash
if [ $# -ne 1 ] then echo "USAGE: $0 <on|off>" exit 1 fi
case "$1" in
off) xrandr --screen 1 --output HDMI-0 --off ;;
on) xrandr --screen 1 --output HDMI-0 --auto ;;
esac
So this is my current setup on Linux for the Rift, I’m running on Arch Linux and I’m using the latest Nvidia drivers (352.09-1 at the moment of this article).