TacidOS
Developers
Documentation

Decision 0088

0088. The face renders through wgpu, because that is what carries an alpha channel

Architecture decision record 0088: 0088. The face renders through wgpu, because that is what carries an alpha channel

Status
accepted
Date
2026-09-10

Status: accepted. Supersedes ADR-0087, whose decision was right on what it knew and wrong within the hour, and amends the renderer clause of ADR-0047.

Context

ADR-0087 accepted that tacid-shell cannot be translucent, because tiny-skia reaches Wayland through softbuffer, whose every buffer is wl_shm::Format::Xrgb8888 — no alpha channel, hardcoded. That is true and remains true. What the record got wrong is the conclusion, and it named its own three reasons for not switching to wgpu. Each was checked afterwards and each failed.

“No face on the boot where the driver is broken.” This is ADR-0047’s strongest argument and it does not apply to the shell. Hyprland renders through aquamarine, which has no software renderer; a machine that cannot give this shell a graphics device cannot give it a compositor either. What a person gets on that machine is a tty and the terminal interface — already true, already documented, already the reason ADR-0020 puts the TUI first. Requiring a device for the shell costs nothing that is not already gone.

“Not verifiable here.” Mesa ships lavapipe, a Vulkan implementation that runs on the processor: one ICD path in the environment and checks.*.face has a device on any machine, with no card. The glass became a measurement instead of a claim in the same afternoon the objection was written.

“Let the compositor do it instead.” Hyprland 0.56.2 has no layerrule opacity — asked of its own parser, which answers config option <layerrule:opacity> does not exist. A layer surface’s alpha is the client’s to supply or nobody’s.

And the thing that decided it: iced_wgpu asks its surface for PostMultiplied, then PreMultiplied, and settles for Auto only if it can have neither. It is trying to carry alpha. The software path was never going to.

Decision

tacid-shell renders through wgpu, and through nothing else. ALPHA_SURVIVES in theme.rs is now true, and the three things that followed from it being false are reversed: surfaces draw at the tokens’ glass.opacity, the window paints nothing so the compositor sees what no container covered, and the command box hugs its content because what is left over is the desktop.

No fallback renderer, deliberately. A shell built with both would pick tiny-skia on a machine with no device and not say so, and a shell that cannot know which renderer it got cannot know whether its own alpha means anything — which is the failure this pair of records is about, arriving a second time by a different road. With one renderer the question does not exist.

The check measures the composite arithmetically. Not a threshold: a * surface + (1 - a) * ground, both read out of the theme the machine generates, against the pixel on the screen. Two guards make it mean something. The desktop behind is the palette’s accent, because the terminals’ own background is seven levels from surface and fourteen percent of that is under the noise — an opaque sheet photographed over one of them satisfied every threshold this check had. And the band is asserted to be able to tell glass from opaque before it is asked which one it sees.

Consequences

The face is glass: rounded, translucent, with the compositor’s blur behind it and the same material in the notification daemon’s surfaces. The screenshot shows a terminal through the sheet of keys and the desktop through its corners.

The shell will not start where there is no Vulkan or GLES device. On a machine with a compositor that cannot happen; where it can, the machine has no compositor either.

Several hundred crates enter the shell’s lock file. They enter nowhere else: the shell has been its own workspace since ADR-0047 and the daemons neither build nor link it.

tacid-shell now needs the Vulkan loader on its rpath. The loader is a stub that finds the machine’s driver at run time, so this adds a small library and no graphics stack to the closure.

Blending is in the encoded values and not in linear light, which is written down because it was measured rather than reasoned: predicting the composite in linear light was out by thirty-seven levels over a bright ground.

Alternatives rejected

Keep ADR-0087. It is a record that says the design cannot have what the design asks for, on three grounds none of which survived being checked. Leaving it accepted would make every later reader inherit the same three.

Both renderers, choosing at run time. iced does not say which one it selected, so the choice would have to be inferred — by probing for an adapter before starting, which answers a slightly different question than the one that matters. A guess about one’s own renderer is how this started.

Draw opaque and let the compositor blend the layer. There is no such rule in this compositor.

A wallpaper for the check that is not the accent. Nothing else in the palette is far enough from surface for fourteen percent of the difference to clear the noise. The green looks like a fixture because it is one.