Thoughts on Linux System Compositors

My work towards deprecating CONFIG_VT recently got stuck due to several kernel changes that are needed to proceed. DRM Render-nodes and Modeset-nodes are on their way and so I thought I’d provide a short update on what is being planned regarding session management in user-space.

This is no technical discussion or comparison between VTs and other session managers. Instead, I try to describe how we intend to proceed and why we need a new kind of user-space session manager. For technical details, feel free to browse through other articles in this blog or join the discussions on systemd-devel, wayland-devel and dri-devel MLs.

Virtual Terminals

While legacy systems with CONFIG_VT will always be supported, the current trend is towards a system without VTs. VTs are controversially discussed, but the major flaw of VTs is that they’re only available on the default seat. So if you’re a big fan of VTs, consider this whole article being about seats other than seat0, that is, no VTs are available! If you’re not so a big fan of VTs, join my dream of a world without VTs (and without fbcon, hurray!).

Systemd

With Ubuntu (and upstart) considering to emulate systemd-logind, it is becoming clear that the systemd-logind API is getting the de-facto standard for seat and session management on desktop linux systems. I don’t care what people think of systemd; for the purpose of this article I will call the session manager logind, feel free to replace it by your favorite seat/session manager.

Non-desktop systems are beyond the scope of this document. However, as long as you have a monitor+keyboard connected to your system, your setup is targeted by this article.

#1: The Problem

Most of the time, on a common linux desktop system, we interact with our favorite Desktop Environment; lets choose Gnome for today. Gnome manages the different screens, applications and tasks that we want to run. We can switch between them, stop them or start them. This is all managed inside a single Gnome-User-Session. The need for multiple sessions (and thus, multiple VTs) is barely noticeable to us. And that fact is very important! Whatever we do to extend session management, the single user session should still be the central part of the design. We must not make it, in any way slower, less stable, or harder to implement. Instead, we design our system around it.

So lets broaden our perspective and look at all the systems running in parallel to the user session: There is the boot-splash, linux-console, emergency-console, sleeping user-sessions, lock-screens, ssh-sessions, custom parallel Wayland/X11 sessions and probably a lot of crazy user-setups I am not even aware of. It is hard to work with such a diverse and moving target, however, they always have something in common: Only one desktop session is active at a time!

But which one?

#2: logind to the rescue

Layout and drawbacks of the VT Session Manager

It is pretty obvious that we need an IPC mechanism to notify the different sessions about who is active and when to switch between them. Historically, VTs provided a decentralized way by letting each session open a different VT and making the active VT responsible of session-management. To be fair, there is support for automatic session-switching, but most sessions take control over input devices and thus need to schedule session switches themselves. Major flaw is that if the active session deadlocks, your system becomes unresponsive. While the VT system has several other drawbacks, discussion is beyond the scope of this document as we always have the situation where we don’t have VTs (think: seats other than seat0).

Advanced access control with FD passing via systemd-logind

Without VTs, we are currently left with only a single session per seat. Pretty boring! And that’s probably also what the desktop group at RedHat thought. A broadly discussed idea from several RedHat developers is to extend logind to arbitrate between the different sessions (Note: this article is about my perception, but the idea of using logind was originally not from me). logind already knows about all sessions on a system, knows about all seats and is the perfect place to implement session management. So instead of opening a VT, sessions now use dbus to tell logind that they provide a new user session. The API hasn’t been figured out, yet, but the big advantage over VTs is that we can pass file-descriptors directly to each session. logind can mute input-devices (patches pending on linux-input ML) for inactive sessions and can revoke DRM access. It guarantees that the active session has exclusive hardware access even if a session dead-locks.

Left for discussion is the design of the logind dbus API. It will include a set of calls to register, activate, deactivate and unregister sessions. Due to the fact that we have control over hardware resources, we can also implement forced session switching. Moreover, we could make logind listen to magic sysrq keys which deactivates the current session and instead activates the emergency console.

