pipewire: Add transparent background support for overlay composition

This patch enables transparent background rendering in the PipeWire backend,
allowing Weston compositor output to be used as a transparent overlay layer
in external composition pipelines.

Use case:
In embedded systems (drones, medical devices, industrial HMI), it is common
to overlay UI elements (telemetry, alerts, controls) on top of live video
feeds. This patch enables any Wayland-native UI toolkit (Qt, GTK, LVGL) to
render as a transparent OSD that can be composited with video streams using
GStreamer or similar frameworks, while maintaining full GPU acceleration and
zero-copy transfers via DMA-BUF.

Implementation:
- frontend/main.c: Force ARGB8888 pixel format when transparent-background
  option is enabled, ensuring alpha channel preservation
- kiosk-shell: Parse alpha component from background-color and skip curtain
  creation when fully transparent (alpha=0)
- backend-pipewire: Add DRM_FORMAT_ARGB8888 to SPA_VIDEO_FORMAT_BGRA mapping
  to properly expose alpha channel to PipeWire consumers

Configuration example (weston.ini):
  [shell]
  background-color=0x00000000

  [output]
  name=pipewire
  transparent-background=true

Usage example:
  # Run UI application through Weston PipeWire backend
  weston --backend=pipewire --shell=kiosk-shell.so -- ui-osd-qt6

  # Compose with video stream in GStreamer
  gst-launch-1.0 compositor name=comp ! videoconvert ! waylandsink \
    v4l2src device=/dev/video0 ! comp.sink_0 \
    pipewiresrc path=55 ! video/x-raw,format=BGRA ! comp.sink_1

Benefits:
- Process isolation: UI crashes don't affect video pipeline
- Toolkit flexibility: Use any Wayland-compatible UI framework
- GPU acceleration: Full hardware compositing and encoding support
- Zero-copy: DMA-BUF sharing throughout the pipeline
- Routing flexibility: PipeWire allows dynamic stream routing

The patch is minimal, backward-compatible (opt-in via configuration), and
follows existing Weston patterns for output configuration.

Tested on: Debian 13, Qt 6.8.2, GStreamer 1.28.0

Signed-off-by: Paul GOULPIÉ <paul.goulpie@smile.fr>
This commit is contained in:
Paul GOULPIÉ 2026-02-08 16:40:46 +01:00
parent d16955a873
commit 3607e3567d
3 changed files with 16 additions and 1 deletions

View file

@ -4402,6 +4402,7 @@ pipewire_backend_output_configure(struct weston_output *output)
struct weston_config *wc = wet_get_config(output->compositor);
struct weston_config_section *section;
char *gbm_format = NULL;
bool transparent_background = false;
int width;
int height;
int framerate = -1;
@ -4419,6 +4420,13 @@ pipewire_backend_output_configure(struct weston_output *output)
parsed_options);
weston_config_section_get_string(section, "gbm-format", &gbm_format, NULL);
weston_config_section_get_bool(section, "transparent-background",
&transparent_background, false);
if (transparent_background) {
free(gbm_format);
gbm_format = strdup("argb8888");
}
wet_output_set_scale(output, section, 1, 0);
weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);

View file

@ -704,7 +704,12 @@ kiosk_shell_output_recreate_background(struct kiosk_shell_output *shoutput)
curtain_params.r = ((bg_color >> 16) & 0xff) / 255.0;
curtain_params.g = ((bg_color >> 8) & 0xff) / 255.0;
curtain_params.b = ((bg_color >> 0) & 0xff) / 255.0;
curtain_params.a = 1.0;
curtain_params.a = ((bg_color >> 24) & 0xff) / 255.0;
if (curtain_params.a == 0.0) {
shoutput->curtain = NULL;
return;
}
curtain_params.pos = output->pos;
curtain_params.width = output->width;

View file

@ -200,6 +200,8 @@ spa_video_format_from_drm_fourcc(uint32_t fourcc)
switch (fourcc) {
case DRM_FORMAT_XRGB8888:
return SPA_VIDEO_FORMAT_BGRx;
case DRM_FORMAT_ARGB8888:
return SPA_VIDEO_FORMAT_BGRA;
case DRM_FORMAT_RGB565:
return SPA_VIDEO_FORMAT_RGB16;
default: