# libdrmtap-sys
Raw FFI bindings for [libdrmtap](https://github.com/fxd0h/libdrmtap) — a C library for capturing Linux screen framebuffers via DRM/KMS.
## What is libdrmtap?
libdrmtap captures screen contents at the kernel level using DRM/KMS APIs. Unlike PipeWire/portal-based capture, it works:
- **At the login screen** (GDM, SDDM, LightDM)
- **Without user interaction** (no "Select screen to share" prompt)
- **On Wayland** (bypasses the compositor security model)
- **Headless** (no display server needed)
## ⚠️ Testing Status
> **Verified here:** Intel Meteor Lake-P (`i915`, multiple displays up to
> 3840x2160, EGL detiling of the tiled/compressed framebuffer), AMD RX560
> (Polaris/gfx8, tiled `XR30`), NVIDIA Jetson Orin Nano (`nvidia-drm`, aarch64,
> Wayland), and `virtio_gpu` (QEMU/Parallels VMs).
>
> **Confirmed by outside testers, on their hardware:** AMD RX Vega 64 (gfx9, X11)
> by GK-Gaming, and Intel Raptor Lake with a hybrid NVIDIA GPU (Ubuntu 26.04,
> GNOME Wayland) by huzhifeng. One host each, not a support matrix.
>
> All of it depends on the EGL detile backend, which this crate always compiles
> in (`build.rs` defines `HAVE_EGL`). It therefore needs the EGL and GLES2
> headers at build time — `libegl-dev` and `libgles2-mesa-dev` on Debian/Ubuntu —
> and `cargo build` fails outright without them rather than producing a
> CPU-only library. `-Degl=enabled` is the equivalent for a Meson build of the C
> library and does not apply here.
>
> If you test other configurations, please report results via
> [GitHub Issues](https://github.com/fxd0h/libdrmtap/issues).
## Requirements
- Linux with DRM/KMS support (kernel 4.20+ for the tiled/modifier framebuffer
path, i.e. Ubuntu 20.04+; linear/VM framebuffers work on older kernels)
- A C compiler — the embedded C sources are compiled statically at build time.
There is **no** system `libdrmtap` install, `meson install`, or `pkg-config`
lookup of a shared library.
- `libdrm` development headers (located via `pkg-config`), plus the EGL and
OpenGL ES 2 headers, plus libseccomp and libcap and their `-dev` headers — the
crate links libdrm, libseccomp and libcap. libEGL and libGLESv2 are never
linked: they are `dlopen`ed lazily as `libEGL.so.1` and `libGLESv2.so.2`, so
the headers are a build requirement and those two shared libraries are a
RUNTIME requirement on the target (`libegl1` and `libgles2` on Debian/Ubuntu).
Without them the EGL detile is unavailable and only the CPU paths remain,
which do not cover every scanout.
The build also compiles the privileged `drmtap-helper` binary from the same
embedded sources, with exploit-mitigation hardening (stack-protector-strong,
FORTIFY, PIE, full RELRO). Its path is exported to downstream build scripts as
`DEP_DRMTAP_HELPER_BIN` so a consumer (e.g. RustDesk) can copy and `setcap` it.
The library captures directly when it already has DRM master / `CAP_SYS_ADMIN`;
otherwise it spawns the helper over a socketpair to read other clients'
framebuffers, returning the scanout as a zero-copy DMA-BUF fd via `SCM_RIGHTS`.
## Pixel output
Frames are returned as 8-bit `XRGB8888` (BGRA in memory). Tiled and compressed
framebuffers (Intel X/Y-tiled + CCS, AMD, Nvidia block-linear, virtio/virgl) are
GPU-detiled through an EGL/GLES2 backend, and **HDR10** scanouts (PQ / BT.2020 —
`AR30`/`XR30` and 16-bit `XR48`/`AR48`/`XB48`/`AB48`) are tone-mapped to SDR when
the connector advertises HDR (`HDR_OUTPUT_METADATA`): PQ decode, BT.2020 → BT.709
gamut, a highlight-preserving curve, then sRGB. Plain SDR 10-bit gets a straight
bit-depth reduction; HLG falls back to that reduction and `P010` (overlay-video
YUV) is not handled.
## Usage
This is a `-sys` crate with raw FFI bindings. For a safe wrapper, use [`libdrmtap`](https://crates.io/crates/libdrmtap).
```rust
use libdrmtap_sys::*;
use std::ptr;
unsafe {
let ctx = drmtap_open(ptr::null());
if !ctx.is_null() {
let driver = drmtap_gpu_driver(ctx);
// ... capture frames ...
drmtap_close(ctx);
}
}
```
## License
MIT