#3: Limitations

logind is no system compositor. logind will never be a system compositor. In fact, if logind becomes the central session manager, the concept of a system compositor will be dead and buried. The problem is, a session manager requires exclusive access over any sessions and hardware. Same is true for a system-compositor. Both concepts don’t play nice together. But what are the benefits of a system-compositor over logind?

While anything a system-compositor can do, could theoretically be implemented in logind, we assume that logind is supposed to stay small and efficient. So logind will never provide any DRM display handling. All sessions must implement it themselves. Same holds true for input handling. logind can only provide FD forwarding, but the heavy lifting must be done directly in each session program. In every small session program! The boot-splash must include complex DRM and XKB code, the screen-lock, too. Even the emergency console has to do all the low-level hardware handling. This introduces complexity and, very likely, bugs. But on the other hand, it guarantees efficiency. An xserver can run with direct hardware access and no extra context-switch to logind is needed on every frame.

But DRM handling could be simplified via a shared library for every session that doesn’t need custom 3D acceleration. So what else do we abandon for the sake of simplicity?

Probably the most hurtful is that global keyboard management is impossible. We cannot make logind listen for keyboard events (other than real emergency shortcuts) at the same time as a session is active. Otherwise, we might end up with logind and the session reacting to a single shortcut, which is unacceptable in any non-emergency situation. So session-switching will be left to the active-session itself. But if the active session dead-locks, we have the same problem as with VTs: an unresponsive system

We can implement emergency-shortcuts which violate this rule, but it will never be a clean solution. Moreover, we will never be able to have global Volume-Up and Volume-Down shortcut handling, no Brightness-keys, no global NumLock handling. Global keyboard handling will be reliant on policies, if implemented at all, and otherwise left to each session to implement.

#4: Quirks

Layout of different quirks working with logind session manager

Upgrading logind to a session-manager has advantages on its own. Most of the code is already available, no external manager is needed, which would have to synchronize with logind. We have direct hardware access in each session and, as mentioned earlier, sessions are self-hosting. A session itself doesn’t need any major modifications to run under this scenario. A session controls itself over the whole runtime and, more importantly, doesn’t depend on another daemon to function properly. Yes, session-management depends on logind, but the session itself, once activated, runs standalone.

To overcome the issues mentioned above, I developed a set of quirks that sit between logind and a session:

UVTD

uvtd (User-Space Virtual-Terminal Daemon) is an implementation of VTs in user-space. It is available as experimental branch in the official kmscon repository. Even if you disable kernel VTs, uvtd can provide legacy VT nodes for backwards compatibility. But in contrast to kernel VTs, uvtd can control the “server side” of each VT and provide a bridge between a fake VT and logind. This allows to run legacy VT applications even if no VTs are available. The current code already allows to run multiple xservers in parallel without any real VT and without modifying a single xserver line of code.

wlsystemc

wlsystemc (Wayland System Compositor) is another research project I was working on. It is a Wayland compositor that displays each client as fullscreen surface. Due to the fast moving Wayland codebase it got slightly out of date during the last year, but it was once working with basic SHM buffers. Anyhow, together with logind, wlsystemc can be redesigned to take over modesetting for basic sessions. For instance, a boot-splash would create a surface in wlsystemc, which itself registers a session in logind for this surface. Once the session gets activated, wlsystemc performs all the heavy DRM operations and the boot-splash does nothing more than simple generic Wayland rendering (i.e., passing custom buffer).

Kernel Log

“No VTs, no kernel log!”. But especially developers want a kernel oops or panic printed on screen whenever they occur. The solution is fblog or drmlog, a kernel module, that does nothing else than printing the kernel log to all connected monitors. logind can register it like any other session and enable or disable it via sysfs. During oops/panic the kernel will activate them automatically and notify logind asynchronously via sysfs. Both modules are still under development, but at least fblog is already working.

Linux Console

