From aca13320b3e6df8cb575f64db736dc38b8b30ed2 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 1 May 2017 15:20:48 +1200 Subject: Inital commit of libotd. --- backend/drm/udev.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 backend/drm/udev.c (limited to 'backend/drm/udev.c') diff --git a/backend/drm/udev.c b/backend/drm/udev.c new file mode 100644 index 00000000..1efa26c2 --- /dev/null +++ b/backend/drm/udev.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "otd.h" +#include "udev.h" +#include "session.h" +#include "drm.h" + +static bool device_is_kms(struct otd *otd, struct udev_device *dev) +{ + const char *path = udev_device_get_devnode(dev); + int fd; + + if (!path) + return false; + + fd = take_device(otd, path, &otd->paused); + if (fd < 0) + return false; + + drmModeRes *res = drmModeGetResources(fd); + if (!res) + goto out_fd; + + if (res->count_crtcs <= 0 || res->count_connectors <= 0 || + res->count_encoders <= 0) + goto out_res; + + if (otd->fd >= 0) { + release_device(otd, otd->fd); + free(otd->drm_path); + } + + otd->fd = fd; + otd->drm_path = strdup(path); + + drmModeFreeResources(res); + return true; + +out_res: + drmModeFreeResources(res); +out_fd: + release_device(otd, fd); + return false; +} + +void otd_udev_find_gpu(struct otd *otd) +{ + struct udev *udev = otd->udev; + otd->fd = -1; + + struct udev_enumerate *en = udev_enumerate_new(udev); + if (!en) + return; + + udev_enumerate_add_match_subsystem(en, "drm"); + udev_enumerate_add_match_sysname(en, "card[0-9]*"); + + udev_enumerate_scan_devices(en); + struct udev_list_entry *entry; + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(en)) { + 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); + 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) { + udev_device_unref(dev); + continue; + } + + struct udev_device *pci = + udev_device_get_parent_with_subsystem_devtype(dev, + "pci", NULL); + + if (pci) { + const char *id = udev_device_get_sysattr_value(pci, "boot_vga"); + if (id && strcmp(id, "1") == 0) + is_boot_vga = true; + udev_device_unref(pci); + } + + if (!is_boot_vga && otd->fd >= 0) { + udev_device_unref(dev); + continue; + } + + if (!device_is_kms(otd, dev)) { + udev_device_unref(dev); + continue; + } + + if (is_boot_vga) { + break; + } + } + + udev_enumerate_unref(en); +} + +bool otd_udev_start(struct otd *otd) +{ + otd->udev = udev_new(); + if (!otd->udev) + return false; + + otd->mon = udev_monitor_new_from_netlink(otd->udev, "udev"); + if (!otd->mon) { + udev_unref(otd->udev); + return false; + } + + udev_monitor_filter_add_match_subsystem_devtype(otd->mon, "drm", NULL); + udev_monitor_enable_receiving(otd->mon); + + otd->udev_fd = udev_monitor_get_fd(otd->mon); + + return true; +} + +void otd_udev_finish(struct otd *otd) +{ + if (!otd) + return; + + udev_monitor_unref(otd->mon); + udev_unref(otd->udev); +} + +void otd_udev_event(struct otd *otd) +{ + struct udev_device *dev = udev_monitor_receive_device(otd->mon); + if (!dev) + return; + + const char *path = udev_device_get_devnode(dev); + if (!path || strcmp(path, otd->drm_path) != 0) + goto out; + + const char *action = udev_device_get_action(dev); + if (!action || strcmp(action, "change") != 0) + goto out; + + scan_connectors(otd); + +out: + udev_device_unref(dev); +} -- cgit v1.2.3 From 9ac46ec5ed6ba67a8c684069f8255384f6acd18b Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 1 May 2017 15:50:19 +1200 Subject: Got it to build --- CMake/FindSystemd.cmake | 40 ++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 1 + backend/CMakeLists.txt | 6 ++++++ backend/drm/drm.c | 6 +++--- backend/drm/event.c | 8 ++++---- backend/drm/otd.c | 10 +++++----- backend/drm/session.c | 6 ++++-- backend/drm/udev.c | 10 ++++++---- 8 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 CMake/FindSystemd.cmake (limited to 'backend/drm/udev.c') diff --git a/CMake/FindSystemd.cmake b/CMake/FindSystemd.cmake new file mode 100644 index 00000000..09d60115 --- /dev/null +++ b/CMake/FindSystemd.cmake @@ -0,0 +1,40 @@ +#.rst: +# FindSystemd +# ------- +# +# Find Systemd library +# +# Try to find Systemd library on UNIX systems. The following values are defined +# +# :: +# +# SYSTEMD_FOUND - True if Systemd is available +# SYSTEMD_INCLUDE_DIRS - Include directories for Systemd +# SYSTEMD_LIBRARIES - List of libraries for Systemd +# SYSTEMD_DEFINITIONS - List of definitions for Systemd +# +#============================================================================= +# Copyright (c) 2015 Jari Vetoniemi +# +# Distributed under the OSI-approved BSD License (the "License"); +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +include(FeatureSummary) +set_package_properties(Systemd PROPERTIES + URL "http://freedesktop.org/wiki/Software/systemd/" + DESCRIPTION "System and Service Manager") + +find_package(PkgConfig) +pkg_check_modules(PC_SYSTEMD QUIET libsystemd) +find_library(SYSTEMD_LIBRARIES NAMES systemd ${PC_SYSTEMD_LIBRARY_DIRS}) +find_path(SYSTEMD_INCLUDE_DIRS systemd/sd-login.h HINTS ${PC_SYSTEMD_INCLUDE_DIRS}) + +set(SYSTEMD_DEFINITIONS ${PC_SYSTEMD_CFLAGS_OTHER}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SYSTEMD DEFAULT_MSG SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES) +mark_as_advanced(SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES SYSTEMD_DEFINITIONS) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd4d9969..30a2c37d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ find_package(DRM REQUIRED) find_package(LibInput REQUIRED) find_package(Udev) find_package(Dbus) +find_package(Systemd) include(Wayland) include(Manpage) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 830a2158..c962b8ed 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories( ${PROTOCOLS_INCLUDE_DIRS} ${WAYLAND_INCLUDE_DIR} + ${DRM_INCLUDE_DIRS} ) add_library(wlr-backend @@ -8,6 +9,11 @@ add_library(wlr-backend wayland/registry.c wayland/wl_seat.c wayland/wl_output.c + drm/drm.c + drm/event.c + drm/otd.c + drm/session.c + drm/udev.c ) target_link_libraries(wlr-backend diff --git a/backend/drm/drm.c b/backend/drm/drm.c index bb6359c5..894d8513 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1,6 +1,6 @@ -#include "otd.h" -#include "drm.h" -#include "event.h" +#include "backend/drm/otd.h" +#include "backend/drm/drm.h" +#include "backend/drm/event.h" #include #include diff --git a/backend/drm/event.c b/backend/drm/event.c index f20cb282..34679514 100644 --- a/backend/drm/event.c +++ b/backend/drm/event.c @@ -1,7 +1,7 @@ -#include "otd.h" -#include "event.h" -#include "drm.h" -#include "udev.h" +#include "backend/drm/otd.h" +#include "backend/drm/event.h" +#include "backend/drm/drm.h" +#include "backend/drm/udev.h" #include #include diff --git a/backend/drm/otd.c b/backend/drm/otd.c index 3d5345c7..f5960793 100644 --- a/backend/drm/otd.c +++ b/backend/drm/otd.c @@ -2,11 +2,11 @@ #include #include -#include "otd.h" -#include "drm.h" -#include "event.h" -#include "session.h" -#include "udev.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) { diff --git a/backend/drm/session.c b/backend/drm/session.c index c845fb27..261c5ac6 100644 --- a/backend/drm/session.c +++ b/backend/drm/session.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L + #include #include #include @@ -9,8 +11,8 @@ #include #include -#include "session.h" -#include "otd.h" +#include "backend/drm/session.h" +#include "backend/drm/otd.h" int take_device(struct otd *restrict otd, const char *restrict path, diff --git a/backend/drm/udev.c b/backend/drm/udev.c index 1efa26c2..5f20a1be 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L + #include #include #include @@ -6,10 +8,10 @@ #include #include -#include "otd.h" -#include "udev.h" -#include "session.h" -#include "drm.h" +#include "backend/drm/otd.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) { -- cgit v1.2.3 From 41a82fd2fcd4759fbb522ffe7e8f6667d6ab945a Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 1 May 2017 17:49:18 +1200 Subject: Renaming. --- backend/CMakeLists.txt | 2 +- backend/drm/backend.c | 71 ++++++++++++++++ backend/drm/drm.c | 188 +++++++++++++++++++++++------------------- backend/drm/event.c | 54 ++++++------ backend/drm/otd.c | 71 ---------------- backend/drm/session.c | 83 +++++++++---------- backend/drm/udev.c | 79 ++++++++++-------- include/backend/drm/backend.h | 37 +++++++++ include/backend/drm/drm.h | 52 ++++++++---- include/backend/drm/event.h | 24 +++--- include/backend/drm/otd.h | 44 ---------- include/backend/drm/session.h | 19 ++--- include/backend/drm/udev.h | 21 ++++- 13 files changed, 395 insertions(+), 350 deletions(-) create mode 100644 backend/drm/backend.c delete mode 100644 backend/drm/otd.c create mode 100644 include/backend/drm/backend.h delete mode 100644 include/backend/drm/otd.h (limited to 'backend/drm/udev.c') 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 +#include +#include + +#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 #include #include -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 -#include -#include - -#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 #include +#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 #include -#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 +#include +#include +#include +#include + +#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 #include -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 +#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 -#include -#include -#include -#include - -#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 #include -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 + +#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 -- cgit v1.2.3 From 562d43a5ecc2f7f4af3ed6924d52f87e3cc018c2 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Tue, 2 May 2017 13:00:25 +1200 Subject: Changed logging. --- backend/drm/backend.c | 17 +++-- backend/drm/drm.c | 168 +++++++++++++++++++++++++++++++++++----------- backend/drm/session.c | 50 +++++++------- backend/drm/udev.c | 13 ++-- include/backend/drm/drm.h | 2 +- 5 files changed, 176 insertions(+), 74 deletions(-) (limited to 'backend/drm/udev.c') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 8c500190..da7ca1e4 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -1,37 +1,42 @@ #include #include #include +#include +#include #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" struct wlr_drm_backend *wlr_drm_backend_init(void) { struct wlr_drm_backend *backend = calloc(1, sizeof *backend); - if (!backend) + if (!backend) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); return NULL; + } if (!wlr_session_start(&backend->session)) { - fprintf(stderr, "Could not create session\n"); + wlr_log(L_ERROR, "Failed to start session"); goto error; } if (!wlr_udev_init(&backend->udev)) { - fprintf(stderr, "Could not start udev\n"); + wlr_log(L_ERROR, "Failed to start udev"); goto error_session; } backend->fd = wlr_udev_find_gpu(&backend->udev, &backend->session); if (backend->fd == -1) { - fprintf(stderr, "Could not open GPU\n"); + wlr_log(L_ERROR, "Failed to open DRM device"); goto error_udev; } if (!wlr_drm_renderer_init(&backend->renderer, backend, backend->fd)) { - fprintf(stderr, "Could not initalise renderer\n"); + wlr_log(L_ERROR, "Failed to initialize renderer"); goto error_fd; } @@ -56,7 +61,7 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend) return; for (size_t i = 0; i < backend->display_len; ++i) { - wlr_drm_display_free(&backend->displays[i]); + wlr_drm_display_free(&backend->displays[i], true); } wlr_drm_renderer_free(&backend->renderer); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index c5b797c3..94d79e5c 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1,7 +1,3 @@ -#include "backend/drm/backend.h" -#include "backend/drm/drm.h" -#include "backend/drm/event.h" - #include #include #include @@ -16,6 +12,11 @@ #include #include +#include "backend/drm/backend.h" +#include "backend/drm/drm.h" +#include "backend/drm/event.h" +#include "common/log.h" + static const char *conn_name[] = { [DRM_MODE_CONNECTOR_Unknown] = "Unknown", [DRM_MODE_CONNECTOR_VGA] = "VGA", @@ -36,6 +37,44 @@ static const char *conn_name[] = { [DRM_MODE_CONNECTOR_DSI] = "DSI", }; +static const char *egl_error(void) +{ + switch (eglGetError()) { + case EGL_SUCCESS: + return "Success"; + case EGL_NOT_INITIALIZED: + return "Not initialized"; + case EGL_BAD_ACCESS: + return "Bad access"; + case EGL_BAD_ALLOC: + return "Bad alloc"; + case EGL_BAD_ATTRIBUTE: + return "Bad attribute"; + case EGL_BAD_CONTEXT: + return "Bad Context"; + case EGL_BAD_CONFIG: + return "Bad Config"; + case EGL_BAD_CURRENT_SURFACE: + return "Bad current surface"; + case EGL_BAD_DISPLAY: + return "Bad display"; + case EGL_BAD_SURFACE: + return "Bad surface"; + case EGL_BAD_MATCH: + return "Bad match"; + case EGL_BAD_PARAMETER: + return "Bad parameter"; + case EGL_BAD_NATIVE_PIXMAP: + return "Bad native pixmap"; + case EGL_BAD_NATIVE_WINDOW: + return "Bad native window"; + case EGL_CONTEXT_LOST: + return "Context lost"; + default: + return "Unknown"; + } +} + // EGL extensions PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display; PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window_surface; @@ -45,10 +84,20 @@ static bool egl_exts() get_platform_display = (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress("eglGetPlatformDisplayEXT"); + if (!get_platform_display) { + wlr_log(L_ERROR, "Failed to load EGL extension 'eglGetPlatformDisplayEXT'"); + return false; + } + create_platform_window_surface = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); - return get_platform_display && create_platform_window_surface; + if (!get_platform_display) { + wlr_log(L_ERROR, "Failed to load EGL extension 'eglCreatePlatformWindowSurfaceEXT'"); + return false; + } + + return true; } static bool egl_get_config(EGLDisplay disp, EGLConfig *out) @@ -88,35 +137,33 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out) 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"); + if (!egl_exts()) return false; - } renderer->gbm = gbm_create_device(fd); if (!renderer->gbm) { - fprintf(stderr, "Could not create gbm device: %s\n", strerror(errno)); + wlr_log(L_ERROR, "Failed to create GBM device: %s", strerror(errno)); return false; } if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { - fprintf(stderr, "Could not bind GLES3 API\n"); + wlr_log(L_ERROR, "Failed to bind to the OpenGL ES API: %s", egl_error()); goto error_gbm; } 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"); + wlr_log(L_ERROR, "Failed to create EGL display: %s", egl_error()); goto error_gbm; } if (eglInitialize(renderer->egl.disp, NULL, NULL) == EGL_FALSE) { - fprintf(stderr, "Could not initalise EGL\n"); + wlr_log(L_ERROR, "Failed to initialize EGL: %s", egl_error()); goto error_egl; } if (!egl_get_config(renderer->egl.disp, &renderer->egl.conf)) { - fprintf(stderr, "Could not get EGL config\n"); + wlr_log(L_ERROR, "Failed to get EGL config"); goto error_egl; } @@ -126,7 +173,7 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, renderer->egl.conf, EGL_NO_CONTEXT, attribs); if (renderer->egl.context == EGL_NO_CONTEXT) { - fprintf(stderr, "Could not create EGL context\n"); + wlr_log(L_ERROR, "Failed to create EGL context: %s", egl_error()); goto error_egl; } @@ -162,16 +209,20 @@ void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer) void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { drmModeRes *res = drmModeGetResources(backend->fd); - if (!res) + if (!res) { + wlr_log(L_ERROR, "Failed to get DRM resources"); 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 > backend->display_len) { struct wlr_drm_display *new = realloc(backend->displays, sizeof *new * res->count_connectors); - if (!new) + if (!new) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); goto error; + } for (int i = backend->display_len; i < res->count_connectors; ++i) { new[i] = (struct wlr_drm_display) { @@ -206,6 +257,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) } 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); } @@ -234,8 +286,10 @@ static uint32_t get_fb_for_bo(int fd, struct gbm_bo *bo) return *id; id = calloc(1, sizeof *id); - if (!id) + if (!id) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); return 0; + } drmModeAddFB(fd, gbm_bo_get_width(bo), gbm_bo_get_height(bo), 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, id); @@ -254,13 +308,19 @@ static bool display_init_renderer(struct wlr_drm_renderer *renderer, disp->width, disp->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - if (!disp->gbm) + if (!disp->gbm) { + wlr_log(L_ERROR, "Failed to create GBM surface for %s: %s", disp->name, + strerror(errno)); return false; + } disp->egl = create_platform_window_surface(renderer->egl.disp, renderer->egl.conf, disp->gbm, NULL); - if (disp->egl == EGL_NO_SURFACE) + if (disp->egl == EGL_NO_SURFACE) { + wlr_log(L_ERROR, "Failed to create EGL surface for %s: %s", disp->name, + egl_error()); return false; + } // Render black frame @@ -294,7 +354,7 @@ static drmModeModeInfo *select_mode(size_t num_modes, if (strcmp(str, "current") == 0) { if (!old_crtc) { - fprintf(stderr, "Display does not have currently configured mode\n"); + wlr_log(L_ERROR, "Display does not have currently configured mode"); return NULL; } @@ -313,7 +373,7 @@ static drmModeModeInfo *select_mode(size_t num_modes, int ret; if ((ret = sscanf(str, "%ux%u@%u", &width, &height, &rate)) != 2 && ret != 3) { - fprintf(stderr, "Invalid modesetting string\n"); + wlr_log(L_ERROR, "Invalid modesetting string '%s'", str); return NULL; } @@ -324,22 +384,40 @@ static drmModeModeInfo *select_mode(size_t num_modes, return &modes[i]; } + wlr_log(L_ERROR, "Unable to find mode %ux%u@%u", width, height, rate); return NULL; } bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, struct wlr_drm_display *disp, const char *str) { + wlr_log(L_INFO, "Modesetting %s with '%s'", disp->name, str); + drmModeConnector *conn = drmModeGetConnector(backend->fd, disp->connector); - if (!conn || conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) + if (!conn) { + wlr_log(L_ERROR, "Failed to get DRM connector"); goto error; + } + + if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) { + wlr_log(L_ERROR, "%s is not connected", disp->name); + goto error; + } disp->num_modes = conn->count_modes; disp->modes = malloc(sizeof *disp->modes * disp->num_modes); - if (!disp->modes) + if (!disp->modes) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); goto error; + } memcpy(disp->modes, conn->modes, sizeof *disp->modes * disp->num_modes); + wlr_log(L_INFO, "Detected modes:"); + for (size_t i = 0; i < disp->num_modes; ++i) + wlr_log(L_INFO, " %"PRIu16"@%"PRIu16"@%"PRIu32, + disp->modes[i].hdisplay, disp->modes[i].vdisplay, + disp->modes[i].vrefresh); + drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, conn->encoder_id); if (curr_enc) { disp->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id); @@ -348,17 +426,15 @@ bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, disp->active_mode = select_mode(disp->num_modes, disp->modes, disp->old_crtc, str); if (!disp->active_mode) { - fprintf(stderr, "Could not find mode '%s' for %s\n", str, disp->name); + wlr_log(L_ERROR, "Failed to configure %s", disp->name); goto error; } - fprintf(stderr, "Configuring %s with mode %ux%u@%u\n", - disp->name, disp->active_mode->hdisplay, disp->active_mode->vdisplay, - disp->active_mode->vrefresh); - drmModeRes *res = drmModeGetResources(backend->fd); - if (!res) + if (!res) { + wlr_log(L_ERROR, "Failed to get DRM resources"); goto error; + } bool success = false; for (int i = 0; !success && i < conn->count_encoders; ++i) { @@ -384,21 +460,33 @@ bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, drmModeFreeResources(res); - if (!success) + if (!success) { + wlr_log(L_ERROR, "Failed to find CRTC for %s", disp->name); goto error; + } disp->state = DRM_DISP_CONNECTED; - drmModeFreeConnector(conn); disp->width = disp->active_mode->hdisplay; disp->height = disp->active_mode->vdisplay; - display_init_renderer(&backend->renderer, disp); + if (!display_init_renderer(&backend->renderer, disp)) { + wlr_log(L_ERROR, "Failed to initalise renderer for %s", disp->name); + goto error; + } + + drmModeFreeConnector(conn); + + wlr_log(L_INFO, "Configuring %s with mode %"PRIu16"x%"PRIu16"@%"PRIu32"\n", + disp->name, disp->active_mode->hdisplay, disp->active_mode->vdisplay, + disp->active_mode->vrefresh); return true; + error: disp->state = DRM_DISP_DISCONNECTED; drmModeFreeConnector(conn); + free(disp->modes); wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM); @@ -418,13 +506,22 @@ static void page_flip_handler(int fd, wlr_drm_add_event(disp->renderer->backend, disp, DRM_EV_RENDER); } -void wlr_drm_display_free(struct wlr_drm_display *disp) +void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore) { if (!disp || disp->state != DRM_DISP_CONNECTED) return; struct wlr_drm_renderer *renderer = disp->renderer; + eglDestroySurface(renderer->egl.disp, disp->egl); + gbm_surface_destroy(disp->gbm); + + free(disp->modes); + disp->state = DRM_DISP_DISCONNECTED; + + if (!restore) + return; + drmModeCrtc *crtc = disp->old_crtc; if (crtc) { // Wait for exising page flips to finish @@ -443,11 +540,6 @@ void wlr_drm_display_free(struct wlr_drm_display *disp) 1, &crtc->mode); drmModeFreeCrtc(crtc); } - - eglDestroySurface(renderer->egl.disp, disp->egl); - gbm_surface_destroy(disp->gbm); - - free(disp->modes); } void wlr_drm_event(int fd) diff --git a/backend/drm/session.c b/backend/drm/session.c index 285f31b9..49223334 100644 --- a/backend/drm/session.c +++ b/backend/drm/session.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include "backend/drm/backend.h" #include "backend/drm/session.h" +#include "common/log.h" int wlr_session_take_device(struct wlr_session *restrict session, const char *restrict path, @@ -25,7 +27,7 @@ int wlr_session_take_device(struct wlr_session *restrict session, struct stat st; if (stat(path, &st) < 0) { - fprintf(stderr, "Failed to stat '%s'\n", path); + wlr_log(L_ERROR, "Failed to stat '%s'", path); return -1; } @@ -37,20 +39,26 @@ int wlr_session_take_device(struct wlr_session *restrict session, &error, &msg, "uu", major(st.st_rdev), minor(st.st_rdev)); if (ret < 0) { - fprintf(stderr, "%s\n", error.message); + wlr_log(L_ERROR, "Failed to take device '%s': %s", path, error.message); goto error; } int paused = 0; ret = sd_bus_message_read(msg, "hb", &fd, &paused); if (ret < 0) { - fprintf(stderr, "%s\n", strerror(-ret)); + wlr_log(L_ERROR, "Failed to parse DBus response for '%s': %s", + path, strerror(-ret)); goto error; } // The original fd seem to be closed when the message is freed // so we just clone it. fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); + if (fd == -1) { + wlr_log(L_ERROR, "Failed to clone file descriptor for '%s': %s", + path, strerror(errno)); + goto error; + } if (paused_out) *paused_out = paused; @@ -69,7 +77,7 @@ void wlr_session_release_device(struct wlr_session *session, int fd) struct stat st; if (fstat(fd, &st) < 0) { - fprintf(stderr, "Could not stat fd %d\n", fd); + wlr_log(L_ERROR, "Failed to stat device '%d'", fd); return; } @@ -80,9 +88,8 @@ void wlr_session_release_device(struct wlr_session *session, int fd) "ReleaseDevice", &error, &msg, "uu", major(st.st_rdev), minor(st.st_rdev)); - if (ret < 0) { - /* Log something */; - } + if (ret < 0) + wlr_log(L_ERROR, "Failed to release device '%d'", fd); sd_bus_error_free(&error); sd_bus_message_unref(msg); @@ -101,9 +108,8 @@ static bool session_activate(struct wlr_session *session) "Activate", &error, &msg, ""); - if (ret < 0) { - fprintf(stderr, "%s\n", error.message); - } + if (ret < 0) + wlr_log(L_ERROR, "Failed to activate session"); sd_bus_error_free(&error); sd_bus_message_unref(msg); @@ -123,9 +129,8 @@ static bool take_control(struct wlr_session *session) "TakeControl", &error, &msg, "b", false); - if (ret < 0) { - /* Log something */; - } + if (ret < 0) + wlr_log(L_ERROR, "Failed to take control of session"); sd_bus_error_free(&error); sd_bus_message_unref(msg); @@ -145,9 +150,8 @@ static void release_control(struct wlr_session *session) "ReleaseControl", &error, &msg, ""); - if (ret < 0) { - /* Log something */; - } + if (ret < 0) + wlr_log(L_ERROR, "Failed to release control of session"); sd_bus_error_free(&error); sd_bus_message_unref(msg); @@ -169,13 +173,13 @@ bool wlr_session_start(struct wlr_session *session) ret = sd_pid_get_session(getpid(), &session->id); if (ret < 0) { - fprintf(stderr, "Could not get session\n"); + wlr_log(L_ERROR, "Failed to get session id: %s", strerror(-ret)); goto error; } ret = sd_session_get_seat(session->id, &session->seat); if (ret < 0) { - fprintf(stderr, "Could not get seat\n"); + wlr_log(L_ERROR, "Failed to get seat id: %s", strerror(-ret)); goto error; } @@ -192,19 +196,15 @@ bool wlr_session_start(struct wlr_session *session) ret = sd_bus_open_system(&session->bus); if (ret < 0) { - fprintf(stderr, "Could not open bus\n"); + wlr_log(L_ERROR, "Failed to open DBus connection: %s", strerror(-ret)); goto error; } - if (!session_activate(session)) { - fprintf(stderr, "Could not activate session\n"); + if (!session_activate(session)) goto error_bus; - } - if (!take_control(session)) { - fprintf(stderr, "Could not take control of session\n"); + if (!take_control(session)) goto error_bus; - } return true; diff --git a/backend/drm/udev.c b/backend/drm/udev.c index c5440303..ebc68c6b 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -12,6 +12,7 @@ #include "backend/drm/udev.h" #include "backend/drm/session.h" #include "backend/drm/drm.h" +#include "common/log.h" static bool device_is_kms(struct wlr_udev *udev, struct wlr_session *session, @@ -59,8 +60,10 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) int fd = -1; struct udev_enumerate *en = udev_enumerate_new(udev->udev); - if (!en) + if (!en) { + wlr_log(L_ERROR, "Failed to create udev enumeration"); return -1; + } udev_enumerate_add_match_subsystem(en, "drm"); udev_enumerate_add_match_sysname(en, "card[0-9]*"); @@ -84,8 +87,7 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) } struct udev_device *pci = - udev_device_get_parent_with_subsystem_devtype(dev, - "pci", NULL); + udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL); if (pci) { const char *id = udev_device_get_sysattr_value(pci, "boot_vga"); @@ -117,11 +119,14 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) bool wlr_udev_init(struct wlr_udev *udev) { udev->udev = udev_new(); - if (!udev->udev) + 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; } diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index bd3d4105..1fe4b7b0 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -59,7 +59,7 @@ struct wlr_drm_display { 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 wlr_drm_display_free(struct wlr_drm_display *disp, bool restore); void wlr_drm_display_begin(struct wlr_drm_display *disp); void wlr_drm_display_end(struct wlr_drm_display *disp); -- cgit v1.2.3 From 115d4ae637673e348d5542740a158e6dcee0cf80 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Tue, 2 May 2017 14:08:34 +1200 Subject: Changed events to use wayland functions. --- backend/CMakeLists.txt | 1 - backend/drm/backend.c | 23 ++++++++--- backend/drm/drm.c | 65 +++++++++++++++++------------- backend/drm/event.c | 93 ------------------------------------------- backend/drm/udev.c | 69 ++++++++++++++++++++------------ include/backend/drm/backend.h | 17 ++++++-- include/backend/drm/event.h | 25 ------------ include/backend/drm/udev.h | 5 +-- 8 files changed, 114 insertions(+), 184 deletions(-) delete mode 100644 backend/drm/event.c delete mode 100644 include/backend/drm/event.h (limited to 'backend/drm/udev.c') diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 2d6e734f..344dd3cc 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -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 ) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index da7ca1e4..769a4a5c 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.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; } + 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_session_start(&backend->session)) { wlr_log(L_ERROR, "Failed to start session"); - goto error; + goto error_loop; } - if (!wlr_udev_init(&backend->udev)) { + 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); } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 94d79e5c..d1d68224 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -11,10 +11,10 @@ #include #include #include +#include #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; diff --git a/backend/drm/event.c b/backend/drm/event.c deleted file mode 100644 index db17b5b7..00000000 --- a/backend/drm/event.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include - -#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; -} diff --git a/backend/drm/udev.c b/backend/drm/udev.c index ebc68c6b..6c4aa074 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "backend/drm/backend.h" #include "backend/drm/udev.h" @@ -116,8 +117,34 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) return fd; } -bool wlr_udev_init(struct wlr_udev *udev) +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 1; + + const char *path = udev_device_get_devnode(dev); + 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; + + wlr_drm_scan_connectors(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"); @@ -127,17 +154,29 @@ bool wlr_udev_init(struct wlr_udev *udev) 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; + goto error_udev; } 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); + 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) @@ -150,25 +189,3 @@ void wlr_udev_free(struct wlr_udev *udev) udev_unref(udev->udev); free(udev->drm_path); } - -void wlr_udev_event(struct wlr_drm_backend *backend) -{ - 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, udev->drm_path) != 0) - goto out; - - const char *action = udev_device_get_action(dev); - if (!action || strcmp(action, "change") != 0) - goto out; - - wlr_drm_scan_connectors(backend); - -out: - udev_device_unref(dev); -} diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h index caa18bcc..25a42c37 100644 --- a/include/backend/drm/backend.h +++ b/include/backend/drm/backend.h @@ -6,6 +6,7 @@ #include #include #include +#include #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; diff --git a/include/backend/drm/event.h b/include/backend/drm/event.h deleted file mode 100644 index 2155bd32..00000000 --- a/include/backend/drm/event.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef EVENT_H -#define EVENT_H - -#include -#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 diff --git a/include/backend/drm/udev.h b/include/backend/drm/udev.h index 6b10c9ec..576b5d6e 100644 --- a/include/backend/drm/udev.h +++ b/include/backend/drm/udev.h @@ -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 -- cgit v1.2.3 From e446a5300b742dd8a7f403bf96d1137e91ba1b11 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Tue, 2 May 2017 18:13:17 +1200 Subject: Added example. --- CMake/FindGBM.cmake | 39 +++++++++++++++ CMakeLists.txt | 5 +- backend/CMakeLists.txt | 7 +++ backend/drm/backend.c | 17 ++++++- backend/drm/drm.c | 10 ++-- backend/drm/session.c | 2 +- backend/drm/udev.c | 8 ++-- example/CMakeLists.txt | 8 ++++ example/example-drm.c | 109 ++++++++++++++++++++++++++++++++++++++++++ include/backend/drm/backend.h | 5 +- include/backend/drm/drm.h | 3 +- include/wlr/backend/drm.h | 20 ++++++++ 12 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 CMake/FindGBM.cmake create mode 100644 example/example-drm.c create mode 100644 include/wlr/backend/drm.h (limited to 'backend/drm/udev.c') diff --git a/CMake/FindGBM.cmake b/CMake/FindGBM.cmake new file mode 100644 index 00000000..85df1f7c --- /dev/null +++ b/CMake/FindGBM.cmake @@ -0,0 +1,39 @@ +#.rst: +# FindGBM +# ------- +# +# Find GBM library +# +# Try to find GBM library on UNIX systems. The following values are defined +# +# :: +# +# GBM_FOUND - True if gbm is available +# GBM_INCLUDE_DIRS - Include directories for gbm +# GBM_LIBRARIES - List of libraries for gbm +# GBM_DEFINITIONS - List of definitions for gbm +# +#============================================================================= +# Copyright (c) 2015 Jari Vetoniemi +# +# Distributed under the OSI-approved BSD License (the "License"); +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +set_package_properties(GBM PROPERTIES + URL "http://www.mesa3d.org/" + DESCRIPTION "Generic buffer manager") + +find_package(PkgConfig) +pkg_check_modules(PC_GBM QUIET gbm) +find_library(GBM_LIBRARIES NAMES gbm HINTS ${PC_GBM_LIBRARY_DIRS}) +find_path(GBM_INCLUDE_DIRS gbm.h HINTS ${PC_GBM_INCLUDE_DIRS}) + +set(GBM_DEFINITIONS ${PC_GBM_CFLAGS_OTHER}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GBM DEFAULT_MSG GBM_INCLUDE_DIRS GBM_LIBRARIES) +mark_as_advanced(GBM_INCLUDE_DIRS GBM_LIBRARIES GBM_DEFINITIONS) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30a2c37d..192eb444 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,10 +48,11 @@ find_package(WaylandProtocols REQUIRED) find_package(EGL REQUIRED) find_package(GLESv2 REQUIRED) find_package(DRM REQUIRED) +find_package(GBM REQUIRED) find_package(LibInput REQUIRED) -find_package(Udev) +find_package(Udev REQUIRED) find_package(Dbus) -find_package(Systemd) +find_package(Systemd REQUIRED) include(Wayland) include(Manpage) diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 344dd3cc..184854fe 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -19,4 +19,11 @@ target_link_libraries(wlr-backend wlr-common wlr-wayland ${WAYLAND_LIBRARIES} + ${DRM_LIBRARIES} + ${GBM_LIBRARIES} + ${GLESv2_LIBRARIES} + ${EGL_LIBRARIES} + ${SYSTEMD_LIBRARIES} + ${UDEV_LIBRARIES} + ${GBM_LIBRARIES} ) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 73e57bfa..7db6e9a1 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -12,7 +12,9 @@ #include "backend/drm/udev.h" #include "common/log.h" -struct wlr_drm_backend *wlr_drm_backend_init(void) +struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, + struct wl_listener *rem, + struct wl_listener *render) { struct wlr_drm_backend *backend = calloc(1, sizeof *backend); if (!backend) { @@ -57,6 +59,13 @@ struct wlr_drm_backend *wlr_drm_backend_init(void) wl_signal_init(&backend->signals.display_rem); wl_signal_init(&backend->signals.display_render); + if (add) + wl_signal_add(&backend->signals.display_add, add); + if (rem) + wl_signal_add(&backend->signals.display_rem, rem); + if (render) + wl_signal_add(&backend->signals.display_render, render); + wlr_drm_scan_connectors(backend); return backend; @@ -80,6 +89,7 @@ static void free_display(void *item) { struct wlr_drm_display *disp = item; wlr_drm_display_free(disp, true); + free(disp); } void wlr_drm_backend_free(struct wlr_drm_backend *backend) @@ -95,9 +105,14 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend) wlr_session_end(&backend->session); wl_event_source_remove(backend->event_src.drm); + wl_event_source_remove(backend->event_src.udev); wl_event_loop_destroy(backend->event_loop); list_free(backend->displays); free(backend); } +struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend) +{ + return backend->event_loop; +} diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 226c79fb..470a76bb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -281,6 +281,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) continue; } + disp->renderer = &backend->renderer; disp->state = DRM_DISP_DISCONNECTED; disp->connector = res->connectors[i]; snprintf(disp->name, sizeof disp->name, "%s-%"PRIu32, @@ -288,6 +289,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) conn->connector_type_id); list_add(backend->displays, disp); + wlr_log(L_INFO, "Found display '%s'", disp->name); } else { disp = backend->displays->items[index]; } @@ -295,12 +297,14 @@ 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_log(L_INFO, "Sending modesetting signal for '%s'", disp->name); 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_log(L_INFO, "Sending destruction signal for '%s'", disp->name); wl_signal_emit(&backend->signals.display_rem, disp); } @@ -430,9 +434,9 @@ static drmModeModeInfo *select_mode(size_t num_modes, return NULL; } -bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, - struct wlr_drm_display *disp, const char *str) +bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str) { + struct wlr_drm_backend *backend = disp->renderer->backend; wlr_log(L_INFO, "Modesetting %s with '%s'", disp->name, str); drmModeConnector *conn = drmModeGetConnector(backend->fd, disp->connector); @@ -519,7 +523,7 @@ bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, drmModeFreeConnector(conn); - wlr_log(L_INFO, "Configuring %s with mode %"PRIu16"x%"PRIu16"@%"PRIu32"\n", + wlr_log(L_INFO, "Configuring %s with mode %"PRIu16"x%"PRIu16"@%"PRIu32"", disp->name, disp->active_mode->hdisplay, disp->active_mode->vdisplay, disp->active_mode->vrefresh); diff --git a/backend/drm/session.c b/backend/drm/session.c index 49223334..073f822b 100644 --- a/backend/drm/session.c +++ b/backend/drm/session.c @@ -194,7 +194,7 @@ bool wlr_session_start(struct wlr_session *session) sprintf(session->path, fmt, session->id); - ret = sd_bus_open_system(&session->bus); + ret = sd_bus_default_system(&session->bus); if (ret < 0) { wlr_log(L_ERROR, "Failed to open DBus connection: %s", strerror(-ret)); goto error; diff --git a/backend/drm/udev.c b/backend/drm/udev.c index 6c4aa074..ae99bcfc 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -94,9 +94,10 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) const char *id = udev_device_get_sysattr_value(pci, "boot_vga"); if (id && strcmp(id, "1") == 0) is_boot_vga = true; - udev_device_unref(pci); + //udev_device_unref(pci); } + // We already have a valid GPU if (!is_boot_vga && fd >= 0) { udev_device_unref(dev); continue; @@ -107,9 +108,10 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) continue; } - if (is_boot_vga) { + udev_device_unref(dev); + + if (is_boot_vga) break; - } } udev_enumerate_unref(en); diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 73768393..dfb069b4 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -5,3 +5,11 @@ add_executable(example target_link_libraries(example wlr-backend ) + +add_executable(example-drm + example-drm.c +) + +target_link_libraries(example-drm + wlr-backend +) diff --git a/example/example-drm.c b/example/example-drm.c new file mode 100644 index 00000000..4c944226 --- /dev/null +++ b/example/example-drm.c @@ -0,0 +1,109 @@ +#define _POSIX_C_SOURCE 199309L +#include +#include +#include +#include +#include + +#include + +struct state { + float color[3]; + int dec; + + struct timespec last_frame; + + struct wl_listener add; + struct wl_listener rem; + struct wl_listener render; +}; + +void display_add(struct wl_listener *listener, void *data) +{ + struct wlr_drm_display *disp = data; + + fprintf(stderr, "Display added\n"); + wlr_drm_display_modeset(disp, "preferred"); +} + +void display_rem(struct wl_listener *listener, void *data) +{ + fprintf(stderr, "Display removed\n"); +} + +void display_render(struct wl_listener *listener, void *data) +{ + struct wlr_drm_display *disp = data; + struct state *s = wl_container_of(listener, s, render); + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + long ms = (now.tv_sec - s->last_frame.tv_sec) * 1000 + + (now.tv_nsec - s->last_frame.tv_nsec) / 1000000; + int inc = (s->dec + 1) % 3; + + s->color[inc] += ms / 2000.0f; + s->color[s->dec] -= ms / 2000.0f; + + if (s->color[s->dec] < 0.0f) { + s->color[inc] = 1.0f; + s->color[s->dec] = 0.0f; + + s->dec = inc; + } + + s->last_frame = now; + + wlr_drm_display_begin(disp); + + glClearColor(s->color[0], s->color[1], s->color[2], 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + wlr_drm_display_end(disp); +} + +int timer_done(void *data) +{ + *(bool *)data = true; + return 1; +} + +int main() +{ + if (getenv("DISPLAY")) { + fprintf(stderr, "Detected that X is running. Run this in its own virtual terminal.\n"); + return 1; + } else if (getenv("WAYLAND_DISPLAY")) { + fprintf(stderr, "Detected that Wayland is running. Run this in its own virtual terminal.\n"); + return 1; + } + + struct state state = { + .color = { 1.0, 0.0, 0.0 }, + .dec = 0, + .add = { .notify = display_add }, + .rem = { .notify = display_rem }, + .render = { .notify = display_render }, + }; + + wl_list_init(&state.add.link); + wl_list_init(&state.rem.link); + wl_list_init(&state.render.link); + clock_gettime(CLOCK_MONOTONIC, &state.last_frame); + + struct wlr_drm_backend *wlr = wlr_drm_backend_init(&state.add, &state.rem, &state.render); + + bool done = false; + struct wl_event_loop *event_loop = wlr_drm_backend_get_event_loop(wlr); + struct wl_event_source *timer = wl_event_loop_add_timer(event_loop, + timer_done, &done); + + wl_event_source_timer_update(timer, 10000); + + while (!done) + wl_event_loop_dispatch(event_loop, 0); + + wl_event_source_remove(timer); + wlr_drm_backend_free(wlr); +} diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h index 87471fbb..1ad8e479 100644 --- a/include/backend/drm/backend.h +++ b/include/backend/drm/backend.h @@ -9,6 +9,7 @@ #include #include +#include #include "session.h" #include "udev.h" @@ -41,7 +42,9 @@ struct wlr_drm_backend { struct wlr_udev udev; }; -struct wlr_drm_backend *wlr_drm_backend_init(void); +struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, + struct wl_listener *rem, + struct wl_listener *render); 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 1fe4b7b0..17d4aa90 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -57,8 +57,7 @@ struct wlr_drm_display { bool cleanup; }; -bool wlr_drm_display_modeset(struct wlr_drm_backend *backend, - struct wlr_drm_display *disp, const char *str); +bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str); void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore); void wlr_drm_display_begin(struct wlr_drm_display *disp); diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h new file mode 100644 index 00000000..5179db4b --- /dev/null +++ b/include/wlr/backend/drm.h @@ -0,0 +1,20 @@ +#ifndef WLR_BACKEND_DRM_H +#define WLR_BACKEND_DRM_H + +#include + +struct wlr_drm_backend; +struct wlr_drm_display; + +struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, + struct wl_listener *rem, + struct wl_listener *render); +void wlr_drm_backend_free(struct wlr_drm_backend *backend); + +struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend); + +bool wlr_drm_display_modeset(struct wlr_drm_display *disp, const char *str); +void wlr_drm_display_begin(struct wlr_drm_display *disp); +void wlr_drm_display_end(struct wlr_drm_display *disp); + +#endif -- cgit v1.2.3 From 81998fdc98231cb1b2e050da2fcec7c75d46320c Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Wed, 3 May 2017 16:23:07 +1200 Subject: Removed old session code from DRM backend. --- backend/CMakeLists.txt | 1 - backend/drm/backend.c | 26 ++--- backend/drm/session.c | 219 ------------------------------------------ backend/drm/udev.c | 11 ++- example/CMakeLists.txt | 1 + example/example-drm.c | 9 +- include/backend/drm/backend.h | 9 +- include/backend/drm/session.h | 24 ----- include/backend/drm/udev.h | 2 +- include/wlr/backend/drm.h | 6 +- session/logind.c | 3 + session/session.c | 3 + 12 files changed, 40 insertions(+), 274 deletions(-) delete mode 100644 backend/drm/session.c delete mode 100644 include/backend/drm/session.h (limited to 'backend/drm/udev.c') diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 184854fe..ee8b04d6 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -11,7 +11,6 @@ add_library(wlr-backend wayland/wl_output.c drm/backend.c drm/drm.c - drm/session.c drm/udev.c ) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 7db6e9a1..9f9a02c7 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -4,17 +4,16 @@ #include #include +#include #include #include "backend/drm/backend.h" #include "backend/drm/drm.h" -#include "backend/drm/session.h" #include "backend/drm/udev.h" #include "common/log.h" -struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, - struct wl_listener *rem, - struct wl_listener *render) +struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, + struct wl_listener *add, struct wl_listener *rem, struct wl_listener *render) { struct wlr_drm_backend *backend = calloc(1, sizeof *backend); if (!backend) { @@ -22,6 +21,8 @@ struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, return NULL; } + backend->session = session; + backend->displays = list_create(); if (!backend->displays) { wlr_log(L_ERROR, "Failed to allocate list"); @@ -34,17 +35,12 @@ struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, goto error_list; } - 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; + goto error_loop; } - backend->fd = wlr_udev_find_gpu(&backend->udev, &backend->session); + backend->fd = wlr_udev_find_gpu(&backend->udev, backend->session); if (backend->fd == -1) { wlr_log(L_ERROR, "Failed to open DRM device"); goto error_udev; @@ -71,11 +67,9 @@ struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, return backend; error_fd: - wlr_session_release_device(&backend->session, backend->fd); + wlr_session_close_file(backend->session, backend->fd); error_udev: wlr_udev_free(&backend->udev); -error_session: - wlr_session_end(&backend->session); error_loop: wl_event_loop_destroy(backend->event_loop); error_list: @@ -101,8 +95,8 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend) wlr_drm_renderer_free(&backend->renderer); wlr_udev_free(&backend->udev); - wlr_session_release_device(&backend->session, backend->fd); - wlr_session_end(&backend->session); + wlr_session_close_file(backend->session, backend->fd); + wlr_session_finish(backend->session); wl_event_source_remove(backend->event_src.drm); wl_event_source_remove(backend->event_src.udev); diff --git a/backend/drm/session.c b/backend/drm/session.c deleted file mode 100644 index 073f822b..00000000 --- a/backend/drm/session.c +++ /dev/null @@ -1,219 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backend/drm/backend.h" -#include "backend/drm/session.h" -#include "common/log.h" - -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 stat st; - if (stat(path, &st) < 0) { - wlr_log(L_ERROR, "Failed to stat '%s'", path); - return -1; - } - - ret = sd_bus_call_method(session->bus, - "org.freedesktop.login1", - session->path, - "org.freedesktop.login1.Session", - "TakeDevice", - &error, &msg, - "uu", major(st.st_rdev), minor(st.st_rdev)); - if (ret < 0) { - wlr_log(L_ERROR, "Failed to take device '%s': %s", path, error.message); - goto error; - } - - int paused = 0; - ret = sd_bus_message_read(msg, "hb", &fd, &paused); - if (ret < 0) { - wlr_log(L_ERROR, "Failed to parse DBus response for '%s': %s", - path, strerror(-ret)); - goto error; - } - - // The original fd seem to be closed when the message is freed - // so we just clone it. - fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); - if (fd == -1) { - wlr_log(L_ERROR, "Failed to clone file descriptor for '%s': %s", - path, strerror(errno)); - goto error; - } - - if (paused_out) - *paused_out = paused; - -error: - sd_bus_error_free(&error); - sd_bus_message_unref(msg); - return 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 stat st; - if (fstat(fd, &st) < 0) { - wlr_log(L_ERROR, "Failed to stat device '%d'", fd); - return; - } - - ret = sd_bus_call_method(session->bus, - "org.freedesktop.login1", - session->path, - "org.freedesktop.login1.Session", - "ReleaseDevice", - &error, &msg, - "uu", major(st.st_rdev), minor(st.st_rdev)); - if (ret < 0) - wlr_log(L_ERROR, "Failed to release device '%d'", fd); - - sd_bus_error_free(&error); - sd_bus_message_unref(msg); -} - -static bool session_activate(struct wlr_session *session) -{ - int ret; - sd_bus_message *msg = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - - ret = sd_bus_call_method(session->bus, - "org.freedesktop.login1", - session->path, - "org.freedesktop.login1.Session", - "Activate", - &error, &msg, - ""); - if (ret < 0) - wlr_log(L_ERROR, "Failed to activate session"); - - sd_bus_error_free(&error); - sd_bus_message_unref(msg); - return ret >= 0; -} - -static bool take_control(struct wlr_session *session) -{ - int ret; - sd_bus_message *msg = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - - ret = sd_bus_call_method(session->bus, - "org.freedesktop.login1", - session->path, - "org.freedesktop.login1.Session", - "TakeControl", - &error, &msg, - "b", false); - if (ret < 0) - wlr_log(L_ERROR, "Failed to take control of session"); - - sd_bus_error_free(&error); - sd_bus_message_unref(msg); - return ret >= 0; -} - -static void release_control(struct wlr_session *session) -{ - int ret; - sd_bus_message *msg = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - - ret = sd_bus_call_method(session->bus, - "org.freedesktop.login1", - session->path, - "org.freedesktop.login1.Session", - "ReleaseControl", - &error, &msg, - ""); - if (ret < 0) - wlr_log(L_ERROR, "Failed to release control of session"); - - sd_bus_error_free(&error); - sd_bus_message_unref(msg); -} - -void wlr_session_end(struct wlr_session *session) -{ - release_control(session); - - sd_bus_unref(session->bus); - free(session->id); - free(session->path); - free(session->seat); -} - -bool wlr_session_start(struct wlr_session *session) -{ - int ret; - - ret = sd_pid_get_session(getpid(), &session->id); - if (ret < 0) { - wlr_log(L_ERROR, "Failed to get session id: %s", strerror(-ret)); - goto error; - } - - ret = sd_session_get_seat(session->id, &session->seat); - if (ret < 0) { - wlr_log(L_ERROR, "Failed to get seat id: %s", strerror(-ret)); - goto error; - } - - // 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, session->id); - - session->path = malloc(len + 1); - if (!session->path) - goto error; - - sprintf(session->path, fmt, session->id); - - ret = sd_bus_default_system(&session->bus); - if (ret < 0) { - wlr_log(L_ERROR, "Failed to open DBus connection: %s", strerror(-ret)); - goto error; - } - - if (!session_activate(session)) - goto error_bus; - - if (!take_control(session)) - goto error_bus; - - return true; - -error_bus: - sd_bus_unref(session->bus); - -error: - free(session->path); - free(session->id); - free(session->seat); - return false; -} diff --git a/backend/drm/udev.c b/backend/drm/udev.c index ae99bcfc..6921a998 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -9,9 +9,10 @@ #include #include +#include + #include "backend/drm/backend.h" #include "backend/drm/udev.h" -#include "backend/drm/session.h" #include "backend/drm/drm.h" #include "common/log.h" @@ -26,7 +27,7 @@ static bool device_is_kms(struct wlr_udev *udev, if (!path) return false; - fd = wlr_session_take_device(session, path, NULL); + fd = wlr_session_open_file(session, path); if (fd < 0) return false; @@ -39,7 +40,7 @@ static bool device_is_kms(struct wlr_udev *udev, goto out_res; if (*fd_out >= 0) { - wlr_session_release_device(session, *fd_out); + wlr_session_close_file(session, *fd_out); free(udev->drm_path); } @@ -52,7 +53,7 @@ static bool device_is_kms(struct wlr_udev *udev, out_res: drmModeFreeResources(res); out_fd: - wlr_session_release_device(session, fd); + wlr_session_close_file(session, fd); return false; } @@ -79,6 +80,7 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) if (!dev) continue; + /* const char *seat = udev_device_get_property_value(dev, "ID_SEAT"); if (!seat) seat = "seat0"; @@ -86,6 +88,7 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) udev_device_unref(dev); continue; } + */ struct udev_device *pci = udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL); diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index dfb069b4..fb2f3823 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -12,4 +12,5 @@ add_executable(example-drm target_link_libraries(example-drm wlr-backend + wlr-session ) diff --git a/example/example-drm.c b/example/example-drm.c index 4c944226..a3a2a8fd 100644 --- a/example/example-drm.c +++ b/example/example-drm.c @@ -6,6 +6,7 @@ #include #include +#include struct state { float color[3]; @@ -92,7 +93,13 @@ int main() wl_list_init(&state.render.link); clock_gettime(CLOCK_MONOTONIC, &state.last_frame); - struct wlr_drm_backend *wlr = wlr_drm_backend_init(&state.add, &state.rem, &state.render); + struct wlr_session *session = wlr_session_start(); + if (!session) { + return 1; + } + + struct wlr_drm_backend *wlr = wlr_drm_backend_init(session, + &state.add, &state.rem, &state.render); bool done = false; struct wl_event_loop *event_loop = wlr_drm_backend_get_event_loop(wlr); diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h index 1ad8e479..32182d0c 100644 --- a/include/backend/drm/backend.h +++ b/include/backend/drm/backend.h @@ -8,10 +8,10 @@ #include #include +#include #include #include -#include "session.h" #include "udev.h" #include "event.h" #include "drm.h" @@ -38,13 +38,12 @@ struct wlr_drm_backend { uint32_t taken_crtcs; struct wlr_drm_renderer renderer; - struct wlr_session session; + struct wlr_session *session; struct wlr_udev udev; }; -struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, - struct wl_listener *rem, - struct wl_listener *render); +struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, + struct wl_listener *add, struct wl_listener *rem, struct wl_listener *render); void wlr_drm_backend_free(struct wlr_drm_backend *backend); #endif diff --git a/include/backend/drm/session.h b/include/backend/drm/session.h deleted file mode 100644 index 6936b19a..00000000 --- a/include/backend/drm/session.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SESSION_H -#define SESSION_H - -#include -#include - -struct wlr_session { - sd_bus *bus; - - char *id; - char *path; - char *seat; -}; - -bool wlr_session_start(struct wlr_session *session); -void wlr_session_end(struct wlr_session *session); - -int wlr_session_take_device(struct wlr_session *restrict session, - const char *restrict path, - bool *restrict paused_out); - -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 576b5d6e..a09ee218 100644 --- a/include/backend/drm/udev.h +++ b/include/backend/drm/udev.h @@ -3,7 +3,7 @@ #include -#include "backend/drm/session.h" +#include struct wlr_udev { struct udev *udev; diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 5179db4b..ede43fda 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -2,13 +2,13 @@ #define WLR_BACKEND_DRM_H #include +#include struct wlr_drm_backend; struct wlr_drm_display; -struct wlr_drm_backend *wlr_drm_backend_init(struct wl_listener *add, - struct wl_listener *rem, - struct wl_listener *render); +struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, + struct wl_listener *add, struct wl_listener *rem, struct wl_listener *render); void wlr_drm_backend_free(struct wlr_drm_backend *backend); struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend); diff --git a/session/logind.c b/session/logind.c index c81a2020..0d8a52b5 100644 --- a/session/logind.c +++ b/session/logind.c @@ -200,6 +200,9 @@ static struct wlr_session *logind_session_start(void) { if (!take_control(session)) goto error_bus; + wl_log(L_INFO, "Successfully loaded logind session"); + + session->base.iface = session_logind_iface; return &session->base; error_bus: diff --git a/session/session.c b/session/session.c index 88391e6e..2f1b87be 100644 --- a/session/session.c +++ b/session/session.c @@ -1,6 +1,8 @@ #include #include +#include +#include "common/log.h" #include "session/interface.h" static const struct session_interface *ifaces[] = { @@ -20,6 +22,7 @@ struct wlr_session *wlr_session_start(void) { } } + wlr_log(L_ERROR, "Failed to load session backend"); return NULL; } -- cgit v1.2.3 From d196a79b6c493d74d0057d74238353180d717255 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Wed, 3 May 2017 21:28:44 +1200 Subject: Changed backend to accept wl_display. --- backend/drm/backend.c | 53 +++++++++++------------ backend/drm/drm.c | 29 +++---------- backend/drm/udev.c | 99 +++++++++++++++++++++++++------------------ example/example-drm.c | 6 ++- include/backend/drm/backend.h | 14 +----- include/backend/drm/drm.h | 5 +-- include/backend/drm/udev.h | 5 ++- include/wlr/backend/drm.h | 7 ++- 8 files changed, 106 insertions(+), 112 deletions(-) (limited to 'backend/drm/udev.c') diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 03e34d97..5d72d9dc 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -12,9 +13,10 @@ #include "backend/drm/udev.h" #include "common/log.h" -struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, - struct wl_listener *add, struct wl_listener *rem, struct wl_listener *render) -{ +struct wlr_drm_backend *wlr_drm_backend_init(struct wl_display *display, + struct wlr_session *session, struct wl_listener *add, struct wl_listener *rem, + struct wl_listener *render) { + struct wlr_drm_backend *backend = calloc(1, sizeof *backend); if (!backend) { wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); @@ -29,15 +31,9 @@ struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, goto error_backend; } - backend->event_loop = wl_event_loop_create(); - if (!backend->event_loop) { - wlr_log(L_ERROR, "Failed to create event loop"); - goto error_list; - } - - if (!wlr_udev_init(backend)) { + if (!wlr_udev_init(display, &backend->udev)) { wlr_log(L_ERROR, "Failed to start udev"); - goto error_loop; + goto error_list; } backend->fd = wlr_udev_find_gpu(&backend->udev, backend->session); @@ -46,32 +42,44 @@ struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, goto error_udev; } - if (!wlr_drm_renderer_init(&backend->renderer, backend, backend->fd)) { - wlr_log(L_ERROR, "Failed to initialize renderer"); + struct wl_event_loop *event_loop = wl_display_get_event_loop(display); + + backend->drm_event = wl_event_loop_add_fd(event_loop, backend->fd, + WL_EVENT_READABLE, wlr_drm_event, NULL); + if (!backend->drm_event) { + wlr_log(L_ERROR, "Failed to create DRM event source"); goto error_fd; } + if (!wlr_drm_renderer_init(&backend->renderer, backend->fd)) { + wlr_log(L_ERROR, "Failed to initialize renderer"); + goto error_event; + } + wl_signal_init(&backend->signals.output_add); wl_signal_init(&backend->signals.output_rem); wl_signal_init(&backend->signals.output_render); - if (add) + if (add) { wl_signal_add(&backend->signals.output_add, add); - if (rem) + } + if (rem) { wl_signal_add(&backend->signals.output_rem, rem); - if (render) + } + if (render) { wl_signal_add(&backend->signals.output_render, render); + } wlr_drm_scan_connectors(backend); return backend; +error_event: + wl_event_source_remove(backend->drm_event); error_fd: wlr_session_close_file(backend->session, backend->fd); error_udev: wlr_udev_free(&backend->udev); -error_loop: - wl_event_loop_destroy(backend->event_loop); error_list: list_free(backend->outputs); error_backend: @@ -98,15 +106,8 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend) wlr_session_close_file(backend->session, backend->fd); wlr_session_finish(backend->session); - wl_event_source_remove(backend->event_src.drm); - wl_event_source_remove(backend->event_src.udev); - wl_event_loop_destroy(backend->event_loop); + wl_event_source_remove(backend->drm_event); list_free(backend->outputs); free(backend); } - -struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend) -{ - return backend->event_loop; -} diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 13971687..f636c42c 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -41,7 +41,7 @@ static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv void *user) { struct wlr_drm_output *out = user; - struct wlr_drm_backend *backend = out->renderer->backend; + struct wlr_drm_backend *backend = wl_container_of(out->renderer, backend, renderer); out->pageflip_pending = true; if (!out->cleanup) { @@ -49,7 +49,7 @@ static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv } } -static int drm_event(int fd, uint32_t mask, void *data) { +int wlr_drm_event(int fd, uint32_t mask, void *data) { drmEventContext event = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, @@ -60,8 +60,7 @@ static int drm_event(int fd, uint32_t mask, void *data) { return 1; } -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_backend *backend, int fd) { +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { renderer->gbm = gbm_create_device(fd); if (!renderer->gbm) { @@ -70,28 +69,12 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, } if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, renderer->gbm)) { - goto error_gbm; - } - - 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; + gbm_device_destroy(renderer->gbm); + return false; } renderer->fd = fd; - renderer->backend = backend; - return true; - -error_egl: - wlr_egl_free(&renderer->egl); - -error_gbm: - gbm_device_destroy(renderer->gbm); - - return false; } void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer) { @@ -296,7 +279,7 @@ static drmModeModeInfo *select_mode(size_t num_modes, drmModeModeInfo modes[stat } bool wlr_drm_output_modeset(struct wlr_drm_output *out, const char *str) { - struct wlr_drm_backend *backend = out->renderer->backend; + struct wlr_drm_backend *backend = wl_container_of(out->renderer, backend, renderer); wlr_log(L_INFO, "Modesetting %s with '%s'", out->name, str); drmModeConnector *conn = drmModeGetConnector(backend->fd, out->connector); diff --git a/backend/drm/udev.c b/backend/drm/udev.c index 6921a998..438047d6 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -16,36 +16,39 @@ #include "backend/drm/drm.h" #include "common/log.h" -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); +/* Tests if 'path' is KMS compatible by trying to open it. + * It leaves the open device in *fd_out it it succeeds. + */ +static bool device_is_kms(struct wlr_session *restrict session, + const char *restrict path, int *restrict fd_out) { + int fd; - if (!path) + if (!path) { return false; + } fd = wlr_session_open_file(session, path); - if (fd < 0) + if (fd < 0) { return false; + } drmModeRes *res = drmModeGetResources(fd); - if (!res) + if (!res) { goto out_fd; + } if (res->count_crtcs <= 0 || res->count_connectors <= 0 || - res->count_encoders <= 0) + res->count_encoders <= 0) { + goto out_res; + } if (*fd_out >= 0) { wlr_session_close_file(session, *fd_out); - free(udev->drm_path); } *fd_out = fd; - udev->drm_path = strdup(path); drmModeFreeResources(res); return true; @@ -57,10 +60,10 @@ out_fd: return false; } -int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) -{ - int fd = -1; - +/* Tries to find the primary GPU by checking for the "boot_vga" attribute. + * If it's not found, it returns the first valid GPU it finds. + */ +int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { struct udev_enumerate *en = udev_enumerate_new(udev->udev); if (!en) { wlr_log(L_ERROR, "Failed to create udev enumeration"); @@ -69,16 +72,20 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) udev_enumerate_add_match_subsystem(en, "drm"); udev_enumerate_add_match_sysname(en, "card[0-9]*"); - udev_enumerate_scan_devices(en); + struct udev_list_entry *entry; + int fd = -1; + char *drm_path = NULL; + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(en)) { bool is_boot_vga = false; const char *path = udev_list_entry_get_name(entry); struct udev_device *dev = udev_device_new_from_syspath(udev->udev, path); - if (!dev) + if (!dev) { continue; + } /* const char *seat = udev_device_get_property_value(dev, "ID_SEAT"); @@ -90,14 +97,15 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) } */ + // This is owned by 'dev', so we don't need to free it struct udev_device *pci = udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL); if (pci) { const char *id = udev_device_get_sysattr_value(pci, "boot_vga"); - if (id && strcmp(id, "1") == 0) + if (id && strcmp(id, "1") == 0) { is_boot_vga = true; - //udev_device_unref(pci); + } } // We already have a valid GPU @@ -106,38 +114,47 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) continue; } - if (!device_is_kms(udev, session, dev, &fd)) { + path = udev_device_get_devnode(dev); + if (!device_is_kms(session, path, &fd)) { udev_device_unref(dev); continue; } + free(drm_path); + drm_path = strdup(path); + udev_device_unref(dev); - if (is_boot_vga) + // We've found the primary GPU + if (is_boot_vga) { break; + } } udev_enumerate_unref(en); + udev->drm_path = drm_path; return fd; } -static int udev_event(int fd, uint32_t mask, void *data) -{ - struct wlr_drm_backend *backend = data; - struct wlr_udev *udev = &backend->udev; +static int udev_event(int fd, uint32_t mask, void *data) { + struct wlr_udev *udev = data; + struct wlr_drm_backend *backend = wl_container_of(udev, backend, udev); struct udev_device *dev = udev_monitor_receive_device(udev->mon); - if (!dev) + if (!dev) { return 1; + } const char *path = udev_device_get_devnode(dev); - if (!path || strcmp(path, udev->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) + if (!action || strcmp(action, "change") != 0) { goto out; + } wlr_drm_scan_connectors(backend); @@ -146,10 +163,7 @@ out: return 1; } -bool wlr_udev_init(struct wlr_drm_backend *backend) -{ - struct wlr_udev *udev = &backend->udev; - +bool wlr_udev_init(struct wl_display *display, struct wlr_udev *udev) { udev->udev = udev_new(); if (!udev->udev) { wlr_log(L_ERROR, "Failed to create udev context"); @@ -165,10 +179,12 @@ bool wlr_udev_init(struct wlr_drm_backend *backend) 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) { + struct wl_event_loop *event_loop = wl_display_get_event_loop(display); + int fd = udev_monitor_get_fd(udev->mon); + + udev->event = wl_event_loop_add_fd(event_loop, fd, WL_EVENT_READABLE, + udev_event, udev); + if (!udev->event) { wlr_log(L_ERROR, "Failed to create udev event source"); goto error_mon; } @@ -184,11 +200,12 @@ error_udev: return false; } -void wlr_udev_free(struct wlr_udev *udev) - -{ - if (!udev) +void wlr_udev_free(struct wlr_udev *udev) { + if (!udev) { return; + } + + wl_event_source_remove(udev->event); udev_monitor_unref(udev->mon); udev_unref(udev->udev); diff --git a/example/example-drm.c b/example/example-drm.c index 072e5ce4..35a4f9a2 100644 --- a/example/example-drm.c +++ b/example/example-drm.c @@ -93,16 +93,18 @@ int main() wl_list_init(&state.render.link); clock_gettime(CLOCK_MONOTONIC, &state.last_frame); + struct wl_display *display = wl_display_create(); + struct wl_event_loop *event_loop = wl_display_get_event_loop(display); + struct wlr_session *session = wlr_session_start(); if (!session) { return 1; } - struct wlr_drm_backend *wlr = wlr_drm_backend_init(session, + struct wlr_drm_backend *wlr = wlr_drm_backend_init(display, session, &state.add, &state.rem, &state.render); bool done = false; - struct wl_event_loop *event_loop = wlr_drm_backend_get_event_loop(wlr); struct wl_event_source *timer = wl_event_loop_add_timer(event_loop, timer_done, &done); diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h index d6093bc2..8689c010 100644 --- a/include/backend/drm/backend.h +++ b/include/backend/drm/backend.h @@ -20,12 +20,7 @@ struct wlr_drm_backend { int fd; bool paused; - struct wl_event_loop *event_loop; - - struct { - struct wl_event_source *drm; - struct wl_event_source *udev; - } event_src; + struct wl_event_source *drm_event; struct { struct wl_signal output_add; @@ -33,17 +28,12 @@ struct wlr_drm_backend { struct wl_signal output_render; } signals; - list_t *outputs; - uint32_t taken_crtcs; + list_t *outputs; struct wlr_drm_renderer renderer; struct wlr_session *session; struct wlr_udev udev; }; -struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, - struct wl_listener *add, struct wl_listener *rem, struct wl_listener *render); -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 6c3bb49f..3373f024 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -21,8 +21,7 @@ struct wlr_drm_renderer { struct wlr_egl egl; }; -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_backend *backend, int fd); +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer); enum wlr_drm_output_state { @@ -62,6 +61,6 @@ void wlr_drm_output_begin(struct wlr_drm_output *out); void wlr_drm_output_end(struct wlr_drm_output *out); void wlr_drm_scan_connectors(struct wlr_drm_backend *backend); -void wlr_drm_event(int fd); +int wlr_drm_event(int fd, uint32_t mask, void *data); #endif diff --git a/include/backend/drm/udev.h b/include/backend/drm/udev.h index a09ee218..99c2c403 100644 --- a/include/backend/drm/udev.h +++ b/include/backend/drm/udev.h @@ -4,15 +4,18 @@ #include #include +#include struct wlr_udev { struct udev *udev; struct udev_monitor *mon; char *drm_path; + + struct wl_event_source *event; }; struct wlr_drm_backend; -bool wlr_udev_init(struct wlr_drm_backend *backend); +bool wlr_udev_init(struct wl_display *display, 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); diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 13679782..d56c7e77 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -7,12 +7,11 @@ struct wlr_drm_backend; struct wlr_drm_output; -struct wlr_drm_backend *wlr_drm_backend_init(struct wlr_session *session, - struct wl_listener *add, struct wl_listener *rem, struct wl_listener *render); +struct wlr_drm_backend *wlr_drm_backend_init(struct wl_display *display, + struct wlr_session *session, struct wl_listener *add, struct wl_listener *rem, + struct wl_listener *render); void wlr_drm_backend_free(struct wlr_drm_backend *backend); -struct wl_event_loop *wlr_drm_backend_get_event_loop(struct wlr_drm_backend *backend); - bool wlr_drm_output_modeset(struct wlr_drm_output *out, const char *str); void wlr_drm_output_begin(struct wlr_drm_output *out); void wlr_drm_output_end(struct wlr_drm_output *out); -- cgit v1.2.3 From 15b1ce9e6ced22a90ab0df7a6b86c6d35c40ca93 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 7 May 2017 10:00:23 -0400 Subject: Refactor backend state management --- backend/CMakeLists.txt | 1 + backend/backend.c | 37 ++++++++++++++ backend/drm/backend.c | 113 ++++++++++++++++++++---------------------- backend/drm/drm.c | 51 ++++++++++--------- backend/drm/udev.c | 5 +- example/example-drm.c | 51 +++++++++---------- include/backend.h | 17 +++++++ include/backend/drm/backend.h | 10 ++-- include/backend/drm/drm.h | 3 +- include/wlr/backend.h | 27 +++++++++- include/wlr/backend/drm.h | 7 ++- 11 files changed, 196 insertions(+), 126 deletions(-) create mode 100644 backend/backend.c create mode 100644 include/backend.h (limited to 'backend/drm/udev.c') diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 938dc1ab..7183617c 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(wlr-backend drm/backend.c drm/drm.c drm/udev.c + backend.c egl.c ) diff --git a/backend/backend.c b/backend/backend.c new file mode 100644 index 00000000..e40aaefe --- /dev/null +++ b/backend/backend.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include "common/log.h" +#include "backend.h" + +struct wlr_backend *wlr_backend_create(const struct wlr_backend_impl *impl, + struct wlr_backend_state *state) { + struct wlr_backend *backend = calloc(1, sizeof(struct wlr_backend)); + if (!backend) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); + return NULL; + } + backend->state = state; + backend->impl = impl; + wl_signal_init(&backend->events.output_add); + wl_signal_init(&backend->events.output_remove); + wl_signal_init(&backend->events.output_frame); + wl_signal_init(&backend->events.keyboard_add); + wl_signal_init(&backend->events.keyboard_remove); + wl_signal_init(&backend->events.pointer_add); + wl_signal_init(&backend->events.pointer_remove); + wl_signal_init(&backend->events.touch_add); + wl_signal_init(&backend->events.touch_remove); + return backend; +} + +bool wlr_backend_init(struct wlr_backend *backend) { + return backend->impl->init(backend->state); +} + +void wlr_backend_destroy(struct wlr_backend *backend) { + backend->impl->destroy(backend->state); + // TODO: Free anything else? + free(backend); +} diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 42e7f5fd..8c02669a 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -8,106 +8,101 @@ #include #include +#include "backend.h" #include "backend/drm/backend.h" #include "backend/drm/drm.h" #include "backend/drm/udev.h" #include "common/log.h" -struct wlr_drm_backend *wlr_drm_backend_init(struct wl_display *display, - struct wlr_session *session, struct wl_listener *add, struct wl_listener *rem, - struct wl_listener *render) { +static bool wlr_drm_backend_init(struct wlr_backend_state *state) { + wlr_drm_scan_connectors(state); + return true; +} - struct wlr_drm_backend *backend = calloc(1, sizeof *backend); - if (!backend) { +static void free_output(void *item) { + struct wlr_drm_output *out = item; + wlr_drm_output_cleanup(out, true); + free(out); +} + +static void wlr_drm_backend_destroy(struct wlr_backend_state *state) { + if (!state) { + return; + } + list_foreach(state->outputs, free_output); + list_free(state->outputs); + wlr_drm_renderer_free(&state->renderer); + wlr_udev_free(&state->udev); + wlr_session_close_file(state->session, state->fd); + wlr_session_finish(state->session); + wl_event_source_remove(state->drm_event); + free(state); +} + +static struct wlr_backend_impl backend_impl = { + .init = wlr_drm_backend_init, + .destroy = wlr_drm_backend_destroy +}; + +struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, + struct wlr_session *session) { + struct wlr_backend_state *state = calloc(1, sizeof(struct wlr_backend_state)); + if (!state) { wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); return NULL; } - backend->session = session; + struct wlr_backend *backend = wlr_backend_create(&backend_impl, state); + if (!backend) { + wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); + return NULL; + } - backend->outputs = list_create(); - if (!backend->outputs) { + state->backend = backend; + state->session = session; + state->outputs = list_create(); + if (!state->outputs) { wlr_log(L_ERROR, "Failed to allocate list"); goto error_backend; } - if (!wlr_udev_init(display, &backend->udev)) { + if (!wlr_udev_init(display, &state->udev)) { wlr_log(L_ERROR, "Failed to start udev"); goto error_list; } - backend->fd = wlr_udev_find_gpu(&backend->udev, backend->session); - if (backend->fd == -1) { + state->fd = wlr_udev_find_gpu(&state->udev, state->session); + if (state->fd == -1) { wlr_log(L_ERROR, "Failed to open DRM device"); goto error_udev; } struct wl_event_loop *event_loop = wl_display_get_event_loop(display); - backend->drm_event = wl_event_loop_add_fd(event_loop, backend->fd, + state->drm_event = wl_event_loop_add_fd(event_loop, state->fd, WL_EVENT_READABLE, wlr_drm_event, NULL); - if (!backend->drm_event) { + if (!state->drm_event) { wlr_log(L_ERROR, "Failed to create DRM event source"); goto error_fd; } - if (!wlr_drm_renderer_init(&backend->renderer, backend->fd)) { + if (!wlr_drm_renderer_init(&state->renderer, state->fd)) { wlr_log(L_ERROR, "Failed to initialize renderer"); goto error_event; } - wl_signal_init(&backend->signals.output_add); - wl_signal_init(&backend->signals.output_rem); - wl_signal_init(&backend->signals.output_render); - - if (add) { - wl_signal_add(&backend->signals.output_add, add); - } - if (rem) { - wl_signal_add(&backend->signals.output_rem, rem); - } - if (render) { - wl_signal_add(&backend->signals.output_render, render); - } - - wlr_drm_scan_connectors(backend); - return backend; error_event: - wl_event_source_remove(backend->drm_event); + wl_event_source_remove(state->drm_event); error_fd: - wlr_session_close_file(backend->session, backend->fd); + wlr_session_close_file(state->session, state->fd); error_udev: - wlr_udev_free(&backend->udev); + wlr_udev_free(&state->udev); error_list: - list_free(backend->outputs); + list_free(state->outputs); error_backend: + free(state); free(backend); return NULL; } - -static void free_output(void *item) -{ - struct wlr_drm_output *out = item; - wlr_drm_output_cleanup(out, true); - free(out); -} - -void wlr_drm_backend_free(struct wlr_drm_backend *backend) -{ - if (!backend) - return; - - list_foreach(backend->outputs, free_output); - - wlr_drm_renderer_free(&backend->renderer); - wlr_udev_free(&backend->udev); - wlr_session_close_file(backend->session, backend->fd); - wlr_session_finish(backend->session); - - wl_event_source_remove(backend->drm_event); - - list_free(backend->outputs); - free(backend); -} diff --git a/backend/drm/drm.c b/backend/drm/drm.c index b5e5739a..abb3fb26 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -13,6 +13,7 @@ #include #include +#include "backend.h" #include "backend/drm/backend.h" #include "backend/drm/drm.h" #include "common/log.h" @@ -167,10 +168,10 @@ static int find_id(const void *item, const void *cmp_to) { } } -void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { +void wlr_drm_scan_connectors(struct wlr_backend_state *state) { wlr_log(L_INFO, "Scanning DRM connectors"); - drmModeRes *res = drmModeGetResources(backend->fd); + drmModeRes *res = drmModeGetResources(state->fd); if (!res) { wlr_log(L_ERROR, "Failed to get DRM resources"); return; @@ -179,40 +180,40 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { for (int i = 0; i < res->count_connectors; ++i) { uint32_t id = res->connectors[i]; - drmModeConnector *conn = drmModeGetConnector(backend->fd, id); + drmModeConnector *conn = drmModeGetConnector(state->fd, id); if (!conn) { wlr_log(L_ERROR, "Failed to get DRM connector"); continue; } struct wlr_drm_output *out; - int index = list_seq_find(backend->outputs, find_id, &id); + int index = list_seq_find(state->outputs, find_id, &id); if (index == -1) { - out = calloc(1, sizeof *out); + out = calloc(1, sizeof(struct wlr_drm_output)); if (!out) { wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); drmModeFreeConnector(conn); continue; } - out->renderer = &backend->renderer; + out->renderer = &state->renderer; out->state = DRM_OUTPUT_DISCONNECTED; out->connector = id; snprintf(out->name, sizeof out->name, "%s-%"PRIu32, conn_name[conn->connector_type], conn->connector_type_id); - drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, conn->encoder_id); + drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id); if (curr_enc) { - out->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id); + out->old_crtc = drmModeGetCrtc(state->fd, curr_enc->crtc_id); free(curr_enc); } - list_add(backend->outputs, out); + list_add(state->outputs, out); wlr_log(L_INFO, "Found display '%s'", out->name); } else { - out = backend->outputs->items[index]; + out = state->outputs->items[index]; } if (out->state == DRM_OUTPUT_DISCONNECTED && @@ -244,8 +245,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { out->state = DRM_OUTPUT_NEEDS_MODESET; wlr_log(L_INFO, "Sending modesetting signal for '%s'", out->name); - wl_signal_emit(&backend->signals.output_add, out); - + wl_signal_emit(&state->backend->events.output_add, out); } else if (out->state == DRM_OUTPUT_CONNECTED && conn->connection != DRM_MODE_CONNECTED) { @@ -270,12 +270,12 @@ struct wlr_drm_mode *wlr_drm_output_get_modes(struct wlr_drm_output *out, size_t } bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mode) { - struct wlr_drm_backend *backend = wl_container_of(out->renderer, backend, renderer); + struct wlr_backend_state *state = wl_container_of(out->renderer, state, renderer); wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u'", out->name, mode->width, mode->height, mode->rate); - drmModeConnector *conn = drmModeGetConnector(backend->fd, out->connector); + drmModeConnector *conn = drmModeGetConnector(state->fd, out->connector); if (!conn) { wlr_log(L_ERROR, "Failed to get DRM connector"); goto error; @@ -286,7 +286,7 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod goto error; } - drmModeRes *res = drmModeGetResources(backend->fd); + drmModeRes *res = drmModeGetResources(state->fd); if (!res) { wlr_log(L_ERROR, "Failed to get DRM resources"); goto error; @@ -294,7 +294,7 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod bool success = false; for (int i = 0; !success && i < conn->count_encoders; ++i) { - drmModeEncoder *enc = drmModeGetEncoder(backend->fd, conn->encoders[i]); + drmModeEncoder *enc = drmModeGetEncoder(state->fd, conn->encoders[i]); if (!enc) continue; @@ -303,8 +303,8 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod continue; } - if ((backend->taken_crtcs & (1 << j)) == 0) { - backend->taken_crtcs |= 1 << j; + if ((state->taken_crtcs & (1 << j)) == 0) { + state->taken_crtcs |= 1 << j; out->crtc = res->crtcs[j]; success = true; @@ -327,7 +327,7 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod out->width = mode->width; out->height = mode->height; - if (!display_init_renderer(&backend->renderer, out)) { + if (!display_init_renderer(&state->renderer, out)) { wlr_log(L_ERROR, "Failed to initalise renderer for %s", out->name); goto error; } @@ -343,15 +343,14 @@ error: return false; } -static 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 wlr_drm_output *out = user; - struct wlr_drm_backend *backend = wl_container_of(out->renderer, backend, renderer); + struct wlr_backend_state *state = wl_container_of(out->renderer, state, renderer); out->pageflip_pending = false; if (out->state == DRM_OUTPUT_CONNECTED) { - wl_signal_emit(&backend->signals.output_render, out); + wl_signal_emit(&state->backend->events.output_frame, out); } } @@ -388,7 +387,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *out, bool restore) { } struct wlr_drm_renderer *renderer = out->renderer; - struct wlr_drm_backend *backend = wl_container_of(renderer, backend, renderer); + struct wlr_backend_state *state = wl_container_of(renderer, state, renderer); switch (out->state) { case DRM_OUTPUT_CONNECTED: @@ -414,7 +413,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *out, bool restore) { } wlr_log(L_INFO, "Emmiting destruction signal for '%s'", out->name); - wl_signal_emit(&backend->signals.output_rem, out); + wl_signal_emit(&state->backend->events.output_remove, out); break; case DRM_OUTPUT_DISCONNECTED: diff --git a/backend/drm/udev.c b/backend/drm/udev.c index 438047d6..e5470157 100644 --- a/backend/drm/udev.c +++ b/backend/drm/udev.c @@ -11,6 +11,7 @@ #include +#include "backend.h" #include "backend/drm/backend.h" #include "backend/drm/udev.h" #include "backend/drm/drm.h" @@ -139,7 +140,7 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { static int udev_event(int fd, uint32_t mask, void *data) { struct wlr_udev *udev = data; - struct wlr_drm_backend *backend = wl_container_of(udev, backend, udev); + struct wlr_backend_state *state = wl_container_of(udev, state, udev); struct udev_device *dev = udev_monitor_receive_device(udev->mon); if (!dev) { @@ -156,7 +157,7 @@ static int udev_event(int fd, uint32_t mask, void *data) { goto out; } - wlr_drm_scan_connectors(backend); + wlr_drm_scan_connectors(state); out: udev_device_unref(dev); diff --git a/example/example-drm.c b/example/example-drm.c index 1b1cce79..2e33e039 100644 --- a/example/example-drm.c +++ b/example/example-drm.c @@ -14,13 +14,12 @@ struct state { struct timespec last_frame; - struct wl_listener add; - struct wl_listener rem; - struct wl_listener render; + struct wl_listener output_add; + struct wl_listener output_remove; + struct wl_listener output_frame; }; -void output_add(struct wl_listener *listener, void *data) -{ +void output_add(struct wl_listener *listener, void *data) { struct wlr_drm_output *out = data; fprintf(stderr, "Output '%s' added\n", wlr_drm_output_get_name(out)); @@ -30,16 +29,14 @@ void output_add(struct wl_listener *listener, void *data) wlr_drm_output_modeset(out, &modes[0]); } -void output_rem(struct wl_listener *listener, void *data) -{ +void output_remove(struct wl_listener *listener, void *data) { struct wlr_drm_output *out = data; fprintf(stderr, "Output '%s' removed\n", wlr_drm_output_get_name(out)); } -void output_render(struct wl_listener *listener, void *data) -{ +void output_frame(struct wl_listener *listener, void *data) { struct wlr_drm_output *out = data; - struct state *s = wl_container_of(listener, s, render); + struct state *s = wl_container_of(listener, s, output_frame); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -68,14 +65,12 @@ void output_render(struct wl_listener *listener, void *data) wlr_drm_output_end(out); } -int timer_done(void *data) -{ +int timer_done(void *data) { *(bool *)data = true; return 1; } -int main() -{ +int main() { if (getenv("DISPLAY")) { fprintf(stderr, "Detected that X is running. Run this in its own virtual terminal.\n"); return 1; @@ -87,14 +82,14 @@ int main() struct state state = { .color = { 1.0, 0.0, 0.0 }, .dec = 0, - .add = { .notify = output_add }, - .rem = { .notify = output_rem }, - .render = { .notify = output_render }, + .output_add = { .notify = output_add }, + .output_remove = { .notify = output_remove }, + .output_frame = { .notify = output_frame }, }; - wl_list_init(&state.add.link); - wl_list_init(&state.rem.link); - wl_list_init(&state.render.link); + wl_list_init(&state.output_add.link); + wl_list_init(&state.output_remove.link); + wl_list_init(&state.output_frame.link); clock_gettime(CLOCK_MONOTONIC, &state.last_frame); struct wl_display *display = wl_display_create(); @@ -105,19 +100,25 @@ int main() return 1; } - struct wlr_drm_backend *wlr = wlr_drm_backend_init(display, session, - &state.add, &state.rem, &state.render); + struct wlr_backend *wlr = wlr_drm_backend_create(display, session); + wl_signal_add(&wlr->events.output_add, &state.output_add); + wl_signal_add(&wlr->events.output_remove, &state.output_remove); + wl_signal_add(&wlr->events.output_frame, &state.output_frame); + if (!wlr || !wlr_backend_init(wlr)) { + return 1; + } bool done = false; struct wl_event_source *timer = wl_event_loop_add_timer(event_loop, timer_done, &done); - wl_event_source_timer_update(timer, 10000); + wl_event_source_timer_update(timer, 5000); - while (!done) + while (!done) { wl_event_loop_dispatch(event_loop, 0); + } wl_event_source_remove(timer); - wlr_drm_backend_free(wlr); + wlr_backend_destroy(wlr); wl_display_destroy(display); } diff --git a/include/backend.h b/include/backend.h new file mode 100644 index 00000000..d42c6f17 --- /dev/null +++ b/include/backend.h @@ -0,0 +1,17 @@ +#ifndef _WLR_BACKEND_INTERNAL_H +#define _WLR_BACKEND_INTERNAL_H + +#include +#include + +struct wlr_backend_state; + +struct wlr_backend_impl { + bool (*init)(struct wlr_backend_state *state); + void (*destroy)(struct wlr_backend_state *state); +}; + +struct wlr_backend *wlr_backend_create(const struct wlr_backend_impl *impl, + struct wlr_backend_state *state); + +#endif diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h index bdda7ea7..0c725ccb 100644 --- a/include/backend/drm/backend.h +++ b/include/backend/drm/backend.h @@ -12,21 +12,17 @@ #include #include +#include "backend.h" #include "udev.h" #include "event.h" #include "drm.h" -struct wlr_drm_backend { +struct wlr_backend_state { int fd; + struct wlr_backend *backend; struct wl_event_source *drm_event; - struct { - struct wl_signal output_add; - struct wl_signal output_rem; - struct wl_signal output_render; - } signals; - uint32_t taken_crtcs; list_t *outputs; diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 51b0cdc6..3e83058a 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -8,6 +8,7 @@ #include #include "backend/egl.h" +#include "backend.h" struct wlr_drm_renderer { int fd; @@ -50,7 +51,7 @@ struct wlr_drm_output { void wlr_drm_output_cleanup(struct wlr_drm_output *out, bool restore); -void wlr_drm_scan_connectors(struct wlr_drm_backend *backend); +void wlr_drm_scan_connectors(struct wlr_backend_state *state); int wlr_drm_event(int fd, uint32_t mask, void *data); #endif diff --git a/include/wlr/backend.h b/include/wlr/backend.h index 527efa05..88a5c8e9 100644 --- a/include/wlr/backend.h +++ b/include/wlr/backend.h @@ -1,7 +1,30 @@ #ifndef _WLR_BACKEND_H #define _WLR_BACKEND_H -struct wlr_backend *wlr_backend_init(); -void wlr_backend_free(struct wlr_backend *backend); +#include + +struct wlr_backend_impl; +struct wlr_backend_state; + +struct wlr_backend { + const struct wlr_backend_impl *impl; + struct wlr_backend_state *state; + + struct { + struct wl_signal output_add; + struct wl_signal output_remove; + struct wl_signal output_frame; + struct wl_signal keyboard_add; + struct wl_signal keyboard_remove; + struct wl_signal pointer_add; + struct wl_signal pointer_remove; + struct wl_signal touch_add; + struct wl_signal touch_remove; + } events; +}; + +struct wlr_backend *wlr_backend_autocreate(); +bool wlr_backend_init(struct wlr_backend *backend); +void wlr_backend_destroy(struct wlr_backend *backend); #endif diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 4131b4cb..5db9b35c 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -3,6 +3,7 @@ #include #include +#include #include // drmModeModeInfo struct wlr_drm_backend; @@ -15,10 +16,8 @@ struct wlr_drm_mode { drmModeModeInfo mode; }; -struct wlr_drm_backend *wlr_drm_backend_init(struct wl_display *display, - struct wlr_session *session, struct wl_listener *add, struct wl_listener *rem, - struct wl_listener *render); -void wlr_drm_backend_free(struct wlr_drm_backend *backend); +struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, + struct wlr_session *session); const char *wlr_drm_output_get_name(struct wlr_drm_output *out); -- cgit v1.2.3