
Intro to Low-Level Graphics on Linux - mabynogy
http://betteros.org/tut/graphics1.php
======
zokier
Personally I find the heavy use of ioctls in modern Linux APIs bit
distasteful. Sure, its pragmatic and easy, but it really feels abusing the
UNIX mantra of "everything is a file" when the only operation you can do for
that "file" is some specific ioctls. I first noticed this in the very nice KVM
article that ran on LWN few years back, and now again here. I really wish
there was some more structured way of talking to the kernel, but I can
understand that introducing a ton of new syscalls probably is not practical.

~~~
vardump
> Personally I find the heavy use of ioctls in modern Linux APIs bit
> distasteful.

That's how things work in Windows as well. That's how userland talks to kernel
mode drivers.

Well, except everything is an object.

~~~
Const-me
> That's how things work in Windows as well.

GPU drivers are different. Basically, Windows have Direct3D already in the
kernel, exposing relatively large API surface for the userland half of the
driver.

[https://docs.microsoft.com/en-us/windows-
hardware/drivers/di...](https://docs.microsoft.com/en-us/windows-
hardware/drivers/display/windows-vista-and-later-display-driver-model-
operation-flow)

------
shmerl
Interesting write up, but it would be useful to explain how major graphics
APIs fit into this (i.e. Vulkan / OpenGL) and how it all glues together (GPU
drivers with KMS/DRM and higher level APIs).

Also note, that Mir is now basically gone, Canonical decided now to stop that
rift and stick to Wayland.

~~~
d_theorist
Also, I'm curious about portable (i.e. across different Unixes) low-level
graphics, if such a thing exists.

I assume that the interfaces discussed here are Linux specific, and the BSDs
have something different.

Does POSIX have anything to say about graphics interfaces?

What is the lowest-level portable way to draw graphics? X11?

It's funny, because I always thought of X as being more of a windowing
abstraction, rather than graphics in general. Perhaps I am making a
distinction that does not really exist.

Obviously I am not a graphics guy :)

~~~
0xcde4c3db
The BSDs and Solaris/Illumos have had DRM for years (where available), but it
tends to lag the Linux version significantly because it's not trivial to port
the code from Linux. I'm not sure where the compatibility breaks relative to
the code given on the page, but most of them have some derivative of the
original drm.h header that defines most of the structs and ioctls mentioned
(e.g. [1] [2] [3])