For completeness: kmscon can easily replace the linux-console in this setup. It will register a text-console as a normal session just like any other session does.

#5: Conclusion

While I was an enthusiastic advocate of the system-compositor idea, it did become pretty clear, that the performance penalty for input-event forwarding and the huge required kernel API extensions make it very unlikely that it will get accepted in the community. Furthermore, besides global keyboard handling, most technical concerns on the logind idea can be solved with quirks like wlsystemc and uvtd.

This post didn’t discuss or highlight the low-level technical concerns on kernel VTs, but I hope it explains why we get a lot more flexibility and possibilities by moving session handling into user-space. logind can be taught boot-splash awareness, emergency-handling or forced session-switching, which will be very unlikely to get implemented in kernel VTs.

But independent of how we implement it, moving VT handling to userspace and disabling CONFIG_VT still has one major advantage: it simplifies kernel programming a lot. And I know, nearly every DRM developer would be very happy to see this happen!

DRM Render- and Modeset-Nodes

Another year, another Google Summer of Code. This time I got the chance to work on something that I had on my TODO list for quite a long time: DRM Render- and Modeset-Nodes

As part of the X.org Foundation mentoring organization, I will try to pick up the work from Ilija HadzicDave AirlieKristian HoegsbergMartin Peres and others. The idea is to extend the DRM user-space API of the linux kernel to split modeset and rendering interfaces apart. The main usage is to allow different access-modes for graphics-compositors (which require the modeset API) and client-side rendering or GPGPU-users (which both require the rendering API). We currently use the DRM-Master interface to restrict the modeset API to privileged applications. However, this requires SYS_CAP_ADMIN privileges, which is roughly equivalent to root-privileges. With two different interfaces for modeset and rendering APIs, we can apply a different set of filesystem-access-modes to each of them and thus get fine-grained access-control.

Apart from fine-grained access control, we also get some other nice features almost for free:

  • We will be able to run GPGPU clients without any running compositor or event without any display controller
  • We can split modeset objects across multiple nodes to allow multi-seat setups with a single display controller
  • Efficient compositor-stacking by granting page-flip access or full modeset access temporarily to sub-compositors

There are actually a lot of other ideas how to extend this. So I decided to concentrate on the modeset-node / render-node split first. Once that is done (and fully working), I will pick different ideas that depend on this and try to implement them. Considering the lot of work others have put in this already, I think if I get the split merged into mainline, the project will already be a great success. Everything on top of it will be some bonus that will probably take more time to get merged. But lets see, maybe it turns out to be easier than I think and we end up with some of the use-cases merged upstream, too.

Thanks to the X.org Foundation, Google and my GSoC-mentor Dave Airlie for giving me the chance to work on the DRM API! I hope it will be a productive summer.

GSoC-Proposal

If someone is interested in more details, some excerpts from my original GSoC proposal:

Project Description:
Since several years xserver is no longer the only user-space project that makes
use of the kernel DRM API. The introduction of KMS allowed many new projects to
emerge, including plymouth, weston and kmscon. On the other side, OpenCL support
allows applications to make use of DRM without requiring any KMS APIs. Even though
both use-cases work with the current APIs, there are a lot of restrictions that
need to be worked around.

The most problematic concept is DRM-Master. KMS applications are required to be
DRM-Master to perform modesetting, but DRM-Master is tightly coupled to
CAP_SYS_ADMIN/root. On the other side, render clients are required to be assigned
to a DRM-Master so they can get authenticated. This prevents off-screen/offline
rendering without a running compositor.

One possible solution is to split render- and modeset-nodes apart. The DRM control
node can be used as the management node (which is, as far as I understand, what
it was designed for, anyway). A separate static render-node is created for each
DRM device which is restricted to ioctls specific to rendering operations. Instead
of requiring drmAuth() for authorization, we can now use filesystem access-modes.
This allows slightly more dynamic access-control, but the biggest advantage is
that we can do off-screen/offline rendering without a running
compositor/DRM-Master.

