From 9b4be5a59506a81175ab2eb9248f4035176df5f0 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 17 Jan 2019 20:13:55 +1000 Subject: Introduce noop backend The noop backend is similar to headless, but it doesn't contain a renderer. It can be used as a place to stash views for when there's no physical outputs connected. --- backend/backend.c | 17 ++++++++++++ backend/meson.build | 2 ++ backend/noop/backend.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ backend/noop/output.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 backend/noop/backend.c create mode 100644 backend/noop/output.c (limited to 'backend') diff --git a/backend/backend.c b/backend/backend.c index b369a135..33ad20f2 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,20 @@ static struct wlr_backend *attempt_headless_backend( return backend; } +static struct wlr_backend *attempt_noop_backend(struct wl_display *display) { + struct wlr_backend *backend = wlr_noop_backend_create(display); + if (backend == NULL) { + return NULL; + } + + size_t outputs = parse_outputs_env("WLR_NOOP_OUTPUTS"); + for (size_t i = 0; i < outputs; ++i) { + wlr_noop_add_output(backend); + } + + return backend; +} + static struct wlr_backend *attempt_drm_backend(struct wl_display *display, struct wlr_backend *backend, struct wlr_session *session, wlr_renderer_create_func_t create_renderer_func) { @@ -170,6 +185,8 @@ static struct wlr_backend *attempt_backend_by_name(struct wl_display *display, #endif } else if (strcmp(name, "headless") == 0) { return attempt_headless_backend(display, create_renderer_func); + } else if (strcmp(name, "noop") == 0) { + return attempt_noop_backend(display); } else if (strcmp(name, "drm") == 0 || strcmp(name, "libinput") == 0) { // DRM and libinput need a session if (!*session) { diff --git a/backend/meson.build b/backend/meson.build index bf9b4f83..39769ecd 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -20,6 +20,8 @@ backend_files = files( 'libinput/tablet_tool.c', 'libinput/touch.c', 'multi/backend.c', + 'noop/backend.c', + 'noop/output.c', 'session/direct-ipc.c', 'session/session.c', 'wayland/backend.c', diff --git a/backend/noop/backend.c b/backend/noop/backend.c new file mode 100644 index 00000000..340fce0d --- /dev/null +++ b/backend/noop/backend.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include "backend/noop.h" +#include "util/signal.h" + +struct wlr_noop_backend *noop_backend_from_backend( + struct wlr_backend *wlr_backend) { + assert(wlr_backend_is_noop(wlr_backend)); + return (struct wlr_noop_backend *)wlr_backend; +} + +static bool backend_start(struct wlr_backend *wlr_backend) { + struct wlr_noop_backend *backend = noop_backend_from_backend(wlr_backend); + wlr_log(WLR_INFO, "Starting noop backend"); + + struct wlr_noop_output *output; + wl_list_for_each(output, &backend->outputs, link) { + wlr_output_update_enabled(&output->wlr_output, true); + wlr_signal_emit_safe(&backend->backend.events.new_output, + &output->wlr_output); + } + + backend->started = true; + return true; +} + +static void backend_destroy(struct wlr_backend *wlr_backend) { + struct wlr_noop_backend *backend = noop_backend_from_backend(wlr_backend); + if (!wlr_backend) { + return; + } + + struct wlr_noop_output *output, *output_tmp; + wl_list_for_each_safe(output, output_tmp, &backend->outputs, link) { + wlr_output_destroy(&output->wlr_output); + } + + wlr_signal_emit_safe(&wlr_backend->events.destroy, backend); + + free(backend); +} + +static const struct wlr_backend_impl backend_impl = { + .start = backend_start, + .destroy = backend_destroy, +}; + +struct wlr_backend *wlr_noop_backend_create(struct wl_display *display) { + wlr_log(WLR_INFO, "Creating noop backend"); + + struct wlr_noop_backend *backend = + calloc(1, sizeof(struct wlr_noop_backend)); + if (!backend) { + wlr_log(WLR_ERROR, "Failed to allocate wlr_noop_backend"); + return NULL; + } + wlr_backend_init(&backend->backend, &backend_impl); + backend->display = display; + wl_list_init(&backend->outputs); + + return &backend->backend; +} + +bool wlr_backend_is_noop(struct wlr_backend *backend) { + return backend->impl == &backend_impl; +} diff --git a/backend/noop/output.c b/backend/noop/output.c new file mode 100644 index 00000000..a2595eff --- /dev/null +++ b/backend/noop/output.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include "backend/noop.h" +#include "util/signal.h" + +static struct wlr_noop_output *noop_output_from_output( + struct wlr_output *wlr_output) { + assert(wlr_output_is_noop(wlr_output)); + return (struct wlr_noop_output *)wlr_output; +} + +static void output_transform(struct wlr_output *wlr_output, + enum wl_output_transform transform) { + // empty +} + +static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age) { + return true; +} + +static bool output_swap_buffers(struct wlr_output *wlr_output, + pixman_region32_t *damage) { + return true; +} + +static void output_destroy(struct wlr_output *wlr_output) { + struct wlr_noop_output *output = + noop_output_from_output(wlr_output); + + wl_list_remove(&output->link); + + free(output); +} + +static const struct wlr_output_impl output_impl = { + .transform = output_transform, + .destroy = output_destroy, + .make_current = output_make_current, + .swap_buffers = output_swap_buffers, +}; + +bool wlr_output_is_noop(struct wlr_output *wlr_output) { + return wlr_output->impl == &output_impl; +} + +struct wlr_output *wlr_noop_add_output(struct wlr_backend *wlr_backend) { + struct wlr_noop_backend *backend = noop_backend_from_backend(wlr_backend); + + struct wlr_noop_output *output = calloc(1, sizeof(struct wlr_noop_output)); + if (output == NULL) { + wlr_log(WLR_ERROR, "Failed to allocate wlr_noop_output"); + return NULL; + } + output->backend = backend; + wlr_output_init(&output->wlr_output, &backend->backend, &output_impl, + backend->display); + struct wlr_output *wlr_output = &output->wlr_output; + + strncpy(wlr_output->make, "noop", sizeof(wlr_output->make)); + strncpy(wlr_output->model, "noop", sizeof(wlr_output->model)); + snprintf(wlr_output->name, sizeof(wlr_output->name), "NOOP-%d", + wl_list_length(&backend->outputs) + 1); + + wl_list_insert(&backend->outputs, &output->link); + + if (backend->started) { + wlr_output_update_enabled(wlr_output, true); + wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output); + } + + return wlr_output; +} -- cgit v1.2.3