Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update to 0.18.0 #13

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 147 additions & 42 deletions backend/backend.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
Expand All @@ -16,6 +15,7 @@
#include "backend/backend.h"
#include "backend/multi.h"
#include "render/allocator/allocator.h"
#include "types/wlr_output.h"
#include "util/env.h"
#include "util/time.h"

Expand Down Expand Up @@ -71,9 +71,9 @@ void wlr_backend_destroy(struct wlr_backend *backend) {
}
}

static struct wlr_session *session_create_and_wait(struct wl_display *disp) {
static struct wlr_session *session_create_and_wait(struct wl_event_loop *loop) {
#if WLR_HAS_SESSION
struct wlr_session *session = wlr_session_create(disp);
struct wlr_session *session = wlr_session_create(loop);

if (!session) {
wlr_log(WLR_ERROR, "Failed to start a session");
Expand All @@ -85,11 +85,9 @@ static struct wlr_session *session_create_and_wait(struct wl_display *disp) {

int64_t started_at = get_current_time_msec();
int64_t timeout = WAIT_SESSION_TIMEOUT;
struct wl_event_loop *event_loop =
wl_display_get_event_loop(session->display);

while (!session->active) {
int ret = wl_event_loop_dispatch(event_loop, (int)timeout);
int ret = wl_event_loop_dispatch(loop, (int)timeout);
if (ret < 0) {
wlr_log_errno(WLR_ERROR, "Failed to wait for session active: "
"wl_event_loop_dispatch failed");
Expand Down Expand Up @@ -147,8 +145,55 @@ static size_t parse_outputs_env(const char *name) {
return outputs;
}

static struct wlr_backend *attempt_wl_backend(struct wl_display *display) {
struct wlr_backend *backend = wlr_wl_backend_create(display, NULL);
/**
* Helper to destroy the multi backend when one of its nested backends is
* destroyed.
*/
struct wlr_auto_backend_monitor {
struct wlr_backend *multi;
struct wlr_backend *primary;

struct wl_listener multi_destroy;
struct wl_listener primary_destroy;
};

static void auto_backend_monitor_destroy(struct wlr_auto_backend_monitor *monitor) {
wl_list_remove(&monitor->multi_destroy.link);
wl_list_remove(&monitor->primary_destroy.link);
free(monitor);
}

static void monitor_handle_multi_destroy(struct wl_listener *listener, void *data) {
struct wlr_auto_backend_monitor *monitor = wl_container_of(listener, monitor, multi_destroy);
auto_backend_monitor_destroy(monitor);
}

static void monitor_handle_primary_destroy(struct wl_listener *listener, void *data) {
struct wlr_auto_backend_monitor *monitor = wl_container_of(listener, monitor, primary_destroy);
wlr_backend_destroy(monitor->multi);
}

static struct wlr_auto_backend_monitor *auto_backend_monitor_create(
struct wlr_backend *multi, struct wlr_backend *primary) {
struct wlr_auto_backend_monitor *monitor = calloc(1, sizeof(*monitor));
if (monitor == NULL) {
return NULL;
}

monitor->multi = multi;
monitor->primary = primary;

monitor->multi_destroy.notify = monitor_handle_multi_destroy;
wl_signal_add(&multi->events.destroy, &monitor->multi_destroy);

monitor->primary_destroy.notify = monitor_handle_primary_destroy;
wl_signal_add(&primary->events.destroy, &monitor->primary_destroy);

return monitor;
}

static struct wlr_backend *attempt_wl_backend(struct wl_event_loop *loop) {
struct wlr_backend *backend = wlr_wl_backend_create(loop, NULL);
if (backend == NULL) {
return NULL;
}
Expand All @@ -161,10 +206,10 @@ static struct wlr_backend *attempt_wl_backend(struct wl_display *display) {
return backend;
}

static struct wlr_backend *attempt_x11_backend(struct wl_display *display,
static struct wlr_backend *attempt_x11_backend(struct wl_event_loop *loop,
const char *x11_display) {
#if WLR_HAS_X11_BACKEND
struct wlr_backend *backend = wlr_x11_backend_create(display, x11_display);
struct wlr_backend *backend = wlr_x11_backend_create(loop, x11_display);
if (backend == NULL) {
return NULL;
}
Expand All @@ -181,9 +226,8 @@ static struct wlr_backend *attempt_x11_backend(struct wl_display *display,
#endif
}

static struct wlr_backend *attempt_headless_backend(
struct wl_display *display) {
struct wlr_backend *backend = wlr_headless_backend_create(display);
static struct wlr_backend *attempt_headless_backend(struct wl_event_loop *loop) {
struct wlr_backend *backend = wlr_headless_backend_create(loop);
if (backend == NULL) {
return NULL;
}
Expand All @@ -196,27 +240,25 @@ static struct wlr_backend *attempt_headless_backend(
return backend;
}

static bool attempt_drm_backend(struct wl_display *display,
struct wlr_backend *backend, struct wlr_session *session) {
static struct wlr_backend *attempt_drm_backend(struct wlr_backend *backend, struct wlr_session *session) {
#if WLR_HAS_DRM_BACKEND
struct wlr_device *gpus[8];
ssize_t num_gpus = wlr_session_find_gpus(session, 8, gpus);
if (num_gpus < 0) {
wlr_log(WLR_ERROR, "Failed to find GPUs");
return false;
return NULL;
}

if (num_gpus == 0) {
wlr_log(WLR_ERROR, "Found 0 GPUs, cannot create backend");
return false;
return NULL;
} else {
wlr_log(WLR_INFO, "Found %zu GPUs", num_gpus);
}

struct wlr_backend *primary_drm = NULL;
for (size_t i = 0; i < (size_t)num_gpus; ++i) {
struct wlr_backend *drm = wlr_drm_backend_create(display, session,
gpus[i], primary_drm);
struct wlr_backend *drm = wlr_drm_backend_create(session, gpus[i], primary_drm);
if (!drm) {
wlr_log(WLR_ERROR, "Failed to create DRM backend");
continue;
Expand All @@ -237,48 +279,47 @@ static bool attempt_drm_backend(struct wl_display *display,
drm_backend_monitor_create(backend, primary_drm, session);
}

return true;
return primary_drm;
#else
wlr_log(WLR_ERROR, "Cannot create DRM backend: disabled at compile-time");
return false;
return NULL;
#endif
}

static struct wlr_backend *attempt_libinput_backend(struct wl_display *display,
struct wlr_session *session) {
static struct wlr_backend *attempt_libinput_backend(struct wlr_session *session) {
#if WLR_HAS_LIBINPUT_BACKEND
return wlr_libinput_backend_create(display, session);
return wlr_libinput_backend_create(session);
#else
wlr_log(WLR_ERROR, "Cannot create libinput backend: disabled at compile-time");
return NULL;
#endif
}

static bool attempt_backend_by_name(struct wl_display *display,
static bool attempt_backend_by_name(struct wl_event_loop *loop,
struct wlr_backend *multi, char *name,
struct wlr_session **session_ptr) {
struct wlr_backend *backend = NULL;
if (strcmp(name, "wayland") == 0) {
backend = attempt_wl_backend(display);
backend = attempt_wl_backend(loop);
} else if (strcmp(name, "x11") == 0) {
backend = attempt_x11_backend(display, NULL);
backend = attempt_x11_backend(loop, NULL);
} else if (strcmp(name, "headless") == 0) {
backend = attempt_headless_backend(display);
backend = attempt_headless_backend(loop);
} else if (strcmp(name, "drm") == 0 || strcmp(name, "libinput") == 0) {
// DRM and libinput need a session
if (*session_ptr == NULL) {
*session_ptr = session_create_and_wait(display);
*session_ptr = session_create_and_wait(loop);
if (*session_ptr == NULL) {
wlr_log(WLR_ERROR, "failed to start a session");
return false;
}
}

if (strcmp(name, "libinput") == 0) {
backend = attempt_libinput_backend(display, *session_ptr);
backend = attempt_libinput_backend(*session_ptr);
} else {
// attempt_drm_backend() adds the multi drm backends itself
return attempt_drm_backend(display, multi, *session_ptr);
return attempt_drm_backend(multi, *session_ptr) != NULL;
}
} else {
wlr_log(WLR_ERROR, "unrecognized backend '%s'", name);
Expand All @@ -291,14 +332,14 @@ static bool attempt_backend_by_name(struct wl_display *display,
return wlr_multi_backend_add(multi, backend);
}

struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
struct wlr_backend *wlr_backend_autocreate(struct wl_event_loop *loop,
struct wlr_session **session_ptr) {
if (session_ptr != NULL) {
*session_ptr = NULL;
}

struct wlr_session *session = NULL;
struct wlr_backend *multi = wlr_multi_backend_create(display);
struct wlr_backend *multi = wlr_multi_backend_create(loop);
if (!multi) {
wlr_log(WLR_ERROR, "could not allocate multibackend");
return NULL;
Expand All @@ -318,7 +359,7 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
char *saveptr;
char *name = strtok_r(names, ",", &saveptr);
while (name != NULL) {
if (!attempt_backend_by_name(display, multi, name, &session)) {
if (!attempt_backend_by_name(loop, multi, name, &session)) {
wlr_log(WLR_ERROR, "failed to add backend '%s'", name);
free(names);
goto error;
Expand All @@ -332,37 +373,47 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
}

if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET")) {
struct wlr_backend *wl_backend = attempt_wl_backend(display);
struct wlr_backend *wl_backend = attempt_wl_backend(loop);
if (!wl_backend) {
goto error;
}

wlr_multi_backend_add(multi, wl_backend);

if (!auto_backend_monitor_create(multi, wl_backend)) {
goto error;
}

goto success;
}

const char *x11_display = getenv("DISPLAY");
if (x11_display) {
struct wlr_backend *x11_backend =
attempt_x11_backend(display, x11_display);
struct wlr_backend *x11_backend = attempt_x11_backend(loop, x11_display);
if (!x11_backend) {
goto error;
}

wlr_multi_backend_add(multi, x11_backend);

if (!auto_backend_monitor_create(multi, x11_backend)) {
goto error;
}

goto success;
}

// Attempt DRM+libinput
session = session_create_and_wait(display);
session = session_create_and_wait(loop);
if (!session) {
wlr_log(WLR_ERROR, "Failed to start a DRM session");
goto error;
}

struct wlr_backend *libinput = attempt_libinput_backend(display, session);
struct wlr_backend *libinput = attempt_libinput_backend(session);
if (libinput) {
wlr_multi_backend_add(multi, libinput);
if (!auto_backend_monitor_create(multi, libinput)) {
goto error;
}
} else if (env_parse_bool("WLR_LIBINPUT_NO_DEVICES")) {
wlr_log(WLR_INFO, "WLR_LIBINPUT_NO_DEVICES is set, "
"starting without libinput backend");
Expand All @@ -372,11 +423,16 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
goto error;
}

if (!attempt_drm_backend(display, multi, session)) {
struct wlr_backend *primary_drm = attempt_drm_backend(multi, session);
if (primary_drm == NULL) {
wlr_log(WLR_ERROR, "Failed to open any DRM device");
goto error;
}

if (!auto_backend_monitor_create(multi, primary_drm)) {
goto error;
}

success:
if (session_ptr != NULL) {
*session_ptr = session;
Expand All @@ -390,3 +446,52 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display,
#endif
return NULL;
}

bool wlr_backend_test(struct wlr_backend *backend,
const struct wlr_backend_output_state *states, size_t states_len) {
if (backend->impl->test) {
return backend->impl->test(backend, states, states_len);
}

for (size_t i = 0; i < states_len; i++) {
const struct wlr_backend_output_state *state = &states[i];
assert(state->output->backend == backend);
if (!wlr_output_test_state(states[i].output, &state->base)) {
return false;
}
}

return true;
}

bool wlr_backend_commit(struct wlr_backend *backend,
const struct wlr_backend_output_state *states, size_t states_len) {
if (!backend->impl->commit) {
for (size_t i = 0; i < states_len; i++) {
const struct wlr_backend_output_state *state = &states[i];
if (!wlr_output_commit_state(state->output, &state->base)) {
return false;
}
}

return true;
}

for (size_t i = 0; i < states_len; i++) {
const struct wlr_backend_output_state *state = &states[i];
if (!output_prepare_commit(state->output, &state->base)) {
return false;
}
}

if (!backend->impl->commit(backend, states, states_len)) {
return false;
}

for (size_t i = 0; i < states_len; i++) {
const struct wlr_backend_output_state *state = &states[i];
output_apply_commit(state->output, &state->base);
}

return true;
}
Loading
Loading