On the other side, a modeset-node is a concept to have KMS separated from DRM.
The use-case is to split modeset objects (eg., crtcs, encoders, connectors) across
different modesetting applications. This allows one compositor to use one
CRTC+connector combination, while another compositor (maybe on another seat) can
use another CRTC+external-connector. This doesn't have to be a static setup. On
the contrary, one use-case I am very interested in is a dynamic modeset-object
assignment to temporary clients. This way, a fullscreen application can be granted
page-flip rights from the compositor to avoid context-switches to the compositor
for doing trivial page-flips only.

Deliverables
* Working render-node clients: Preferably an offline OpenCL example and
  a wayland EGL client
* Merged kernel render-node implementation with at least i915 support
* Dynamic kernel modeset-nodes
* "Zero-context-switches" wayland/weston fullscreen client (optional)

Known Problems:
There were several attempts to push render-nodes into the kernel, but all failed
due to missing motivation to finish the user-space clients. Writing up new fancy
APIs is one part, but pushing API changes to such big projects requires the whole
environment to work well with the changes. That's why I want to concentrate on
the user-space side of render-nodes. And I want to finish the render-nodes project
before continuing with modeset-nodes. The idea has been around long enough that
it's time that we get it done.

However, one problem is that I never worked with the low-level X11 stack. The
wayland environment is great for experiments and quite active. I am very familiar
with it and know how to get examples easily running. The xserver, however, is a
huge black box to me. I know the concepts and understand the input and graphics
drivers design. But I never read xserver core code. That's something I'd like to
change during this project. I will probably be limited to DRI and graphics
drivers, but that's a good start.

Another idea that came up quite often is something like gem-fs. It's far beyond
the scope of this project, but it's something I'd like to keep in mind when
designing the API. It's hard to account for something that's only an idea, but
the concepts seem related so I will try to understand the reasons behind gem-fs
and avoid orthogonal implementations.

A few smaller implementation-specific problems are already known, including the
mmap-security problem, static "possible_encoders"/"possible_crtcs" bitsets and
missing MMUs on GPUs. However, there already have been ideas how to solve them
so I don't consider them blockers for render-nodes.

Linux Wii Remote Driver Updates

Linux Bluetooth HID handling has been slightly broken in the kernel since several years. Reconnecting devices caused a kernel oops nearly every time you tried. Two months ago I sat down and rewrote the HIDP session handling and fixed several bugs. The series now got merged and will be part of linux-3.10. If you still encounter bugs please leave me a note.

Based on this I tried recovering my hid-wiimote work. Since the last time I reverse-engineered Nintendo devices, a lot has happened. The most significant change is probably the release of the Wii U. While the Gamepad is still an ongoing target for r/e, other devices were much easier to get working. Motivated by the new hardware I just got, I finally figured out a reliable way for extension hotplugging. This wasn’t supported in the kernel until now and required nasty polling-techniques to work around race-conditions in the proprietary protocol (who designs asynchronous protocols without protocol barriers?). So I rewrote most of the core device handling and moved the input parsers to a module based infrastructure. This allows us to easily extend the hid-wiimote driver to support new devices that are based on the same protocol.

The series is still pending on the linux-input ML but I hope to get basic hotplugging support into linux-3.10. Further support for the built-in speaker device or the Wii U Pro Controller will hopefully follow with 3.11.

The xwiimote user-space stack has already been updated and I will push the changes this weekend.

Wii U Gamepad Connection

I’ve been playing with the Wii-U Gamepad lately and am trying to figure out how it connects to the Wii U console. Once we get that working, we can start reverse-engineering the protocol and write a linux driver for it. It would make a great remote display for every linux box. So how does it work?

