Changed events to use wayland functions.

This commit is contained in:
Scott Anderson 2017-05-02 14:08:34 +12:00
parent 562d43a5ec
commit 115d4ae637
8 changed files with 127 additions and 197 deletions

View File

@ -11,7 +11,6 @@ add_library(wlr-backend
wayland/wl_output.c wayland/wl_output.c
drm/backend.c drm/backend.c
drm/drm.c drm/drm.c
drm/event.c
drm/session.c drm/session.c
drm/udev.c drm/udev.c
) )

View File

@ -6,7 +6,6 @@
#include "backend/drm/backend.h" #include "backend/drm/backend.h"
#include "backend/drm/drm.h" #include "backend/drm/drm.h"
#include "backend/drm/event.h"
#include "backend/drm/session.h" #include "backend/drm/session.h"
#include "backend/drm/udev.h" #include "backend/drm/udev.h"
#include "common/log.h" #include "common/log.h"
@ -19,12 +18,18 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
return NULL; return NULL;
} }
if (!wlr_session_start(&backend->session)) { backend->event_loop = wl_event_loop_create();
wlr_log(L_ERROR, "Failed to start session"); if (!backend->event_loop) {
goto error; 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"); wlr_log(L_ERROR, "Failed to start udev");
goto error_session; goto error_session;
} }
@ -40,6 +45,10 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
goto error_fd; 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); wlr_drm_scan_connectors(backend);
return backend; return backend;
@ -50,7 +59,9 @@ error_udev:
wlr_udev_free(&backend->udev); wlr_udev_free(&backend->udev);
error_session: error_session:
wlr_session_end(&backend->session); wlr_session_end(&backend->session);
error: error_loop:
wl_event_loop_destroy(backend->event_loop);
error_backend:
free(backend); free(backend);
return NULL; 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_release_device(&backend->session, backend->fd);
wlr_session_end(&backend->session); 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->displays);
free(backend); free(backend);
} }

View File

@ -11,10 +11,10 @@
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <gbm.h> #include <gbm.h>
#include <GLES3/gl3.h> #include <GLES3/gl3.h>
#include <wayland-server.h>
#include "backend/drm/backend.h" #include "backend/drm/backend.h"
#include "backend/drm/drm.h" #include "backend/drm/drm.h"
#include "backend/drm/event.h"
#include "common/log.h" #include "common/log.h"
static const char *conn_name[] = { static const char *conn_name[] = {
@ -134,6 +134,33 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out)
return false; 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, bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer,
struct wlr_drm_backend *backend, int fd) struct wlr_drm_backend *backend, int fd)
{ {
@ -177,6 +204,13 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer,
goto error_egl; 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->fd = fd;
renderer->backend = backend; renderer->backend = backend;
@ -252,13 +286,13 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
if (disp->state == DRM_DISP_DISCONNECTED && if (disp->state == DRM_DISP_DISCONNECTED &&
conn->connection == DRM_MODE_CONNECTED) { conn->connection == DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_NEEDS_MODESET; 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 && } else if (disp->state == DRM_DISP_CONNECTED &&
conn->connection != DRM_MODE_CONNECTED) { conn->connection != DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_DISCONNECTED; disp->state = DRM_DISP_DISCONNECTED;
wlr_drm_display_free(disp, false); 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); drmModeFreeConnector(conn);
@ -488,24 +522,11 @@ error:
drmModeFreeConnector(conn); drmModeFreeConnector(conn);
free(disp->modes); free(disp->modes);
wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM); wl_signal_emit(&backend->signals.display_rem, disp);
return false; 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) void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore)
{ {
if (!disp || disp->state != DRM_DISP_CONNECTED) 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) void wlr_drm_display_begin(struct wlr_drm_display *disp)
{ {
struct wlr_drm_renderer *renderer = disp->renderer; struct wlr_drm_renderer *renderer = disp->renderer;

View File

@ -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;
}

View File

@ -7,6 +7,7 @@
#include <stdint.h> #include <stdint.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include <wayland-server.h>
#include "backend/drm/backend.h" #include "backend/drm/backend.h"
#include "backend/drm/udev.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; return fd;
} }
bool wlr_udev_init(struct wlr_udev *udev) static int udev_event(int fd, uint32_t mask, void *data)
{
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)
{ {
struct wlr_drm_backend *backend = data;
struct wlr_udev *udev = &backend->udev; struct wlr_udev *udev = &backend->udev;
struct udev_device *dev = udev_monitor_receive_device(udev->mon); struct udev_device *dev = udev_monitor_receive_device(udev->mon);
if (!dev) if (!dev)
return; return 1;
const char *path = udev_device_get_devnode(dev); const char *path = udev_device_get_devnode(dev);
if (!path || strcmp(path, udev->drm_path) != 0) if (!path || strcmp(path, udev->drm_path) != 0)
@ -171,4 +138,54 @@ void wlr_udev_event(struct wlr_drm_backend *backend)
out: out:
udev_device_unref(dev); 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);
} }

View File

@ -6,6 +6,7 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include <gbm.h> #include <gbm.h>
#include <libudev.h> #include <libudev.h>
#include <wayland-server.h>
#include "session.h" #include "session.h"
#include "udev.h" #include "udev.h"
@ -16,10 +17,18 @@ struct wlr_drm_backend {
int fd; int fd;
bool paused; bool paused;
// Priority Queue (Max-heap) struct wl_event_loop *event_loop;
size_t event_cap;
size_t event_len; struct {
struct wlr_drm_event *events; 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; size_t display_len;
struct wlr_drm_display *displays; struct wlr_drm_display *displays;

View File

@ -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

View File

@ -8,15 +8,14 @@
struct wlr_udev { struct wlr_udev {
struct udev *udev; struct udev *udev;
struct udev_monitor *mon; struct udev_monitor *mon;
int mon_fd;
char *drm_path; 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); void wlr_udev_free(struct wlr_udev *udev);
int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session); 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); void wlr_udev_event(struct wlr_drm_backend *backend);
#endif #endif