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,
struct wlr_backend *backend, struct wlr_session *session,
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);
struct wlr_backend *primary_drm = NULL;
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,
gpus[i], primary_drm, create_renderer_func);
if (!drm) {
wlr_log(WLR_ERROR, "Failed to open DRM device %d", gpus[i]);
wlr_log(WLR_ERROR, "Failed to create DRM backend");
continue;
}

View file

@ -50,7 +50,7 @@ static void backend_destroy(struct wlr_backend *backend) {
finish_drm_resources(drm);
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);
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_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) {
assert(display && session && gpu_fd >= 0);
assert(display && session && dev);
assert(!parent || wlr_backend_is_drm(parent));
char *name = drmGetDeviceNameFromFd2(gpu_fd);
drmVersion *version = drmGetVersion(gpu_fd);
char *name = drmGetDeviceNameFromFd2(dev->fd);
drmVersion *version = drmGetVersion(dev->fd);
wlr_log(WLR_INFO, "Initializing DRM backend for %s (%s)", name, version->name);
free(name);
drmFreeVersion(version);
@ -149,13 +150,14 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
drm->session = session;
wl_list_init(&drm->outputs);
drm->fd = gpu_fd;
drm->dev = dev;
drm->fd = dev->fd;
if (parent != NULL) {
drm->parent = get_drm_backend_from_backend(parent);
}
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;
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_event_source_remove(drm->drm_event);
error_fd:
wlr_session_close_file(drm->session, drm->fd);
wlr_session_close_file(drm->session, dev);
free(drm);
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,
int flags, void *_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) {
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 = {

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) {
if (dev->dev == devnum) {
wlr_signal_emit_safe(&dev->signal, session);
wlr_signal_emit_safe(&dev->events.change, NULL);
break;
}
}
@ -169,10 +169,11 @@ void wlr_session_destroy(struct wlr_session *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);
if (fd < 0) {
return fd;
return NULL;
}
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->dev = st.st_rdev;
wl_signal_init(&dev->signal);
wl_signal_init(&dev->events.change);
wl_list_insert(&session->devices, &dev->link);
return fd;
return dev;
error:
free(dev);
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;
}
void wlr_session_close_file(struct wlr_session *session, int fd) {
struct wlr_device *dev = find_device(session, fd);
session->impl->close(session, fd);
void wlr_session_close_file(struct wlr_session *session,
struct wlr_device *dev) {
session->impl->close(session, dev->fd);
wl_list_remove(&dev->link);
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) {
if (!session) {
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.
* 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) {
if (!path) {
return -1;
return NULL;
}
int fd = wlr_session_open_file(session, path);
if (fd < 0) {
return -1;
struct wlr_device *dev = wlr_session_open_file(session, path);
if (!dev) {
return NULL;
}
drmVersion *ver = drmGetVersion(fd);
drmVersion *ver = drmGetVersion(dev->fd);
if (!ver) {
goto out_fd;
goto out_dev;
}
drmFreeVersion(ver);
return fd;
return dev;
out_fd:
wlr_session_close_file(session, fd);
return -1;
out_dev:
wlr_session_close_file(session, dev);
return NULL;
}
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);
if (!gpus) {
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);
if (ret[i] < 0) {
if (!ret[i]) {
wlr_log(WLR_ERROR, "Unable to open %s as DRM device", ptr);
} else {
++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.
*/
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");
if (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));
if (fd < 0) {
struct wlr_device *wlr_dev =
open_if_kms(session, udev_device_get_devnode(dev));
if (!wlr_dev) {
udev_device_unref(dev);
continue;
}
udev_device_unref(dev);
ret[i] = fd;
ret[i] = wlr_dev;
if (is_boot_vga) {
int tmp = ret[0];
struct wlr_device *tmp = ret[0];
ret[0] = ret[i];
ret[i] = tmp;
}

View file

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

View file

@ -22,7 +22,8 @@
* a DRM backend, other kinds of backends raise SIGABRT).
*/
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);
bool wlr_backend_is_drm(struct wlr_backend *backend);

View file

@ -11,9 +11,11 @@ struct session_impl;
struct wlr_device {
int fd;
dev_t dev;
struct wl_signal signal;
struct wl_list link;
struct {
struct wl_signal change;
} events;
};
struct wlr_session {
@ -74,21 +76,21 @@ void wlr_session_destroy(struct wlr_session *session);
*
* 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.
*/
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.
*/
bool wlr_session_change_vt(struct wlr_session *session, unsigned vt);
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