Building a custom Intel graphics stack

When I worked as a Linux kernel developer, I often ran across people who were very concerned about compiling and installing a custom kernel. They really didn’t like running the bleeding edge kernel in order to check that a specific bug still existed. Who can blame them? A rogue kernel can corrupt your file system and you could lose data.

Fortunately, there is a safer way to build the latest version of drm and Mesa in order to check if an Intel bug still exists in the master branch. Since Mesa is just a userspace program, it is possible to install it to a custom directory, set a lot of environment variables right, and then your programs will dynamically link against that custom drm and Mesa binaries. Your desktop programs will still run under your distro’s system-installed mesa version, but you can run other programs linked against your custom mesa.

Unfortunately, mesa has some dependencies, and the instructions for how to build into a custom directory are kind of scattered all over the mesa homepage, the DRI wiki, the Xserver wiki, github, and mailing list posts. I’m going to attempt to condense these instructions into one single place, and then clean up those pages to be consistent later.

Debug build or better performance?

In this tutorial, I’ll assume that you want to build a version of drm and mesa with debugging enabled. This *will* slow down performance, but it will enable you to get backtraces, run gdb, and gather more debugging information than you normally would. If you don’t want a debug build, remove the parts of the commands that add the “debug” flag to the USE environment variable or config.mk files.

The point of this tutorial is to be able to install drm and mesa in a directory, so that you don’t have to install them over your distro’s binaries. This means you’ll be able to run the specific test you need, without running into other bugs by running your full desktop environment on the bleeding edge graphics stack. In this tutorial, I will assume you want to put your graphics installation in $HOME/graphics-install. Change that to whatever your heart’s desire is.

If you are working behind a proxy, you’ll need to have a .gitconfig file in your homedir that tells git how to clone through the proxy.

I also assume you’re running a debian-based system, specifically Ubuntu 14.04 in my case. If you’re on an RPM-based distro, change the package install commands accordingly.

Get mesa dependencies

sudo apt-get build-dep libdrm mesa mesa-utils
sudo apt-get install linux-headers-`uname -r` \
    libxi-dev libxmu-dev x11proto-xf86vidmode-dev \
    xutils-dev mesa-utils llvm git autoconf automake \
    libtool ninja-build libgbm-dev

Clone the repositories

mkdir git; cd git
git clone git://anongit.freedesktop.org/git/mesa/mesa
git clone git://anongit.freedesktop.org/mesa/drm
git clone git://github.com/chadversary/dev-tools.git
git clone git://anongit.freedesktop.org/piglit
git clone git://github.com/waffle-gl/waffle.git
git clone git://anongit.freedesktop.org/mesa/demos.git

Set up Chad’s development tools

Chad Versace has been working on a set of scripts that will set up all the right environment variables to run programs that will use custom-installed mesa and drm binaries. Let’s get those configured properly.

Edit your .bashrc to include the following lines:

export GOPATH=$HOME/go
export PATH=/usr/lib/ccache:$HOME/bin:$PATH:$GOPATH/bin
export PYTHONPATH=~/bin/mesa-dev-tools/bin/:$PYTHONPATH

Now it’s time to set up Chad’s tools.

cd dev-tools/

We’ll be installing everything in ~/graphics-install, so we need to create a config.mk file with this contents:

prefix := $(HOME)/graphics-install
USE := "debug"

This will add the debug flag to all builds, which will add symbols so you can use gdb (as well as add some additional code that could impact performance, so don’t add the flag if you’re doing performance testing!).

Build and install the development scripts:

make && make install

Exit your current shell, and start a new shell, so that the changes to the .bashrc and the installation of Chad’s scripts take effect.

Next, we need to get all the paths set properly to use Chad’s scripts to build mesa and libdrm into ~/graphics-install. We invoke the prefix-env script, and tell it to exec the command to start a new shell:

cd git/dev-tools
PREFIX="$HOME/graphics-install" USE="debug" \
    bin/prefix-env exec --prefix=$HOME/graphics-install bash

Double check that worked by seeing whether we have the right mesa-configure script on our path:

sarah@dingo:~/git/dev-tools$ which mesa-configure
/home/sarah/graphics-install/bin/mesa-configure

Check which Mesa version you’re running. Later, after installing a custom Mesa, we’ll verify the installation by confirming that the active Mesa version has changed.

sudo glxinfo > /tmp/glxinfo-old.txt

Note that glxinfo calls through the Xserver to get the information for what Mesa we’re using. Note that if your system xorg installation is too old, the Xserver won’t be able to find an API-compatible version of Mesa, and you’ll see errors like:

Error: "couldn't find RGB GLX visual or fbconfig"

Fortunately, we can run many Mesa programs without involving the Xserver. Another way to find what version of mesa you’re running without going through the Xserver is to use wflinfo command:

sudo wflinfo --platform gbm --api gl > /tmp/wflinfo-old.txt

We can see which version of mesa (11.0.2) is installed by default on Ubuntu 14.04:

sarah@dingo:~/git/dev-tools$ grep Mesa /tmp/*info-old.txt
client glx vendor string: Mesa Project and SGI
OpenGL core profile version string: 3.3 (Core Profile) Mesa 11.0.2
OpenGL version string: 3.0 Mesa 11.0.2
OpenGL ES profile version string: OpenGL ES 3.0 Mesa 11.0.2

Now, that we have Chad’s tools set up, and we’ve set up the environment variables, it’s important to build everything from the shell where you ran the prefix-env command. If you need to open up additional virtual consoles, make sure to change into ~/git/dev-tools/ and re-run the prefix-env command.

Building libdrm

The direct rendering manager library, libdrm, is a prerequistite for mesa. The two projects are pretty intertwined, so you need to have updated installations of both.

Change directories into your libdrm repository, and configure libdrm with the libdrm-configure script (note that PREFIX was already set when we exec’ed with the prefix-env script):

USE="debug" libdrm-configure
make && make install

Building Mesa

Change directories into your mesa repository, and configure mesa with the mesa-configure script:

cd ../mesa
USE="debug" mesa-configure
make && make install

Building Waffle

Waffle is a library for selecting an OpenGL API and window system at runtime.

cd ../waffle
USE=debug waffle-configure
ninja && ninja install

For some reason, waffle is different from all the other projects, and likes to install libraries into $PREFIX/lib/x86_64-linux-gnu/ If you’re on a debian-based system, you may have to change the configuration files, or simply move the libraries one directory down.

Building glxinfo

Confusingly, a useful debugging tool like glxinfo is found in a mesa repository named demos. Change into that directory:

cd ../demos

Since Chad’s tools don’t cover installation of the demo tools, we’ll have to configure them by hand:

autoreconf --verbose --install -s
./configure --prefix="$HOME/graphics-install"
make -j8 && make install

Confirm installation

Confirm that the environment’s Mesa version matches the version you installed. It should differ from the Mesa version we checked earlier.

sudo glxinfo > /tmp/glxinfo-new.txt

Or run wflinfo instead:

sudo wflinfo --platform gbm --api gl > /tmp/wflinfo-new.txt
grep Mesa /tmp/*info-new.txt

You should see something about a development version of mesa in the output.

Building Piglit

Piglit is the test infrastructure and tests for libdrm and mesa.  Let’s build it:

cd ../piglit
USE=debug piglit-configure

Piglit has a slightly different build system than drm, mesa, and waffle. After the first build, the dependencies for piglit tests means it takes a very long time to recompile the tests after a small change is made. This is due to the simplicity of cmake. Instead, it’s recommended to use the ninja build system with piglit.

Make piglit:

ninja

Install piglit:

ninja install

Run your tests

Anytime we want to use the newly installed mesa and drm, we need to rerun the prefix-env script to set up all the graphics environment variables to point to those binaries:

PREFIX="$HOME/graphics-install" USE="debug" \
    bin/prefix-env exec --prefix=$HOME/graphics-install bash

Since we haven’t compiled the full Xserver stack, we have to run piglit with a different platform than X11. If you run `piglit run –help`, you’ll see that a platform could be x11_egl, glx (which is actually calling the GLX api through the Xserver), mixed_glx_egl (which also implies going through the Xserver), wayland, and gbm. The most simple platform is gbm.

Here’s how you run your very first sanity test with gbm:

PIGLIT_PLATFORM=gbm ./piglit run \
    tests/sanity.tests results/sanity.results

If the output says you passed, give yourself a pat on the back! If not, you probably don’t have something installed correctly. You may want to exit all shells, run `git clean -dfx` (to clean out all tracked files) in all the repos, and try again.

To get a more detailed test report, you can run the `piglit summary` command with either console (for text output, good if you don’t have X running), or with html to generate pretty webpages for you to look at on another machine. Piglit will also output test results in a form Jenkins can use.

./piglit summary console results/sanity.results
./piglit summary html --overwrite summary/sanity results/sanity.results

You’ll need the overwrite or append flag if you’re writing results to the same directory.

There’s even more explanations of what you can do with piglit on these two blog posts.

Running games or benchmarks

Once you’ve run the prefix-env script, you should be able launch benchmarks or other tests. Running games or steam with a custom mesa installation is harder. Since most games are going to use the Xserver platform to call into Mesa’s GL or EGL API, you may need to compile a new Xserver as well.

Optional kernel installation

Sometimes you may want to run the bleeding-edge Intel graphics kernel. Confusingly, the kernel isn’t hosted on git.kernel.org! Use the drm-intel-nightly branch from the drm-intel repo on freedesktop.org:

git clone git://anongit.freedesktop.org/drm-intel

Instructions on compiling a custom kernel can be found here:

http://kernelnewbies.org/FirstKernelPatch

Additionally, you may need to set the i915 kernel module parameter to enable new hardware support.  You can do this by changing the line your grub configuration defaults in /etc/default/grub to this:

GRUB_CMDLINE_LINUX_DEFAULT="i915.preliminary_hw_support=1"

And then you’ll need to update your grub configuration files in /boot by running:

sudo update-grub

2 thoughts on “Building a custom Intel graphics stack

  1. Very nice! I’m sure you’ve considered getting this into the Mesa or X.Org docs or both: please do. It would answer a lot of questions for a lot of people.

    Thanks much for writing this.

Leave a Reply

Your email address will not be published. Required fields are marked *