The communication between Wii-U and GamePad is done via 5Ghz Wi-Fi. It uses the range 5150-5250 Mhz (Sony UWA-BR100 is a nice dual-band ath9_htc USB dongle with perfect linux support). The console opens a soft AP without any encryption. SSID is set similar to “WiiU34af2c5fa6134af2c5fa61c_STA1”. The GamePad connects to this AP and then creates some private link. I haven’t figured out how this works, yet.

The IE fields do not advertise any Wifi-Direct (P2P), Wifi-Display (WFD) or Direct-Link (TDLS) features. The only features found are WMM QoS fields.

How to proceed? I need to figure out how to create a soft-AP with the advertised features so I can make the GamePad connect to me. Two Nintendo extensions are advertised “OUI a4:c0:e1” which probably identify the AP. The other vendor IEs are Broadcom/EPIGRAM IDs which can also be found on other networks. After that, I need to test P2P discovery, TDLS discovery or 802.11e DLS setup to find out what kind of direct-link Nintendo uses. According to Broadcom’s Dino Bekis a form a Miracast is used which would mandate P2P or TDLS.

If anyone has more information on that, I’d be very thankful!

Btw., dhcp is provided on the unprotected soft-AP and I can ping the console but my port-scans didn’t return any useful information. I will try connecting to WFD/RTSP default port 7236 next…

 

Soft-AP during Synchronization:

BSS 34:af:2c:5f:a6:1c (on wlan1)
	TSF: 3126337 usec (0d, 00:00:03)
	freq: 5180
	beacon interval: 100
	capability: ESS (0x0001)
	signal: -55.00 dBm
	last seen: 3208 ms ago
	Information elements from Probe Response frame:
	SSID: WiiU34af2c5fa6134af2c5fa61c_STA1
	Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0 
	HT capabilities:
		Capabilities: 0x1c
			HT20
			SM Power Save disabled
			RX Greenfield
			No RX STBC
			Max AMSDU length: 3839 bytes
			No DSSS/CCK HT40
		Maximum RX AMPDU length 16383 bytes (exponent: 0x001)
		Minimum RX AMPDU time spacing: 8 usec (0x06)
		HT RX MCS rate indexes supported: 0-15
		HT TX MCS rate indexes are undefined
	HT operation:
		 * primary channel: 36
		 * secondary channel offset: no secondary
		 * STA channel width: 20 MHz
		 * RIFS: 1
		 * HT protection: no
		 * non-GF present: 0
		 * OBSS non-GF present: 0
		 * dual beacon: 0
		 * dual CTS protection: 0
		 * STBC beacon: 0
		 * L-SIG TXOP Prot: 0
		 * PCO active: 0
		 * PCO phase: 0
	Vendor specific: OUI a4:c0:e1, data: f5 00
	Vendor specific: OUI a4:c0:e1, data: f4 10 4a 00 01 10 10 44 00 01 02 10 41 00 01 01 10 12 00 02 00 00 10 53 00 02 00 84 10 3b 00 01 03 10 47 00 10 22 21 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 21 00 08 42 72 6f 61 64 63 6f 6d 10 23 00 06 53 6f 66 74 41 50 10 24 00 01 30 10 42 00 01 30 10 54 00 08 00 06 a4 c0 e1 f4 00 01 10 11 00 10 57 69 69 55 33 34 61 66 32 63 35 66 61 36 31 63 10 08 00 02 00 84
	Vendor specific: OUI 00:10:18, data: 02 00 00 04 00 00
	WMM:	 * Parameter version 1
		 * u-APSD
		 * BE: CW 15-31, AIFSN 2, TXOP 1504 usec
		 * BK: CW 15-1023, AIFSN 7
		 * VI: CW 15-31, AIFSN 3, TXOP 3008 usec
		 * VO: CW 15-31, AIFSN 3, TXOP 1504 usec

Soft-AP during normal operation with GamePad:

