diff options
-rw-r--r-- | backend/CMakeLists.txt | 2 | ||||
-rw-r--r-- | backend/drm/backend.c | 71 | ||||
-rw-r--r-- | backend/drm/drm.c | 188 | ||||
-rw-r--r-- | backend/drm/event.c | 54 | ||||
-rw-r--r-- | backend/drm/otd.c | 71 | ||||
-rw-r--r-- | backend/drm/session.c | 83 | ||||
-rw-r--r-- | backend/drm/udev.c | 79 | ||||
-rw-r--r-- | include/backend/drm/backend.h | 37 | ||||
-rw-r--r-- | include/backend/drm/drm.h | 52 | ||||
-rw-r--r-- | include/backend/drm/event.h | 24 | ||||
-rw-r--r-- | include/backend/drm/otd.h | 44 | ||||
-rw-r--r-- | include/backend/drm/session.h | 19 | ||||
-rw-r--r-- | include/backend/drm/udev.h | 21 |
13 files changed, 395 insertions, 350 deletions
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index c962b8ed..2d6e734f 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -9,9 +9,9 @@ add_library(wlr-backend wayland/registry.c wayland/wl_seat.c wayland/wl_output.c + drm/backend.c drm/drm.c drm/event.c - drm/otd.c drm/session.c drm/udev.c ) diff --git a/backend/drm/backend.c b/backend/drm/backend.c new file mode 100644 index 00000000..8c500190 --- /dev/null +++ b/backend/drm/backend.c @@ -0,0 +1,71 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +#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" + +struct wlr_drm_backend *wlr_drm_backend_init(void) +{ + struct wlr_drm_backend *backend = calloc(1, sizeof *backend); + if (!backend) + return NULL; + + if (!wlr_session_start(&backend->session)) { + fprintf(stderr, "Could not create session\n"); + goto error; + } + + if (!wlr_udev_init(&backend->udev)) { + fprintf(stderr, "Could not start udev\n"); + goto error_session; + } + + backend->fd = wlr_udev_find_gpu(&backend->udev, &backend->session); + if (backend->fd == -1) { + fprintf(stderr, "Could not open GPU\n"); + goto error_udev; + } + + if (!wlr_drm_renderer_init(&backend->renderer, backend, backend->fd)) { + fprintf(stderr, "Could not initalise renderer\n"); + goto error_fd; + } + + wlr_drm_scan_connectors(backend); + + return backend; + +error_fd: + wlr_session_release_device(&backend->session, backend->fd); +error_udev: + wlr_udev_free(&backend->udev); +error_session: + wlr_session_end(&backend->session); +error: + free(backend); + return NULL; +} + +void wlr_drm_backend_free(struct wlr_drm_backend *backend) +{ + if (!backend) + return; + + for (size_t i = 0; i < backend->display_len; ++i) { + wlr_drm_display_free(&backend->displays[i]); + } + + wlr_drm_renderer_free(&backend->renderer); + wlr_udev_free(&backend->udev); + wlr_session_release_device(&backend->session, backend->fd); + wlr_session_end(&backend->session); + + free(backend->events); + free(backend->displays); + free(backend); +} + diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 894d8513..c5b797c3 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1,4 +1,4 @@ -#include "backend/drm/otd.h" +#include "backend/drm/backend.h" #include "backend/drm/drm.h" #include "backend/drm/event.h" @@ -51,7 +51,7 @@ static bool egl_exts() return get_platform_display && create_platform_window_surface; } -bool egl_get_config(EGLDisplay disp, EGLConfig *out) +static bool egl_get_config(EGLDisplay disp, EGLConfig *out) { EGLint count = 0, matched = 0, ret; @@ -85,15 +85,16 @@ bool egl_get_config(EGLDisplay disp, EGLConfig *out) return false; } -bool init_renderer(struct otd *otd) +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, + struct wlr_drm_backend *backend, int fd) { if (!egl_exts()) { fprintf(stderr, "Could not get EGL extensions\n"); return false; } - otd->gbm = gbm_create_device(otd->fd); - if (!otd->gbm) { + renderer->gbm = gbm_create_device(fd); + if (!renderer->gbm) { fprintf(stderr, "Could not create gbm device: %s\n", strerror(errno)); return false; } @@ -103,103 +104,109 @@ bool init_renderer(struct otd *otd) goto error_gbm; } - otd->egl.disp = get_platform_display(EGL_PLATFORM_GBM_MESA, otd->gbm, NULL); - if (otd->egl.disp == EGL_NO_DISPLAY) { + renderer->egl.disp = get_platform_display(EGL_PLATFORM_GBM_MESA, renderer->gbm, NULL); + if (renderer->egl.disp == EGL_NO_DISPLAY) { fprintf(stderr, "Could not create EGL display\n"); goto error_gbm; } - if (eglInitialize(otd->egl.disp, NULL, NULL) == EGL_FALSE) { + if (eglInitialize(renderer->egl.disp, NULL, NULL) == EGL_FALSE) { fprintf(stderr, "Could not initalise EGL\n"); goto error_egl; } - if (!egl_get_config(otd->egl.disp, &otd->egl.conf)) { + if (!egl_get_config(renderer->egl.disp, &renderer->egl.conf)) { fprintf(stderr, "Could not get EGL config\n"); goto error_egl; } static const EGLint attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; - otd->egl.context = eglCreateContext(otd->egl.disp, otd->egl.conf, EGL_NO_CONTEXT, attribs); - if (otd->egl.context == EGL_NO_CONTEXT) { + + renderer->egl.context = eglCreateContext(renderer->egl.disp, + renderer->egl.conf, EGL_NO_CONTEXT, attribs); + + if (renderer->egl.context == EGL_NO_CONTEXT) { fprintf(stderr, "Could not create EGL context\n"); goto error_egl; } + renderer->fd = fd; + renderer->backend = backend; + return true; error_egl: - eglTerminate(otd->egl.disp); + eglTerminate(renderer->egl.disp); eglReleaseThread(); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); error_gbm: - gbm_device_destroy(otd->gbm); + gbm_device_destroy(renderer->gbm); return false; } -void destroy_renderer(struct otd *otd) +void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer) { - if (!otd) + if (!renderer) return; - eglDestroyContext(otd->egl.disp, otd->egl.context); - eglTerminate(otd->egl.disp); + eglDestroyContext(renderer->egl.disp, renderer->egl.context); + eglTerminate(renderer->egl.disp); eglReleaseThread(); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - gbm_device_destroy(otd->gbm); + gbm_device_destroy(renderer->gbm); } -void scan_connectors(struct otd *otd) +void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { - drmModeRes *res = drmModeGetResources(otd->fd); + drmModeRes *res = drmModeGetResources(backend->fd); if (!res) return; // I don't know if this needs to be allocated with realloc like this, // as it may not even be possible for the number of connectors to change. // I'll just have to see how DisplayPort MST works with DRM. - if ((size_t)res->count_connectors > otd->display_len) { - struct otd_display *new = realloc(otd->displays, sizeof *new * res->count_connectors); + if ((size_t)res->count_connectors > backend->display_len) { + struct wlr_drm_display *new = realloc(backend->displays, sizeof *new * res->count_connectors); if (!new) goto error; - for (int i = otd->display_len; i < res->count_connectors; ++i) { - new[i] = (struct otd_display) { - .state = OTD_DISP_INVALID, - .otd = otd, + for (int i = backend->display_len; i < res->count_connectors; ++i) { + new[i] = (struct wlr_drm_display) { + .state = DRM_DISP_INVALID, + .renderer = &backend->renderer, }; } - otd->display_len = res->count_connectors; - otd->displays = new; + backend->display_len = res->count_connectors; + backend->displays = new; } for (int i = 0; i < res->count_connectors; ++i) { - struct otd_display *disp = &otd->displays[i]; - drmModeConnector *conn = drmModeGetConnector(otd->fd, res->connectors[i]); + struct wlr_drm_display *disp = &backend->displays[i]; + drmModeConnector *conn = drmModeGetConnector(backend->fd, res->connectors[i]); if (!conn) continue; - if (otd->displays[i].state == OTD_DISP_INVALID) { - disp->state = OTD_DISP_DISCONNECTED; + if (backend->displays[i].state == DRM_DISP_INVALID) { + disp->state = DRM_DISP_DISCONNECTED; disp->connector = res->connectors[i]; snprintf(disp->name, sizeof disp->name, "%s-%"PRIu32, conn_name[conn->connector_type], conn->connector_type_id); } - if (disp->state == OTD_DISP_DISCONNECTED && + if (disp->state == DRM_DISP_DISCONNECTED && conn->connection == DRM_MODE_CONNECTED) { - disp->state = OTD_DISP_NEEDS_MODESET; - event_add(otd, disp, OTD_EV_DISPLAY_ADD); + disp->state = DRM_DISP_NEEDS_MODESET; + wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_ADD); - } else if (disp->state == OTD_DISP_CONNECTED && + } else if (disp->state == DRM_DISP_CONNECTED && conn->connection != DRM_MODE_CONNECTED) { - disp->state = OTD_DISP_DISCONNECTED; - event_add(otd, disp, OTD_EV_DISPLAY_REM); + disp->state = DRM_DISP_DISCONNECTED; + wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM); } drmModeFreeConnector(conn); @@ -238,44 +245,49 @@ static uint32_t get_fb_for_bo(int fd, struct gbm_bo *bo) return *id; } -static void init_display_renderer(struct otd *otd, struct otd_display *disp) +static bool display_init_renderer(struct wlr_drm_renderer *renderer, + struct wlr_drm_display *disp) { - disp->gbm = gbm_surface_create(otd->gbm, + disp->renderer = renderer; + + disp->gbm = gbm_surface_create(renderer->gbm, disp->width, disp->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); if (!disp->gbm) - return; + return false; - disp->egl = create_platform_window_surface(otd->egl.disp, otd->egl.conf, + disp->egl = create_platform_window_surface(renderer->egl.disp, renderer->egl.conf, disp->gbm, NULL); if (disp->egl == EGL_NO_SURFACE) - return; + return false; // Render black frame - eglMakeCurrent(otd->egl.disp, disp->egl, disp->egl, otd->egl.context); + eglMakeCurrent(renderer->egl.disp, disp->egl, disp->egl, renderer->egl.context); glViewport(0, 0, disp->width, disp->height); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(otd->egl.disp, disp->egl); + eglSwapBuffers(renderer->egl.disp, disp->egl); struct gbm_bo *bo = gbm_surface_lock_front_buffer(disp->gbm); - uint32_t fb_id = get_fb_for_bo(otd->fd, bo); + uint32_t fb_id = get_fb_for_bo(renderer->fd, bo); - drmModeSetCrtc(otd->fd, disp->crtc, fb_id, 0, 0, + drmModeSetCrtc(renderer->fd, disp->crtc, fb_id, 0, 0, &disp->connector, 1, disp->active_mode); - drmModePageFlip(otd->fd, disp->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, disp); + drmModePageFlip(renderer->fd, disp->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, disp); gbm_surface_release_buffer(disp->gbm, bo); + + return true; } static drmModeModeInfo *select_mode(size_t num_modes, - drmModeModeInfo modes[static num_modes], - drmModeCrtc *old_crtc, - const char *str) + drmModeModeInfo modes[static num_modes], + drmModeCrtc *old_crtc, + const char *str) { if (strcmp(str, "preferred") == 0) return &modes[0]; @@ -315,9 +327,10 @@ static drmModeModeInfo *select_mode(size_t num_modes, return NULL; } -bool modeset_str(struct otd *otd, struct otd_display *disp, const char *str) +bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, + struct wlr_drm_display *disp, const char *str) { - drmModeConnector *conn = drmModeGetConnector(otd->fd, disp->connector); + drmModeConnector *conn = drmModeGetConnector(backend->fd, disp->connector); if (!conn || conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) goto error; @@ -327,9 +340,9 @@ bool modeset_str(struct otd *otd, struct otd_display *disp, const char *str) goto error; memcpy(disp->modes, conn->modes, sizeof *disp->modes * disp->num_modes); - drmModeEncoder *curr_enc = drmModeGetEncoder(otd->fd, conn->encoder_id); + drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, conn->encoder_id); if (curr_enc) { - disp->old_crtc = drmModeGetCrtc(otd->fd, curr_enc->crtc_id); + disp->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id); free(curr_enc); } @@ -343,13 +356,13 @@ bool modeset_str(struct otd *otd, struct otd_display *disp, const char *str) disp->name, disp->active_mode->hdisplay, disp->active_mode->vdisplay, disp->active_mode->vrefresh); - drmModeRes *res = drmModeGetResources(otd->fd); + drmModeRes *res = drmModeGetResources(backend->fd); if (!res) goto error; bool success = false; for (int i = 0; !success && i < conn->count_encoders; ++i) { - drmModeEncoder *enc = drmModeGetEncoder(otd->fd, conn->encoders[i]); + drmModeEncoder *enc = drmModeGetEncoder(backend->fd, conn->encoders[i]); if (!enc) continue; @@ -357,8 +370,8 @@ bool modeset_str(struct otd *otd, struct otd_display *disp, const char *str) if ((enc->possible_crtcs & (1 << j)) == 0) continue; - if ((otd->taken_crtcs & (1 << j)) == 0) { - otd->taken_crtcs |= 1 << j; + if ((backend->taken_crtcs & (1 << j)) == 0) { + backend->taken_crtcs |= 1 << j; disp->crtc = res->crtcs[j]; success = true; @@ -374,45 +387,48 @@ bool modeset_str(struct otd *otd, struct otd_display *disp, const char *str) if (!success) goto error; - disp->state = OTD_DISP_CONNECTED; + disp->state = DRM_DISP_CONNECTED; drmModeFreeConnector(conn); disp->width = disp->active_mode->hdisplay; disp->height = disp->active_mode->vdisplay; - init_display_renderer(otd, disp); + display_init_renderer(&backend->renderer, disp); return true; error: - disp->state = OTD_DISP_DISCONNECTED; + disp->state = DRM_DISP_DISCONNECTED; drmModeFreeConnector(conn); - event_add(otd, disp, OTD_EV_DISPLAY_REM); + wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM); return false; } - -void page_flip_handler(int fd, - unsigned seq, - unsigned tv_sec, - unsigned tv_usec, - void *user) +static void page_flip_handler(int fd, + unsigned seq, + unsigned tv_sec, + unsigned tv_usec, + void *user) { - struct otd_display *disp = user; + struct wlr_drm_display *disp = user; disp->pageflip_pending = true; if (!disp->cleanup) - event_add(disp->otd, disp, OTD_EV_RENDER); + wlr_drm_add_event(disp->renderer->backend, disp, DRM_EV_RENDER); } -void destroy_display_renderer(struct otd *otd, struct otd_display *disp) +void wlr_drm_display_free(struct wlr_drm_display *disp) { - if (!otd || !disp || disp->state != OTD_DISP_CONNECTED) + if (!disp || disp->state != DRM_DISP_CONNECTED) return; + struct wlr_drm_renderer *renderer = disp->renderer; + drmModeCrtc *crtc = disp->old_crtc; if (crtc) { + // Wait for exising page flips to finish + drmEventContext event = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, @@ -420,45 +436,45 @@ void destroy_display_renderer(struct otd *otd, struct otd_display *disp) disp->cleanup = true; while (disp->pageflip_pending) - drmHandleEvent(otd->fd, &event); + drmHandleEvent(renderer->fd, &event); - drmModeSetCrtc(otd->fd, crtc->crtc_id, crtc->buffer_id, + drmModeSetCrtc(renderer->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &disp->connector, 1, &crtc->mode); drmModeFreeCrtc(crtc); } - eglDestroySurface(otd->egl.disp, disp->egl); + eglDestroySurface(renderer->egl.disp, disp->egl); gbm_surface_destroy(disp->gbm); free(disp->modes); } -void get_drm_event(struct otd *otd) +void wlr_drm_event(int fd) { drmEventContext event = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, }; - drmHandleEvent(otd->fd, &event); + drmHandleEvent(fd, &event); } -void rendering_begin(struct otd_display *disp) +void wlr_drm_display_begin(struct wlr_drm_display *disp) { - struct otd *otd = disp->otd; - eglMakeCurrent(otd->egl.disp, disp->egl, disp->egl, otd->egl.context); + struct wlr_drm_renderer *renderer = disp->renderer; + eglMakeCurrent(renderer->egl.disp, disp->egl, disp->egl, renderer->egl.context); } -void rendering_end(struct otd_display *disp) +void wlr_drm_display_end(struct wlr_drm_display *disp) { - struct otd *otd = disp->otd; - eglSwapBuffers(otd->egl.disp, disp->egl); + struct wlr_drm_renderer *renderer = disp->renderer; + eglSwapBuffers(renderer->egl.disp, disp->egl); struct gbm_bo *bo = gbm_surface_lock_front_buffer(disp->gbm); - uint32_t fb_id = get_fb_for_bo(otd->fd, bo); + uint32_t fb_id = get_fb_for_bo(renderer->fd, bo); - drmModePageFlip(otd->fd, disp->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, disp); + drmModePageFlip(renderer->fd, disp->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, disp); gbm_surface_release_buffer(disp->gbm, bo); diff --git a/backend/drm/event.c b/backend/drm/event.c index 34679514..db17b5b7 100644 --- a/backend/drm/event.c +++ b/backend/drm/event.c @@ -1,47 +1,48 @@ -#include "backend/drm/otd.h" -#include "backend/drm/event.h" -#include "backend/drm/drm.h" -#include "backend/drm/udev.h" - #include <stdbool.h> #include <stdlib.h> #include <poll.h> -static inline void event_swap(struct otd_event *a, struct otd_event *b) +#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 otd_event tmp = *a; + struct wlr_drm_event tmp = *a; *a = *b; *b = tmp; } -bool otd_get_event(struct otd *otd, struct otd_event *restrict ret) +bool wlr_drm_get_event(struct wlr_drm_backend *backend, + struct wlr_drm_event *restrict ret) { struct pollfd fds[] = { - { .fd = otd->fd, .events = POLLIN }, - { .fd = otd->udev_fd, .events = POLLIN }, + { .fd = backend->fd, .events = POLLIN }, + { .fd = backend->udev.mon_fd, .events = POLLIN }, }; while (poll(fds, 2, 0) > 0) { if (fds[0].revents) - get_drm_event(otd); + wlr_drm_event(backend->fd); if (fds[1].revents) - otd_udev_event(otd); + wlr_udev_event(backend); } - if (otd->event_len == 0) { - ret->type = OTD_EV_NONE; + if (backend->event_len == 0) { + ret->type = DRM_EV_NONE; ret->display = NULL; return false; } - struct otd_event *ev = otd->events; + struct wlr_drm_event *ev = backend->events; // Downheap *ret = ev[0]; - ev[0] = ev[--otd->event_len]; + ev[0] = ev[--backend->event_len]; size_t i = 0; - while (i < otd->event_len / 2) { + 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; @@ -57,27 +58,28 @@ bool otd_get_event(struct otd *otd, struct otd_event *restrict ret) return true; } -bool event_add(struct otd *otd, struct otd_display *disp, enum otd_event_type type) +bool wlr_drm_add_event(struct wlr_drm_backend *backend, + struct wlr_drm_display *disp, enum wlr_drm_event_type type) { - if (type == OTD_EV_NONE) + if (type == DRM_EV_NONE) return true; - if (otd->event_len == otd->event_cap) { - size_t new_size = (otd->event_cap == 0) ? 8 : otd->event_cap * 2; + if (backend->event_len == backend->event_cap) { + size_t new_size = (backend->event_cap == 0) ? 8 : backend->event_cap * 2; - struct otd_event *new = realloc(otd->events, sizeof *new * new_size); + struct wlr_drm_event *new = realloc(backend->events, sizeof *new * new_size); if (!new) { return false; } - otd->event_cap = new_size; - otd->events = new; + backend->event_cap = new_size; + backend->events = new; } - struct otd_event *ev = otd->events; + struct wlr_drm_event *ev = backend->events; // Upheap - size_t i = otd->event_len++; + size_t i = backend->event_len++; ev[i].type = type; ev[i].display = disp; diff --git a/backend/drm/otd.c b/backend/drm/otd.c deleted file mode 100644 index f5960793..00000000 --- a/backend/drm/otd.c +++ /dev/null @@ -1,71 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> - -#include "backend/drm/otd.h" -#include "backend/drm/drm.h" -#include "backend/drm/event.h" -#include "backend/drm/session.h" -#include "backend/drm/udev.h" - -struct otd *otd_start(void) -{ - struct otd *otd = calloc(1, sizeof *otd); - if (!otd) - return NULL; - - if (!otd_new_session(otd)) { - fprintf(stderr, "Could not create session\n"); - goto error; - } - - if (!otd_udev_start(otd)) { - fprintf(stderr, "Could not start udev\n"); - goto error_session; - } - - otd_udev_find_gpu(otd); - if (otd->fd == -1) { - fprintf(stderr, "Could not open GPU\n"); - goto error_udev; - } - - if (!init_renderer(otd)) { - fprintf(stderr, "Could not initalise renderer\n"); - goto error_fd; - } - - scan_connectors(otd); - - return otd; - -error_fd: - release_device(otd, otd->fd); -error_udev: - otd_udev_finish(otd); -error_session: - otd_close_session(otd); -error: - free(otd); - return NULL; -} - -void otd_finish(struct otd *otd) -{ - if (!otd) - return; - - for (size_t i = 0; i < otd->display_len; ++i) { - destroy_display_renderer(otd, &otd->displays[i]); - } - - destroy_renderer(otd); - otd_close_session(otd); - otd_udev_finish(otd); - - close(otd->fd); - free(otd->events); - free(otd->displays); - free(otd); -} - diff --git a/backend/drm/session.c b/backend/drm/session.c index 261c5ac6..285f31b9 100644 --- a/backend/drm/session.c +++ b/backend/drm/session.c @@ -11,18 +11,17 @@ #include <sys/stat.h> #include <fcntl.h> +#include "backend/drm/backend.h" #include "backend/drm/session.h" -#include "backend/drm/otd.h" -int take_device(struct otd *restrict otd, - const char *restrict path, - bool *restrict paused_out) +int wlr_session_take_device(struct wlr_session *restrict session, + const char *restrict path, + bool *restrict paused_out) { int ret; int fd = -1; sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - struct otd_session *s = &otd->session; struct stat st; if (stat(path, &st) < 0) { @@ -30,9 +29,9 @@ int take_device(struct otd *restrict otd, return -1; } - ret = sd_bus_call_method(s->bus, + ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", - s->path, + session->path, "org.freedesktop.login1.Session", "TakeDevice", &error, &msg, @@ -62,12 +61,11 @@ error: return fd; } -void release_device(struct otd *otd, int fd) +void wlr_session_release_device(struct wlr_session *session, int fd) { int ret; sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - struct otd_session *s = &otd->session; struct stat st; if (fstat(fd, &st) < 0) { @@ -75,9 +73,9 @@ void release_device(struct otd *otd, int fd) return; } - ret = sd_bus_call_method(s->bus, + ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", - s->path, + session->path, "org.freedesktop.login1.Session", "ReleaseDevice", &error, &msg, @@ -90,16 +88,15 @@ void release_device(struct otd *otd, int fd) sd_bus_message_unref(msg); } -static bool session_activate(struct otd *otd) +static bool session_activate(struct wlr_session *session) { int ret; sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - struct otd_session *s = &otd->session; - ret = sd_bus_call_method(s->bus, + ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", - s->path, + session->path, "org.freedesktop.login1.Session", "Activate", &error, &msg, @@ -113,16 +110,15 @@ static bool session_activate(struct otd *otd) return ret >= 0; } -static bool take_control(struct otd *otd) +static bool take_control(struct wlr_session *session) { int ret; sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - struct otd_session *s = &otd->session; - ret = sd_bus_call_method(s->bus, + ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", - s->path, + session->path, "org.freedesktop.login1.Session", "TakeControl", &error, &msg, @@ -136,16 +132,15 @@ static bool take_control(struct otd *otd) return ret >= 0; } -static void release_control(struct otd *otd) +static void release_control(struct wlr_session *session) { int ret; sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; - struct otd_session *s = &otd->session; - ret = sd_bus_call_method(s->bus, + ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", - s->path, + session->path, "org.freedesktop.login1.Session", "ReleaseControl", &error, &msg, @@ -158,29 +153,27 @@ static void release_control(struct otd *otd) sd_bus_message_unref(msg); } -void otd_close_session(struct otd *otd) +void wlr_session_end(struct wlr_session *session) { - release_device(otd, otd->fd); - release_control(otd); + release_control(session); - sd_bus_unref(otd->session.bus); - free(otd->session.id); - free(otd->session.path); - free(otd->session.seat); + sd_bus_unref(session->bus); + free(session->id); + free(session->path); + free(session->seat); } -bool otd_new_session(struct otd *otd) +bool wlr_session_start(struct wlr_session *session) { int ret; - struct otd_session *s = &otd->session; - ret = sd_pid_get_session(getpid(), &s->id); + ret = sd_pid_get_session(getpid(), &session->id); if (ret < 0) { fprintf(stderr, "Could not get session\n"); goto error; } - ret = sd_session_get_seat(s->id, &s->seat); + ret = sd_session_get_seat(session->id, &session->seat); if (ret < 0) { fprintf(stderr, "Could not get seat\n"); goto error; @@ -189,26 +182,26 @@ bool otd_new_session(struct otd *otd) // This could be done using asprintf, but I don't want to define _GNU_SOURCE const char *fmt = "/org/freedesktop/login1/session/%s"; - int len = snprintf(NULL, 0, fmt, s->id); + int len = snprintf(NULL, 0, fmt, session->id); - s->path = malloc(len + 1); - if (!s->path) + session->path = malloc(len + 1); + if (!session->path) goto error; - sprintf(s->path, fmt, s->id); + sprintf(session->path, fmt, session->id); - ret = sd_bus_open_system(&s->bus); + ret = sd_bus_open_system(&session->bus); if (ret < 0) { fprintf(stderr, "Could not open bus\n"); goto error; } - if (!session_activate(otd)) { + if (!session_activate(session)) { fprintf(stderr, "Could not activate session\n"); goto error_bus; } - if (!take_control(otd)) { + if (!take_control(session)) { fprintf(stderr, "Could not take control of session\n"); goto error_bus; } @@ -216,11 +209,11 @@ bool otd_new_session(struct otd *otd) return true; error_bus: - sd_bus_unref(s->bus); + sd_bus_unref(session->bus); error: - free(s->path); - free(s->id); - free(s->seat); + free(session->path); + free(session->id); + free(session->seat); return false; } diff --git a/backend/drm/udev.c b/backend/drm/udev.c index 5f20a1be..c5440303 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -8,12 +8,15 @@ #include <xf86drm.h> #include <xf86drmMode.h> -#include "backend/drm/otd.h" +#include "backend/drm/backend.h" #include "backend/drm/udev.h" #include "backend/drm/session.h" #include "backend/drm/drm.h" -static bool device_is_kms(struct otd *otd, struct udev_device *dev) +static bool device_is_kms(struct wlr_udev *udev, + struct wlr_session *session, + struct udev_device *dev, + int *fd_out) { const char *path = udev_device_get_devnode(dev); int fd; @@ -21,7 +24,7 @@ static bool device_is_kms(struct otd *otd, struct udev_device *dev) if (!path) return false; - fd = take_device(otd, path, &otd->paused); + fd = wlr_session_take_device(session, path, NULL); if (fd < 0) return false; @@ -33,13 +36,13 @@ static bool device_is_kms(struct otd *otd, struct udev_device *dev) res->count_encoders <= 0) goto out_res; - if (otd->fd >= 0) { - release_device(otd, otd->fd); - free(otd->drm_path); + if (*fd_out >= 0) { + wlr_session_release_device(session, *fd_out); + free(udev->drm_path); } - otd->fd = fd; - otd->drm_path = strdup(path); + *fd_out = fd; + udev->drm_path = strdup(path); drmModeFreeResources(res); return true; @@ -47,18 +50,17 @@ static bool device_is_kms(struct otd *otd, struct udev_device *dev) out_res: drmModeFreeResources(res); out_fd: - release_device(otd, fd); + wlr_session_release_device(session, fd); return false; } -void otd_udev_find_gpu(struct otd *otd) +int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { - struct udev *udev = otd->udev; - otd->fd = -1; + int fd = -1; - struct udev_enumerate *en = udev_enumerate_new(udev); + struct udev_enumerate *en = udev_enumerate_new(udev->udev); if (!en) - return; + return -1; udev_enumerate_add_match_subsystem(en, "drm"); udev_enumerate_add_match_sysname(en, "card[0-9]*"); @@ -69,14 +71,14 @@ void otd_udev_find_gpu(struct otd *otd) bool is_boot_vga = false; const char *path = udev_list_entry_get_name(entry); - struct udev_device *dev = udev_device_new_from_syspath(udev, path); + struct udev_device *dev = udev_device_new_from_syspath(udev->udev, path); if (!dev) continue; const char *seat = udev_device_get_property_value(dev, "ID_SEAT"); if (!seat) seat = "seat0"; - if (strcmp(otd->session.seat, seat) != 0) { + if (strcmp(session->seat, seat) != 0) { udev_device_unref(dev); continue; } @@ -92,12 +94,12 @@ void otd_udev_find_gpu(struct otd *otd) udev_device_unref(pci); } - if (!is_boot_vga && otd->fd >= 0) { + if (!is_boot_vga && fd >= 0) { udev_device_unref(dev); continue; } - if (!device_is_kms(otd, dev)) { + if (!device_is_kms(udev, session, dev, &fd)) { udev_device_unref(dev); continue; } @@ -108,52 +110,59 @@ void otd_udev_find_gpu(struct otd *otd) } udev_enumerate_unref(en); + + return fd; } -bool otd_udev_start(struct otd *otd) +bool wlr_udev_init(struct wlr_udev *udev) { - otd->udev = udev_new(); - if (!otd->udev) + udev->udev = udev_new(); + if (!udev->udev) return false; - otd->mon = udev_monitor_new_from_netlink(otd->udev, "udev"); - if (!otd->mon) { - udev_unref(otd->udev); + udev->mon = udev_monitor_new_from_netlink(udev->udev, "udev"); + if (!udev->mon) { + udev_unref(udev->udev); return false; } - udev_monitor_filter_add_match_subsystem_devtype(otd->mon, "drm", NULL); - udev_monitor_enable_receiving(otd->mon); + udev_monitor_filter_add_match_subsystem_devtype(udev->mon, "drm", NULL); + udev_monitor_enable_receiving(udev->mon); - otd->udev_fd = udev_monitor_get_fd(otd->mon); + udev->mon_fd = udev_monitor_get_fd(udev->mon); + udev->drm_path = NULL; return true; } -void otd_udev_finish(struct otd *otd) +void wlr_udev_free(struct wlr_udev *udev) + { - if (!otd) + if (!udev) return; - udev_monitor_unref(otd->mon); - udev_unref(otd->udev); + udev_monitor_unref(udev->mon); + udev_unref(udev->udev); + free(udev->drm_path); } -void otd_udev_event(struct otd *otd) +void wlr_udev_event(struct wlr_drm_backend *backend) { - struct udev_device *dev = udev_monitor_receive_device(otd->mon); + struct wlr_udev *udev = &backend->udev; + + struct udev_device *dev = udev_monitor_receive_device(udev->mon); if (!dev) return; const char *path = udev_device_get_devnode(dev); - if (!path || strcmp(path, otd->drm_path) != 0) + if (!path || strcmp(path, udev->drm_path) != 0) goto out; const char *action = udev_device_get_action(dev); if (!action || strcmp(action, "change") != 0) goto out; - scan_connectors(otd); + wlr_drm_scan_connectors(backend); out: udev_device_unref(dev); diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h new file mode 100644 index 00000000..caa18bcc --- /dev/null +++ b/include/backend/drm/backend.h @@ -0,0 +1,37 @@ +#ifndef DRM_BACKEND_H +#define DRM_BACKEND_H + +#include <stdbool.h> +#include <stddef.h> +#include <EGL/egl.h> +#include <gbm.h> +#include <libudev.h> + +#include "session.h" +#include "udev.h" +#include "event.h" +#include "drm.h" + +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; + + size_t display_len; + struct wlr_drm_display *displays; + + uint32_t taken_crtcs; + + struct wlr_drm_renderer renderer; + struct wlr_session session; + struct wlr_udev udev; +}; + +struct wlr_drm_backend *wlr_drm_backend_init(void); +void wlr_drm_backend_free(struct wlr_drm_backend *backend); + +#endif diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 8744b440..bd3d4105 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -7,17 +7,35 @@ #include <EGL/egl.h> #include <gbm.h> -enum otd_display_state { - OTD_DISP_INVALID, - OTD_DISP_DISCONNECTED, - OTD_DISP_NEEDS_MODESET, - OTD_DISP_CONNECTED, +struct wlr_drm_renderer { + int fd; + + // Currently here so that rendering has access to the event queue. + // Ideally this is will be removed later once the way events are + // handled is changed. + struct wlr_drm_backend *backend; + + struct gbm_device *gbm; + struct { + EGLDisplay disp; + EGLConfig conf; + EGLContext context; + } egl; }; -struct otd_display { - struct otd *otd; +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, + struct wlr_drm_backend *backend, int fd); +void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer); - enum otd_display_state state; +enum wlr_drm_display_state { + DRM_DISP_INVALID, + DRM_DISP_DISCONNECTED, + DRM_DISP_NEEDS_MODESET, + DRM_DISP_CONNECTED, +}; + +struct wlr_drm_display { + enum wlr_drm_display_state state; uint32_t connector; char name[16]; @@ -31,24 +49,22 @@ struct otd_display { uint32_t crtc; drmModeCrtc *old_crtc; + struct wlr_drm_renderer *renderer; struct gbm_surface *gbm; EGLSurface *egl; - uint32_t fb_id; bool pageflip_pending; bool cleanup; }; -bool init_renderer(struct otd *otd); -void destroy_renderer(struct otd *otd); - -void scan_connectors(struct otd *otd); -bool modeset_str(struct otd *otd, struct otd_display *disp, const char *str); -void destroy_display_renderer(struct otd *otd, struct otd_display *disp); +bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, + struct wlr_drm_display *disp, const char *str); +void wlr_drm_display_free(struct wlr_drm_display *disp); -void get_drm_event(struct otd *otd); +void wlr_drm_display_begin(struct wlr_drm_display *disp); +void wlr_drm_display_end(struct wlr_drm_display *disp); -void rendering_begin(struct otd_display *disp); -void rendering_end(struct otd_display *disp); +void wlr_drm_scan_connectors(struct wlr_drm_backend *backend); +void wlr_drm_event(int fd); #endif diff --git a/include/backend/drm/event.h b/include/backend/drm/event.h index fc4f6f9a..2155bd32 100644 --- a/include/backend/drm/event.h +++ b/include/backend/drm/event.h @@ -2,20 +2,24 @@ #define EVENT_H #include <stdbool.h> +#include "drm.h" -enum otd_event_type { - OTD_EV_NONE, - OTD_EV_RENDER, - OTD_EV_DISPLAY_REM, - OTD_EV_DISPLAY_ADD, +enum wlr_drm_event_type { + DRM_EV_NONE, + DRM_EV_RENDER, + DRM_EV_DISPLAY_REM, + DRM_EV_DISPLAY_ADD, }; -struct otd_event { - enum otd_event_type type; - struct otd_display *display; +struct wlr_drm_event { + enum wlr_drm_event_type type; + struct wlr_drm_display *display; }; -bool otd_get_event(struct otd *otd, struct otd_event *restrict ret); -bool event_add(struct otd *otd, struct otd_display *disp, enum otd_event_type type); +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 diff --git a/include/backend/drm/otd.h b/include/backend/drm/otd.h deleted file mode 100644 index eef0e991..00000000 --- a/include/backend/drm/otd.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef LIBOTD_H -#define LIBOTD_H - -#include <stdbool.h> -#include <stddef.h> -#include <EGL/egl.h> -#include <gbm.h> -#include <libudev.h> - -#include "session.h" - -struct otd { - int fd; - bool paused; - - // Priority Queue (Max-heap) - size_t event_cap; - size_t event_len; - struct otd_event *events; - - size_t display_len; - struct otd_display *displays; - - uint32_t taken_crtcs; - - struct gbm_device *gbm; - struct { - EGLDisplay disp; - EGLConfig conf; - EGLContext context; - } egl; - - struct otd_session session; - - struct udev *udev; - struct udev_monitor *mon; - int udev_fd; - char *drm_path; -}; - -struct otd *otd_start(void); -void otd_finish(struct otd *otd); - -#endif diff --git a/include/backend/drm/session.h b/include/backend/drm/session.h index c21900e9..6936b19a 100644 --- a/include/backend/drm/session.h +++ b/include/backend/drm/session.h @@ -4,22 +4,21 @@ #include <systemd/sd-bus.h> #include <stdbool.h> -struct otd_session { +struct wlr_session { + sd_bus *bus; + char *id; char *path; char *seat; - - sd_bus *bus; }; -struct otd; -bool otd_new_session(struct otd *otd); -void otd_close_session(struct otd *otd); +bool wlr_session_start(struct wlr_session *session); +void wlr_session_end(struct wlr_session *session); -int take_device(struct otd *restrict otd, - const char *restrict path, - bool *restrict paused_out); +int wlr_session_take_device(struct wlr_session *restrict session, + const char *restrict path, + bool *restrict paused_out); -void release_device(struct otd *otd, int fd); +void wlr_session_release_device(struct wlr_session *session, int fd); #endif diff --git a/include/backend/drm/udev.h b/include/backend/drm/udev.h index 9bd4c0d0..6b10c9ec 100644 --- a/include/backend/drm/udev.h +++ b/include/backend/drm/udev.h @@ -1,9 +1,22 @@ #ifndef UDEV_H #define UDEV_H -bool otd_udev_start(struct otd *otd); -void otd_udev_finish(struct otd *otd); -void otd_udev_find_gpu(struct otd *otd); -void otd_udev_event(struct otd *otd); +#include <libudev.h> + +#include "backend/drm/session.h" + +struct wlr_udev { + struct udev *udev; + struct udev_monitor *mon; + int mon_fd; + char *drm_path; +}; + +bool wlr_udev_init(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); + +struct wlr_drm_backend; +void wlr_udev_event(struct wlr_drm_backend *backend); #endif |