backend/session: operate on wlr_device

Instead of operating on FDs in {open,close}_device, operate on
wlr_devices. This avoids the device lookup in wlr_session and allows
callers to have access to wlr_device fields.

For now, we use it to remove wlr_session_signal_add and replace it with
a more idiomatic wlr_session.events.change field. In the future, other
events will be added.
This commit is contained in:
Simon Ser 2020-11-06 10:16:07 +01:00
parent 63df2bcbe6
commit 44a4792fd8
7 changed files with 69 additions and 68 deletions

View File

@ -151,7 +151,7 @@ static struct wlr_backend *attempt_noop_backend(struct wl_display *display) {
static struct wlr_backend *attempt_drm_backend(struct wl_display *display, static struct wlr_backend *attempt_drm_backend(struct wl_display *display,
struct wlr_backend *backend, struct wlr_session *session, struct wlr_backend *backend, struct wlr_session *session,
wlr_renderer_create_func_t create_renderer_func) { wlr_renderer_create_func_t create_renderer_func) {
int gpus[8]; struct wlr_device *gpus[8];
size_t num_gpus = wlr_session_find_gpus(session, 8, gpus); size_t num_gpus = wlr_session_find_gpus(session, 8, gpus);
struct wlr_backend *primary_drm = NULL; struct wlr_backend *primary_drm = NULL;
wlr_log(WLR_INFO, "Found %zu GPUs", num_gpus); wlr_log(WLR_INFO, "Found %zu GPUs", num_gpus);
@ -160,7 +160,7 @@ static struct wlr_backend *attempt_drm_backend(struct wl_display *display,
struct wlr_backend *drm = wlr_drm_backend_create(display, session, struct wlr_backend *drm = wlr_drm_backend_create(display, session,
gpus[i], primary_drm, create_renderer_func); gpus[i], primary_drm, create_renderer_func);
if (!drm) { if (!drm) {
wlr_log(WLR_ERROR, "Failed to open DRM device %d", gpus[i]); wlr_log(WLR_ERROR, "Failed to create DRM backend");
continue; continue;
} }

View File

@ -50,7 +50,7 @@ static void backend_destroy(struct wlr_backend *backend) {
finish_drm_resources(drm); finish_drm_resources(drm);
finish_drm_renderer(&drm->renderer); finish_drm_renderer(&drm->renderer);
wlr_session_close_file(drm->session, drm->fd); wlr_session_close_file(drm->session, drm->dev);
wl_event_source_remove(drm->drm_event); wl_event_source_remove(drm->drm_event);
free(drm); free(drm);
} }
@ -128,13 +128,14 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
} }
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
struct wlr_session *session, int gpu_fd, struct wlr_backend *parent, struct wlr_session *session, struct wlr_device *dev,
struct wlr_backend *parent,
wlr_renderer_create_func_t create_renderer_func) { wlr_renderer_create_func_t create_renderer_func) {
assert(display && session && gpu_fd >= 0); assert(display && session && dev);
assert(!parent || wlr_backend_is_drm(parent)); assert(!parent || wlr_backend_is_drm(parent));
char *name = drmGetDeviceNameFromFd2(gpu_fd); char *name = drmGetDeviceNameFromFd2(dev->fd);
drmVersion *version = drmGetVersion(gpu_fd); drmVersion *version = drmGetVersion(dev->fd);
wlr_log(WLR_INFO, "Initializing DRM backend for %s (%s)", name, version->name); wlr_log(WLR_INFO, "Initializing DRM backend for %s (%s)", name, version->name);
free(name); free(name);
drmFreeVersion(version); drmFreeVersion(version);
@ -149,13 +150,14 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
drm->session = session; drm->session = session;
wl_list_init(&drm->outputs); wl_list_init(&drm->outputs);
drm->fd = gpu_fd; drm->dev = dev;
drm->fd = dev->fd;
if (parent != NULL) { if (parent != NULL) {
drm->parent = get_drm_backend_from_backend(parent); drm->parent = get_drm_backend_from_backend(parent);
} }
drm->drm_invalidated.notify = drm_invalidated; drm->drm_invalidated.notify = drm_invalidated;
wlr_session_signal_add(session, gpu_fd, &drm->drm_invalidated); wl_signal_add(&dev->events.change, &drm->drm_invalidated);
drm->display = display; drm->display = display;
struct wl_event_loop *event_loop = wl_display_get_event_loop(display); struct wl_event_loop *event_loop = wl_display_get_event_loop(display);
@ -195,7 +197,7 @@ error_event:
wl_list_remove(&drm->session_signal.link); wl_list_remove(&drm->session_signal.link);
wl_event_source_remove(drm->drm_event); wl_event_source_remove(drm->drm_event);
error_fd: error_fd:
wlr_session_close_file(drm->session, drm->fd); wlr_session_close_file(drm->session, dev);
free(drm); free(drm);
return NULL; return NULL;
} }

View File

@ -17,12 +17,27 @@ static struct wlr_libinput_backend *get_libinput_backend_from_backend(
static int libinput_open_restricted(const char *path, static int libinput_open_restricted(const char *path,
int flags, void *_backend) { int flags, void *_backend) {
struct wlr_libinput_backend *backend = _backend; struct wlr_libinput_backend *backend = _backend;
return wlr_session_open_file(backend->session, path); struct wlr_device *dev = wlr_session_open_file(backend->session, path);
if (dev == NULL) {
return -1;
}
return dev->fd;
} }
static void libinput_close_restricted(int fd, void *_backend) { static void libinput_close_restricted(int fd, void *_backend) {
struct wlr_libinput_backend *backend = _backend; struct wlr_libinput_backend *backend = _backend;
wlr_session_close_file(backend->session, fd);
struct wlr_device *dev;
bool found = false;
wl_list_for_each(dev, &backend->session->devices, link) {
if (dev->fd == fd) {
found = true;
break;
}
}
if (found) {
wlr_session_close_file(backend->session, dev);
}
} }
static const struct libinput_interface libinput_impl = { static const struct libinput_interface libinput_impl = {

View File

@ -55,7 +55,7 @@ static int udev_event(int fd, uint32_t mask, void *data) {
wl_list_for_each(dev, &session->devices, link) { wl_list_for_each(dev, &session->devices, link) {
if (dev->dev == devnum) { if (dev->dev == devnum) {
wlr_signal_emit_safe(&dev->signal, session); wlr_signal_emit_safe(&dev->events.change, NULL);
break; break;
} }
} }
@ -169,10 +169,11 @@ void wlr_session_destroy(struct wlr_session *session) {
session->impl->destroy(session); session->impl->destroy(session);
} }
int wlr_session_open_file(struct wlr_session *session, const char *path) { struct wlr_device *wlr_session_open_file(struct wlr_session *session,
const char *path) {
int fd = session->impl->open(session, path); int fd = session->impl->open(session, path);
if (fd < 0) { if (fd < 0) {
return fd; return NULL;
} }
struct wlr_device *dev = malloc(sizeof(*dev)); struct wlr_device *dev = malloc(sizeof(*dev));
@ -189,46 +190,24 @@ int wlr_session_open_file(struct wlr_session *session, const char *path) {
dev->fd = fd; dev->fd = fd;
dev->dev = st.st_rdev; dev->dev = st.st_rdev;
wl_signal_init(&dev->signal); wl_signal_init(&dev->events.change);
wl_list_insert(&session->devices, &dev->link); wl_list_insert(&session->devices, &dev->link);
return fd; return dev;
error: error:
free(dev); free(dev);
close(fd); close(fd);
return -1;
}
static struct wlr_device *find_device(struct wlr_session *session, int fd) {
struct wlr_device *dev;
wl_list_for_each(dev, &session->devices, link) {
if (dev->fd == fd) {
return dev;
}
}
wlr_log(WLR_ERROR, "Tried to use fd %d not opened by session", fd);
assert(0);
return NULL; return NULL;
} }
void wlr_session_close_file(struct wlr_session *session, int fd) { void wlr_session_close_file(struct wlr_session *session,
struct wlr_device *dev = find_device(session, fd); struct wlr_device *dev) {
session->impl->close(session, dev->fd);
session->impl->close(session, fd);
wl_list_remove(&dev->link); wl_list_remove(&dev->link);
free(dev); free(dev);
} }
void wlr_session_signal_add(struct wlr_session *session, int fd,
struct wl_listener *listener) {
struct wlr_device *dev = find_device(session, fd);
wl_signal_add(&dev->signal, listener);
}
bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) { bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) {
if (!session) { if (!session) {
return false; return false;
@ -240,32 +219,32 @@ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) {
/* Tests if 'path' is KMS compatible by trying to open it. /* Tests if 'path' is KMS compatible by trying to open it.
* It leaves the open device in *fd_out it it succeeds. * It leaves the open device in *fd_out it it succeeds.
*/ */
static int open_if_kms(struct wlr_session *restrict session, static struct wlr_device *open_if_kms(struct wlr_session *restrict session,
const char *restrict path) { const char *restrict path) {
if (!path) { if (!path) {
return -1; return NULL;
} }
int fd = wlr_session_open_file(session, path); struct wlr_device *dev = wlr_session_open_file(session, path);
if (fd < 0) { if (!dev) {
return -1; return NULL;
} }
drmVersion *ver = drmGetVersion(fd); drmVersion *ver = drmGetVersion(dev->fd);
if (!ver) { if (!ver) {
goto out_fd; goto out_dev;
} }
drmFreeVersion(ver); drmFreeVersion(ver);
return fd; return dev;
out_fd: out_dev:
wlr_session_close_file(session, fd); wlr_session_close_file(session, dev);
return -1; return NULL;
} }
static size_t explicit_find_gpus(struct wlr_session *session, static size_t explicit_find_gpus(struct wlr_session *session,
size_t ret_len, int ret[static ret_len], const char *str) { size_t ret_len, struct wlr_device *ret[static ret_len], const char *str) {
char *gpus = strdup(str); char *gpus = strdup(str);
if (!gpus) { if (!gpus) {
wlr_log_errno(WLR_ERROR, "Allocation failed"); wlr_log_errno(WLR_ERROR, "Allocation failed");
@ -281,7 +260,7 @@ static size_t explicit_find_gpus(struct wlr_session *session,
} }
ret[i] = open_if_kms(session, ptr); ret[i] = open_if_kms(session, ptr);
if (ret[i] < 0) { if (!ret[i]) {
wlr_log(WLR_ERROR, "Unable to open %s as DRM device", ptr); wlr_log(WLR_ERROR, "Unable to open %s as DRM device", ptr);
} else { } else {
++i; ++i;
@ -296,7 +275,7 @@ static size_t explicit_find_gpus(struct wlr_session *session,
* If it's not found, it returns the first valid GPU it finds. * If it's not found, it returns the first valid GPU it finds.
*/ */
size_t wlr_session_find_gpus(struct wlr_session *session, size_t wlr_session_find_gpus(struct wlr_session *session,
size_t ret_len, int *ret) { size_t ret_len, struct wlr_device **ret) {
const char *explicit = getenv("WLR_DRM_DEVICES"); const char *explicit = getenv("WLR_DRM_DEVICES");
if (explicit) { if (explicit) {
return explicit_find_gpus(session, ret_len, ret, explicit); return explicit_find_gpus(session, ret_len, ret, explicit);
@ -348,17 +327,18 @@ size_t wlr_session_find_gpus(struct wlr_session *session,
} }
} }
int fd = open_if_kms(session, udev_device_get_devnode(dev)); struct wlr_device *wlr_dev =
if (fd < 0) { open_if_kms(session, udev_device_get_devnode(dev));
if (!wlr_dev) {
udev_device_unref(dev); udev_device_unref(dev);
continue; continue;
} }
udev_device_unref(dev); udev_device_unref(dev);
ret[i] = fd; ret[i] = wlr_dev;
if (is_boot_vga) { if (is_boot_vga) {
int tmp = ret[0]; struct wlr_device *tmp = ret[0];
ret[0] = ret[i]; ret[0] = ret[i];
ret[i] = tmp; ret[i] = tmp;
} }

View File

@ -82,6 +82,7 @@ struct wlr_drm_backend {
bool addfb2_modifiers; bool addfb2_modifiers;
int fd; int fd;
struct wlr_device *dev;
size_t num_crtcs; size_t num_crtcs;
struct wlr_drm_crtc *crtcs; struct wlr_drm_crtc *crtcs;

View File

@ -22,7 +22,8 @@
* a DRM backend, other kinds of backends raise SIGABRT). * a DRM backend, other kinds of backends raise SIGABRT).
*/ */
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
struct wlr_session *session, int gpu_fd, struct wlr_backend *parent, struct wlr_session *session, struct wlr_device *dev,
struct wlr_backend *parent,
wlr_renderer_create_func_t create_renderer_func); wlr_renderer_create_func_t create_renderer_func);
bool wlr_backend_is_drm(struct wlr_backend *backend); bool wlr_backend_is_drm(struct wlr_backend *backend);

View File

@ -11,9 +11,11 @@ struct session_impl;
struct wlr_device { struct wlr_device {
int fd; int fd;
dev_t dev; dev_t dev;
struct wl_signal signal;
struct wl_list link; struct wl_list link;
struct {
struct wl_signal change;
} events;
}; };
struct wlr_session { struct wlr_session {
@ -74,21 +76,21 @@ void wlr_session_destroy(struct wlr_session *session);
* *
* Returns -errno on error. * Returns -errno on error.
*/ */
int wlr_session_open_file(struct wlr_session *session, const char *path); struct wlr_device *wlr_session_open_file(struct wlr_session *session,
const char *path);
/* /*
* Closes a file previously opened with wlr_session_open_file. * Closes a file previously opened with wlr_session_open_file.
*/ */
void wlr_session_close_file(struct wlr_session *session, int fd); void wlr_session_close_file(struct wlr_session *session,
struct wlr_device *device);
void wlr_session_signal_add(struct wlr_session *session, int fd,
struct wl_listener *listener);
/* /*
* Changes the virtual terminal. * Changes the virtual terminal.
*/ */
bool wlr_session_change_vt(struct wlr_session *session, unsigned vt); bool wlr_session_change_vt(struct wlr_session *session, unsigned vt);
size_t wlr_session_find_gpus(struct wlr_session *session, size_t wlr_session_find_gpus(struct wlr_session *session,
size_t ret_len, int *ret); size_t ret_len, struct wlr_device **ret);
#endif #endif