[1]
[https://github.com/freebsd/freebsd/blob/master/sys/dev/drm/d...](https://github.com/freebsd/freebsd/blob/master/sys/dev/drm/drm.h)

[2]
[https://github.com/openbsd/src/blob/master/sys/dev/pci/drm/d...](https://github.com/openbsd/src/blob/master/sys/dev/pci/drm/drm.h)

[3] [https://github.com/illumos/illumos-
gate/blob/master/usr/src/...](https://github.com/illumos/illumos-
gate/blob/master/usr/src/uts/common/io/drm/drm.h)

~~~
d_theorist
Ah, thanks. Interesting.

------
mrb
Using the Linux kernel API is too high level :) Back in 1999 I wrote a simple
3D engine that hooked into a lower level API: the code was calling directly
into the VESA BIOS Extensions of the graphics card. This worked on Windows 98
I think, but not NT4.
[https://en.wikipedia.org/wiki/VESA_BIOS_Extensions](https://en.wikipedia.org/wiki/VESA_BIOS_Extensions)

~~~
makapuf
You used BIOS calls ? Luxury , I used VGA registers directly to get vga mode X
back in the days. [http://www.jagregory.com/abrash-black-
book/](http://www.jagregory.com/abrash-black-book/) now that I call low level.

~~~
a3f
You had a VGA controller? That's nice. I had to design my own back in the
days.
[https://github.com/a3f/r3k.vhdl/tree/Demo-v1/vhdl/io/vga](https://github.com/a3f/r3k.vhdl/tree/Demo-v1/vhdl/io/vga)

~~~
makapuf
You have an FPGA ? That's also nice, all I have is a bunch of resistors and a
MCU :) [https://hackaday.com/2014/02/23/the-bitbox-console-gets-
upgr...](https://hackaday.com/2014/02/23/the-bitbox-console-gets-upgraded/)
(nice project btw !)

------
tombert
These articles always make me appreciate the work that must go into something
like SDL or OpenGL and the like. It's easy to take these things for granted,
but if this is the stuff that they have to make everything work, then I have
to give some props and respect to the authors.

~~~
pjmlp
A nice way to give value to it, and at the same time a learning exercise, is
to try do implement software rendering like we were doing in the MS-DOS days.

For something more modern, grabbing an ESP32 coupled with a LCD screen, for
example.

~~~
outworlder
I made my first serious attempt almost as soon as I joined my university,
CompSci. First attempt took a long time, as I did not really know how matrices
applied to computer graphics, so I did all operations again and again, when
they were required.

My first rotating cube "exploded" due to numerical errors, as I was modifying
the geometry instead of using matrix projections.

That made me appreciate the linear algebra classes much more.

------
ausjke
great write-up, fbdev is straightforward but the kernel is phasing it out in
favor of DRM, I hope DRM will maintain a fbdev emulation at least. it's sad
SDL2 did not have fddev support either as most people are fond of doing
opengl/2d/3d-accleration these days.

~~~
Jasper_
As much as I would want to push people away from the fbdev API (doesn't
support multimonitor, page flipping, cursor planes, etc.), it will be
supported in an emulation layer for new DRM-based devices. Mostly for fbcon,
but still supported.

[https://github.com/torvalds/linux/blob/master/drivers/gpu/dr...](https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/drm_fb_helper.c)

~~~
badsectoracula
Wouldn't removing it break the "never break the user space" promise Linux has?

~~~
lomnakkus
No. The "never break user space" thing (AFAIUI, at least) is about not
changing existing behavior. Removal of features is a different thing
altogether which usually only happens after _long_ deprecation periods or when
there's nobody around to support the code.

------
em3rgent0rdr
The frontpage mentions Wirth's Law: "software is getting slower more rapidly
than hardware becomes faster".
[https://en.wikipedia.org/wiki/Wirth%27s_law](https://en.wikipedia.org/wiki/Wirth%27s_law)

------
AceJohnny2
Tangential question from an embedded-but-not-Linux developer:

The structs use the types like ____u32 __or ____u16 __. I know the kernel
defines its own types for internal usage[1], but why redefine types exposed to
user-space? Why not use C99 <stdint.h> types?

Is it only historical?

And why are they double-underscore?

[1] because... reasons? I never really understood why

~~~
valarauca1
Generally speaking when you interface with a c library you should use the same
types it uses. So while you can like get by with `stdint.h`'s `uint64_t` on
_most_ platforms you hurt portability.

Example:

This is because `stdint.h` isn't 100% compatible with _every_ platform Linux
supports. This gets in hair brained definitions of pointers lengths on some
obscure platforms. For example SPARC64's `long`, `long long`, `void\ _`, and
`uint64_t` aren 't all the same size (`long long` is `uint64_t`, while void\_
and `long` are `uint32_t`, but in kernel land `void\\*` is `uint64_t`).

Just like C11 Atomics can fail on ARM and PPC under some scenarios so the
kernel doesn't use these as well.

Its my understand the Kernel supports more platforms then the C
standardization committee xD

\---

So the kernel likes to define its own primitives, and when you interface with
it its is generally best to just use those definitions. Or if you want to use
_standard_ types, you have to understand you are hurting portability.

~~~
AceJohnny2
Thanks for your explanation :)

One thing I still don't understand though:

> _This is because `stdint.h` isn 't 100% compatible with _every_ platform
> Linux supports. This gets in hair brained definitions of pointers lengths on
> some obscure platforms. For example SPARC64's `long`, `long long`, `void` ,
> and `uint64_t` aren't all the same size (`long long` is `uint64_t`, while
> void\ and `long` are `uint32_t`, but in kernel land `voidx` is `uint64_t`)._

In these cases, you just defined the variably-lengthed types (void* ) using
the fixed-length types (uint64_t). This would just demonstrate that the fixed-
length types are absolute, and IMO then good candidates to base absolute-sized
types on. And yet that's still not good enough?

A bit of googling brings up the book Linux Device Drivers 3rd Ed (2005)[1], in
which chap11 specifically addresses the topic of types. It argues against the
usage of standard C types (int, long, etc) specifically because of their size
variability. That's all well and good, but _it doesn 't make any mention of
stdint.h_!

A hypothesis comes up: maybe stdtint.h is meant to be a user-space header
exposed by the system/compiler, and the kernel, having to be entirely
bootstrapped, can't even depend on that? So it just redefines the types for
itself? With the side-effect of exposing those to userspace at the API?

[1] [https://lwn.net/Kernel/LDD3/](https://lwn.net/Kernel/LDD3/)

~~~
AceJohnny2
Ah, found the explanation:

 _The problem with that idea is that the kernel cannot count on those types
being consistently defined for all configurations, and cannot create its own
definitions for the standard types. So the kernel /user interface must
continue to be defined using kernel-specific types (__u16 and such)._

From: [https://lwn.net/Articles/113349/](https://lwn.net/Articles/113349/)

And as close to Word Of God as I can get:

[http://yarchive.net/comp/linux/int_types.html](http://yarchive.net/comp/linux/int_types.html)

------
unwttng
I notice there are no pictures

~~~
unwttng
Just how low level _are_ these graphics?

------
jdironman
Quiet a bit off topic, but this website is a joy to browse just for it's
simplicity, high visibility, and speed. Just good ole basic HTML & PHP pages
without a ton of overhead.

~~~
notamy
> high visibility

Really? I found it quite difficult to read due to the text color being too
close to the background color.

~~~
khedoros1
It's similar to my preferred terminal settings. Dark background, light grey
text, some brighter colors to highlight important things.

~~~
_ph_
For me, light fonts on dark backgrounds are very difficult to read, I quickly
get a lot of after images making reading the text very difficult. I was always
fine with green and amber monochrome screens back then - perhaps my eyes just
were much younger. I have not been able to find out what changed that for me,
unfortunately.

------
kodfodrasz
One would expect some images in a graphics tutorial...

