May 27, 2014 - KMS and DRM
May 27, 2014
KMS and DRM
Recently, I released a neat game called "The Return", which runs on the Linux
Framebuffer Device. However, I had planned to also build a KMS/DRM backend for
it. So recently I implemented this KMS/DRM backend.
Working with KMS/DRM is interesting, but not particularly fun. I constrained
myself to not using the C library, since that was the original constraint which
led to me creating "The Return". This wasn't a big problem for fbdev, since
all that has to be done is opening up the device file, some ioctl calls, and
then mapping the framebuffer. However, for KMS/DRM, most applications using
KMS/DRM use libdrm, but libdrm needs the standard C library, which I rejected.
So I spent a lot of time reading through the libdrm source code to figure it
I discovered first of all that KMS/DRM is a lot more complicated than fbdev.
This makes sense since it's meant to do more, but it doesn't make my job any
easier. In my opinion there is also a lot of room for improvement.
Once I figured out what was supposed to be going on, it shed light on a few
issues that I would face later. First of all, the KMS/DRM API expects a lot of
things to be stored in dynamically allocated memory, but without the standard C
library, there is no malloc, and dynamic memory management is pretty
complicated. I worked around this by just statically allocating what I figured
would be more than enough memory.
The next problem is more severe. The KMS/DRM API allows you to do a lot of
things with your code, sounds good, but it also means you have a lot more
things that you have to worry about. Mode Setting (KMS) is basically a method
of telling the kernel how you want your graphics card to be set up. You have
to do this by first asking for information about the graphics card, like what
connectors are available and then checking if anything is plugged in to those
connectors, and if so, what are the valid "modes" that you can use. Now a
"mode" essentially means the possible dimensions of your display. For instance,
I am using 1366x768 on my main screen, and 1024x768 on my external monitor
right now. This is important because you have to create the framebuffer at the
right size. So far this is all logical, but if you think about it for a little
while you might come up with a few questions. For instance, what should I do if
I find two displays with different available modes? What criteria should I use
to select a mode? If there is more than one active display, which one should my
application display on? I haven't come up with a really nice clean solution to
these problems yet, but for now what I am doing is checking all the first mode
of each connector and picking the one with the largest dimensions. I suppose
this is one of the purposes of X11 or Wayland or Mir, to solve some of those
Speaking of X11 (which does it's own KMS), I discovered some fun issues while
working on the KMS/DRM code. Namely, like fbdev, I have to switch to an unused
tty to run the code, which is no problem. However, while the program is
running and the device file is open, it has exclusive control of the device.
This means that I cannot switch back to X11 while the program is running, since
X will fail to get control. This did not keep me from trying, hundreds of
times, and each time the result was the same: X failed to get control of the
device and crashed. Which is really wonderful because then I lose all the
things I was working on at the time.
Anyways, I finally got the code working and integrated into "The Return". Now
the game can be compiled with either KMS/DRM or with fbdev as the backend. I
have not yet uploaded this code to the website. The KMS/DRM backend has been
tested only on my computer, and I am a bit worried about how it will behave on
Actually, I am a bit worried about how it behaves on my own machine too. The
first time I ran "The Return" with DRM instead of fbdev, I noticed it was
ridiculously slow. I made some optimization, and I got it to the point where
the delay is almost acceptable (but not acceptable), but the fact remains,
fbdev is faster. This may just be due to my particular graphics card and system
set up, probably my code as well. It also might just be that DRM has more
overhead than fbdev does, which would be very sad.
Anyways, regardless of all the problems I encountered, I wrote up a quick
tutorial on how to use the KMS/DRM API and added it to the
Linux Low-Level Graphics tutorial on this site. It needs some improvement,
and the method I used for selecting the correct mode in "The Return" is
different (and probably better) than what I described in the tutorial, but it
does work. If you think you can improve on my tutorial, email me at
Anyways, have fun. That's all for now. Peace!