A desktop capture source for OBS on X11 + NVIDIA that keeps frames in VRAM instead of copying them across PCIe.
OBS's built-in XSHM display capture reads the framebuffer into CPU shared memory and re-uploads it to the GPU every frame. On a bandwidth-limited PCIe link this dominates GPU "utilization" — a 4K/60 capture measured 65% on a Gen3 x8 link, all of it bus transfer rather than compute.
texsub avoids the round trip:
XCopyAreablits the root window into an X Pixmap. On the NVIDIA proprietary driver both are VRAM-backed, so this stays on the GPU.gs_texture_create_from_pixmapbinds that pixmap as an OBS texture viaeglCreateImageKHR/EGL_NATIVE_PIXMAP_KHR— zero copy.
Same 4K/60 capture measured ~10% GPU after the switch.
- OBS 32.x (X11 EGL backend —
obs_get_nix_platform()must beX11_EGL) - NVIDIA proprietary driver
- libobs, libX11, libxcb, libXrandr, libXcomposite dev headers
Does not work under Wayland or on the XCB-only software path; it relies on the NVIDIA driver keeping pixmaps in video memory.
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr/local
cmake --build build
sudo cp build/obs-texsub.so /usr/local/lib/obs-plugins/
(On FreeBSD, OBS loads plugins from /usr/local/lib/obs-plugins/, not the
per-user ~/.config/obs-studio/plugins directory.)
Add a "Display Capture (TexSub)" source and pick a monitor. "All monitors" captures the full X screen.
- The texture is sampled raw (no sRGB decode). The pixmap-backed EGLImage is
GS_BGRA_UNORMwith no sRGB view, so requesting a decode washes the image out. The root window is depth 24, so the opaque effect fixes alpha at 1.0. - The pixmap lives on OBS's X connection (EGL needs the XID); a second
connection runs
XCopyAreaso it doesn't stall OBS's event loop. - Cost scales with captured pixel count but never crosses PCIe, so it's flat with respect to link width/generation.
Early. Known gaps: cursor is not yet composited, capture region doesn't track monitor hotplug/resolution changes, no damage tracking (blits every tick).