diff options
author | Marius Vlad <marius.vlad@collabora.com> | 2024-11-18 18:05:17 +0200 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2024-11-25 21:13:11 +0200 |
commit | c8f26648ef9ed09ca842fd81202802b73a07f789 (patch) | |
tree | fd704f920cdda3b24a6e7ba1aab9a5d4df38ba7c | |
parent | de6dfd292a1c55f8e275d301607eadc228aecb90 (diff) |
compositor: Add support for loading multiple back-ends
Using multiple backends allows to mirror out output or have
different outputs like RDP, VNC, PipeWire. So yeah, allowing to load
them as the same time will help towards different goals.
Bug-AGL: SPEC-5290, SPEC-4689
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: I0657fee5b1105007fd4ef00ac237b0ee2d68ea21
-rw-r--r-- | src/compositor.c | 226 | ||||
-rw-r--r-- | src/ivi-compositor.h | 11 |
2 files changed, 171 insertions, 66 deletions
diff --git a/src/compositor.c b/src/compositor.c index 2568246..6aec416 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -64,6 +64,9 @@ static int cached_tm_mday = -1; static struct weston_log_scope *log_scope; +static void +weston_output_lazy_align(struct weston_output *output); + struct ivi_compositor * to_ivi_compositor(struct weston_compositor *ec) { @@ -101,6 +104,25 @@ ivi_init_parsed_options(struct weston_compositor *compositor) } static void +ivi_backend_destroy(struct ivi_backend *b) +{ + wl_list_remove(&b->link); + wl_list_remove(&b->heads_changed.link); + + free(b); +} + + +static void +ivi_compositor_destroy_backends(struct ivi_compositor *ivi) +{ + struct ivi_backend *b, *tmp; + + wl_list_for_each_safe(b, tmp, &ivi->backends, link) + ivi_backend_destroy(b); +} + +static void screenshot_allow_all(struct wl_listener *l, struct weston_output_capture_attempt *att) { att->authorized = true; @@ -226,8 +248,8 @@ ivi_output_configure_app_id(struct ivi_output *ivi_output) } static struct ivi_output * -ivi_ensure_output(struct ivi_compositor *ivi, char *name, - struct weston_config_section *config, +ivi_ensure_output(struct ivi_compositor *ivi, struct ivi_backend *ivi_backend, + char *name, struct weston_config_section *config, struct weston_head *head) { struct ivi_output *output = NULL; @@ -264,8 +286,8 @@ ivi_ensure_output(struct ivi_compositor *ivi, char *name, weston_output_add_destroy_listener(output->output, &output->output_destroy); - if (ivi->simple_output_configure) { - int ret = ivi->simple_output_configure(output->output); + if (ivi_backend->simple_output_configure) { + int ret = ivi_backend->simple_output_configure(output->output); if (ret < 0) { weston_log("Configuring output \"%s\" failed.\n", weston_head_get_name(head)); @@ -274,6 +296,8 @@ ivi_ensure_output(struct ivi_compositor *ivi, char *name, return NULL; } + weston_output_lazy_align(output->output); + if (weston_output_enable(output->output) < 0) { weston_log("Enabling output \"%s\" failed.\n", weston_head_get_name(head)); @@ -618,6 +642,19 @@ process_output(struct ivi_output *output) return try_attach_enable_heads(output); } +static struct weston_head * +ivi_backend_iterate_heads(struct ivi_compositor *ivi, struct ivi_backend *wb, + struct weston_head *iter) +{ + while ((iter = weston_compositor_iterate_heads(ivi->compositor, iter))) { + if (iter->backend == wb->backend) + break; + } + + return iter; +} + + static void drm_head_disable(struct ivi_compositor *ivi, struct weston_head *head) { @@ -689,7 +726,7 @@ find_controlling_output_config(struct weston_config *config, } static void -drm_head_prepare_enable(struct ivi_compositor *ivi, struct weston_head *head) +drm_head_prepare_enable(struct ivi_compositor *ivi, struct ivi_backend *ivi_backend, struct weston_head *head) { const char *name = weston_head_get_name(head); struct weston_config_section *section; @@ -717,7 +754,7 @@ drm_head_prepare_enable(struct ivi_compositor *ivi, struct weston_head *head) if (!output_name) return; - output = ivi_ensure_output(ivi, output_name, section, head); + output = ivi_ensure_output(ivi, ivi_backend, output_name, section, head); if (!output) return; @@ -734,15 +771,17 @@ drm_heads_changed(struct wl_listener *listener, void *arg) struct weston_head *head = NULL; struct ivi_compositor *ivi = to_ivi_compositor(compositor); struct ivi_output *output; + struct ivi_backend *ivi_backend = + container_of(listener, struct ivi_backend, heads_changed); - while ((head = weston_compositor_iterate_heads(ivi->compositor, head))) { + while ((head = ivi_backend_iterate_heads(ivi, ivi_backend, head))) { bool connected = weston_head_is_connected(head); bool enabled = weston_head_is_enabled(head); bool changed = weston_head_is_device_changed(head); bool non_desktop = weston_head_is_non_desktop(head); if (connected && !enabled && !non_desktop) - drm_head_prepare_enable(ivi, head); + drm_head_prepare_enable(ivi, ivi_backend, head); else if (!connected && enabled) drm_head_disable(ivi, head); else if (enabled && changed) @@ -765,7 +804,8 @@ drm_heads_changed(struct wl_listener *listener, void *arg) } static void -simple_head_enable(struct ivi_compositor *ivi, struct weston_head *head) +simple_head_enable(struct ivi_compositor *ivi, struct ivi_backend *ivi_backend, + struct weston_head *head) { struct ivi_output *output; struct weston_config_section *section; @@ -792,7 +832,7 @@ simple_head_enable(struct ivi_compositor *ivi, struct weston_head *head) if (!output_name) return; - output = ivi_ensure_output(ivi, output_name, section, head); + output = ivi_ensure_output(ivi, ivi_backend, output_name, section, head); if (!output) { weston_log("Failed to create output %s\n", output_name); return; @@ -827,15 +867,17 @@ simple_heads_changed(struct wl_listener *listener, void *arg) bool enabled; bool changed; bool non_desktop; + struct ivi_backend *ivi_backend = + container_of(listener, struct ivi_backend, heads_changed); - while ((head = weston_compositor_iterate_heads(ivi->compositor, head))) { + while ((head = ivi_backend_iterate_heads(ivi, ivi_backend, head))) { connected = weston_head_is_connected(head); enabled = weston_head_is_enabled(head); changed = weston_head_is_device_changed(head); non_desktop = weston_head_is_non_desktop(head); if (connected && !enabled && !non_desktop) { - simple_head_enable(ivi, head); + simple_head_enable(ivi, ivi_backend, head); } else if (!connected && enabled) { simple_head_disable(head); } else if (enabled && changed) { @@ -862,6 +904,7 @@ load_drm_backend(struct ivi_compositor *ivi, int *argc, char *argv[], bool force_pixman = false; bool use_shadow; bool without_input = false; + struct ivi_backend *ivi_backend = NULL; const struct weston_option options[] = { { WESTON_OPTION_STRING, "seat", 0, &config.seat_id }, @@ -891,16 +934,20 @@ load_drm_backend(struct ivi_compositor *ivi, int *argc, char *argv[], if (without_input) ivi->compositor->require_input = !without_input; - ivi->heads_changed.notify = drm_heads_changed; - weston_compositor_add_heads_changed_listener(ivi->compositor, - &ivi->heads_changed); - - if (!weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_DRM, - &config.base)) { + ivi_backend = zalloc(sizeof(struct ivi_backend)); + ivi_backend->backend = + weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_DRM, + &config.base); + if (!ivi_backend->backend) { weston_log("Failed to load DRM backend\n"); return -1; } + ivi_backend->heads_changed.notify = drm_heads_changed; + weston_compositor_add_heads_changed_listener(ivi->compositor, + &ivi_backend->heads_changed); + wl_list_insert(&ivi->backends, &ivi_backend->link); + ivi->drm_api = weston_drm_output_get_api(ivi->compositor); if (!ivi->drm_api) { weston_log("Cannot use drm output api.\n"); @@ -943,6 +990,7 @@ windowed_parse_common_options(struct ivi_compositor *ivi, int *argc, char *argv[ static int windowed_create_outputs(struct ivi_compositor *ivi, int output_count, + struct weston_backend *backend, const char *match_prefix, const char *name_prefix) { struct weston_config_section *section = NULL; @@ -968,7 +1016,7 @@ windowed_create_outputs(struct ivi_compositor *ivi, int output_count, continue; } - if (ivi->window_api->create_head(ivi->backend, output_name) < 0) { + if (ivi->window_api->create_head(backend, output_name) < 0) { free(output_name); return -1; } @@ -981,7 +1029,7 @@ windowed_create_outputs(struct ivi_compositor *ivi, int output_count, if (asprintf(&default_output, "%s%d", name_prefix, i) < 0) return -1; - if (ivi->window_api->create_head(ivi->backend, default_output) < 0) { + if (ivi->window_api->create_head(backend, default_output) < 0) { free(default_output); return -1; } @@ -1027,6 +1075,7 @@ load_wayland_backend(struct ivi_compositor *ivi, int *argc, char *argv[], int sprawl = 0; int output_count; bool force_pixman = false; + struct ivi_backend *ivi_backend = NULL; const struct weston_option options[] = { { WESTON_OPTION_STRING, "display", 0, &config.display_name }, @@ -1045,23 +1094,25 @@ load_wayland_backend(struct ivi_compositor *ivi, int *argc, char *argv[], weston_config_section_get_int(section, "cursor-size", &config.cursor_size, 32); - ivi->simple_output_configure = wayland_backend_output_configure; - ivi->heads_changed.notify = simple_heads_changed; - weston_compositor_add_heads_changed_listener(ivi->compositor, - &ivi->heads_changed); - - ivi->backend = weston_compositor_load_backend(ivi->compositor, + ivi_backend = zalloc(sizeof(struct ivi_backend)); + ivi_backend->backend = weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_WAYLAND, &config.base); - if (!ivi->backend) { - weston_log("Failed to create Wayland backend!\n"); - } - free(config.cursor_theme); free(config.display_name); - if (!ivi->backend) + if (!ivi_backend->backend) { + weston_log("Failed to create Wayland backend!\n"); return -1; + } + + ivi_backend->simple_output_configure = wayland_backend_output_configure; + ivi_backend->heads_changed.notify = simple_heads_changed; + weston_compositor_add_heads_changed_listener(ivi->compositor, + &ivi_backend->heads_changed); + + + wl_list_insert(&ivi->backends, &ivi_backend->link); ivi->window_api = weston_windowed_output_get_api(ivi->compositor); @@ -1075,7 +1126,7 @@ load_wayland_backend(struct ivi_compositor *ivi, int *argc, char *argv[], if (ivi->window_api == NULL) return 0; - return windowed_create_outputs(ivi, output_count, "WL", "wayland"); + return windowed_create_outputs(ivi, output_count, ivi_backend->backend, "WL", "wayland"); } #ifdef HAVE_BACKEND_X11 @@ -1113,6 +1164,7 @@ load_x11_backend(struct ivi_compositor *ivi, int *argc, char *argv[], int no_input = 0; int output_count; bool force_pixman = false; + struct ivi_backend *ivi_backend = NULL; const struct weston_option options[] = { { WESTON_OPTION_BOOLEAN, "no-input", 0, &no_input }, @@ -1128,27 +1180,31 @@ load_x11_backend(struct ivi_compositor *ivi, int *argc, char *argv[], config.renderer = WESTON_RENDERER_AUTO; config.no_input = no_input; - ivi->simple_output_configure = x11_backend_output_configure; - - ivi->heads_changed.notify = simple_heads_changed; - weston_compositor_add_heads_changed_listener(ivi->compositor, - &ivi->heads_changed); - ivi->backend = weston_compositor_load_backend(ivi->compositor, + ivi_backend = zalloc(sizeof(struct ivi_backend)); + ivi_backend->backend = weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_X11, &config.base); - if (!ivi->backend) { + if (!ivi_backend->backend) { weston_log("Failed to create X11 backend!\n"); return -1; } + ivi_backend->simple_output_configure = x11_backend_output_configure; + ivi_backend->heads_changed.notify = simple_heads_changed; + weston_compositor_add_heads_changed_listener(ivi->compositor, + &ivi_backend->heads_changed); + + ivi->window_api = weston_windowed_output_get_api(ivi->compositor); if (!ivi->window_api) { weston_log("Cannot use weston_windowed_output_api.\n"); return -1; } - return windowed_create_outputs(ivi, output_count, "X", "screen"); + wl_list_insert(&ivi->backends, &ivi_backend->link); + + return windowed_create_outputs(ivi, output_count, ivi_backend->backend, "X", "screen"); } #else static int @@ -1249,6 +1305,7 @@ load_rdp_backend(struct ivi_compositor *ivi, int *argc, char **argv, struct weston_rdp_backend_config config = {}; struct weston_config_section *section; bool no_remotefx_codec = false; + struct ivi_backend *ivi_backend = NULL; struct ivi_output_config *parsed_options = ivi_init_parsed_options(ivi->compositor); if (!parsed_options) @@ -1290,23 +1347,28 @@ load_rdp_backend(struct ivi_compositor *ivi, int *argc, char **argv, parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv); weston_log("No clients resize: %d\n", config.no_clients_resize); - ivi->simple_output_configure = rdp_backend_output_configure; - - ivi->heads_changed.notify = simple_heads_changed; - weston_compositor_add_heads_changed_listener(ivi->compositor, - &ivi->heads_changed); - if (!weston_compositor_load_backend(ivi->compositor, - WESTON_BACKEND_RDP, &config.base)) { + ivi_backend = zalloc(sizeof(struct ivi_backend)); + ivi_backend->backend = weston_compositor_load_backend(ivi->compositor, + WESTON_BACKEND_RDP, &config.base); + if (!ivi_backend->backend) { weston_log("Failed to create RDP backend\n"); return -1; } + ivi_backend->simple_output_configure = rdp_backend_output_configure; + ivi_backend->heads_changed.notify = simple_heads_changed; + weston_compositor_add_heads_changed_listener(ivi->compositor, + &ivi_backend->heads_changed); + + free(config.bind_address); free(config.rdp_key); free(config.server_cert); free(config.server_key); + wl_list_insert(&ivi->backends, &ivi_backend->link); + return 0; } #else @@ -1387,6 +1449,7 @@ load_pipewire_backend(struct ivi_compositor *ivi, int *argc, char **argv, struct weston_config_section *section; struct ivi_output_config *parsed_options = ivi_init_parsed_options(ivi->compositor); + struct ivi_backend *ivi_backend = NULL; if (!parsed_options) return -1; @@ -1410,17 +1473,22 @@ load_pipewire_backend(struct ivi_compositor *ivi, int *argc, char **argv, weston_config_section_get_int(section, "num-outputs", &config.num_outputs, 1); - ivi->simple_output_configure = pipewire_backend_output_configure; - ivi->heads_changed.notify = simple_heads_changed; - weston_compositor_add_heads_changed_listener(ivi->compositor, - &ivi->heads_changed); - if (!weston_compositor_load_backend(ivi->compositor, - WESTON_BACKEND_PIPEWIRE, &config.base)) { + ivi_backend = zalloc(sizeof(struct ivi_backend)); + ivi_backend->backend = weston_compositor_load_backend(ivi->compositor, + WESTON_BACKEND_PIPEWIRE, &config.base); + if (!ivi_backend->backend) { weston_log("Failed to create PipeWire backend\n"); return -1; } + ivi_backend->simple_output_configure = pipewire_backend_output_configure; + ivi_backend->heads_changed.notify = simple_heads_changed; + weston_compositor_add_heads_changed_listener(ivi->compositor, + &ivi_backend->heads_changed); + + wl_list_insert(&ivi->backends, &ivi_backend->link); + return 0; } #else @@ -1468,6 +1536,33 @@ load_backend(struct ivi_compositor *ivi, int *argc, char **argv, } static int +load_backends(struct ivi_compositor *ivi, const char *backends, + int *argc, char **argv, const char *renderer) +{ + const char *p, *end; + char buffer[256]; + + if (backends == NULL) + return 0; + + p = backends; + while (*p) { + end = strchrnul(p, ','); + snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p); + + if (load_backend(ivi, argc, argv, buffer, renderer) < 0) + return -1; + + p = end; + while (*p == ',') + p++; + } + + return 0; +} + + +static int load_modules(struct ivi_compositor *ivi, const char *modules, int *argc, char *argv[], bool *xwayland) { @@ -1939,7 +2034,7 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da struct wl_event_source *signals[3] = { 0 }; struct weston_config_section *section; /* Command line options */ - char *backend = NULL; + char *backends = NULL; char *socket_name = NULL; char *log = NULL; char *modules = NULL; @@ -1962,7 +2057,8 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da const struct weston_option core_options[] = { { WESTON_OPTION_STRING, "renderer", 'r', &renderer }, - { WESTON_OPTION_STRING, "backend", 'B', &backend }, + { WESTON_OPTION_STRING, "backend", 'B', &backends }, + { WESTON_OPTION_STRING, "backends", 0, &backends }, { WESTON_OPTION_STRING, "socket", 'S', &socket_name }, { WESTON_OPTION_STRING, "log", 0, &log }, { WESTON_OPTION_BOOLEAN, "help", 'h', &help }, @@ -1985,6 +2081,7 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da wl_list_init(&ivi.split_pending_apps); wl_list_init(&ivi.remote_pending_apps); wl_list_init(&ivi.desktop_clients); + wl_list_init(&ivi.backends); wl_list_init(&ivi.child_process_list); wl_list_init(&ivi.pending_apps); @@ -2025,11 +2122,11 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da if (load_config(&ivi.config, no_config, config_file) < 0) goto error_signals; section = weston_config_get_section(ivi.config, "core", NULL, NULL); - if (!backend) { - weston_config_section_get_string(section, "backend", &backend, + if (!backends) { + weston_config_section_get_string(section, "backend", &backends, NULL); - if (!backend) - backend = choose_default_backend(); + if (!backends) + backends = choose_default_backend(); } display = wl_display_create(); @@ -2075,8 +2172,9 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da if (compositor_init_config(&ivi) < 0) goto error_compositor; - if (load_backend(&ivi, &argc, argv, backend, renderer) < 0) { - weston_log("fatal: failed to create compositor backend.\n"); + ivi.compositor->multi_backend = backends && strchr(backends, ','); + if (load_backends(&ivi, backends, &argc, argv, renderer) < 0) { + weston_log("fatal: failed to create compositor backend\n"); goto error_compositor; } @@ -2163,11 +2261,13 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da ret = ivi.compositor->exit_code; + ivi_compositor_destroy_backends(&ivi); + wl_display_destroy_clients(display); error_compositor: - free(backend); - backend = NULL; + free(backends); + backends = NULL; free(modules); modules = NULL; diff --git a/src/ivi-compositor.h b/src/ivi-compositor.h index 5c826af..1e8c55a 100644 --- a/src/ivi-compositor.h +++ b/src/ivi-compositor.h @@ -59,14 +59,18 @@ struct ivi_output_config { uint32_t transform; }; +struct ivi_backend { + struct weston_backend *backend; + struct wl_listener heads_changed; + int (*simple_output_configure)(struct weston_output *output); + struct wl_list link; +}; + struct ivi_compositor { struct weston_compositor *compositor; - struct weston_backend *backend; struct weston_config *config; struct ivi_output_config *parsed_options; - struct wl_listener heads_changed; - int (*simple_output_configure)(struct weston_output *output); bool init_failed; bool disable_cursor; @@ -117,6 +121,7 @@ struct ivi_compositor { struct wl_list outputs; /* ivi_output.link */ struct wl_list saved_outputs; /* ivi_output.link */ struct wl_list surfaces; /* ivi_surface.link */ + struct wl_list backends; struct weston_desktop *desktop; struct wl_listener seat_created_listener; |