BSS 34:af:2c:5f:a6:1c (on wlan1)
	TSF: 413388858 usec (0d, 00:06:53)
	freq: 5180
	beacon interval: 100
	capability: ESS Privacy (0x0011)
	signal: -48.00 dBm
	last seen: 3201 ms ago
	Information elements from Probe Response frame:
	SSID: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
	Supported rates: 6.0* 9.0 12.0* 18.0 24.0* 36.0 48.0 54.0 
	TIM: DTIM Count 1 DTIM Period 3 Bitmap Control 0x0 Bitmap[0] 0x0
	RSN:	 * Version: 1
		 * Group cipher: a4-c0-e1:4
		 * Pairwise ciphers: a4-c0-e1:4
		 * Authentication suites: a4-c0-e1:2
		 * Capabilities: 4-PTKSA-RC (0x0008)
	HT capabilities:
		Capabilities: 0x1c
			HT20
			SM Power Save disabled
			RX Greenfield
			No RX STBC
			Max AMSDU length: 3839 bytes
			No DSSS/CCK HT40
		Maximum RX AMPDU length 16383 bytes (exponent: 0x001)
		Minimum RX AMPDU time spacing: 8 usec (0x06)
		HT RX MCS rate indexes supported: 0-15
		HT TX MCS rate indexes are undefined
	HT operation:
		 * primary channel: 36
		 * secondary channel offset: no secondary
		 * STA channel width: 20 MHz
		 * RIFS: 1
		 * HT protection: no
		 * non-GF present: 1
		 * OBSS non-GF present: 0
		 * dual beacon: 0
		 * dual CTS protection: 0
		 * STBC beacon: 0
		 * L-SIG TXOP Prot: 0
		 * PCO active: 0
		 * PCO phase: 0
	Vendor specific: OUI 00:90:4c, data: 07 00 45 55 17
	Vendor specific: OUI 00:10:18, data: 02 01 00 04 00 00
	WMM:	 * Parameter version 1
		 * u-APSD
		 * BE: CW 15-31, AIFSN 2, TXOP 1504 usec
		 * BK: CW 15-1023, AIFSN 7
		 * VI: CW 15-31, AIFSN 3, TXOP 3008 usec
		 * VO: CW 15-31, AIFSN 3, TXOP 1504 usec

Linking binary data

Took me half a weak to figure this out, but here is a quick description how to link your binary data into a library/executable:

We want this to:

  • work with GNU-ld
  • work with GNU-gold
  • work with GNU-libtool (if required)
  • work with cross-compiling
  • work with LLVM
  • not require any external non-standard tools

For now lets assume we have a file src/mydata.bin that contains your binary data that you want to link into your executable as a huge C-array.

With GNU-autotools

If you use GNU-autotools, add the following rule to your Makefile.am:

CLEANFILES += src/*.bin.lo src/*.bin.o

src/%.bin.lo: src/%.bin
     $(AM_V_GEN)$(LD) -r -o "src/$*.bin.o" -z noexecstack --format=binary "$<"
     $(AM_V_at)$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "src/$*.bin.o
     $(AM_V_at)echo "# $@ - a libtool object file" >"$@"
     $(AM_V_at)echo "# Generated by $(shell $(LIBTOOL) --version | head -n 1)" >>"$@"
     $(AM_V_at)echo "#" >>"$@"
     $(AM_V_at)echo "# Please DO NOT delete this file!" >>"$@"
     $(AM_V_at)echo "# It is necessary for linking the library." >>"$@"
     $(AM_V_at)echo >>"$@"
     $(AM_V_at)echo "# Name of the PIC object." >>"$@"
     $(AM_V_at)echo "pic_object='$*.bin.o'" >>"$@"
     $(AM_V_at)echo >>"$@"
     $(AM_V_at)echo "# Name of the non-PIC object" >>"$@"
     $(AM_V_at)echo "non_pic_object='$*.bin.o'" >>"$@"
     $(AM_V_at)echo >>"$@"

Now you can simply use src/mydata.bin.lo as libtool-object file in any _LIBADD automake variable. This rule causes $(LD) to link the binary into the object file src/mydata.bin.o (via partial-linking/relocatables). After that we create the corresponding libtool object file src/mydata.bin.lo. Note that the comments in the libtool file are mandatory. You must not remove them!

The objcopy line causes the .data section to be renamed to .rodata and marked as read-only. You can drop it if you require write access.

Without GNU-autotools

Obviously, this is much easier. You can simply use:

$(LD) -r -o "src/mydata.bin.o" -z noexecstack --format=binary "src/mydata.bin"
$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "src/mydata.bin.o"

This produces src/mydata.bin.o which you can then link like any other object.

That’s already it!

You can now access the binary data via:

extern const char _binary_<path>_start[];
extern const char _binary_<path>_end[];

In our case this would be:

extern const char _binary_src_mydata_bin_start[];
extern const char _binary_src_mydata_bin_end[];

The linker automatically creates these symbols. It also creates *_size symbols but I never had to use these. The linker also alignes the start address correctly, but the content isn’t touched, of course.

The data is placed in .data by default and marked as read/write. The objcopy command renames it to .rodata and marks it as read-only. Drop it if you require write access.

If you think you know another way to do this, please let me know! I have tried lots of other ways and they all fail in some subtle way:

  • Converting it into a C-source file with a static array. Problem: It works but the C-compiler might take considerably longer to compile the sources. On my machine a 2MB array file took >10min to compile.
  • Using objcopy to convert binary files into object files. Problem: This requires the target architecture as -B command. Unfortunately, it has some weird format and doesn’t accept the standard GNU $host_cpu kind of strings. For instance it requires i386:x86-64 instead of x86_64. I haven’t found a way to get these BFD strings reliably via autoconf.
  • Use objcopy without -B to produce architecture=UNKNOWN object files and link via –accept-unknown-input-arch with GNU-ldProblem: This doesn’t work with GNU-gold as it doesn’t support this command-line option.
  • Avoid partial-linking and add this to your LDFLAGS: -Wl,--format=binary -Wl,src/mydata.bin -Wl,--format=default Problem: This marks the file as requiring an executable-stack. You can fix this with -Wl,-z,noexecstack but that forces all other linked files to also not require an executable stack. And also, GNU-gold doesn’t support --format=default, it requires --format=elf which itself isn’t supported by GNU-ld. Hilarious, right?

I also got some other hints to use GNU-as or other nice workarounds. However, I wanted a solution that uses the tools that were created for that task. I mean, why should I create an assembler or C source file to link binary data? Seriously, the only reason to do this is to work around crappy binutils interfaces. I want ld and objcopy to do the task and if they can’t, then we should fix them!

Advanced DRM Mode-Setting API

I recently wrote a short How-To that introduces the linux DRM Mode-Setting API. It didn’t use any advanced techniques but I got several responses that it is a great introduction if you want to get started with linux DRM Mode-Setting. So I decided to go further and extend the examples to use double-buffering and vsync’ed page-flips.

The first extension that I wrote can be found here:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-double-buffered.c

It extends the old example to use two buffers so we no longer render into the front-buffer. It reduces a lot of tearing that you get when using the single-buffered example. However, it is still not perfect as you might swap the front and back buffer during a scanout-period and the display-controller will use the new buffer in the middle of the screen. So I extended this further to do the page-flip during a vertical-blank period using drmModePageFlip(). You can find this example here:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c

This example also shows how to wait for page-flip events and integrate it into any select(), poll() or epoll based event-loop. Everything regarding page-flip-timing beyond that point depends on the use-cases and can get very hard to get right. I recommend reading Owen Taylor’s posts #1 and #2 on frame-timing for compositors.

There are still many more things like “DRM hardware-accelerated rendering”, “DRM planes/overlays/sprites”, “DRM flink/dmabuf buffer-passing” that I want to write How-Tos for. But time is short around Christmas so that’ll have to wait until next year.

Feedback is always welcome and you can find my email address in all the examples. Happy reading!