mirror of
https://gitlab.freedesktop.org/wayland/weston
synced 2024-10-04 21:02:44 +00:00
backend-pipewire: add PipeWire backend
Add a separate PipeWire backend based on the PipeWire plugin. The backend requires PipeWire 0.3.x. The PipeWire backend can be used as a standalone-backend backend for streaming and composing Wayland clients to PipeWire. The backend supports the on-demand creation of heads via the weston_pipewire_output_api_v1. It also supports per-output pixel format configuration via a gbm-format option. Multiple PipeWire outputs can be created by setting the num-outputs option in the [pipewire] section. Co-authored-by: Michael Tretter <m.tretter@pengutronix.de> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
This commit is contained in:
parent
bcacd9ec5a
commit
ebc3a22b09
|
@ -40,6 +40,7 @@ struct {
|
||||||
} backend_name_map[] = {
|
} backend_name_map[] = {
|
||||||
{ "drm", "drm-backend.so", WESTON_BACKEND_DRM },
|
{ "drm", "drm-backend.so", WESTON_BACKEND_DRM },
|
||||||
{ "headless", "headless-backend.so", WESTON_BACKEND_HEADLESS },
|
{ "headless", "headless-backend.so", WESTON_BACKEND_HEADLESS },
|
||||||
|
{ "pipewire", "pipewire-backend.so", WESTON_BACKEND_PIPEWIRE },
|
||||||
{ "rdp", "rdp-backend.so", WESTON_BACKEND_RDP },
|
{ "rdp", "rdp-backend.so", WESTON_BACKEND_RDP },
|
||||||
{ "vnc", "vnc-backend.so", WESTON_BACKEND_VNC },
|
{ "vnc", "vnc-backend.so", WESTON_BACKEND_VNC },
|
||||||
{ "wayland", "wayland-backend.so", WESTON_BACKEND_WAYLAND },
|
{ "wayland", "wayland-backend.so", WESTON_BACKEND_WAYLAND },
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
|
|
||||||
#include <libweston/backend-drm.h>
|
#include <libweston/backend-drm.h>
|
||||||
#include <libweston/backend-headless.h>
|
#include <libweston/backend-headless.h>
|
||||||
|
#include <libweston/backend-pipewire.h>
|
||||||
#include <libweston/backend-rdp.h>
|
#include <libweston/backend-rdp.h>
|
||||||
#include <libweston/backend-vnc.h>
|
#include <libweston/backend-vnc.h>
|
||||||
#include <libweston/backend-x11.h>
|
#include <libweston/backend-x11.h>
|
||||||
|
@ -658,6 +659,9 @@ usage(int error_code)
|
||||||
#if defined(BUILD_HEADLESS_COMPOSITOR)
|
#if defined(BUILD_HEADLESS_COMPOSITOR)
|
||||||
"\t\t\t\theadless\n"
|
"\t\t\t\theadless\n"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(BUILD_PIPEWIRE_COMPOSITOR)
|
||||||
|
"\t\t\t\tpipewire\n"
|
||||||
|
#endif
|
||||||
#if defined(BUILD_RDP_COMPOSITOR)
|
#if defined(BUILD_RDP_COMPOSITOR)
|
||||||
"\t\t\t\trdp\n"
|
"\t\t\t\trdp\n"
|
||||||
#endif
|
#endif
|
||||||
|
@ -721,6 +725,14 @@ usage(int error_code)
|
||||||
"\n");
|
"\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(BUILD_PIPEWIRE_COMPOSITOR)
|
||||||
|
fprintf(out,
|
||||||
|
"Options for pipewire\n\n"
|
||||||
|
" --width=WIDTH\t\tWidth of desktop\n"
|
||||||
|
" --height=HEIGHT\tHeight of desktop\n"
|
||||||
|
"\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(BUILD_RDP_COMPOSITOR)
|
#if defined(BUILD_RDP_COMPOSITOR)
|
||||||
fprintf(out,
|
fprintf(out,
|
||||||
"Options for rdp:\n\n"
|
"Options for rdp:\n\n"
|
||||||
|
@ -3071,6 +3083,98 @@ load_headless_backend(struct weston_compositor *c,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pipewire_backend_output_configure(struct weston_output *output)
|
||||||
|
{
|
||||||
|
struct wet_output_config defaults = {
|
||||||
|
.width = 640,
|
||||||
|
.height = 480,
|
||||||
|
};
|
||||||
|
struct wet_compositor *compositor = to_wet_compositor(output->compositor);
|
||||||
|
struct wet_output_config *parsed_options = compositor->parsed_options;
|
||||||
|
const struct weston_pipewire_output_api *api = weston_pipewire_output_get_api(output->compositor);
|
||||||
|
struct weston_config *wc = wet_get_config(output->compositor);
|
||||||
|
struct weston_config_section *section;
|
||||||
|
char *gbm_format = NULL;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
assert(parsed_options);
|
||||||
|
|
||||||
|
if (!api) {
|
||||||
|
weston_log("Cannot use weston_pipewire_output_api.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
section = weston_config_get_section(wc, "output", "name", output->name);
|
||||||
|
|
||||||
|
parse_simple_mode(output, section, &width, &height, &defaults,
|
||||||
|
parsed_options);
|
||||||
|
|
||||||
|
if (section)
|
||||||
|
weston_config_section_get_string(section, "gbm-format",
|
||||||
|
&gbm_format, NULL);
|
||||||
|
|
||||||
|
weston_output_set_scale(output, 1);
|
||||||
|
weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
|
||||||
|
api->set_gbm_format(output, gbm_format);
|
||||||
|
free(gbm_format);
|
||||||
|
|
||||||
|
if (api->output_set_size(output, width, height) < 0) {
|
||||||
|
weston_log("Cannot configure output \"%s\" using weston_pipewire_output_api.\n",
|
||||||
|
output->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
weston_log("pipewire_backend_output_configure.. Done\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
weston_pipewire_backend_config_init(struct weston_pipewire_backend_config *config)
|
||||||
|
{
|
||||||
|
config->base.struct_version = WESTON_PIPEWIRE_BACKEND_CONFIG_VERSION;
|
||||||
|
config->base.struct_size = sizeof(struct weston_pipewire_backend_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_pipewire_backend(struct weston_compositor *c,
|
||||||
|
int *argc, char *argv[], struct weston_config *wc,
|
||||||
|
enum weston_renderer_type renderer)
|
||||||
|
{
|
||||||
|
struct weston_pipewire_backend_config config = {{ 0, }};
|
||||||
|
struct weston_config_section *section;
|
||||||
|
struct wet_output_config *parsed_options = wet_init_parsed_options(c);
|
||||||
|
|
||||||
|
if (!parsed_options)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
weston_pipewire_backend_config_init(&config);
|
||||||
|
|
||||||
|
const struct weston_option pipewire_options[] = {
|
||||||
|
{ WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
|
||||||
|
{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
|
||||||
|
};
|
||||||
|
|
||||||
|
parse_options(pipewire_options, ARRAY_LENGTH(pipewire_options), argc, argv);
|
||||||
|
|
||||||
|
config.renderer = renderer;
|
||||||
|
|
||||||
|
wet_set_simple_head_configurator(c, pipewire_backend_output_configure);
|
||||||
|
|
||||||
|
section = weston_config_get_section(wc, "core", NULL, NULL);
|
||||||
|
weston_config_section_get_string(section, "gbm-format",
|
||||||
|
&config.gbm_format, NULL);
|
||||||
|
|
||||||
|
section = weston_config_get_section(wc, "pipewire", NULL, NULL);
|
||||||
|
weston_config_section_get_int(section, "num-outputs",
|
||||||
|
&config.num_outputs, 1);
|
||||||
|
|
||||||
|
return weston_compositor_load_backend(c, WESTON_BACKEND_PIPEWIRE,
|
||||||
|
&config.base);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
|
weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
|
||||||
{
|
{
|
||||||
|
@ -3608,6 +3712,9 @@ load_backend(struct weston_compositor *compositor, const char *name,
|
||||||
case WESTON_BACKEND_HEADLESS:
|
case WESTON_BACKEND_HEADLESS:
|
||||||
return load_headless_backend(compositor, argc, argv, config,
|
return load_headless_backend(compositor, argc, argv, config,
|
||||||
renderer);
|
renderer);
|
||||||
|
case WESTON_BACKEND_PIPEWIRE:
|
||||||
|
return load_pipewire_backend(compositor, argc, argv, config,
|
||||||
|
renderer);
|
||||||
case WESTON_BACKEND_RDP:
|
case WESTON_BACKEND_RDP:
|
||||||
return load_rdp_backend(compositor, argc, argv, config,
|
return load_rdp_backend(compositor, argc, argv, config,
|
||||||
renderer);
|
renderer);
|
||||||
|
|
108
include/libweston/backend-pipewire.h
Normal file
108
include/libweston/backend-pipewire.h
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2021-2023 Philipp Zabel <p.zabel@pengutronix.de>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial
|
||||||
|
* portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WESTON_COMPOSITOR_PIPEWIRE_H
|
||||||
|
#define WESTON_COMPOSITOR_PIPEWIRE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libweston/libweston.h>
|
||||||
|
#include <libweston/plugin-registry.h>
|
||||||
|
|
||||||
|
#define WESTON_PIPEWIRE_OUTPUT_API_NAME "weston_pipewire_output_api_v1"
|
||||||
|
|
||||||
|
struct pipewire_config {
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
uint32_t framerate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_pipewire_output_api {
|
||||||
|
/** Create a new PipeWire head.
|
||||||
|
*
|
||||||
|
* \param compositor The compositor instance.
|
||||||
|
* \param name Desired name for the new head
|
||||||
|
* \param config The pipewire_config of the new head.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
void (*head_create)(struct weston_compositor *compositor,
|
||||||
|
const char *name,
|
||||||
|
const struct pipewire_config *config);
|
||||||
|
|
||||||
|
/** Set the size of a PipeWire output to the specified width and height.
|
||||||
|
*
|
||||||
|
* If the width or height are set to -1, the size of the underlying
|
||||||
|
* PipeWire head will be used.
|
||||||
|
*
|
||||||
|
* \param output The weston output for which the size shall be set
|
||||||
|
* \param width Desired width of the output
|
||||||
|
* \param height Desired height of the output
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
int (*output_set_size)(struct weston_output *output,
|
||||||
|
int width, int height);
|
||||||
|
|
||||||
|
/** The pixel format to be used by the output.
|
||||||
|
*
|
||||||
|
* \param output The weston output for which the pixel format is set
|
||||||
|
* \param gbm_format String representation of the pixel format
|
||||||
|
*
|
||||||
|
* Valid values for the gbm_format are:
|
||||||
|
* - NULL - The format set at backend creation time will be used;
|
||||||
|
* - "xrgb8888";
|
||||||
|
* - "rgb565";
|
||||||
|
*/
|
||||||
|
void (*set_gbm_format)(struct weston_output *output,
|
||||||
|
const char *gbm_format);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline const struct weston_pipewire_output_api *
|
||||||
|
weston_pipewire_output_get_api(struct weston_compositor *compositor)
|
||||||
|
{
|
||||||
|
const void *api;
|
||||||
|
api = weston_plugin_api_get(compositor, WESTON_PIPEWIRE_OUTPUT_API_NAME,
|
||||||
|
sizeof(struct weston_pipewire_output_api));
|
||||||
|
|
||||||
|
return (const struct weston_pipewire_output_api *)api;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WESTON_PIPEWIRE_BACKEND_CONFIG_VERSION 1
|
||||||
|
|
||||||
|
struct weston_pipewire_backend_config {
|
||||||
|
struct weston_backend_config base;
|
||||||
|
enum weston_renderer_type renderer;
|
||||||
|
char *gbm_format;
|
||||||
|
int32_t num_outputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* WESTON_COMPOSITOR_PIPEWIRE_H */
|
|
@ -2252,6 +2252,7 @@ weston_compositor_add_destroy_listener_once(struct weston_compositor *compositor
|
||||||
enum weston_compositor_backend {
|
enum weston_compositor_backend {
|
||||||
WESTON_BACKEND_DRM,
|
WESTON_BACKEND_DRM,
|
||||||
WESTON_BACKEND_HEADLESS,
|
WESTON_BACKEND_HEADLESS,
|
||||||
|
WESTON_BACKEND_PIPEWIRE,
|
||||||
WESTON_BACKEND_RDP,
|
WESTON_BACKEND_RDP,
|
||||||
WESTON_BACKEND_VNC,
|
WESTON_BACKEND_VNC,
|
||||||
WESTON_BACKEND_WAYLAND,
|
WESTON_BACKEND_WAYLAND,
|
||||||
|
|
|
@ -15,6 +15,7 @@ install_headers(
|
||||||
|
|
||||||
backend_drm_h = files('backend-drm.h')
|
backend_drm_h = files('backend-drm.h')
|
||||||
backend_headless_h = files('backend-headless.h')
|
backend_headless_h = files('backend-headless.h')
|
||||||
|
backend_pipewire_h = files('backend-pipewire.h')
|
||||||
backend_rdp_h = files('backend-rdp.h')
|
backend_rdp_h = files('backend-rdp.h')
|
||||||
backend_vnc_h = files('backend-vnc.h')
|
backend_vnc_h = files('backend-vnc.h')
|
||||||
backend_wayland_h = files('backend-wayland.h')
|
backend_wayland_h = files('backend-wayland.h')
|
||||||
|
|
35
libweston/backend-pipewire/meson.build
Normal file
35
libweston/backend-pipewire/meson.build
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
if not get_option('backend-pipewire')
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
user_hint = 'If you rather not build this, set \'-Dbackend-pipewire=false\'.'
|
||||||
|
|
||||||
|
config_h.set('BUILD_PIPEWIRE_COMPOSITOR', '1')
|
||||||
|
|
||||||
|
dep_libpipewire = dependency('libpipewire-0.3', required: false)
|
||||||
|
if not dep_libpipewire.found()
|
||||||
|
error('PipeWire backend requires libpipewire 0.3 which was not found. ' + user_hint)
|
||||||
|
endif
|
||||||
|
|
||||||
|
dep_libspa = dependency('libspa-0.2', required: false)
|
||||||
|
if not dep_libspa.found()
|
||||||
|
error('Pipewire plugin requires libspa 0.2 which was not found. ' + user_hint)
|
||||||
|
endif
|
||||||
|
|
||||||
|
deps_pipewire = [
|
||||||
|
dep_libweston_private,
|
||||||
|
dep_libpipewire,
|
||||||
|
dep_libspa,
|
||||||
|
dep_libdrm_headers,
|
||||||
|
]
|
||||||
|
|
||||||
|
plugin_pipewire = shared_library(
|
||||||
|
'pipewire-backend',
|
||||||
|
[ 'pipewire.c' ],
|
||||||
|
include_directories: common_inc,
|
||||||
|
dependencies: deps_pipewire,
|
||||||
|
name_prefix: '',
|
||||||
|
install: true,
|
||||||
|
install_dir: dir_module_libweston
|
||||||
|
)
|
||||||
|
env_modmap += 'pipewire-backend.so=@0@;'.format(plugin_pipewire.full_path())
|
||||||
|
install_headers(backend_pipewire_h, subdir: dir_include_libweston_install)
|
1001
libweston/backend-pipewire/pipewire.c
Normal file
1001
libweston/backend-pipewire/pipewire.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9024,6 +9024,7 @@ weston_compositor_get_user_data(struct weston_compositor *compositor)
|
||||||
static const char * const backend_map[] = {
|
static const char * const backend_map[] = {
|
||||||
[WESTON_BACKEND_DRM] = "drm-backend.so",
|
[WESTON_BACKEND_DRM] = "drm-backend.so",
|
||||||
[WESTON_BACKEND_HEADLESS] = "headless-backend.so",
|
[WESTON_BACKEND_HEADLESS] = "headless-backend.so",
|
||||||
|
[WESTON_BACKEND_PIPEWIRE] = "pipewire-backend.so",
|
||||||
[WESTON_BACKEND_RDP] = "rdp-backend.so",
|
[WESTON_BACKEND_RDP] = "rdp-backend.so",
|
||||||
[WESTON_BACKEND_VNC] = "vnc-backend.so",
|
[WESTON_BACKEND_VNC] = "vnc-backend.so",
|
||||||
[WESTON_BACKEND_WAYLAND] = "wayland-backend.so",
|
[WESTON_BACKEND_WAYLAND] = "wayland-backend.so",
|
||||||
|
|
|
@ -268,6 +268,7 @@ subdir('color-lcms')
|
||||||
subdir('renderer-gl')
|
subdir('renderer-gl')
|
||||||
subdir('backend-drm')
|
subdir('backend-drm')
|
||||||
subdir('backend-headless')
|
subdir('backend-headless')
|
||||||
|
subdir('backend-pipewire')
|
||||||
subdir('backend-rdp')
|
subdir('backend-rdp')
|
||||||
subdir('backend-vnc')
|
subdir('backend-vnc')
|
||||||
subdir('backend-wayland')
|
subdir('backend-wayland')
|
||||||
|
|
|
@ -20,6 +20,12 @@ option(
|
||||||
value: true,
|
value: true,
|
||||||
description: 'Weston backend: headless (testing)'
|
description: 'Weston backend: headless (testing)'
|
||||||
)
|
)
|
||||||
|
option(
|
||||||
|
'backend-pipewire',
|
||||||
|
type: 'boolean',
|
||||||
|
value: true,
|
||||||
|
description: 'PipeWire backend: screencasting via PipeWire'
|
||||||
|
)
|
||||||
option(
|
option(
|
||||||
'backend-rdp',
|
'backend-rdp',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
|
|
Loading…
Reference in a new issue