mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2024-11-21 14:42:25 +00:00
Changed events to use wayland functions.
This commit is contained in:
parent
562d43a5ec
commit
115d4ae637
@ -11,7 +11,6 @@ add_library(wlr-backend
|
||||
wayland/wl_output.c
|
||||
drm/backend.c
|
||||
drm/drm.c
|
||||
drm/event.c
|
||||
drm/session.c
|
||||
drm/udev.c
|
||||
)
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "backend/drm/backend.h"
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/event.h"
|
||||
#include "backend/drm/session.h"
|
||||
#include "backend/drm/udev.h"
|
||||
#include "common/log.h"
|
||||
@ -19,12 +18,18 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!wlr_session_start(&backend->session)) {
|
||||
wlr_log(L_ERROR, "Failed to start session");
|
||||
goto error;
|
||||
backend->event_loop = wl_event_loop_create();
|
||||
if (!backend->event_loop) {
|
||||
wlr_log(L_ERROR, "Failed to create event loop");
|
||||
goto error_backend;
|
||||
}
|
||||
|
||||
if (!wlr_udev_init(&backend->udev)) {
|
||||
if (!wlr_session_start(&backend->session)) {
|
||||
wlr_log(L_ERROR, "Failed to start session");
|
||||
goto error_loop;
|
||||
}
|
||||
|
||||
if (!wlr_udev_init(backend)) {
|
||||
wlr_log(L_ERROR, "Failed to start udev");
|
||||
goto error_session;
|
||||
}
|
||||
@ -40,6 +45,10 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
|
||||
goto error_fd;
|
||||
}
|
||||
|
||||
wl_signal_init(&backend->signals.display_add);
|
||||
wl_signal_init(&backend->signals.display_rem);
|
||||
wl_signal_init(&backend->signals.display_render);
|
||||
|
||||
wlr_drm_scan_connectors(backend);
|
||||
|
||||
return backend;
|
||||
@ -50,7 +59,9 @@ error_udev:
|
||||
wlr_udev_free(&backend->udev);
|
||||
error_session:
|
||||
wlr_session_end(&backend->session);
|
||||
error:
|
||||
error_loop:
|
||||
wl_event_loop_destroy(backend->event_loop);
|
||||
error_backend:
|
||||
free(backend);
|
||||
return NULL;
|
||||
}
|
||||
@ -69,7 +80,9 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend)
|
||||
wlr_session_release_device(&backend->session, backend->fd);
|
||||
wlr_session_end(&backend->session);
|
||||
|
||||
free(backend->events);
|
||||
wl_event_source_remove(backend->event_src.drm);
|
||||
wl_event_loop_destroy(backend->event_loop);
|
||||
|
||||
free(backend->displays);
|
||||
free(backend);
|
||||
}
|
||||
|
@ -11,10 +11,10 @@
|
||||
#include <EGL/eglext.h>
|
||||
#include <gbm.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "backend/drm/backend.h"
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/event.h"
|
||||
#include "common/log.h"
|
||||
|
||||
static const char *conn_name[] = {
|
||||
@ -134,6 +134,33 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void page_flip_handler(int fd,
|
||||
unsigned seq,
|
||||
unsigned tv_sec,
|
||||
unsigned tv_usec,
|
||||
void *user)
|
||||
{
|
||||
struct wlr_drm_display *disp = user;
|
||||
struct wlr_drm_backend *backend = disp->renderer->backend;
|
||||
|
||||
disp->pageflip_pending = true;
|
||||
if (!disp->cleanup)
|
||||
wl_signal_emit(&backend->signals.display_render, disp);
|
||||
}
|
||||
|
||||
|
||||
static int drm_event(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
drmEventContext event = {
|
||||
.version = DRM_EVENT_CONTEXT_VERSION,
|
||||
.page_flip_handler = page_flip_handler,
|
||||
};
|
||||
|
||||
drmHandleEvent(fd, &event);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer,
|
||||
struct wlr_drm_backend *backend, int fd)
|
||||
{
|
||||
@ -177,6 +204,13 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer,
|
||||
goto error_egl;
|
||||
}
|
||||
|
||||
backend->event_src.drm = wl_event_loop_add_fd(backend->event_loop,
|
||||
backend->fd, WL_EVENT_READABLE, drm_event, NULL);
|
||||
if (!backend->event_src.drm) {
|
||||
wlr_log(L_ERROR, "Failed to create DRM event source");
|
||||
goto error_egl;
|
||||
}
|
||||
|
||||
renderer->fd = fd;
|
||||
renderer->backend = backend;
|
||||
|
||||
@ -252,13 +286,13 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
|
||||
if (disp->state == DRM_DISP_DISCONNECTED &&
|
||||
conn->connection == DRM_MODE_CONNECTED) {
|
||||
disp->state = DRM_DISP_NEEDS_MODESET;
|
||||
wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_ADD);
|
||||
wl_signal_emit(&backend->signals.display_add, disp);
|
||||
|
||||
} else if (disp->state == DRM_DISP_CONNECTED &&
|
||||
conn->connection != DRM_MODE_CONNECTED) {
|
||||
disp->state = DRM_DISP_DISCONNECTED;
|
||||
wlr_drm_display_free(disp, false);
|
||||
wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM);
|
||||
wl_signal_emit(&backend->signals.display_rem, disp);
|
||||
}
|
||||
|
||||
drmModeFreeConnector(conn);
|
||||
@ -488,24 +522,11 @@ error:
|
||||
drmModeFreeConnector(conn);
|
||||
free(disp->modes);
|
||||
|
||||
wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM);
|
||||
wl_signal_emit(&backend->signals.display_rem, disp);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void page_flip_handler(int fd,
|
||||
unsigned seq,
|
||||
unsigned tv_sec,
|
||||
unsigned tv_usec,
|
||||
void *user)
|
||||
{
|
||||
struct wlr_drm_display *disp = user;
|
||||
|
||||
disp->pageflip_pending = true;
|
||||
if (!disp->cleanup)
|
||||
wlr_drm_add_event(disp->renderer->backend, disp, DRM_EV_RENDER);
|
||||
}
|
||||
|
||||
void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore)
|
||||
{
|
||||
if (!disp || disp->state != DRM_DISP_CONNECTED)
|
||||
@ -542,16 +563,6 @@ void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore)
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_drm_event(int fd)
|
||||
{
|
||||
drmEventContext event = {
|
||||
.version = DRM_EVENT_CONTEXT_VERSION,
|
||||
.page_flip_handler = page_flip_handler,
|
||||
};
|
||||
|
||||
drmHandleEvent(fd, &event);
|
||||
}
|
||||
|
||||
void wlr_drm_display_begin(struct wlr_drm_display *disp)
|
||||
{
|
||||
struct wlr_drm_renderer *renderer = disp->renderer;
|
||||
|
@ -1,93 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "backend/drm/backend.h"
|
||||
#include "backend/drm/event.h"
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/udev.h"
|
||||
|
||||
static inline void event_swap(struct wlr_drm_event *a, struct wlr_drm_event *b)
|
||||
{
|
||||
struct wlr_drm_event tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
bool wlr_drm_get_event(struct wlr_drm_backend *backend,
|
||||
struct wlr_drm_event *restrict ret)
|
||||
{
|
||||
struct pollfd fds[] = {
|
||||
{ .fd = backend->fd, .events = POLLIN },
|
||||
{ .fd = backend->udev.mon_fd, .events = POLLIN },
|
||||
};
|
||||
|
||||
while (poll(fds, 2, 0) > 0) {
|
||||
if (fds[0].revents)
|
||||
wlr_drm_event(backend->fd);
|
||||
if (fds[1].revents)
|
||||
wlr_udev_event(backend);
|
||||
}
|
||||
|
||||
if (backend->event_len == 0) {
|
||||
ret->type = DRM_EV_NONE;
|
||||
ret->display = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_drm_event *ev = backend->events;
|
||||
|
||||
// Downheap
|
||||
*ret = ev[0];
|
||||
ev[0] = ev[--backend->event_len];
|
||||
|
||||
size_t i = 0;
|
||||
while (i < backend->event_len / 2) {
|
||||
size_t left = i * 2 + 1;
|
||||
size_t right = i * 2 + 2;
|
||||
size_t max = (ev[left].type > ev[right].type) ? left : right;
|
||||
|
||||
if (ev[i].type <= ev[max].type) {
|
||||
event_swap(&ev[i], &ev[max]);
|
||||
i = max;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wlr_drm_add_event(struct wlr_drm_backend *backend,
|
||||
struct wlr_drm_display *disp, enum wlr_drm_event_type type)
|
||||
{
|
||||
if (type == DRM_EV_NONE)
|
||||
return true;
|
||||
|
||||
if (backend->event_len == backend->event_cap) {
|
||||
size_t new_size = (backend->event_cap == 0) ? 8 : backend->event_cap * 2;
|
||||
|
||||
struct wlr_drm_event *new = realloc(backend->events, sizeof *new * new_size);
|
||||
if (!new) {
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->event_cap = new_size;
|
||||
backend->events = new;
|
||||
}
|
||||
|
||||
struct wlr_drm_event *ev = backend->events;
|
||||
|
||||
// Upheap
|
||||
size_t i = backend->event_len++;
|
||||
ev[i].type = type;
|
||||
ev[i].display = disp;
|
||||
|
||||
size_t j;
|
||||
while (i > 0 && ev[i].type > ev[(j = (i - 1) / 2)].type) {
|
||||
event_swap(&ev[i], &ev[j]);
|
||||
i = j;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#include <stdint.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "backend/drm/backend.h"
|
||||
#include "backend/drm/udev.h"
|
||||
@ -116,48 +117,14 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session)
|
||||
return fd;
|
||||
}
|
||||
|
||||
bool wlr_udev_init(struct wlr_udev *udev)
|
||||
{
|
||||
udev->udev = udev_new();
|
||||
if (!udev->udev) {
|
||||
wlr_log(L_ERROR, "Failed to create udev context");
|
||||
return false;
|
||||
}
|
||||
|
||||
udev->mon = udev_monitor_new_from_netlink(udev->udev, "udev");
|
||||
if (!udev->mon) {
|
||||
wlr_log(L_ERROR, "Failed to create udev monitor");
|
||||
udev_unref(udev->udev);
|
||||
return false;
|
||||
}
|
||||
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev->mon, "drm", NULL);
|
||||
udev_monitor_enable_receiving(udev->mon);
|
||||
|
||||
udev->mon_fd = udev_monitor_get_fd(udev->mon);
|
||||
udev->drm_path = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wlr_udev_free(struct wlr_udev *udev)
|
||||
|
||||
{
|
||||
if (!udev)
|
||||
return;
|
||||
|
||||
udev_monitor_unref(udev->mon);
|
||||
udev_unref(udev->udev);
|
||||
free(udev->drm_path);
|
||||
}
|
||||
|
||||
void wlr_udev_event(struct wlr_drm_backend *backend)
|
||||
static int udev_event(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
struct wlr_drm_backend *backend = data;
|
||||
struct wlr_udev *udev = &backend->udev;
|
||||
|
||||
struct udev_device *dev = udev_monitor_receive_device(udev->mon);
|
||||
if (!dev)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
const char *path = udev_device_get_devnode(dev);
|
||||
if (!path || strcmp(path, udev->drm_path) != 0)
|
||||
@ -171,4 +138,54 @@ void wlr_udev_event(struct wlr_drm_backend *backend)
|
||||
|
||||
out:
|
||||
udev_device_unref(dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wlr_udev_init(struct wlr_drm_backend *backend)
|
||||
{
|
||||
struct wlr_udev *udev = &backend->udev;
|
||||
|
||||
udev->udev = udev_new();
|
||||
if (!udev->udev) {
|
||||
wlr_log(L_ERROR, "Failed to create udev context");
|
||||
return false;
|
||||
}
|
||||
|
||||
udev->mon = udev_monitor_new_from_netlink(udev->udev, "udev");
|
||||
if (!udev->mon) {
|
||||
wlr_log(L_ERROR, "Failed to create udev monitor");
|
||||
goto error_udev;
|
||||
}
|
||||
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev->mon, "drm", NULL);
|
||||
udev_monitor_enable_receiving(udev->mon);
|
||||
|
||||
backend->event_src.udev = wl_event_loop_add_fd(backend->event_loop,
|
||||
udev_monitor_get_fd(udev->mon), WL_EVENT_READABLE,
|
||||
udev_event, backend);
|
||||
if (!backend->event_src.udev) {
|
||||
wlr_log(L_ERROR, "Failed to create udev event source");
|
||||
goto error_mon;
|
||||
}
|
||||
|
||||
udev->drm_path = NULL;
|
||||
|
||||
return true;
|
||||
|
||||
error_mon:
|
||||
udev_monitor_unref(udev->mon);
|
||||
error_udev:
|
||||
udev_unref(udev->udev);
|
||||
return false;
|
||||
}
|
||||
|
||||
void wlr_udev_free(struct wlr_udev *udev)
|
||||
|
||||
{
|
||||
if (!udev)
|
||||
return;
|
||||
|
||||
udev_monitor_unref(udev->mon);
|
||||
udev_unref(udev->udev);
|
||||
free(udev->drm_path);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <gbm.h>
|
||||
#include <libudev.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "session.h"
|
||||
#include "udev.h"
|
||||
@ -16,10 +17,18 @@ struct wlr_drm_backend {
|
||||
int fd;
|
||||
bool paused;
|
||||
|
||||
// Priority Queue (Max-heap)
|
||||
size_t event_cap;
|
||||
size_t event_len;
|
||||
struct wlr_drm_event *events;
|
||||
struct wl_event_loop *event_loop;
|
||||
|
||||
struct {
|
||||
struct wl_event_source *drm;
|
||||
struct wl_event_source *udev;
|
||||
} event_src;
|
||||
|
||||
struct {
|
||||
struct wl_signal display_add;
|
||||
struct wl_signal display_rem;
|
||||
struct wl_signal display_render;
|
||||
} signals;
|
||||
|
||||
size_t display_len;
|
||||
struct wlr_drm_display *displays;
|
||||
|
@ -1,25 +0,0 @@
|
||||
#ifndef EVENT_H
|
||||
#define EVENT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "drm.h"
|
||||
|
||||
enum wlr_drm_event_type {
|
||||
DRM_EV_NONE,
|
||||
DRM_EV_RENDER,
|
||||
DRM_EV_DISPLAY_REM,
|
||||
DRM_EV_DISPLAY_ADD,
|
||||
};
|
||||
|
||||
struct wlr_drm_event {
|
||||
enum wlr_drm_event_type type;
|
||||
struct wlr_drm_display *display;
|
||||
};
|
||||
|
||||
struct wlr_drm_backend;
|
||||
bool wlr_drm_get_event(struct wlr_drm_backend *backend,
|
||||
struct wlr_drm_event *restrict ret);
|
||||
bool wlr_drm_add_event(struct wlr_drm_backend *backend,
|
||||
struct wlr_drm_display *disp, enum wlr_drm_event_type type);
|
||||
|
||||
#endif
|
@ -8,15 +8,14 @@
|
||||
struct wlr_udev {
|
||||
struct udev *udev;
|
||||
struct udev_monitor *mon;
|
||||
int mon_fd;
|
||||
char *drm_path;
|
||||
};
|
||||
|
||||
bool wlr_udev_init(struct wlr_udev *udev);
|
||||
struct wlr_drm_backend;
|
||||
bool wlr_udev_init(struct wlr_drm_backend *backend);
|
||||
void wlr_udev_free(struct wlr_udev *udev);
|
||||
int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session);
|
||||
|
||||
struct wlr_drm_backend;
|
||||
void wlr_udev_event(struct wlr_drm_backend *backend);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user