“DRI”

I spend a lot of time explaining the Linux Graphics Stack to various people online. One of the biggest things I’ve come across is that people have a hard time differentiating between certain acronyms like “DRI”, “DRM” and “KMS”, and where they fit in the Linux kernel, in Xorg, and in Wayland. We’re not the best at naming things, and sometimes we choose the wrong name. But still, let’s go over what these mean, and where they (should) be used.

You see, a long time ago, Linux developers had a bunch of shiny new GPUs and wanted to render 3D graphics on them. We already had an OpenGL implementation that could do software rendering, called mesa. We had some limited drivers that could do hardware rendering in the X server. We just needed to glue it all together: implement hardware support in Mesa, and then put the two together with some duct tape.

So a group of developers much, much older than I am started the “Direct Rendering Infrastructure” project, or “DRI” for short. This project would add functionality and glue it all together. So, the obvious choice when naming a piece of glue technology like this is to give it the name “DRI”, right?

Well, we ended up with a large number of unrelated things all effectively named “DRI”. It’s double the fun when new versions of these components come around, e.g. “DRI2” can either refer to a driver model inside mesa, or an extension to the X server.

Yikes. So let’s try to untangle this a bit. Code was added to primarily three places in the DRI project: the mesa OpenGL implementation, the Xorg server, and the Linux kernel. The code does these three things: In order to get graphics on-screen, mesa needs to allocate a buffer, tell the kernel to render into it, and then pass that buffer over to the X Server, which will then display that buffer on the screen.

The code that was added to the kernel was in the form of a module called the “Direct Rendering Manager” subsystem, or “DRM”. The “DRM” subsystem takes care of controlling the GPU hardware, since userspace does not have the permissions to poke at the raw driver directly. Userspace uses these kernel devices by opening them through a path in “/dev/dri”, like “/dev/dri/card0”. Unfortunately, through historical accident, the device nodes had “DRI” in them, but we cannot change it for backwards-compatibility reasons.

The code that was added to mesa, to allocate and then submit commands to render inside those buffers, was a new driver model. As mentioned, there are two versions of this mesa-internal driver model. The differences aren’t too important. If you’ve ever looked inside /usr/lib/dri/ to see /usr/lib/dri/i915_dri.so and such, this is the DRI that’s being named here. It’s telling you that these libraries are mesa drivers that support the DRI driver model.

The third bit, the code that was added to the X server, which was code to allocate, swap, and render to these buffers, is a protocol extension known as DRI. There are multiple versions of it: DRI1, DRI2 and DRI3. Basically, mesa uses these protocol extensions to supply its buffers to the X server so it can show them on screen when it wants to.

It can be extraordinarily confusing when both meanings of DRI are in a single piece of code, like can be found in mesa. Here, we see a piece of helper code for the DRI2 driver model API that helps implement a piece of the code to work with the DRI3 protocol extension, so we end up with both “DRI2” and “DRI3” in our code.

Additionally, to cut down on the shared amount of code between our X server and our mesa driver when dealing with buffer management, we implemented a simple userspace library to help us out, and we called it “libdrm”. It is mostly a set of wrappers around the kernel’s DRM API, but it can have more complex behavior for more complex kinds of buffer management.

The DRM kernel API also has another, separate API inside it, sometimes known as “DRM mode”, and sometimes known as “KMS”, in order to configure and control display controllers. Display controllers don’t render things, they just take a buffer and show it on an output like an HDMI TV or a laptop panel. Perhaps we should have given it a different name and split it out even further. But the DRM mode API is another name for the KMS API. There is some work ongoing to split out the KMS API from the generic DRM API, so that we have two separate devices nodes for them: “render nodes” and “KMS nodes”.

You can also sometimes see the word “DRM” used in other contexts in userspace APIs as well, usually referring to buffer sharing. As a simple example, in order to pass buffers between Wayland clients and Wayland compositors, the mesa implementation of this uses a secret internal Wayland protocol known as wl_drm. This protocol is eerily similar to DRI3, actually, which goes to show that sometimes we can’t decide on what something should be named ourselves.

8 thoughts on ““DRI”

  1. Thanks for explanation!

    I am looking forward to see more. If possibly
    – why is KMS better than UMS
    – why some are using gallium3D and how is intel doing without it?
    – how is DRI compared to windows? (GDI?)

    • Simple answers:
      – I don’t know how to convince you that KMS is better than UMS, other than to say “it is”. It’s a much better solution all around.
      – Gallium3D is a set of building blocks to construct a driver, and everyone but Intel use it to construct their driver since it’s simpler and easier. Intel has a fully-funded driver team and a driver codebase that predates it. They don’t need those building blocks, and those building blocks are slow, so they’d like to avoid them.
      – GDI is a software rendering mechanism in Windows. The closest equivalent to DRI would be the Windows Display Driver Model, or WDDM.

      • Thanks for all answers! A was thinking if you make full blog post about those questions.

        Anyway, do you know how “slow” exactly is gallium3D? Radeon is actually getting faster than Catalyst (which only shows how “bad” Catalyst is).

        What does WDDM better than DRM (or vica versa)

        • > and those building blocks are slow

          Picture or didn’t happen. E.g. I’d say, with gallium nine on r600 driver games working faster than they were on native Windows7. Of course that says nothing specific about gallium, it might be radeon driver better on GNU/Linux — but your claim is even less specific.

          In general what you say is untrue, unless API is badly written. In the end, “building blocks” is the very core of programming.

  2. Thanks for this article and many other (including the Xplain series). I am an experienced embedded engineer and catching up with the graphics knowledge. Your blog posts really answers a lot of “why”s that I have along the way. Thanks!

  3. Why aren’t graphics drivers part of the kernel, just as other drivers are as well? Is this desireable and does Wayland help to go in that direction?

    • Graphic drivers are broken into 2 parts: kernel driver (e.g. radeon), and user-space driver (e.g. r600). Most part is in the user space, which allows better security — you don’t want whole glsl→tgsi→machine code compiler in the kernel; easier debugging — instead of crashing whole system you’d see just a single app failing; simple upgrades — no need to reboot after graphics upgraded, only to restart the app which you want to use the upgraded driver (though in case of DDX upgrade it’d be whole xserver); easier development — after changing user-space driver you can set LIBGL_DRIVERS_PATH and LD_LIBRARY_PATH to your newly compiled driver, and test an app/driver without even installing the driver.

Leave a Reply

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