Nvidia Optimus on Ubuntu 12.04

Nvidia Optimus is a neat solution to the problem of power consumption vs. 3D performance in notebook computers – the computer comes with two graphics chips, an “integrated graphics package” – the Intel GMA embedded graphics and a “discrete graphics package” – the Nvidia chip. The setup works by running your normal windowing UI on the integrated graphics, only powering on the discrete graphics when you want to play a 3D game or something like that.

Recently I had the fortune to work on a Lenovo T420 laptop1 that has this setup, and it works very well on MS-Windows with the Nvidia Optimus driver – you get battry life around 10 hours with the 9 cell battery.

Unfortunately I spend most of my day in Linux and because Nvidia does not support Optimus on Linux, you have the poor choice of either running everything on the Nvidia chip – decreasing battery life to around 4 hours if you’re careful, or disabling the Nvidia chip completely.

The solution comes from the Bumblebee project – a software suite to handle the switching between the Nvidia discrete graphics and the embedded Intel chip.

The setup is pretty simple to understand (though I suspect under the hood there are many problems to be solved): A service runs and waits for users to ask for 3D accelerated graphics. When a user starts a program using the special command optirun, the service loads the Nvidia driver, starts an X server using the discrete graphics (with the display disconnected from the actual screen) and runs the specified program on that “background” X server. Then it copies the visuals from the program that is rendered using the discrete graphics to a window on the main X server. When the program terminates, the service closes the secondary X server, removes the driver and powers down the graphics card – putting us back into the ~10 hours battery life.

The Bumblebee software had some problems in the past, but the current version – 3.0 – looks very good. There are a few seconds of delay when you launch the application (setting up the driver and X takes some time), but performance is about what you’d expect when running directly on the hardware. All this without any configuration – that is if you are running on the stable Ubuntu version.

As I can’t leave well enough alone, and whenever someone says “alpha”, I say – “I wants”, I’m running the current Ubuntu 12.04 alpha (which is not so bad – due to be released in a couple of months, it works very well). And of course Bumblebee doesn’t work properly here.

So this is what I had to do to get it running:

These instructions assume you are doing everything in a command line. If you are not comfortable with the command line, this guide is not for you – go away.

  1. We will start by installing Bumblbee itself and its dependencies. We will need to add their PPA2 to the Ubuntu software sources list:
    sudo add-apt-repository ppa:bumblebee/stable
    Unfortunately the project has a repository for Ubuntu 12.04, but at this point in time it does not include all the needed packages. I had to edit the source list file and add the 11.10 repositories as well before installation could complete – open the file /etc/apt/sources.list.d/bumblebee-stable-precise.list for editing as root, for example:
    sudo gedit /etc/apt/sources.list.d/bumblebee-stable-precise.list
    and duplicate the two lines found there, changing the word precise to oneiric in the duplicates. Save and exit the editor, then run these:
    sudo apt-get update
    sudo apt-get install bbswitch-dkms bumblebee bumblebee-nvidia virtualgl-libs:i386 libgl1-mesa-glx:i386 libc6:i386
    sudo usermod -a -G bumblebee $USER

    The last line adds the current user (the one you are logged in as) to the “bumblbee” user group – only users who are part of this group may use the Bumblebee service. If you have more users that you want to be able to play 3D games, then you need to add them as well.
  2. The Bumblebee Project recommends Ubuntu users to install the “X-Swat” x-updates PPA, but this isn’t available for 12.04 users, and we are already running the latest X anyway, right? After bumblebee didn’t work for me, I went to the next best thing – the xorg-edgers repository. A word of warning – this is a set of highly experimental software – if it works for you, count yourself lucky and if it doesn’t – don’t complain. To install it, type:
    sudo apt-add-repository ppa:xorg-edgers/ppa
    sudo apt-get update
    sudo apt-get dist-upgrade -y
    At this point most likely your kernel and other important software packages have been upgraded, so its a good idea to reboot.
  3. After you come back from the reboot, the standard Nvidia driver will not work, because of an incompatible ABI3 version. Not to worry, its time to recompile a new Nvidia driver. Start by removing your old one with:
    sudo apt-get purge nvidia-current
    Now to get the most up to date Nvidia driver package to rebuild a driver that works with your latest Xorg and kernel, create a new directory to hold the Nvidia package sources and change into it, and type:
    sudo apt-get install build-essential checkinstall -y
    sudo apt-get build-dep nvidia-current-updates -y
    apt-get source nvidia-current-updates
    Now with the source downloaded and all dependencies installed, we can build a new driver and install it:
    cd nvidia-graphics-drivers*
    dpkg-buildpackage -us -uc -nc
    cd ..
    sudo dpkg -i nvidia-current-updates_*.deb
    If all went well, you have your new Nvidia driver instaled. Lets see if it loads Ok:
    sudo modprobe nvidia_current_updates
    If you get no error, then we can go to the next step.
  4. The Bumblebee configuration must be modified to work with all this cutting edge stuff, so lets start by turning off the Bumblbee service:
    sudo stop bumblebeed

    Now you need to edit the Bumblebee configuration file. Use your favorite text editor to open /etc/bumblebee/bumblebee.conf as root, for example:
    sudo gedit /etc/bumblebee/bumblebee.conf
    . This is a standard INI filewith a lot of comments to help you figure out what is going on in here, and we will need to do some changes to (a) disable auto-detection and force Nvidia mode and (b) help Bumblebee locate the drivers for the Nvidia graphics. Make these changes:

    • In the [bumblebeed] section, set Driver=nvidia
    • In the [driver-nvidia] section, set KernelDriver=nvidia_current_updates and in both LibraryPath and XorgModulePath change nvidia-current to nvidia-current-updates.

    Save the file after all the changes have been complete, and start the service again:
    sudo start bumblbeed

  5. At this point, Bumblebee should be ready to do some damage. The recommended way to test it is to run
    optirun glxspheres
    Give it a few seconds to launch the window (the screen may black out for a bit, don’t worry about it). When the window appears, it should show a graphical demo and a frame per seconds counter at the bottom left corner. On my system it shows a respectable 86 frames per seconds (vs 2 frames per seconds on the embedded Intel chip). If the glxspehere window doesn’t come up, and you get errors from the optirun command, look in the system log file /var/log/syslog for lines from bumblebeed. Also if you haven’t rebooted your computer since you built the Nvidia drivers, it might be a good idea to try that as well.

Running games with optirun is pretty straight forward – either invoke them manually or edit their .desktop files to add the optirun command. I’ve also used this in MS-Windows games running under wine (I recommend using PlayOnLinux – its a beautiful piece of work), and they work perfectly well.

Best of luck, and let me know if it works or if it doesn’t.

Enhanced by Zemanta
  1. with an amazing 1600×900 screen, what they call “HD+”. Truly a work of art []
  2. Private Package Archive []
  3. Application Binary Interface []

96 Responses to “Nvidia Optimus on Ubuntu 12.04”

  1. d:
    Fatal error: Uncaught Error: Call to undefined function comment_dir() in /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/single-comment2.php:17 Stack trace: #0 /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/functions.php(8): include() #1 /vhosts/coil/geek/public_html/wp-includes/class-walker-comment.php(179): themed_comment() #2 /vhosts/coil/geek/public_html/wp-includes/class-wp-walker.php(144): Walker_Comment->start_el() #3 /vhosts/coil/geek/public_html/wp-includes/class-walker-comment.php(139): Walker->display_element() #4 /vhosts/coil/geek/public_html/wp-includes/class-wp-walker.php(387): Walker_Comment->display_element() #5 /vhosts/coil/geek/public_html/wp-includes/comment-template.php(2229): Walker->paged_walk() #6 /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/comments.php(26): wp_list_comments() #7 /vhosts/coil/geek/public_html/wp-includes/comment-template.php(1539): require('/vhosts/coil/ge...') #8 /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/single.php( in /vhosts/coil/geek/public_html/wp-content/themes/modern-bluish/single-comment2.php on line 17