From c8a8ff66f2bdeab0623c11c1c381b52bc41fbf0d Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 26 Aug 2017 16:55:38 +1200 Subject: [PATCH 01/14] Removed unused fields --- backend/drm/backend.c | 7 ------- include/backend/drm.h | 2 -- 2 files changed, 9 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 8d562007..c394ed65 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -119,12 +118,6 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, backend->fd = gpu_fd; - struct stat st; - if (fstat(backend->fd, &st) < 0) { - wlr_log_errno(L_ERROR, "Stat failed"); - } - backend->dev = st.st_rdev; - backend->drm_invalidated.notify = drm_invalidated; wlr_session_signal_add(session, gpu_fd, &backend->drm_invalidated); diff --git a/include/backend/drm.h b/include/backend/drm.h index b474e8b3..6987b0bc 100644 --- a/include/backend/drm.h +++ b/include/backend/drm.h @@ -86,7 +86,6 @@ struct wlr_drm_backend { const struct wlr_drm_interface *iface; int fd; - dev_t dev; size_t num_crtcs; struct wlr_drm_crtc *crtcs; @@ -117,7 +116,6 @@ struct wlr_drm_backend { struct wl_listener session_signal; struct wl_listener drm_invalidated; - uint32_t taken_crtcs; list_t *outputs; struct wlr_drm_renderer renderer; From 610b0493ac4a3bbde44378adf855c7202b1e59c4 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 19:03:34 +1300 Subject: [PATCH 02/14] Rename files to remove pointless drm prefix --- backend/drm/backend.c | 2 +- backend/drm/drm.c | 14 +++++++------- backend/drm/{drm-atomic.c => iface_atomic.c} | 6 +++--- backend/drm/{drm-legacy.c => iface_legacy.c} | 6 +++--- backend/drm/{drm-properties.c => properties.c} | 2 +- backend/drm/{drm-util.c => util.c} | 2 +- backend/meson.build | 8 ++++---- include/backend/{ => drm}/drm.h | 6 +++--- .../backend/{drm-properties.h => drm/properties.h} | 0 include/backend/{drm-util.h => drm/util.h} | 0 10 files changed, 23 insertions(+), 23 deletions(-) rename backend/drm/{drm-atomic.c => iface_atomic.c} (98%) rename backend/drm/{drm-legacy.c => iface_legacy.c} (94%) rename backend/drm/{drm-properties.c => properties.c} (99%) rename backend/drm/{drm-util.c => util.c} (99%) rename include/backend/{ => drm}/drm.h (98%) rename include/backend/{drm-properties.h => drm/properties.h} (100%) rename include/backend/{drm-util.h => drm/util.h} (100%) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index c394ed65..e046cea6 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -12,7 +12,7 @@ #include #include #include -#include "backend/drm.h" +#include "backend/drm/drm.h" static bool wlr_drm_backend_start(struct wlr_backend *_backend) { struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 1a656172..cba41023 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -20,12 +20,12 @@ #include #include #include -#include "backend/drm.h" -#include "backend/drm-util.h" +#include "backend/drm/drm.h" +#include "backend/drm/util.h" bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - extern const struct wlr_drm_interface legacy_iface; - extern const struct wlr_drm_interface atomic_iface; + extern const struct wlr_drm_interface iface_legacy; + extern const struct wlr_drm_interface iface_atomic; if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); @@ -34,13 +34,13 @@ bool wlr_drm_check_features(struct wlr_drm_backend *backend) { if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - backend->iface = &legacy_iface; + backend->iface = &iface_legacy; } else if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - backend->iface = &legacy_iface; + backend->iface = &iface_legacy; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - backend->iface = &atomic_iface; + backend->iface = &iface_atomic; } return true; diff --git a/backend/drm/drm-atomic.c b/backend/drm/iface_atomic.c similarity index 98% rename from backend/drm/drm-atomic.c rename to backend/drm/iface_atomic.c index 16c9c5c3..5bb2da9b 100644 --- a/backend/drm/drm-atomic.c +++ b/backend/drm/iface_atomic.c @@ -2,8 +2,8 @@ #include #include #include -#include "backend/drm.h" -#include "backend/drm-util.h" +#include "backend/drm/drm.h" +#include "backend/drm/util.h" struct atomic { drmModeAtomicReq *req; @@ -180,7 +180,7 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, return atomic_end(backend->fd, &atom); } -const struct wlr_drm_interface atomic_iface = { +const struct wlr_drm_interface iface_atomic = { .conn_enable = atomic_conn_enable, .crtc_pageflip = atomic_crtc_pageflip, .crtc_set_cursor = atomic_crtc_set_cursor, diff --git a/backend/drm/drm-legacy.c b/backend/drm/iface_legacy.c similarity index 94% rename from backend/drm/drm-legacy.c rename to backend/drm/iface_legacy.c index 9b7cd301..856e9060 100644 --- a/backend/drm/drm-legacy.c +++ b/backend/drm/iface_legacy.c @@ -2,8 +2,8 @@ #include #include #include -#include "backend/drm.h" -#include "backend/drm-util.h" +#include "backend/drm/drm.h" +#include "backend/drm/util.h" static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, @@ -57,7 +57,7 @@ bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, return !drmModeMoveCursor(backend->fd, crtc->id, x, y); } -const struct wlr_drm_interface legacy_iface = { +const struct wlr_drm_interface iface_legacy = { .conn_enable = legacy_conn_enable, .crtc_pageflip = legacy_crtc_pageflip, .crtc_set_cursor = legacy_crtc_set_cursor, diff --git a/backend/drm/drm-properties.c b/backend/drm/properties.c similarity index 99% rename from backend/drm/drm-properties.c rename to backend/drm/properties.c index ef24476f..5bec3243 100644 --- a/backend/drm/drm-properties.c +++ b/backend/drm/properties.c @@ -5,7 +5,7 @@ #include #include #include -#include "backend/drm-properties.h" +#include "backend/drm/properties.h" /* * Creates a mapping between property names and an array index where to store diff --git a/backend/drm/drm-util.c b/backend/drm/util.c similarity index 99% rename from backend/drm/drm-util.c rename to backend/drm/util.c index 0f8ee18c..656c070a 100644 --- a/backend/drm/drm-util.c +++ b/backend/drm/util.c @@ -3,7 +3,7 @@ #include #include #include -#include "backend/drm-util.h" +#include "backend/drm/util.h" #include int32_t calculate_refresh_rate(drmModeModeInfo *mode) { diff --git a/backend/meson.build b/backend/meson.build index 9e3b6fed..630bc284 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -5,10 +5,10 @@ backend_files = files( 'session/session.c', 'drm/backend.c', 'drm/drm.c', - 'drm/drm-atomic.c', - 'drm/drm-legacy.c', - 'drm/drm-properties.c', - 'drm/drm-util.c', + 'drm/iface_atomic.c', + 'drm/iface_legacy.c', + 'drm/properties.c', + 'drm/util.c', 'libinput/backend.c', 'libinput/events.c', 'libinput/keyboard.c', diff --git a/include/backend/drm.h b/include/backend/drm/drm.h similarity index 98% rename from include/backend/drm.h rename to include/backend/drm/drm.h index 6987b0bc..43838495 100644 --- a/include/backend/drm.h +++ b/include/backend/drm/drm.h @@ -1,5 +1,5 @@ -#ifndef BACKEND_DRM_H -#define BACKEND_DRM_H +#ifndef BACKEND_DRM_DRM_H +#define BACKEND_DRM_DRM_H #include #include @@ -15,7 +15,7 @@ #include #include -#include "drm-properties.h" +#include "properties.h" struct wlr_drm_plane { uint32_t type; diff --git a/include/backend/drm-properties.h b/include/backend/drm/properties.h similarity index 100% rename from include/backend/drm-properties.h rename to include/backend/drm/properties.h diff --git a/include/backend/drm-util.h b/include/backend/drm/util.h similarity index 100% rename from include/backend/drm-util.h rename to include/backend/drm/util.h From d0708b1a3a3fb9fd3a073d6c5406b26e8bf617e9 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 19:11:41 +1300 Subject: [PATCH 03/14] Split DRM internal interface to its own header --- backend/drm/drm.c | 4 +--- backend/drm/iface_atomic.c | 1 + backend/drm/iface_legacy.c | 1 + include/backend/drm/drm.h | 18 +----------------- include/backend/drm/iface.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 include/backend/drm/iface.h diff --git a/backend/drm/drm.c b/backend/drm/drm.c index cba41023..40a6f37b 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -21,12 +21,10 @@ #include #include #include "backend/drm/drm.h" +#include "backend/drm/iface.h" #include "backend/drm/util.h" bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - extern const struct wlr_drm_interface iface_legacy; - extern const struct wlr_drm_interface iface_atomic; - if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); return false; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index 5bb2da9b..75a3c33a 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -3,6 +3,7 @@ #include #include #include "backend/drm/drm.h" +#include "backend/drm/iface.h" #include "backend/drm/util.h" struct atomic { diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index 856e9060..110b38b5 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -3,6 +3,7 @@ #include #include #include "backend/drm/drm.h" +#include "backend/drm/iface.h" #include "backend/drm/util.h" static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 43838495..c57493f3 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -15,6 +15,7 @@ #include #include +#include "iface.h" #include "properties.h" struct wlr_drm_plane { @@ -156,23 +157,6 @@ struct wlr_drm_output { struct wl_event_source *retry_pageflip; }; -// Used to provide atomic or legacy DRM functions -struct wlr_drm_interface { - // Enable or disable DPMS for output - void (*conn_enable)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable); - // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. - bool (*crtc_pageflip)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode); - // Enable the cursor buffer on crtc. Set bo to NULL to disable - bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); - // Move the cursor on crtc - bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y); -}; - bool wlr_drm_check_features(struct wlr_drm_backend *drm); bool wlr_drm_resources_init(struct wlr_drm_backend *drm); void wlr_drm_resources_free(struct wlr_drm_backend *drm); diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h new file mode 100644 index 00000000..cf77f4d4 --- /dev/null +++ b/include/backend/drm/iface.h @@ -0,0 +1,35 @@ +#ifndef BACKEND_DRM_IFACE_H +#define BACKEND_DRM_IFACE_H + +#include +#include + +#include +#include +#include + +struct wlr_drm_backend; +struct wlr_drm_output; +struct wlr_drm_crtc; + +// Used to provide atomic or legacy DRM functions +struct wlr_drm_interface { + // Enable or disable DPMS for output + void (*conn_enable)(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, bool enable); + // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. + bool (*crtc_pageflip)(struct wlr_drm_backend *backend, + struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode); + // Enable the cursor buffer on crtc. Set bo to NULL to disable + bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + // Move the cursor on crtc + bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, + struct wlr_drm_crtc *crtc, int x, int y); +}; + +extern const struct wlr_drm_interface iface_atomic; +extern const struct wlr_drm_interface iface_legacy; + +#endif From 096249a2a1dc604b062a6fef6c4ca56065724d79 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 20:52:58 +1300 Subject: [PATCH 04/14] Split DRM rendering to its own file --- backend/drm/backend.c | 2 +- backend/drm/drm.c | 161 ++++----------------------------- backend/drm/iface_atomic.c | 8 +- backend/drm/iface_legacy.c | 2 +- backend/drm/renderer.c | 126 ++++++++++++++++++++++++++ backend/meson.build | 1 + include/backend/drm/drm.h | 20 +--- include/backend/drm/renderer.h | 47 ++++++++++ 8 files changed, 202 insertions(+), 165 deletions(-) create mode 100644 backend/drm/renderer.c create mode 100644 include/backend/drm/renderer.h diff --git a/backend/drm/backend.c b/backend/drm/backend.c index e046cea6..95c86bb1 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -33,7 +33,7 @@ static void wlr_drm_backend_destroy(struct wlr_backend *_backend) { wlr_output_destroy(&output->output); } - wlr_drm_renderer_free(&backend->renderer); + wlr_drm_renderer_finish(&backend->renderer); wlr_drm_resources_free(backend); wlr_session_close_file(backend->session, backend->fd); wl_event_source_remove(backend->drm_event); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 40a6f37b..05a050e6 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -173,121 +173,9 @@ void wlr_drm_resources_free(struct wlr_drm_backend *backend) { free(backend->planes); } -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { - renderer->gbm = gbm_create_device(fd); - if (!renderer->gbm) { - wlr_log(L_ERROR, "Failed to create GBM device: %s", strerror(errno)); - return false; - } - - if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, - GBM_FORMAT_ARGB8888, renderer->gbm)) { - gbm_device_destroy(renderer->gbm); - return false; - } - - renderer->fd = fd; - return true; -} - -void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer) { - if (!renderer) { - return; - } - - wlr_egl_free(&renderer->egl); - gbm_device_destroy(renderer->gbm); -} - -static bool wlr_drm_plane_renderer_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { - if (plane->width == width && plane->height == height) { - return true; - } - - plane->width = width; - plane->height = height; - - plane->gbm = gbm_surface_create(renderer->gbm, width, height, - format, GBM_BO_USE_RENDERING | flags); - if (!plane->gbm) { - wlr_log_errno(L_ERROR, "Failed to create GBM surface for plane"); - return false; - } - - plane->egl = wlr_egl_create_surface(&renderer->egl, plane->gbm); - if (plane->egl == EGL_NO_SURFACE) { - wlr_log(L_ERROR, "Failed to create EGL surface for plane"); - return false; - } - - return true; -} - -static void wlr_drm_plane_renderer_free(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - if (!renderer || !plane) { - return; - } - - eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - } - if (plane->back) { - gbm_surface_release_buffer(plane->gbm, plane->back); - } - - if (plane->egl) { - eglDestroySurface(renderer->egl.display, plane->egl); - } - if (plane->gbm) { - gbm_surface_destroy(plane->gbm); - } - - if (plane->wlr_tex) { - wlr_texture_destroy(plane->wlr_tex); - } - if (plane->wlr_rend) { - wlr_renderer_destroy(plane->wlr_rend); - } - if (plane->cursor_bo) { - gbm_bo_destroy(plane->cursor_bo); - } - - plane->width = 0; - plane->height = 0; - plane->egl = EGL_NO_SURFACE; - plane->gbm = NULL; - plane->front = NULL; - plane->back = NULL; - plane->wlr_rend = NULL; - plane->wlr_tex = NULL; - plane->cursor_bo = NULL; -} - -static void wlr_drm_plane_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - eglMakeCurrent(renderer->egl.display, plane->egl, plane->egl, - renderer->egl.context); -} - -static void wlr_drm_plane_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_plane *plane) { - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - } - - eglSwapBuffers(renderer->egl.display, plane->egl); - - plane->front = plane->back; - plane->back = gbm_surface_lock_front_buffer(plane->gbm); -} - static void wlr_drm_output_make_current(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_plane_make_current(output->renderer, output->crtc->primary); + wlr_drm_surface_make_current(output->renderer, &output->crtc->primary->surf); } static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { @@ -298,9 +186,8 @@ static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - wlr_drm_plane_swap_buffers(renderer, plane); - - uint32_t fb_id = get_fb_for_bo(plane->back); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(renderer, &plane->surf); + uint32_t fb_id = get_fb_for_bo(bo); if (backend->iface->crtc_pageflip(backend, output, crtc, fb_id, NULL)) { output->pageflip_pending = true; @@ -338,17 +225,7 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = plane->front; - if (!bo) { - // Render a black frame to start the rendering loop - wlr_drm_plane_make_current(renderer, plane); - glViewport(0, 0, plane->width, plane->height); - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - wlr_drm_plane_swap_buffers(renderer, plane); - - bo = plane->back; - } + struct gbm_bo *bo = wlr_drm_surface_get_front(renderer, &plane->surf); struct wlr_drm_output_mode *_mode = (struct wlr_drm_output_mode *)output->output.current_mode; @@ -415,8 +292,10 @@ static void realloc_planes(struct wlr_drm_backend *backend, const uint32_t *crtc struct wlr_drm_plane *new = &backend->type_planes[type][crtc_res[i]]; if (*old != new) { - wlr_drm_plane_renderer_free(&backend->renderer, *old); - wlr_drm_plane_renderer_free(&backend->renderer, new); + if (*old) { + wlr_drm_surface_finish(&backend->renderer, &(*old)->surf); + } + wlr_drm_surface_finish(&backend->renderer, &new->surf); *old = new; } } @@ -547,7 +426,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, continue; } - if (!wlr_drm_plane_renderer_init(&backend->renderer, crtc->primary, + if (!wlr_drm_surface_init(&backend->renderer, &crtc->primary->surf, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); @@ -598,7 +477,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, crtc->cursor = plane; } - if (!plane->gbm) { + if (!plane->surf.gbm) { int ret; uint64_t w, h; ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_WIDTH, &w); @@ -611,7 +490,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return false; } - if (!wlr_drm_plane_renderer_init(renderer, plane, w, h, GBM_FORMAT_ARGB8888, 0)) { + if (!wlr_drm_surface_init(renderer, &plane->surf, w, h, GBM_FORMAT_ARGB8888, 0)) { wlr_log(L_ERROR, "Cannot allocate cursor resources"); return false; } @@ -625,7 +504,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // OpenGL will read the pixels out upside down, // so we need to flip the image vertically - wlr_matrix_texture(plane->matrix, plane->width, plane->height, + wlr_matrix_texture(plane->matrix, plane->surf.width, plane->surf.height, output->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); // TODO the image needs to be rotated depending on the output rotation @@ -653,12 +532,12 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return false; } - wlr_drm_plane_make_current(renderer, plane); + wlr_drm_surface_make_current(renderer, &plane->surf); wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); - glViewport(0, 0, plane->width, plane->height); + glViewport(0, 0, plane->surf.width, plane->surf.height); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); @@ -668,10 +547,10 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, glFinish(); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride); - glReadPixels(0, 0, plane->width, plane->height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); + glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - wlr_drm_plane_swap_buffers(renderer, plane); + wlr_drm_surface_swap_buffers(renderer, &plane->surf); gbm_bo_unmap(bo, bo_data); @@ -914,9 +793,9 @@ static void page_flip_handler(int fd, unsigned seq, } struct wlr_drm_plane *plane = output->crtc->primary; - if (plane->front) { - gbm_surface_release_buffer(plane->gbm, plane->front); - plane->front = NULL; + if (plane->surf.front) { + gbm_surface_release_buffer(plane->surf.gbm, plane->surf.front); + plane->surf.front = NULL; } if (backend->session->active) { @@ -987,7 +866,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { case WLR_DRM_OUTPUT_CLEANUP:; struct wlr_drm_crtc *crtc = output->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_plane_renderer_free(renderer, crtc->planes[i]); + wlr_drm_surface_finish(renderer, &crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index 75a3c33a..ce5de091 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -84,10 +84,10 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, // The src_* properties are in 16.16 fixed point atomic_add(atom, id, props->src_x, 0); atomic_add(atom, id, props->src_y, 0); - atomic_add(atom, id, props->src_w, plane->width << 16); - atomic_add(atom, id, props->src_h, plane->height << 16); - atomic_add(atom, id, props->crtc_w, plane->width); - atomic_add(atom, id, props->crtc_h, plane->height); + atomic_add(atom, id, props->src_w, plane->surf.width << 16); + atomic_add(atom, id, props->src_h, plane->surf.height << 16); + atomic_add(atom, id, props->crtc_w, plane->surf.width); + atomic_add(atom, id, props->crtc_h, plane->surf.height); atomic_add(atom, id, props->fb_id, fb_id); atomic_add(atom, id, props->crtc_id, crtc_id); if (set_crtc_xy) { diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index 110b38b5..e320af93 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -45,7 +45,7 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, struct wlr_drm_plane *plane = crtc->cursor; if (drmModeSetCursor(backend->fd, crtc->id, gbm_bo_get_handle(bo).u32, - plane->width, plane->height)) { + plane->surf.width, plane->surf.height)) { wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); return false; } diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c new file mode 100644 index 00000000..8afc6dca --- /dev/null +++ b/backend/drm/renderer.c @@ -0,0 +1,126 @@ +#include + +#include +#include +#include +#include + +#include +#include +#include "backend/drm/drm.h" + +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { + renderer->gbm = gbm_create_device(fd); + if (!renderer->gbm) { + wlr_log(L_ERROR, "Failed to create GBM device"); + return false; + } + + if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, + GBM_FORMAT_ARGB8888, renderer->gbm)) { + gbm_device_destroy(renderer->gbm); + return false; + } + + renderer->fd = fd; + return true; +} + +void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { + if (!renderer) { + return; + } + + wlr_egl_free(&renderer->egl); + gbm_device_destroy(renderer->gbm); +} + +bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf, uint32_t width, uint32_t height, + uint32_t format, uint32_t flags) { + if (surf->width == width && surf->height == height) { + return true; + } + + surf->width = width; + surf->height = height; + + surf->gbm = gbm_surface_create(renderer->gbm, width, height, + format, GBM_BO_USE_RENDERING | flags); + if (!surf->gbm) { + wlr_log_errno(L_ERROR, "Failed to create GBM surface"); + goto error_zero; + } + + surf->egl = wlr_egl_create_surface(&renderer->egl, surf->gbm); + if (surf->egl == EGL_NO_SURFACE) { + wlr_log(L_ERROR, "Failed to create EGL surface"); + goto error_gbm; + } + + return true; + +error_gbm: + gbm_surface_destroy(surf->gbm); +error_zero: + memset(surf, 0, sizeof(*surf)); + return false; +} + +void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + if (!renderer || !surf || !surf->gbm) { + return; + } + + eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + } + if (surf->back) { + gbm_surface_release_buffer(surf->gbm, surf->back); + } + + if (surf->egl) { + eglDestroySurface(renderer->egl.display, surf->egl); + } + if (surf->gbm) { + gbm_surface_destroy(surf->gbm); + } + + memset(surf, 0, sizeof(*surf)); +} + +void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + eglMakeCurrent(renderer->egl.display, surf->egl, surf->egl, + renderer->egl.context); +} + +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + } + + eglSwapBuffers(renderer->egl.display, surf->egl); + + surf->front = surf->back; + surf->back = gbm_surface_lock_front_buffer(surf->gbm); + return surf->back; +} + +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf) { + if (surf->front) { + return surf->front; + } + + wlr_drm_surface_make_current(renderer, surf); + glViewport(0, 0, surf->width, surf->height); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + return wlr_drm_surface_swap_buffers(renderer, surf); +} diff --git a/backend/meson.build b/backend/meson.build index 630bc284..caf2c8b0 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -8,6 +8,7 @@ backend_files = files( 'drm/iface_atomic.c', 'drm/iface_legacy.c', 'drm/properties.c', + 'drm/renderer.c', 'drm/util.c', 'libinput/backend.c', 'libinput/events.c', diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index c57493f3..b13cb5e7 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -17,6 +17,7 @@ #include "iface.h" #include "properties.h" +#include "renderer.h" struct wlr_drm_plane { uint32_t type; @@ -24,13 +25,7 @@ struct wlr_drm_plane { uint32_t possible_crtcs; - uint32_t width, height; - - struct gbm_surface *gbm; - EGLSurface egl; - - struct gbm_bo *front; - struct gbm_bo *back; + struct wlr_drm_surface surf; // Only used by cursor float matrix[16]; @@ -70,17 +65,6 @@ struct wlr_drm_connector { struct wl_list link; }; -struct wlr_drm_renderer { - int fd; - struct gbm_device *gbm; - struct wlr_egl egl; -}; - -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); -void wlr_drm_renderer_free(struct wlr_drm_renderer *renderer); - -struct wlr_drm_interface; - struct wlr_drm_backend { struct wlr_backend backend; diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h new file mode 100644 index 00000000..bbcf4f0c --- /dev/null +++ b/include/backend/drm/renderer.h @@ -0,0 +1,47 @@ +#ifndef BACKEND_DRM_RENDERER_H +#define BACKEND_DRM_RENDERER_H + +#include +#include + +#include +#include + +struct wlr_drm_renderer { + int fd; + struct gbm_device *gbm; + struct wlr_egl egl; +}; + +struct wlr_drm_surface { + uint32_t width; + uint32_t height; + + struct gbm_surface *gbm; + EGLSurface egl; + + struct gbm_bo *front; + struct gbm_bo *back; +}; + +bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); + +void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer); + +bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf, uint32_t width, uint32_t height, + uint32_t format, uint32_t flags); + +void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, + struct wlr_drm_surface *surf); + +#endif From ec5b95e08f7549fc3628d9790d62f22d8b975300 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 22:01:59 +1300 Subject: [PATCH 05/14] Add pointer to backend from DRM outputs --- backend/drm/drm.c | 38 ++++++++++++++------------------------ include/backend/drm/drm.h | 3 +-- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 05a050e6..96feba15 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -175,14 +175,13 @@ void wlr_drm_resources_free(struct wlr_drm_backend *backend) { static void wlr_drm_output_make_current(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_surface_make_current(output->renderer, &output->crtc->primary->surf); + wlr_drm_surface_make_current(&output->drm->renderer, &output->crtc->primary->surf); } static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; @@ -200,8 +199,7 @@ static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { static void wlr_drm_output_set_gamma(struct wlr_output *_output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; drmModeCrtcSetGamma(backend->fd, output->crtc->id, size, r, g, b); } @@ -219,9 +217,8 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { return; } - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; @@ -240,8 +237,7 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { return; } @@ -367,8 +363,7 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, static bool wlr_drm_output_set_mode(struct wlr_output *_output, struct wlr_output_mode *mode) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend - = wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, mode->width, mode->height, mode->refresh); @@ -457,9 +452,8 @@ static void wlr_drm_output_transform(struct wlr_output *output, static bool wlr_drm_output_set_cursor(struct wlr_output *_output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend - = wl_container_of(output->renderer, backend, renderer); - struct wlr_drm_renderer *renderer = output->renderer; + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->cursor; @@ -560,8 +554,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, static bool wlr_drm_output_move_cursor(struct wlr_output *_output, int x, int y) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; int width, height, tmp; wlr_output_effective_resolution(_output, &width, &height); @@ -678,7 +671,6 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { output); - output->renderer = &backend->renderer; output->state = WLR_DRM_OUTPUT_DISCONNECTED; output->connector = conn->connector_id; @@ -784,8 +776,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { struct wlr_drm_output *output = user; - struct wlr_drm_backend *backend = - wl_container_of(output->renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; output->pageflip_pending = false; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { @@ -857,9 +848,8 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { return; } - struct wlr_drm_renderer *renderer = output->renderer; - struct wlr_drm_backend *backend = - wl_container_of(renderer, backend, renderer); + struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_renderer *renderer = &backend->renderer; switch (output->state) { case WLR_DRM_OUTPUT_CONNECTED: diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index b13cb5e7..6f1abc00 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -121,6 +121,7 @@ struct wlr_drm_output_mode { struct wlr_drm_output { struct wlr_output output; + struct wlr_drm_backend *drm; enum wlr_drm_output_state state; uint32_t connector; @@ -135,8 +136,6 @@ struct wlr_drm_output { drmModeCrtc *old_crtc; - struct wlr_drm_renderer *renderer; - bool pageflip_pending; struct wl_event_source *retry_pageflip; }; From 22e77d919570c0a8d4a84878c377db8fa9a0edfb Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 22:22:26 +1300 Subject: [PATCH 06/14] Rename backend to drm --- backend/drm/backend.c | 97 +++++++------ backend/drm/drm.c | 262 ++++++++++++++++++------------------ backend/drm/iface_atomic.c | 28 ++-- backend/drm/iface_legacy.c | 20 +-- include/backend/drm/iface.h | 18 +-- 5 files changed, 210 insertions(+), 215 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 95c86bb1..f634eee6 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -14,36 +14,37 @@ #include #include "backend/drm/drm.h" -static bool wlr_drm_backend_start(struct wlr_backend *_backend) { - struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; - wlr_drm_scan_connectors(backend); +static bool wlr_drm_backend_start(struct wlr_backend *backend) { + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; + wlr_drm_scan_connectors(drm); return true; } -static void wlr_drm_backend_destroy(struct wlr_backend *_backend) { - if (!_backend) { +static void wlr_drm_backend_destroy(struct wlr_backend *backend) { + if (!backend) { return; } - struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; - wlr_drm_restore_outputs(backend); + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; - for (size_t i = 0; backend->outputs && i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; + wlr_drm_restore_outputs(drm); + + for (size_t i = 0; drm->outputs && i < drm->outputs->length; ++i) { + struct wlr_drm_output *output = drm->outputs->items[i]; wlr_output_destroy(&output->output); } - wlr_drm_renderer_finish(&backend->renderer); - wlr_drm_resources_free(backend); - wlr_session_close_file(backend->session, backend->fd); - wl_event_source_remove(backend->drm_event); - list_free(backend->outputs); - free(backend); + wlr_drm_renderer_finish(&drm->renderer); + wlr_drm_resources_free(drm); + wlr_session_close_file(drm->session, drm->fd); + wl_event_source_remove(drm->drm_event); + list_free(drm->outputs); + free(drm); } static struct wlr_egl *wlr_drm_backend_get_egl(struct wlr_backend *_backend) { - struct wlr_drm_backend *backend = (struct wlr_drm_backend *)_backend; - return &backend->renderer.egl; + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)_backend; + return &drm->renderer.egl; } static struct wlr_backend_impl backend_impl = { @@ -57,15 +58,14 @@ bool wlr_backend_is_drm(struct wlr_backend *b) { } static void session_signal(struct wl_listener *listener, void *data) { - struct wlr_drm_backend *backend = - wl_container_of(listener, backend, session_signal); + struct wlr_drm_backend *drm = wl_container_of(listener, drm, session_signal); struct wlr_session *session = data; if (session->active) { wlr_log(L_INFO, "DRM fd resumed"); - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_output *output = drm->outputs->items[i]; wlr_drm_output_start_renderer(output); if (!output->crtc) { @@ -73,7 +73,7 @@ static void session_signal(struct wl_listener *listener, void *data) { } struct wlr_drm_plane *plane = output->crtc->cursor; - backend->iface->crtc_set_cursor(backend, output->crtc, + drm->iface->crtc_set_cursor(drm, output->crtc, plane ? plane->cursor_bo : NULL); } } else { @@ -82,14 +82,13 @@ static void session_signal(struct wl_listener *listener, void *data) { } static void drm_invalidated(struct wl_listener *listener, void *data) { - struct wlr_drm_backend *backend = - wl_container_of(listener, backend, drm_invalidated); + struct wlr_drm_backend *drm = wl_container_of(listener, drm, drm_invalidated); - char *name = drmGetDeviceNameFromFd2(backend->fd); + char *name = drmGetDeviceNameFromFd2(drm->fd); wlr_log(L_DEBUG, "%s invalidated", name); free(name); - wlr_drm_scan_connectors(backend); + wlr_drm_scan_connectors(drm); } struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, @@ -102,63 +101,63 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, free(name); drmFreeVersion(version); - struct wlr_drm_backend *backend = calloc(1, sizeof(struct wlr_drm_backend)); - if (!backend) { + struct wlr_drm_backend *drm = calloc(1, sizeof(struct wlr_drm_backend)); + if (!drm) { wlr_log_errno(L_ERROR, "Allocation failed"); return NULL; } - wlr_backend_init(&backend->backend, &backend_impl); + wlr_backend_init(&drm->backend, &backend_impl); - backend->session = session; - backend->outputs = list_create(); - if (!backend->outputs) { + drm->session = session; + drm->outputs = list_create(); + if (!drm->outputs) { wlr_log(L_ERROR, "Failed to allocate list"); goto error_backend; } - backend->fd = gpu_fd; + drm->fd = gpu_fd; - backend->drm_invalidated.notify = drm_invalidated; - wlr_session_signal_add(session, gpu_fd, &backend->drm_invalidated); + drm->drm_invalidated.notify = drm_invalidated; + wlr_session_signal_add(session, gpu_fd, &drm->drm_invalidated); - backend->display = display; + drm->display = display; struct wl_event_loop *event_loop = wl_display_get_event_loop(display); - backend->drm_event = wl_event_loop_add_fd(event_loop, backend->fd, + drm->drm_event = wl_event_loop_add_fd(event_loop, drm->fd, WL_EVENT_READABLE, wlr_drm_event, NULL); - if (!backend->drm_event) { + if (!drm->drm_event) { wlr_log(L_ERROR, "Failed to create DRM event source"); goto error_fd; } - backend->session_signal.notify = session_signal; - wl_signal_add(&session->session_signal, &backend->session_signal); + drm->session_signal.notify = session_signal; + wl_signal_add(&session->session_signal, &drm->session_signal); - if (!wlr_drm_check_features(backend)) { + if (!wlr_drm_check_features(drm)) { goto error_event; } - if (!wlr_drm_resources_init(backend)) { + if (!wlr_drm_resources_init(drm)) { goto error_event; } - if (!wlr_drm_renderer_init(&backend->renderer, backend->fd)) { + if (!wlr_drm_renderer_init(&drm->renderer, drm->fd)) { wlr_log(L_ERROR, "Failed to initialize renderer"); goto error_event; } - if (!wlr_egl_bind_display(&backend->renderer.egl, display)) { + if (!wlr_egl_bind_display(&drm->renderer.egl, display)) { wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error()); } - return &backend->backend; + return &drm->backend; error_event: - wl_event_source_remove(backend->drm_event); + wl_event_source_remove(drm->drm_event); error_fd: - wlr_session_close_file(backend->session, backend->fd); - list_free(backend->outputs); + wlr_session_close_file(drm->session, drm->fd); + list_free(drm->outputs); error_backend: - free(backend); + free(drm); return NULL; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 96feba15..a50216cb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -24,21 +24,21 @@ #include "backend/drm/iface.h" #include "backend/drm/util.h" -bool wlr_drm_check_features(struct wlr_drm_backend *backend) { - if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { +bool wlr_drm_check_features(struct wlr_drm_backend *drm) { + if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(L_ERROR, "DRM universal planes unsupported"); return false; } if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - backend->iface = &iface_legacy; - } else if (drmSetClientCap(backend->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { + drm->iface = &iface_legacy; + } else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - backend->iface = &iface_legacy; + drm->iface = &iface_legacy; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - backend->iface = &iface_atomic; + drm->iface = &iface_atomic; } return true; @@ -51,8 +51,8 @@ static int cmp_plane(const void *arg1, const void *arg2) { return (int)a->type - (int)b->type; } -static bool init_planes(struct wlr_drm_backend *backend) { - drmModePlaneRes *plane_res = drmModeGetPlaneResources(backend->fd); +static bool init_planes(struct wlr_drm_backend *drm) { + drmModePlaneRes *plane_res = drmModeGetPlaneResources(drm->fd); if (!plane_res) { wlr_log_errno(L_ERROR, "Failed to get DRM plane resources"); return false; @@ -65,17 +65,17 @@ static bool init_planes(struct wlr_drm_backend *backend) { return true; } - backend->num_planes = plane_res->count_planes; - backend->planes = calloc(backend->num_planes, sizeof(*backend->planes)); - if (!backend->planes) { + drm->num_planes = plane_res->count_planes; + drm->planes = calloc(drm->num_planes, sizeof(*drm->planes)); + if (!drm->planes) { wlr_log_errno(L_ERROR, "Allocation failed"); goto error_res; } - for (size_t i = 0; i < backend->num_planes; ++i) { - struct wlr_drm_plane *p = &backend->planes[i]; + for (size_t i = 0; i < drm->num_planes; ++i) { + struct wlr_drm_plane *p = &drm->planes[i]; - drmModePlane *plane = drmModeGetPlane(backend->fd, plane_res->planes[i]); + drmModePlane *plane = drmModeGetPlane(drm->fd, plane_res->planes[i]); if (!plane) { wlr_log_errno(L_ERROR, "Failed to get DRM plane"); goto error_planes; @@ -85,44 +85,43 @@ static bool init_planes(struct wlr_drm_backend *backend) { p->possible_crtcs = plane->possible_crtcs; uint64_t type; - if (!wlr_drm_get_plane_props(backend->fd, p->id, &p->props) || - !wlr_drm_get_prop(backend->fd, p->id, p->props.type, &type)) { + if (!wlr_drm_get_plane_props(drm->fd, p->id, &p->props) || + !wlr_drm_get_prop(drm->fd, p->id, p->props.type, &type)) { drmModeFreePlane(plane); goto error_planes; } p->type = type; - backend->num_type_planes[type]++; + drm->num_type_planes[type]++; drmModeFreePlane(plane); } wlr_log(L_INFO, "(%zu overlay, %zu primary, %zu cursor)", - backend->num_overlay_planes, - backend->num_primary_planes, - backend->num_cursor_planes); + drm->num_overlay_planes, + drm->num_primary_planes, + drm->num_cursor_planes); - qsort(backend->planes, backend->num_planes, - sizeof(*backend->planes), cmp_plane); + qsort(drm->planes, drm->num_planes, sizeof(*drm->planes), cmp_plane); - backend->overlay_planes = backend->planes; - backend->primary_planes = backend->overlay_planes - + backend->num_overlay_planes; - backend->cursor_planes = backend->primary_planes - + backend->num_primary_planes; + drm->overlay_planes = drm->planes; + drm->primary_planes = drm->overlay_planes + + drm->num_overlay_planes; + drm->cursor_planes = drm->primary_planes + + drm->num_primary_planes; drmModeFreePlaneResources(plane_res); return true; error_planes: - free(backend->planes); + free(drm->planes); error_res: drmModeFreePlaneResources(plane_res); return false; } -bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { - drmModeRes *res = drmModeGetResources(backend->fd); +bool wlr_drm_resources_init(struct wlr_drm_backend *drm) { + drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { wlr_log_errno(L_ERROR, "Failed to get DRM resources"); return false; @@ -130,20 +129,20 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { wlr_log(L_INFO, "Found %d DRM CRTCs", res->count_crtcs); - backend->num_crtcs = res->count_crtcs; - backend->crtcs = calloc(backend->num_crtcs, sizeof(backend->crtcs[0])); - if (!backend->crtcs) { + drm->num_crtcs = res->count_crtcs; + drm->crtcs = calloc(drm->num_crtcs, sizeof(drm->crtcs[0])); + if (!drm->crtcs) { wlr_log_errno(L_ERROR, "Allocation failed"); goto error_res; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { - struct wlr_drm_crtc *crtc = &backend->crtcs[i]; + for (size_t i = 0; i < drm->num_crtcs; ++i) { + struct wlr_drm_crtc *crtc = &drm->crtcs[i]; crtc->id = res->crtcs[i]; - wlr_drm_get_crtc_props(backend->fd, crtc->id, &crtc->props); + wlr_drm_get_crtc_props(drm->fd, crtc->id, &crtc->props); } - if (!init_planes(backend)) { + if (!init_planes(drm)) { goto error_crtcs; } @@ -152,25 +151,26 @@ bool wlr_drm_resources_init(struct wlr_drm_backend *backend) { return true; error_crtcs: - free(backend->crtcs); + free(drm->crtcs); error_res: drmModeFreeResources(res); return false; } -void wlr_drm_resources_free(struct wlr_drm_backend *backend) { - if (!backend) { +void wlr_drm_resources_free(struct wlr_drm_backend *drm) { + if (!drm) { return; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { - struct wlr_drm_crtc *crtc = &backend->crtcs[i]; + + for (size_t i = 0; i < drm->num_crtcs; ++i) { + struct wlr_drm_crtc *crtc = &drm->crtcs[i]; drmModeAtomicFree(crtc->atomic); if (crtc->mode_id) { - drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); + drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); } } - free(backend->crtcs); - free(backend->planes); + free(drm->crtcs); + free(drm->planes); } static void wlr_drm_output_make_current(struct wlr_output *_output) { @@ -180,15 +180,15 @@ static void wlr_drm_output_make_current(struct wlr_output *_output) { static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_swap_buffers(renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&drm->renderer, &plane->surf); uint32_t fb_id = get_fb_for_bo(bo); - if (backend->iface->crtc_pageflip(backend, output, crtc, fb_id, NULL)) { + if (drm->iface->crtc_pageflip(drm, output, crtc, fb_id, NULL)) { output->pageflip_pending = true; } else { wl_event_source_timer_update(output->retry_pageflip, @@ -199,8 +199,7 @@ static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { static void wlr_drm_output_set_gamma(struct wlr_output *_output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; - drmModeCrtcSetGamma(backend->fd, output->crtc->id, size, r, g, b); + drmModeCrtcSetGamma(output->drm->fd, output->crtc->id, size, r, g, b); } static uint16_t wlr_drm_output_get_gamma_size(struct wlr_output *_output) { @@ -217,17 +216,16 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { return; } - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_get_front(renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_get_front(&drm->renderer, &plane->surf); struct wlr_drm_output_mode *_mode = (struct wlr_drm_output_mode *)output->output.current_mode; drmModeModeInfo *mode = &_mode->mode; - if (backend->iface->crtc_pageflip(backend, output, crtc, get_fb_for_bo(bo), mode)) { + if (drm->iface->crtc_pageflip(drm, output, crtc, get_fb_for_bo(bo), mode)) { output->pageflip_pending = true; } else { wl_event_source_timer_update(output->retry_pageflip, @@ -237,82 +235,81 @@ void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { return; } - backend->iface->conn_enable(backend, output, enable); + struct wlr_drm_backend *drm = output->drm; + drm->iface->conn_enable(drm, output, enable); if (enable) { wlr_drm_output_start_renderer(output); } } -static void realloc_planes(struct wlr_drm_backend *backend, const uint32_t *crtc_in) { +static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) { // overlay, primary, cursor for (int type = 0; type < 3; ++type) { - if (backend->num_type_planes[type] == 0) { + if (drm->num_type_planes[type] == 0) { continue; } - uint32_t possible[backend->num_type_planes[type]]; - uint32_t crtc[backend->num_crtcs]; - uint32_t crtc_res[backend->num_crtcs]; + uint32_t possible[drm->num_type_planes[type]]; + uint32_t crtc[drm->num_crtcs]; + uint32_t crtc_res[drm->num_crtcs]; - for (size_t i = 0; i < backend->num_type_planes[type]; ++i) { - possible[i] = backend->type_planes[type][i].possible_crtcs; + for (size_t i = 0; i < drm->num_type_planes[type]; ++i) { + possible[i] = drm->type_planes[type][i].possible_crtcs; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_in[i] == UNMATCHED) { crtc[i] = SKIP; - } else if (backend->crtcs[i].planes[type]) { - crtc[i] = backend->crtcs[i].planes[type] - - backend->type_planes[type]; + } else if (drm->crtcs[i].planes[type]) { + crtc[i] = drm->crtcs[i].planes[type] + - drm->type_planes[type]; } else { crtc[i] = UNMATCHED; } } - match_obj(backend->num_type_planes[type], possible, - backend->num_crtcs, crtc, crtc_res); + match_obj(drm->num_type_planes[type], possible, + drm->num_crtcs, crtc, crtc_res); - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_res[i] == UNMATCHED || crtc_res[i] == SKIP) { continue; } - struct wlr_drm_crtc *c = &backend->crtcs[i]; + struct wlr_drm_crtc *c = &drm->crtcs[i]; struct wlr_drm_plane **old = &c->planes[type]; - struct wlr_drm_plane *new = &backend->type_planes[type][crtc_res[i]]; + struct wlr_drm_plane *new = &drm->type_planes[type][crtc_res[i]]; if (*old != new) { if (*old) { - wlr_drm_surface_finish(&backend->renderer, &(*old)->surf); + wlr_drm_surface_finish(&drm->renderer, &(*old)->surf); } - wlr_drm_surface_finish(&backend->renderer, &new->surf); + wlr_drm_surface_finish(&drm->renderer, &new->surf); *old = new; } } } } -static void realloc_crtcs(struct wlr_drm_backend *backend, - struct wlr_drm_output *output) { - uint32_t crtc[backend->num_crtcs]; - uint32_t crtc_res[backend->num_crtcs]; - uint32_t possible_crtc[backend->outputs->length]; +static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *output) { + uint32_t crtc[drm->num_crtcs]; + uint32_t crtc_res[drm->num_crtcs]; + uint32_t possible_crtc[drm->outputs->length]; - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { crtc[i] = UNMATCHED; } memset(possible_crtc, 0, sizeof(possible_crtc)); ssize_t index = -1; - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *o = backend->outputs->items[i]; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_output *o = drm->outputs->items[i]; if (o == output) { index = i; } @@ -322,16 +319,16 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, } possible_crtc[i] = o->possible_crtc; - crtc[o->crtc - backend->crtcs] = i; + crtc[o->crtc - drm->crtcs] = i; } assert(index != -1); possible_crtc[index] = output->possible_crtc; - match_obj(backend->outputs->length, possible_crtc, - backend->num_crtcs, crtc, crtc_res); + match_obj(drm->outputs->length, possible_crtc, + drm->num_crtcs, crtc, crtc_res); bool matched = false; - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { // We don't want any of the current monitors to be deactivated. if (crtc[i] != UNMATCHED && crtc_res[i] == UNMATCHED) { return; @@ -346,29 +343,29 @@ static void realloc_crtcs(struct wlr_drm_backend *backend, return; } - for (size_t i = 0; i < backend->num_crtcs; ++i) { + for (size_t i = 0; i < drm->num_crtcs; ++i) { if (crtc_res[i] == UNMATCHED) { continue; } if (crtc_res[i] != crtc[i]) { - struct wlr_drm_output *o = backend->outputs->items[crtc_res[i]]; - o->crtc = &backend->crtcs[i]; + struct wlr_drm_output *o = drm->outputs->items[crtc_res[i]]; + o->crtc = &drm->crtcs[i]; } } - realloc_planes(backend, crtc_res); + realloc_planes(drm, crtc_res); } static bool wlr_drm_output_set_mode(struct wlr_output *_output, struct wlr_output_mode *mode) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_backend *drm = output->drm; wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, mode->width, mode->height, mode->refresh); - drmModeConnector *conn = drmModeGetConnector(backend->fd, output->connector); + drmModeConnector *conn = drmModeGetConnector(drm->fd, output->connector); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); goto error_output; @@ -381,7 +378,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, drmModeEncoder *enc = NULL; for (int i = 0; !enc && i < conn->count_encoders; ++i) { - enc = drmModeGetEncoder(backend->fd, conn->encoders[i]); + enc = drmModeGetEncoder(drm->fd, conn->encoders[i]); } if (!enc) { @@ -390,7 +387,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, } output->possible_crtc = enc->possible_crtcs; - realloc_crtcs(backend, output); + realloc_crtcs(drm, output); if (!output->crtc) { wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->output.name); @@ -399,10 +396,10 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, struct wlr_drm_crtc *crtc = output->crtc; wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", output->output.name, - crtc - backend->crtcs, - crtc->overlay ? crtc->overlay - backend->overlay_planes : -1, - crtc->primary ? crtc->primary - backend->primary_planes : -1, - crtc->cursor ? crtc->cursor - backend->cursor_planes : -1); + crtc - drm->crtcs, + crtc->overlay ? crtc->overlay - drm->overlay_planes : -1, + crtc->primary ? crtc->primary - drm->primary_planes : -1, + crtc->cursor ? crtc->cursor - drm->cursor_planes : -1); output->state = WLR_DRM_OUTPUT_CONNECTED; output->width = output->output.width = mode->width; @@ -412,8 +409,8 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, // Since realloc_crtcs can deallocate planes on OTHER outputs, // we actually need to reinitalise all of them - for (size_t i = 0; i < backend->outputs->length; ++i) { - struct wlr_drm_output *output = backend->outputs->items[i]; + for (size_t i = 0; i < drm->outputs->length; ++i) { + struct wlr_drm_output *output = drm->outputs->items[i]; struct wlr_output_mode *mode = output->output.current_mode; struct wlr_drm_crtc *crtc = output->crtc; @@ -421,7 +418,7 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, continue; } - if (!wlr_drm_surface_init(&backend->renderer, &crtc->primary->surf, + if (!wlr_drm_surface_init(&drm->renderer, &crtc->primary->surf, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); @@ -452,13 +449,13 @@ static void wlr_drm_output_transform(struct wlr_output *output, static bool wlr_drm_output_set_cursor(struct wlr_output *_output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_renderer *renderer = &drm->renderer; struct wlr_drm_crtc *crtc = output->crtc; struct wlr_drm_plane *plane = crtc->cursor; if (!buf) { - return backend->iface->crtc_set_cursor(backend, crtc, NULL); + return drm->iface->crtc_set_cursor(drm, crtc, NULL); } // We don't have a real cursor plane, so we make a fake one @@ -474,9 +471,9 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, if (!plane->surf.gbm) { int ret; uint64_t w, h; - ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_WIDTH, &w); + ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &w); w = ret ? 64 : w; - ret = drmGetCap(backend->fd, DRM_CAP_CURSOR_HEIGHT, &h); + ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h); h = ret ? 64 : h; if (width > w || height > h) { @@ -503,7 +500,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // TODO the image needs to be rotated depending on the output rotation - plane->wlr_rend = wlr_gles2_renderer_create(&backend->backend); + plane->wlr_rend = wlr_gles2_renderer_create(&drm->backend); if (!plane->wlr_rend) { return false; } @@ -548,13 +545,13 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, gbm_bo_unmap(bo, bo_data); - return backend->iface->crtc_set_cursor(backend, crtc, bo); + return drm->iface->crtc_set_cursor(drm, crtc, bo); } static bool wlr_drm_output_move_cursor(struct wlr_output *_output, int x, int y) { struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_backend *drm = output->drm; int width, height, tmp; wlr_output_effective_resolution(_output, &width, &height); @@ -580,7 +577,7 @@ static bool wlr_drm_output_move_cursor(struct wlr_output *_output, break; } - return backend->iface->crtc_move_cursor(backend, output->crtc, x, y); + return drm->iface->crtc_move_cursor(drm, output->crtc, x, y); } static void wlr_drm_output_destroy(struct wlr_output *_output) { @@ -632,22 +629,22 @@ static const int32_t subpixel_map[] = { [DRM_MODE_SUBPIXEL_NONE] = WL_OUTPUT_SUBPIXEL_NONE, }; -void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { +void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { wlr_log(L_INFO, "Scanning DRM connectors"); - drmModeRes *res = drmModeGetResources(backend->fd); + drmModeRes *res = drmModeGetResources(drm->fd); if (!res) { wlr_log_errno(L_ERROR, "Failed to get DRM resources"); return; } - size_t seen_len = backend->outputs->length; + size_t seen_len = drm->outputs->length; // +1 so it can never be 0 bool seen[seen_len + 1]; memset(seen, 0, sizeof(seen)); for (int i = 0; i < res->count_connectors; ++i) { - drmModeConnector *conn = drmModeGetConnector(backend->fd, + drmModeConnector *conn = drmModeGetConnector(drm->fd, res->connectors[i]); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); @@ -655,7 +652,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { } struct wlr_drm_output *output; - int index = list_seq_find(backend->outputs, find_id, &conn->connector_id); + int index = list_seq_find(drm->outputs, find_id, &conn->connector_id); if (index == -1) { output = calloc(1, sizeof(*output)); @@ -666,7 +663,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { } wlr_output_init(&output->output, &output_impl); - struct wl_event_loop *ev = wl_display_get_event_loop(backend->display); + struct wl_event_loop *ev = wl_display_get_event_loop(drm->display); output->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, output); @@ -674,10 +671,10 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { output->state = WLR_DRM_OUTPUT_DISCONNECTED; output->connector = conn->connector_id; - drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, + drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, conn->encoder_id); if (curr_enc) { - output->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id); + output->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); drmModeFreeEncoder(curr_enc); } @@ -688,26 +685,26 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { conn_get_name(conn->connector_type), conn->connector_type_id); - wlr_drm_get_connector_props(backend->fd, + wlr_drm_get_connector_props(drm->fd, output->connector, &output->props); size_t edid_len = 0; - uint8_t *edid = wlr_drm_get_prop_blob(backend->fd, + uint8_t *edid = wlr_drm_get_prop_blob(drm->fd, output->connector, output->props.edid, &edid_len); parse_edid(&output->output, edid_len, edid); free(edid); - if (list_add(backend->outputs, output) == -1) { + if (list_add(drm->outputs, output) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); drmModeFreeConnector(conn); wl_event_source_remove(output->retry_pageflip); free(output); continue; } - wlr_output_create_global(&output->output, backend->display); + wlr_output_create_global(&output->output, drm->display); wlr_log(L_INFO, "Found display '%s'", output->output.name); } else { - output = backend->outputs->items[index]; + output = drm->outputs->items[index]; seen[index] = true; } @@ -742,7 +739,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { output->state = WLR_DRM_OUTPUT_NEEDS_MODESET; wlr_log(L_INFO, "Sending modesetting signal for '%s'", output->output.name); - wl_signal_emit(&backend->backend.events.output_add, &output->output); + wl_signal_emit(&drm->backend.events.output_add, &output->output); } else if (output->state == WLR_DRM_OUTPUT_CONNECTED && conn->connection != DRM_MODE_CONNECTED) { @@ -760,7 +757,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { continue; } - struct wlr_drm_output *output = backend->outputs->items[i]; + struct wlr_drm_output *output = drm->outputs->items[i]; wlr_log(L_INFO, "'%s' disappeared", output->output.name); wlr_drm_output_cleanup(output); @@ -769,14 +766,14 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) { wl_event_source_remove(output->retry_pageflip); free(output); - list_del(backend->outputs, i); + list_del(drm->outputs, i); } } static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { struct wlr_drm_output *output = user; - struct wlr_drm_backend *backend = output->drm; + struct wlr_drm_backend *drm = output->drm; output->pageflip_pending = false; if (output->state != WLR_DRM_OUTPUT_CONNECTED) { @@ -789,7 +786,7 @@ static void page_flip_handler(int fd, unsigned seq, plane->surf.front = NULL; } - if (backend->session->active) { + if (drm->session->active) { wl_signal_emit(&output->output.events.frame, &output->output); } } @@ -848,15 +845,14 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { return; } - struct wlr_drm_backend *backend = output->drm; - struct wlr_drm_renderer *renderer = &backend->renderer; + struct wlr_drm_backend *drm = output->drm; switch (output->state) { case WLR_DRM_OUTPUT_CONNECTED: case WLR_DRM_OUTPUT_CLEANUP:; struct wlr_drm_crtc *crtc = output->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_surface_finish(renderer, &crtc->planes[i]->surf); + wlr_drm_surface_finish(&drm->renderer, &crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; @@ -869,7 +865,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { case WLR_DRM_OUTPUT_NEEDS_MODESET: wlr_log(L_INFO, "Emmiting destruction signal for '%s'", output->output.name); - wl_signal_emit(&backend->backend.events.output_remove, &output->output); + wl_signal_emit(&drm->backend.events.output_remove, &output->output); break; case WLR_DRM_OUTPUT_DISCONNECTED: break; diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index ce5de091..7e506fe7 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -96,16 +96,16 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, } } -static bool atomic_crtc_pageflip(struct wlr_drm_backend *backend, +static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { if (crtc->mode_id) { - drmModeDestroyPropertyBlob(backend->fd, crtc->mode_id); + drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); } - if (drmModeCreatePropertyBlob(backend->fd, mode, sizeof(*mode), &crtc->mode_id)) { + if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode), &crtc->mode_id)) { wlr_log_errno(L_ERROR, "Unable to create property blob"); return false; } @@ -118,25 +118,25 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *backend, atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id); atomic_add(&atom, crtc->id, crtc->props.active, 1); set_plane_props(&atom, crtc->primary, crtc->id, fb_id, true); - return atomic_commit(backend->fd, &atom, output, + return atomic_commit(drm->fd, &atom, output, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, mode); } -static void atomic_conn_enable(struct wlr_drm_backend *backend, +static void atomic_conn_enable(struct wlr_drm_backend *drm, struct wlr_drm_output *output, bool enable) { struct wlr_drm_crtc *crtc = output->crtc; struct atomic atom; atomic_begin(crtc, &atom); atomic_add(&atom, crtc->id, crtc->props.active, enable); - atomic_end(backend->fd, &atom); + atomic_end(drm->fd, &atom); } -bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, struct gbm_bo *bo); -static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, +static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { if (!crtc || !crtc->cursor) { return true; @@ -145,7 +145,7 @@ static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, struct wlr_drm_plane *plane = crtc->cursor; // We can't use atomic operations on fake planes if (plane->id == 0) { - return legacy_crtc_set_cursor(backend, crtc, bo); + return legacy_crtc_set_cursor(drm, crtc, bo); } struct atomic atom; @@ -159,18 +159,18 @@ static bool atomic_crtc_set_cursor(struct wlr_drm_backend *backend, atomic_add(&atom, plane->id, plane->props.crtc_id, 0); } - return atomic_end(backend->fd, &atom); + return atomic_end(drm->fd, &atom); } -bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, int x, int y); -static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, +static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, int x, int y) { struct wlr_drm_plane *plane = crtc->cursor; // We can't use atomic operations on fake planes if (plane->id == 0) { - return legacy_crtc_move_cursor(backend, crtc, x, y); + return legacy_crtc_move_cursor(drm, crtc, x, y); } struct atomic atom; @@ -178,7 +178,7 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *backend, atomic_begin(crtc, &atom); atomic_add(&atom, plane->id, plane->props.crtc_x, x); atomic_add(&atom, plane->id, plane->props.crtc_y, y); - return atomic_end(backend->fd, &atom); + return atomic_end(drm->fd, &atom); } const struct wlr_drm_interface iface_atomic = { diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index e320af93..ffa8157b 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -6,18 +6,18 @@ #include "backend/drm/iface.h" #include "backend/drm/util.h" -static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, +static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { - if (drmModeSetCrtc(backend->fd, crtc->id, fb_id, 0, 0, + if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, &output->connector, 1, mode)) { wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", output->output.name); return false; } } - if (drmModePageFlip(backend->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { + if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { wlr_log_errno(L_ERROR, "%s: Failed to page flip", output->output.name); return false; } @@ -25,26 +25,26 @@ static bool legacy_crtc_pageflip(struct wlr_drm_backend *backend, return true; } -static void legacy_conn_enable(struct wlr_drm_backend *backend, +static void legacy_conn_enable(struct wlr_drm_backend *drm, struct wlr_drm_output *output, bool enable) { - drmModeConnectorSetProperty(backend->fd, output->connector, output->props.dpms, + drmModeConnectorSetProperty(drm->fd, output->connector, output->props.dpms, enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); } -bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { if (!crtc || !crtc->cursor) { return true; } if (!bo) { - drmModeSetCursor(backend->fd, crtc->id, 0, 0, 0); + drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0); return true; } struct wlr_drm_plane *plane = crtc->cursor; - if (drmModeSetCursor(backend->fd, crtc->id, gbm_bo_get_handle(bo).u32, + if (drmModeSetCursor(drm->fd, crtc->id, gbm_bo_get_handle(bo).u32, plane->surf.width, plane->surf.height)) { wlr_log_errno(L_ERROR, "Failed to set hardware cursor"); return false; @@ -53,9 +53,9 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *backend, return true; } -bool legacy_crtc_move_cursor(struct wlr_drm_backend *backend, +bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc, int x, int y) { - return !drmModeMoveCursor(backend->fd, crtc->id, x, y); + return !drmModeMoveCursor(drm->fd, crtc->id, x, y); } const struct wlr_drm_interface iface_legacy = { diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index cf77f4d4..291b9a30 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -15,18 +15,18 @@ struct wlr_drm_crtc; // Used to provide atomic or legacy DRM functions struct wlr_drm_interface { // Enable or disable DPMS for output - void (*conn_enable)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, bool enable); + void (*conn_enable)(struct wlr_drm_backend *drm, + struct wlr_drm_output *output, bool enable); // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. - bool (*crtc_pageflip)(struct wlr_drm_backend *backend, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, - uint32_t fb_id, drmModeModeInfo *mode); + bool (*crtc_pageflip)(struct wlr_drm_backend *drm, + struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + uint32_t fb_id, drmModeModeInfo *mode); // Enable the cursor buffer on crtc. Set bo to NULL to disable - bool (*crtc_set_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, struct gbm_bo *bo); + bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, struct gbm_bo *bo); // Move the cursor on crtc - bool (*crtc_move_cursor)(struct wlr_drm_backend *backend, - struct wlr_drm_crtc *crtc, int x, int y); + bool (*crtc_move_cursor)(struct wlr_drm_backend *drm, + struct wlr_drm_crtc *crtc, int x, int y); }; extern const struct wlr_drm_interface iface_atomic; From 4101b897000602caf04aba8a10c1b4a4b229f4d6 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sat, 30 Sep 2017 23:31:08 +1300 Subject: [PATCH 07/14] Rename wlr_drm_output to wlr_drm_connector --- backend/drm/backend.c | 14 +- backend/drm/drm.c | 422 ++++++++++++++++++------------------ backend/drm/iface_atomic.c | 20 +- backend/drm/iface_legacy.c | 14 +- include/backend/drm/drm.h | 34 +-- include/backend/drm/iface.h | 8 +- 6 files changed, 252 insertions(+), 260 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index f634eee6..442e5d0e 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -30,8 +30,8 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) { wlr_drm_restore_outputs(drm); for (size_t i = 0; drm->outputs && i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - wlr_output_destroy(&output->output); + struct wlr_drm_connector *conn = drm->outputs->items[i]; + wlr_output_destroy(&conn->output); } wlr_drm_renderer_finish(&drm->renderer); @@ -65,15 +65,15 @@ static void session_signal(struct wl_listener *listener, void *data) { wlr_log(L_INFO, "DRM fd resumed"); for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - wlr_drm_output_start_renderer(output); + struct wlr_drm_connector *conn = drm->outputs->items[i]; + wlr_drm_connector_start_renderer(conn); - if (!output->crtc) { + if (!conn->crtc) { continue; } - struct wlr_drm_plane *plane = output->crtc->cursor; - drm->iface->crtc_set_cursor(drm, output->crtc, + struct wlr_drm_plane *plane = conn->crtc->cursor; + drm->iface->crtc_set_cursor(drm, conn->crtc, plane ? plane->cursor_bo : NULL); } } else { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index a50216cb..676f5f7b 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -173,77 +173,73 @@ void wlr_drm_resources_free(struct wlr_drm_backend *drm) { free(drm->planes); } -static void wlr_drm_output_make_current(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_surface_make_current(&output->drm->renderer, &output->crtc->primary->surf); +static void wlr_drm_connector_make_current(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + wlr_drm_surface_make_current(&conn->drm->renderer, &conn->crtc->primary->surf); } -static void wlr_drm_output_swap_buffers(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; +static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&drm->renderer, &plane->surf); uint32_t fb_id = get_fb_for_bo(bo); - if (drm->iface->crtc_pageflip(drm, output, crtc, fb_id, NULL)) { - output->pageflip_pending = true; + if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { + conn->pageflip_pending = true; } else { - wl_event_source_timer_update(output->retry_pageflip, - 1000.0f / output->output.current_mode->refresh); + wl_event_source_timer_update(conn->retry_pageflip, + 1000.0f / conn->output.current_mode->refresh); } } -static void wlr_drm_output_set_gamma(struct wlr_output *_output, +static void wlr_drm_connector_set_gamma(struct wlr_output *output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - drmModeCrtcSetGamma(output->drm->fd, output->crtc->id, size, r, g, b); + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + drmModeCrtcSetGamma(conn->drm->fd, conn->crtc->id, size, r, g, b); } -static uint16_t wlr_drm_output_get_gamma_size(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - drmModeCrtc *crtc = output->old_crtc; - if (!crtc) { - return 0; - } - return crtc->gamma_size; +static uint16_t wlr_drm_connector_get_gamma_size(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + drmModeCrtc *crtc = conn->old_crtc; + return crtc ? crtc->gamma_size : 0; } -void wlr_drm_output_start_renderer(struct wlr_drm_output *output) { - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { +void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_backend *drm = output->drm; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_backend *drm = conn->drm; + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; struct gbm_bo *bo = wlr_drm_surface_get_front(&drm->renderer, &plane->surf); + uint32_t fb_id = get_fb_for_bo(bo); - struct wlr_drm_output_mode *_mode = - (struct wlr_drm_output_mode *)output->output.current_mode; - drmModeModeInfo *mode = &_mode->mode; - if (drm->iface->crtc_pageflip(drm, output, crtc, get_fb_for_bo(bo), mode)) { - output->pageflip_pending = true; + struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; + if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, &mode->drm_mode)) { + conn->pageflip_pending = true; } else { - wl_event_source_timer_update(output->retry_pageflip, - 1000.0f / output->output.current_mode->refresh); + wl_event_source_timer_update(conn->retry_pageflip, + 1000.0f / conn->output.current_mode->refresh); } } -static void wlr_drm_output_enable(struct wlr_output *_output, bool enable) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { +static void wlr_drm_connector_enable(struct wlr_output *output, bool enable) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_backend *drm = output->drm; - drm->iface->conn_enable(drm, output, enable); + struct wlr_drm_backend *drm = conn->drm; + drm->iface->conn_enable(drm, conn, enable); if (enable) { - wlr_drm_output_start_renderer(output); + wlr_drm_connector_start_renderer(conn); } } @@ -296,7 +292,7 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) } } -static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *output) { +static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_connector *conn) { uint32_t crtc[drm->num_crtcs]; uint32_t crtc_res[drm->num_crtcs]; uint32_t possible_crtc[drm->outputs->length]; @@ -309,23 +305,23 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *ou ssize_t index = -1; for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *o = drm->outputs->items[i]; - if (o == output) { + struct wlr_drm_connector *c = drm->outputs->items[i]; + if (c == conn) { index = i; } - if (o->state != WLR_DRM_OUTPUT_CONNECTED) { + if (c->state != WLR_DRM_CONN_CONNECTED) { continue; } - possible_crtc[i] = o->possible_crtc; - crtc[o->crtc - drm->crtcs] = i; + possible_crtc[i] = c->possible_crtc; + crtc[c->crtc - drm->crtcs] = i; } assert(index != -1); - possible_crtc[index] = output->possible_crtc; - match_obj(drm->outputs->length, possible_crtc, - drm->num_crtcs, crtc, crtc_res); + possible_crtc[index] = conn->possible_crtc; + match_obj(drm->outputs->length, possible_crtc, drm->num_crtcs, + crtc, crtc_res); bool matched = false; for (size_t i = 0; i < drm->num_crtcs; ++i) { @@ -349,36 +345,29 @@ static void realloc_crtcs(struct wlr_drm_backend *drm, struct wlr_drm_output *ou } if (crtc_res[i] != crtc[i]) { - struct wlr_drm_output *o = drm->outputs->items[crtc_res[i]]; - o->crtc = &drm->crtcs[i]; + struct wlr_drm_connector *c = drm->outputs->items[crtc_res[i]]; + c->crtc = &drm->crtcs[i]; } } realloc_planes(drm, crtc_res); } -static bool wlr_drm_output_set_mode(struct wlr_output *_output, - struct wlr_output_mode *mode) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; - - wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", output->output.name, - mode->width, mode->height, mode->refresh); - - drmModeConnector *conn = drmModeGetConnector(drm->fd, output->connector); +static uint32_t get_possible_crtcs(int fd, uint32_t conn_id) { + drmModeConnector *conn = drmModeGetConnector(fd, conn_id); if (!conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); - goto error_output; + return 0; } if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) { - wlr_log(L_ERROR, "%s is not connected", output->output.name); - goto error_output; + wlr_log(L_ERROR, "Output is not connected"); + goto error_conn; } drmModeEncoder *enc = NULL; for (int i = 0; !enc && i < conn->count_encoders; ++i) { - enc = drmModeGetEncoder(drm->fd, conn->encoders[i]); + enc = drmModeGetEncoder(fd, conn->encoders[i]); } if (!enc) { @@ -386,35 +375,58 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, goto error_conn; } - output->possible_crtc = enc->possible_crtcs; - realloc_crtcs(drm, output); + uint32_t ret = enc->possible_crtcs; + drmModeFreeEncoder(enc); + drmModeFreeConnector(conn); + return ret; - if (!output->crtc) { - wlr_log(L_ERROR, "Unable to match %s with a CRTC", output->output.name); - goto error_enc; +error_conn: + drmModeFreeConnector(conn); + return 0; +} + +static bool wlr_drm_connector_set_mode(struct wlr_output *output, + struct wlr_output_mode *mode) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; + + wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", conn->output.name, + mode->width, mode->height, mode->refresh); + + wlr_log(L_DEBUG, "%p %p", conn, drm); + conn->possible_crtc = get_possible_crtcs(drm->fd, conn->id); + if (conn->possible_crtc == 0) { + goto error_conn; } - struct wlr_drm_crtc *crtc = output->crtc; - wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", output->output.name, + realloc_crtcs(drm, conn); + + if (!conn->crtc) { + wlr_log(L_ERROR, "Unable to match %s with a CRTC", conn->output.name); + goto error_conn; + } + + struct wlr_drm_crtc *crtc = conn->crtc; + wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", conn->output.name, crtc - drm->crtcs, crtc->overlay ? crtc->overlay - drm->overlay_planes : -1, crtc->primary ? crtc->primary - drm->primary_planes : -1, crtc->cursor ? crtc->cursor - drm->cursor_planes : -1); - output->state = WLR_DRM_OUTPUT_CONNECTED; - output->width = output->output.width = mode->width; - output->height = output->output.height = mode->height; - output->output.current_mode = mode; - wl_signal_emit(&output->output.events.resolution, &output->output); + conn->state = WLR_DRM_CONN_CONNECTED; + conn->output.width = mode->width; + conn->output.height = mode->height; + conn->output.current_mode = mode; + wl_signal_emit(&conn->output.events.resolution, &conn->output); // Since realloc_crtcs can deallocate planes on OTHER outputs, // we actually need to reinitalise all of them for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - struct wlr_output_mode *mode = output->output.current_mode; - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + struct wlr_output_mode *mode = conn->output.current_mode; + struct wlr_drm_crtc *crtc = conn->crtc; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { + if (conn->state != WLR_DRM_CONN_CONNECTED) { continue; } @@ -422,36 +434,31 @@ static bool wlr_drm_output_set_mode(struct wlr_output *_output, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); - goto error_enc; + goto error_conn; } - wlr_drm_output_start_renderer(output); + wlr_drm_connector_start_renderer(conn); } - drmModeFreeEncoder(enc); - drmModeFreeConnector(conn); return true; -error_enc: - drmModeFreeEncoder(enc); error_conn: - drmModeFreeConnector(conn); -error_output: - wlr_drm_output_cleanup(output); + wlr_drm_connector_cleanup(conn); return false; } -static void wlr_drm_output_transform(struct wlr_output *output, +static void wlr_drm_connector_transform(struct wlr_output *output, enum wl_output_transform transform) { output->transform = transform; } -static bool wlr_drm_output_set_cursor(struct wlr_output *_output, +static bool wlr_drm_connector_set_cursor(struct wlr_output *output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; struct wlr_drm_renderer *renderer = &drm->renderer; - struct wlr_drm_crtc *crtc = output->crtc; + + struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->cursor; if (!buf) { @@ -496,7 +503,7 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, // OpenGL will read the pixels out upside down, // so we need to flip the image vertically wlr_matrix_texture(plane->matrix, plane->surf.width, plane->surf.height, - output->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); + conn->output.transform ^ WL_OUTPUT_TRANSFORM_FLIPPED_180); // TODO the image needs to be rotated depending on the output rotation @@ -548,15 +555,15 @@ static bool wlr_drm_output_set_cursor(struct wlr_output *_output, return drm->iface->crtc_set_cursor(drm, crtc, bo); } -static bool wlr_drm_output_move_cursor(struct wlr_output *_output, +static bool wlr_drm_connector_move_cursor(struct wlr_output *output, int x, int y) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + struct wlr_drm_backend *drm = conn->drm; int width, height, tmp; - wlr_output_effective_resolution(_output, &width, &height); + wlr_output_effective_resolution(output, &width, &height); - switch (_output->transform) { + switch (output->transform) { case WL_OUTPUT_TRANSFORM_NORMAL: // nothing to do break; @@ -573,51 +580,45 @@ static bool wlr_drm_output_move_cursor(struct wlr_output *_output, default: // TODO other transformations wlr_log(L_ERROR, "TODO: handle surface to crtc for transformation = %d", - _output->transform); + output->transform); break; } - return drm->iface->crtc_move_cursor(drm, output->crtc, x, y); + return drm->iface->crtc_move_cursor(drm, conn->crtc, x, y); } -static void wlr_drm_output_destroy(struct wlr_output *_output) { - struct wlr_drm_output *output = (struct wlr_drm_output *)_output; - wlr_drm_output_cleanup(output); - wl_event_source_remove(output->retry_pageflip); - free(output); +static void wlr_drm_connector_destroy(struct wlr_output *output) { + struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; + wlr_drm_connector_cleanup(conn); + wl_event_source_remove(conn->retry_pageflip); + free(conn); } static struct wlr_output_impl output_impl = { - .enable = wlr_drm_output_enable, - .set_mode = wlr_drm_output_set_mode, - .transform = wlr_drm_output_transform, - .set_cursor = wlr_drm_output_set_cursor, - .move_cursor = wlr_drm_output_move_cursor, - .destroy = wlr_drm_output_destroy, - .make_current = wlr_drm_output_make_current, - .swap_buffers = wlr_drm_output_swap_buffers, - .set_gamma = wlr_drm_output_set_gamma, - .get_gamma_size = wlr_drm_output_get_gamma_size, + .enable = wlr_drm_connector_enable, + .set_mode = wlr_drm_connector_set_mode, + .transform = wlr_drm_connector_transform, + .set_cursor = wlr_drm_connector_set_cursor, + .move_cursor = wlr_drm_connector_move_cursor, + .destroy = wlr_drm_connector_destroy, + .make_current = wlr_drm_connector_make_current, + .swap_buffers = wlr_drm_connector_swap_buffers, + .set_gamma = wlr_drm_connector_set_gamma, + .get_gamma_size = wlr_drm_connector_get_gamma_size, }; static int retry_pageflip(void *data) { - struct wlr_drm_output *output = data; - wlr_log(L_INFO, "%s: Retrying pageflip", output->output.name); - wlr_drm_output_start_renderer(output); + struct wlr_drm_connector *conn = data; + wlr_log(L_INFO, "%s: Retrying pageflip", conn->output.name); + wlr_drm_connector_start_renderer(conn); return 0; } static int find_id(const void *item, const void *cmp_to) { - const struct wlr_drm_output *output = item; + const struct wlr_drm_connector *conn = item; const uint32_t *id = cmp_to; - if (output->connector < *id) { - return -1; - } else if (output->connector > *id) { - return 1; - } else { - return 0; - } + return (int)conn->id - (int)*id; } static const int32_t subpixel_map[] = { @@ -644,110 +645,111 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { memset(seen, 0, sizeof(seen)); for (int i = 0; i < res->count_connectors; ++i) { - drmModeConnector *conn = drmModeGetConnector(drm->fd, + drmModeConnector *drm_conn = drmModeGetConnector(drm->fd, res->connectors[i]); - if (!conn) { + if (!drm_conn) { wlr_log_errno(L_ERROR, "Failed to get DRM connector"); continue; } - struct wlr_drm_output *output; - int index = list_seq_find(drm->outputs, find_id, &conn->connector_id); + struct wlr_drm_connector *wlr_conn; + int index = list_seq_find(drm->outputs, find_id, &drm_conn->connector_id); if (index == -1) { - output = calloc(1, sizeof(*output)); - if (!output) { + wlr_conn = calloc(1, sizeof(*wlr_conn)); + if (!wlr_conn) { wlr_log_errno(L_ERROR, "Allocation failed"); - drmModeFreeConnector(conn); + drmModeFreeConnector(drm_conn); continue; } - wlr_output_init(&output->output, &output_impl); + wlr_output_init(&wlr_conn->output, &output_impl); struct wl_event_loop *ev = wl_display_get_event_loop(drm->display); - output->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, - output); + wlr_conn->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, + wlr_conn); - output->state = WLR_DRM_OUTPUT_DISCONNECTED; - output->connector = conn->connector_id; + wlr_conn->drm = drm; + wlr_conn->state = WLR_DRM_CONN_DISCONNECTED; + wlr_conn->id = drm_conn->connector_id; drmModeEncoder *curr_enc = drmModeGetEncoder(drm->fd, - conn->encoder_id); + drm_conn->encoder_id); if (curr_enc) { - output->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); + wlr_conn->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id); drmModeFreeEncoder(curr_enc); } - output->output.phys_width = conn->mmWidth; - output->output.phys_height = conn->mmHeight; - output->output.subpixel = subpixel_map[conn->subpixel]; - snprintf(output->output.name, sizeof(output->output.name), "%s-%"PRIu32, - conn_get_name(conn->connector_type), - conn->connector_type_id); + wlr_conn->output.phys_width = drm_conn->mmWidth; + wlr_conn->output.phys_height = drm_conn->mmHeight; + wlr_conn->output.subpixel = subpixel_map[drm_conn->subpixel]; + snprintf(wlr_conn->output.name, sizeof(wlr_conn->output.name), + "%s-%"PRIu32, + conn_get_name(drm_conn->connector_type), + drm_conn->connector_type_id); - wlr_drm_get_connector_props(drm->fd, - output->connector, &output->props); + wlr_drm_get_connector_props(drm->fd, wlr_conn->id, &wlr_conn->props); size_t edid_len = 0; uint8_t *edid = wlr_drm_get_prop_blob(drm->fd, - output->connector, output->props.edid, &edid_len); - parse_edid(&output->output, edid_len, edid); + wlr_conn->id, wlr_conn->props.edid, &edid_len); + parse_edid(&wlr_conn->output, edid_len, edid); free(edid); - if (list_add(drm->outputs, output) == -1) { + if (list_add(drm->outputs, wlr_conn) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); - drmModeFreeConnector(conn); - wl_event_source_remove(output->retry_pageflip); - free(output); + drmModeFreeConnector(drm_conn); + wl_event_source_remove(wlr_conn->retry_pageflip); + free(wlr_conn); continue; } - wlr_output_create_global(&output->output, drm->display); - wlr_log(L_INFO, "Found display '%s'", output->output.name); + wlr_output_create_global(&wlr_conn->output, drm->display); + wlr_log(L_INFO, "Found display '%s'", wlr_conn->output.name); } else { - output = drm->outputs->items[index]; + wlr_conn = drm->outputs->items[index]; seen[index] = true; } - if (output->state == WLR_DRM_OUTPUT_DISCONNECTED && - conn->connection == DRM_MODE_CONNECTED) { + if (wlr_conn->state == WLR_DRM_CONN_DISCONNECTED && + drm_conn->connection == DRM_MODE_CONNECTED) { - wlr_log(L_INFO, "'%s' connected", output->output.name); + wlr_log(L_INFO, "'%s' connected", wlr_conn->output.name); wlr_log(L_INFO, "Detected modes:"); - for (int i = 0; i < conn->count_modes; ++i) { - struct wlr_drm_output_mode *mode = calloc(1, - sizeof(struct wlr_drm_output_mode)); + for (int i = 0; i < drm_conn->count_modes; ++i) { + struct wlr_drm_mode *mode = calloc(1, sizeof(*mode)); if (!mode) { wlr_log_errno(L_ERROR, "Allocation failed"); continue; } - mode->mode = conn->modes[i]; - mode->wlr_mode.width = mode->mode.hdisplay; - mode->wlr_mode.height = mode->mode.vdisplay; - mode->wlr_mode.refresh = calculate_refresh_rate(&mode->mode); + mode->drm_mode = drm_conn->modes[i]; + mode->wlr_mode.width = mode->drm_mode.hdisplay; + mode->wlr_mode.height = mode->drm_mode.vdisplay; + mode->wlr_mode.refresh = calculate_refresh_rate(&mode->drm_mode); wlr_log(L_INFO, " %"PRId32"@%"PRId32"@%"PRId32, mode->wlr_mode.width, mode->wlr_mode.height, mode->wlr_mode.refresh); - if (list_add(output->output.modes, mode) == -1) { + if (list_add(wlr_conn->output.modes, mode) == -1) { wlr_log_errno(L_ERROR, "Allocation failed"); free(mode); continue; } } - output->state = WLR_DRM_OUTPUT_NEEDS_MODESET; - wlr_log(L_INFO, "Sending modesetting signal for '%s'", output->output.name); - wl_signal_emit(&drm->backend.events.output_add, &output->output); - } else if (output->state == WLR_DRM_OUTPUT_CONNECTED && - conn->connection != DRM_MODE_CONNECTED) { + wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET; + wlr_log(L_INFO, "Sending modesetting signal for '%s'", + wlr_conn->output.name); + wl_signal_emit(&drm->backend.events.output_add, &wlr_conn->output); + } else if (wlr_conn->state == WLR_DRM_CONN_CONNECTED && + drm_conn->connection != DRM_MODE_CONNECTED) { - wlr_log(L_INFO, "'%s' disconnected", output->output.name); - wlr_drm_output_cleanup(output); + wlr_log(L_INFO, "'%s' disconnected", wlr_conn->output.name); + wlr_drm_connector_cleanup(wlr_conn); } - drmModeFreeConnector(conn); + drmModeFreeConnector(drm_conn); } drmModeFreeResources(res); @@ -757,14 +759,14 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { continue; } - struct wlr_drm_output *output = drm->outputs->items[i]; + struct wlr_drm_connector *conn = drm->outputs->items[i]; - wlr_log(L_INFO, "'%s' disappeared", output->output.name); - wlr_drm_output_cleanup(output); + wlr_log(L_INFO, "'%s' disappeared", conn->output.name); + wlr_drm_connector_cleanup(conn); - drmModeFreeCrtc(output->old_crtc); - wl_event_source_remove(output->retry_pageflip); - free(output); + drmModeFreeCrtc(conn->old_crtc); + wl_event_source_remove(conn->retry_pageflip); + free(conn); list_del(drm->outputs, i); } @@ -772,22 +774,22 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) { static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, void *user) { - struct wlr_drm_output *output = user; - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_connector *conn = user; + struct wlr_drm_backend *drm = conn->drm; - output->pageflip_pending = false; - if (output->state != WLR_DRM_OUTPUT_CONNECTED) { + conn->pageflip_pending = false; + if (conn->state != WLR_DRM_CONN_CONNECTED) { return; } - struct wlr_drm_plane *plane = output->crtc->primary; + struct wlr_drm_plane *plane = conn->crtc->primary; if (plane->surf.front) { gbm_surface_release_buffer(plane->surf.gbm, plane->surf.front); plane->surf.front = NULL; } if (drm->session->active) { - wl_signal_emit(&output->output.events.frame, &output->output); + wl_signal_emit(&conn->output.events.frame, &conn->output); } } @@ -805,9 +807,9 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { uint64_t to_close = (1 << drm->outputs->length) - 1; for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - if (output->state == WLR_DRM_OUTPUT_CONNECTED) { - output->state = WLR_DRM_OUTPUT_CLEANUP; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + if (conn->state == WLR_DRM_CONN_CONNECTED) { + conn->state = WLR_DRM_CONN_CLEANUP; } } @@ -816,8 +818,8 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { while (to_close && time(NULL) < timeout) { wlr_drm_event(drm->fd, 0, NULL); for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - if (output->state != WLR_DRM_OUTPUT_CLEANUP || !output->pageflip_pending) { + struct wlr_drm_connector *conn = drm->outputs->items[i]; + if (conn->state != WLR_DRM_CONN_CLEANUP || !conn->pageflip_pending) { to_close &= ~(1 << i); } } @@ -828,29 +830,29 @@ void wlr_drm_restore_outputs(struct wlr_drm_backend *drm) { } for (size_t i = 0; i < drm->outputs->length; ++i) { - struct wlr_drm_output *output = drm->outputs->items[i]; - drmModeCrtc *crtc = output->old_crtc; + struct wlr_drm_connector *conn = drm->outputs->items[i]; + drmModeCrtc *crtc = conn->old_crtc; if (!crtc) { continue; } drmModeSetCrtc(drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, - &output->connector, 1, &crtc->mode); + &conn->id, 1, &crtc->mode); drmModeFreeCrtc(crtc); } } -void wlr_drm_output_cleanup(struct wlr_drm_output *output) { - if (!output) { +void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { + if (!conn) { return; } - struct wlr_drm_backend *drm = output->drm; + struct wlr_drm_backend *drm = conn->drm; - switch (output->state) { - case WLR_DRM_OUTPUT_CONNECTED: - case WLR_DRM_OUTPUT_CLEANUP:; - struct wlr_drm_crtc *crtc = output->crtc; + switch (conn->state) { + case WLR_DRM_CONN_CONNECTED: + case WLR_DRM_CONN_CLEANUP:; + struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { wlr_drm_surface_finish(&drm->renderer, &crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { @@ -859,17 +861,17 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *output) { } } - output->crtc = NULL; - output->possible_crtc = 0; + conn->crtc = NULL; + conn->possible_crtc = 0; /* Fallthrough */ - case WLR_DRM_OUTPUT_NEEDS_MODESET: + case WLR_DRM_CONN_NEEDS_MODESET: wlr_log(L_INFO, "Emmiting destruction signal for '%s'", - output->output.name); - wl_signal_emit(&drm->backend.events.output_remove, &output->output); + conn->output.name); + wl_signal_emit(&drm->backend.events.output_remove, &conn->output); break; - case WLR_DRM_OUTPUT_DISCONNECTED: + case WLR_DRM_CONN_DISCONNECTED: break; } - output->state = WLR_DRM_OUTPUT_DISCONNECTED; + conn->state = WLR_DRM_CONN_DISCONNECTED; } diff --git a/backend/drm/iface_atomic.c b/backend/drm/iface_atomic.c index 7e506fe7..1aef05d1 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/iface_atomic.c @@ -44,23 +44,23 @@ static bool atomic_end(int drm_fd, struct atomic *atom) { } static bool atomic_commit(int drm_fd, struct atomic *atom, - struct wlr_drm_output *output, uint32_t flag, bool modeset) { + struct wlr_drm_connector *conn, uint32_t flag, bool modeset) { if (atom->failed) { return false; } uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag; - int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, output); + int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, conn); if (ret) { wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - output->output.name, modeset ? "modeset" : "pageflip"); + conn->output.name, modeset ? "modeset" : "pageflip"); // Try to commit without new changes drmModeAtomicSetCursor(atom->req, atom->cursor); - if (drmModeAtomicCommit(drm_fd, atom->req, flags, output)) { + if (drmModeAtomicCommit(drm_fd, atom->req, flags, conn)) { wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", - output->output.name, modeset ? "modeset" : "pageflip"); + conn->output.name, modeset ? "modeset" : "pageflip"); } } @@ -97,7 +97,7 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, } static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { @@ -114,18 +114,18 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, struct atomic atom; atomic_begin(crtc, &atom); - atomic_add(&atom, output->connector, output->props.crtc_id, crtc->id); + atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id); atomic_add(&atom, crtc->id, crtc->props.active, 1); set_plane_props(&atom, crtc->primary, crtc->id, fb_id, true); - return atomic_commit(drm->fd, &atom, output, + return atomic_commit(drm->fd, &atom, conn, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK, mode); } static void atomic_conn_enable(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, bool enable) { - struct wlr_drm_crtc *crtc = output->crtc; + struct wlr_drm_connector *conn, bool enable) { + struct wlr_drm_crtc *crtc = conn->crtc; struct atomic atom; atomic_begin(crtc, &atom); diff --git a/backend/drm/iface_legacy.c b/backend/drm/iface_legacy.c index ffa8157b..cf73bb87 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/iface_legacy.c @@ -7,18 +7,18 @@ #include "backend/drm/util.h" static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode) { if (mode) { if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, - &output->connector, 1, mode)) { - wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", output->output.name); + &conn->id, 1, mode)) { + wlr_log_errno(L_ERROR, "%s: Failed to set CRTC", conn->output.name); return false; } } - if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, output)) { - wlr_log_errno(L_ERROR, "%s: Failed to page flip", output->output.name); + if (drmModePageFlip(drm->fd, crtc->id, fb_id, DRM_MODE_PAGE_FLIP_EVENT, conn)) { + wlr_log_errno(L_ERROR, "%s: Failed to page flip", conn->output.name); return false; } @@ -26,8 +26,8 @@ static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, } static void legacy_conn_enable(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, bool enable) { - drmModeConnectorSetProperty(drm->fd, output->connector, output->props.dpms, + struct wlr_drm_connector *conn, bool enable) { + drmModeConnectorSetProperty(drm->fd, conn->id, conn->props.dpms, enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); } diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 6f1abc00..a3a724bc 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -55,16 +55,6 @@ struct wlr_drm_crtc { struct wl_list connectors; }; -struct wlr_drm_connector { - struct wlr_output *base; - uint32_t id; - struct wlr_drm_crtc *crtc; - - union wlr_drm_connector_props props; - - struct wl_list link; -}; - struct wlr_drm_backend { struct wlr_backend backend; @@ -107,24 +97,24 @@ struct wlr_drm_backend { struct wlr_session *session; }; -enum wlr_drm_output_state { - WLR_DRM_OUTPUT_DISCONNECTED, - WLR_DRM_OUTPUT_NEEDS_MODESET, - WLR_DRM_OUTPUT_CLEANUP, - WLR_DRM_OUTPUT_CONNECTED, +enum wlr_drm_connector_state { + WLR_DRM_CONN_DISCONNECTED, + WLR_DRM_CONN_NEEDS_MODESET, + WLR_DRM_CONN_CLEANUP, + WLR_DRM_CONN_CONNECTED, }; -struct wlr_drm_output_mode { +struct wlr_drm_mode { struct wlr_output_mode wlr_mode; - drmModeModeInfo mode; + drmModeModeInfo drm_mode; }; -struct wlr_drm_output { +struct wlr_drm_connector { struct wlr_output output; struct wlr_drm_backend *drm; - enum wlr_drm_output_state state; - uint32_t connector; + enum wlr_drm_connector_state state; + uint32_t id; struct wlr_drm_crtc *crtc; uint32_t possible_crtc; @@ -144,10 +134,10 @@ bool wlr_drm_check_features(struct wlr_drm_backend *drm); bool wlr_drm_resources_init(struct wlr_drm_backend *drm); void wlr_drm_resources_free(struct wlr_drm_backend *drm); void wlr_drm_restore_outputs(struct wlr_drm_backend *drm); -void wlr_drm_output_cleanup(struct wlr_drm_output *output); +void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn); void wlr_drm_scan_connectors(struct wlr_drm_backend *state); int wlr_drm_event(int fd, uint32_t mask, void *data); -void wlr_drm_output_start_renderer(struct wlr_drm_output *output); +void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn); #endif diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index 291b9a30..db1d7ee1 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -9,17 +9,17 @@ #include struct wlr_drm_backend; -struct wlr_drm_output; +struct wlr_drm_connector; struct wlr_drm_crtc; // Used to provide atomic or legacy DRM functions struct wlr_drm_interface { - // Enable or disable DPMS for output + // Enable or disable DPMS for connector void (*conn_enable)(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, bool enable); + struct wlr_drm_connector *conn, bool enable); // Pageflip on crtc. If mode is non-NULL perform a full modeset using it. bool (*crtc_pageflip)(struct wlr_drm_backend *drm, - struct wlr_drm_output *output, struct wlr_drm_crtc *crtc, + struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, uint32_t fb_id, drmModeModeInfo *mode); // Enable the cursor buffer on crtc. Set bo to NULL to disable bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, From eaef028976d32e382c4ebcfbb8605a6f40cd22b8 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 15:55:25 +1300 Subject: [PATCH 08/14] Add renderer pointer inside drm_surface --- backend/drm/drm.c | 20 ++++++++++---------- backend/drm/renderer.c | 33 +++++++++++++++------------------ include/backend/drm/renderer.h | 22 ++++++++-------------- 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 676f5f7b..5c5ac8cd 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -175,7 +175,7 @@ void wlr_drm_resources_free(struct wlr_drm_backend *drm) { static void wlr_drm_connector_make_current(struct wlr_output *output) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; - wlr_drm_surface_make_current(&conn->drm->renderer, &conn->crtc->primary->surf); + wlr_drm_surface_make_current(&conn->crtc->primary->surf); } static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { @@ -185,7 +185,7 @@ static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&drm->renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf); uint32_t fb_id = get_fb_for_bo(bo); if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { @@ -217,7 +217,7 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_get_front(&drm->renderer, &plane->surf); + struct gbm_bo *bo = wlr_drm_surface_get_front(&plane->surf); uint32_t fb_id = get_fb_for_bo(bo); struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; @@ -283,9 +283,9 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in) if (*old != new) { if (*old) { - wlr_drm_surface_finish(&drm->renderer, &(*old)->surf); + wlr_drm_surface_finish(&(*old)->surf); } - wlr_drm_surface_finish(&drm->renderer, &new->surf); + wlr_drm_surface_finish(&new->surf); *old = new; } } @@ -430,7 +430,7 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, continue; } - if (!wlr_drm_surface_init(&drm->renderer, &crtc->primary->surf, + if (!wlr_drm_surface_init(&crtc->primary->surf, &drm->renderer, mode->width, mode->height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); @@ -488,7 +488,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, return false; } - if (!wlr_drm_surface_init(renderer, &plane->surf, w, h, GBM_FORMAT_ARGB8888, 0)) { + if (!wlr_drm_surface_init(&plane->surf, renderer, w, h, GBM_FORMAT_ARGB8888, 0)) { wlr_log(L_ERROR, "Cannot allocate cursor resources"); return false; } @@ -530,7 +530,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, return false; } - wlr_drm_surface_make_current(renderer, &plane->surf); + wlr_drm_surface_make_current(&plane->surf); wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888, stride, width, height, buf); @@ -548,7 +548,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output, glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bo_data); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - wlr_drm_surface_swap_buffers(renderer, &plane->surf); + wlr_drm_surface_swap_buffers(&plane->surf); gbm_bo_unmap(bo, bo_data); @@ -854,7 +854,7 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { case WLR_DRM_CONN_CLEANUP:; struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { - wlr_drm_surface_finish(&drm->renderer, &crtc->planes[i]->surf); + wlr_drm_surface_finish(&crtc->planes[i]->surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 8afc6dca..e1c6a4bc 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -35,13 +35,14 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { gbm_device_destroy(renderer->gbm); } -bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf, uint32_t width, uint32_t height, +bool wlr_drm_surface_init(struct wlr_drm_surface *surf, + struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, uint32_t format, uint32_t flags) { if (surf->width == width && surf->height == height) { return true; } + surf->renderer = renderer; surf->width = width; surf->height = height; @@ -67,13 +68,12 @@ error_zero: return false; } -void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { - if (!renderer || !surf || !surf->gbm) { +void wlr_drm_surface_finish(struct wlr_drm_surface *surf) { + if (!surf || !surf->renderer) { return; } - eglMakeCurrent(renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, + eglMakeCurrent(surf->renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (surf->front) { @@ -84,7 +84,7 @@ void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, } if (surf->egl) { - eglDestroySurface(renderer->egl.display, surf->egl); + eglDestroySurface(surf->renderer->egl.display, surf->egl); } if (surf->gbm) { gbm_surface_destroy(surf->gbm); @@ -93,34 +93,31 @@ void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, memset(surf, 0, sizeof(*surf)); } -void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { - eglMakeCurrent(renderer->egl.display, surf->egl, surf->egl, - renderer->egl.context); +void wlr_drm_surface_make_current(struct wlr_drm_surface *surf) { + eglMakeCurrent(surf->renderer->egl.display, surf->egl, surf->egl, + surf->renderer->egl.context); } -struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf) { if (surf->front) { gbm_surface_release_buffer(surf->gbm, surf->front); } - eglSwapBuffers(renderer->egl.display, surf->egl); + eglSwapBuffers(surf->renderer->egl.display, surf->egl); surf->front = surf->back; surf->back = gbm_surface_lock_front_buffer(surf->gbm); return surf->back; } -struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf) { +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) { if (surf->front) { return surf->front; } - wlr_drm_surface_make_current(renderer, surf); + wlr_drm_surface_make_current(surf); glViewport(0, 0, surf->width, surf->height); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - return wlr_drm_surface_swap_buffers(renderer, surf); + return wlr_drm_surface_swap_buffers(surf); } diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index bbcf4f0c..9982c25f 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -14,6 +14,8 @@ struct wlr_drm_renderer { }; struct wlr_drm_surface { + struct wlr_drm_renderer *renderer; + uint32_t width; uint32_t height; @@ -25,23 +27,15 @@ struct wlr_drm_surface { }; bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); - void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer); -bool wlr_drm_surface_init(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf, uint32_t width, uint32_t height, +bool wlr_drm_surface_init(struct wlr_drm_surface *surf, + struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, uint32_t format, uint32_t flags); -void wlr_drm_surface_finish(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); - -void wlr_drm_surface_make_current(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); - -struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); - -struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_renderer *renderer, - struct wlr_drm_surface *surf); +void wlr_drm_surface_finish(struct wlr_drm_surface *surf); +void wlr_drm_surface_make_current(struct wlr_drm_surface *surf); +struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf); +struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf); #endif From fa3d0ed9295d18405ab65f63f329d3def19509a3 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 16:47:05 +1300 Subject: [PATCH 09/14] Change wlr_session to open every GPU --- backend/backend.c | 41 +++++++++++++++++----------- backend/drm/backend.c | 4 +-- backend/session/session.c | 51 +++++++++++++++-------------------- include/wlr/backend/session.h | 5 ++-- 4 files changed, 52 insertions(+), 49 deletions(-) diff --git a/backend/backend.c b/backend/backend.c index ec309da4..359df3d1 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -91,15 +91,9 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { return NULL; } - int gpu = wlr_session_find_gpu(session); - if (gpu == -1) { - wlr_log(L_ERROR, "Failed to open DRM device"); - goto error_session; - } - backend = wlr_multi_backend_create(session); if (!backend) { - goto error_gpu; + goto error_session; } struct wlr_backend *libinput = wlr_libinput_backend_create(display, session); @@ -107,21 +101,36 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { goto error_multi; } - struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpu); - if (!drm) { - goto error_libinput; + wlr_multi_backend_add(backend, libinput); + + int gpus[8]; + size_t num_gpus = wlr_session_find_gpus(session, 8, gpus); + struct wlr_backend *primary_drm = NULL; + wlr_log(L_INFO, "Found %zu GPUs", num_gpus); + + for (size_t i = 0; i < num_gpus; ++i) { + struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpus[i]); + if (!drm) { + wlr_log(L_ERROR, "Failed to open DRM device"); + continue; + } + + if (!primary_drm) { + primary_drm = drm; + } + + wlr_multi_backend_add(backend, drm); + } + + if (!primary_drm) { + wlr_log(L_ERROR, "Failed to open any DRM device"); + goto error_multi; } - wlr_multi_backend_add(backend, libinput); - wlr_multi_backend_add(backend, drm); return backend; -error_libinput: - wlr_backend_destroy(libinput); error_multi: wlr_backend_destroy(backend); -error_gpu: - wlr_session_close_file(session, gpu); error_session: wlr_session_destroy(session); return NULL; diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 442e5d0e..2d06e5e4 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -42,8 +42,8 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) { free(drm); } -static struct wlr_egl *wlr_drm_backend_get_egl(struct wlr_backend *_backend) { - struct wlr_drm_backend *drm = (struct wlr_drm_backend *)_backend; +static struct wlr_egl *wlr_drm_backend_get_egl(struct wlr_backend *backend) { + struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend; return &drm->renderer.egl; } diff --git a/backend/session/session.c b/backend/session/session.c index cfa617f6..be79c34d 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -191,18 +191,16 @@ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) { /* Tests if 'path' is KMS compatible by trying to open it. * It leaves the open device in *fd_out it it succeeds. */ -static bool device_is_kms(struct wlr_session *restrict session, - const char *restrict path, int *restrict fd_out) { - +static int open_if_kms(struct wlr_session *restrict session, const char *restrict path) { int fd; if (!path) { - return false; + return -1; } fd = wlr_session_open_file(session, path); if (fd < 0) { - return false; + return -1; } drmModeRes *res = drmModeGetResources(fd); @@ -216,26 +214,21 @@ static bool device_is_kms(struct wlr_session *restrict session, goto out_res; } - if (*fd_out >= 0) { - wlr_session_close_file(session, *fd_out); - } - - *fd_out = fd; - drmModeFreeResources(res); - return true; + return fd; out_res: drmModeFreeResources(res); out_fd: wlr_session_close_file(session, fd); - return false; + return -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_session_find_gpu(struct wlr_session *session) { +size_t wlr_session_find_gpus(struct wlr_session *session, + size_t ret_len, int ret[static ret_len]) { struct udev_enumerate *en = udev_enumerate_new(session->udev); if (!en) { wlr_log(L_ERROR, "Failed to create udev enumeration"); @@ -247,9 +240,13 @@ int wlr_session_find_gpu(struct wlr_session *session) { udev_enumerate_scan_devices(en); struct udev_list_entry *entry; - int fd = -1; + size_t i = 0; udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(en)) { + if (i == ret_len) { + break; + } + bool is_boot_vga = false; const char *path = udev_list_entry_get_name(entry); @@ -258,15 +255,13 @@ int wlr_session_find_gpu(struct wlr_session *session) { continue; } - /* const char *seat = udev_device_get_property_value(dev, "ID_SEAT"); if (!seat) seat = "seat0"; - if (strcmp(session->seat, seat) != 0) { + if (session->seat[0] && strcmp(session->seat, seat) != 0) { udev_device_unref(dev); continue; } - */ // This is owned by 'dev', so we don't need to free it struct udev_device *pci = @@ -279,27 +274,25 @@ int wlr_session_find_gpu(struct wlr_session *session) { } } - // We already have a valid GPU - if (!is_boot_vga && fd >= 0) { - udev_device_unref(dev); - continue; - } - - path = udev_device_get_devnode(dev); - if (!device_is_kms(session, path, &fd)) { + int fd = open_if_kms(session, udev_device_get_devnode(dev)); + if (fd < 0) { udev_device_unref(dev); continue; } udev_device_unref(dev); - // We've found the primary GPU + ret[i] = fd; if (is_boot_vga) { - break; + int tmp = ret[0]; + ret[0] = ret[i]; + ret[i] = tmp; } + + ++i; } udev_enumerate_unref(en); - return fd; + return i; } diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h index 52cf13b7..94002bc5 100644 --- a/include/wlr/backend/session.h +++ b/include/wlr/backend/session.h @@ -72,12 +72,13 @@ int wlr_session_open_file(struct wlr_session *session, const char *path); void wlr_session_close_file(struct wlr_session *session, int fd); void wlr_session_signal_add(struct wlr_session *session, int fd, - struct wl_listener *listener); + struct wl_listener *listener); /* * Changes the virtual terminal. */ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt); -int wlr_session_find_gpu(struct wlr_session *session); +size_t wlr_session_find_gpus(struct wlr_session *session, + size_t ret_len, int ret[static ret_len]); #endif From 009c3747a8771bcd441dc9cf95823fe40895f1e0 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 19:22:47 +1300 Subject: [PATCH 10/14] Multi-GPU DRM --- backend/backend.c | 3 +- backend/drm/backend.c | 4 +- backend/drm/drm.c | 21 +++--- backend/drm/renderer.c | 117 +++++++++++++++++++++++++++++++++ include/backend/drm/drm.h | 2 + include/backend/drm/renderer.h | 11 ++++ include/wlr/backend/drm.h | 2 +- include/wlr/render.h | 9 ++- include/wlr/render/interface.h | 4 ++ render/gles2/texture.c | 20 ++++++ render/wlr_texture.c | 5 ++ 11 files changed, 184 insertions(+), 14 deletions(-) diff --git a/backend/backend.c b/backend/backend.c index 359df3d1..d5cd1f70 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -109,7 +109,8 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { wlr_log(L_INFO, "Found %zu GPUs", num_gpus); for (size_t i = 0; i < num_gpus; ++i) { - struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpus[i]); + struct wlr_backend *drm = wlr_drm_backend_create(display, session, + gpus[i], primary_drm); if (!drm) { wlr_log(L_ERROR, "Failed to open DRM device"); continue; diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 2d06e5e4..e3148821 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -92,8 +92,9 @@ static void drm_invalidated(struct wl_listener *listener, void *data) { } struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, - struct wlr_session *session, int gpu_fd) { + struct wlr_session *session, int gpu_fd, struct wlr_backend *parent) { assert(display && session && gpu_fd >= 0); + assert(!parent || wlr_backend_is_drm(parent)); char *name = drmGetDeviceNameFromFd2(gpu_fd); drmVersion *version = drmGetVersion(gpu_fd); @@ -116,6 +117,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, } drm->fd = gpu_fd; + drm->parent = (struct wlr_drm_backend *)parent; drm->drm_invalidated.notify = drm_invalidated; wlr_session_signal_add(session, gpu_fd, &drm->drm_invalidated); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 5c5ac8cd..3effa9ff 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -186,6 +186,10 @@ static void wlr_drm_connector_swap_buffers(struct wlr_output *output) { struct wlr_drm_plane *plane = crtc->primary; struct gbm_bo *bo = wlr_drm_surface_swap_buffers(&plane->surf); + if (drm->parent) { + bo = wlr_drm_surface_mgpu_copy(&plane->mgpu_surf, bo); + } + uint32_t fb_id = get_fb_for_bo(bo); if (drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) { @@ -217,7 +221,8 @@ void wlr_drm_connector_start_renderer(struct wlr_drm_connector *conn) { struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_plane *plane = crtc->primary; - struct gbm_bo *bo = wlr_drm_surface_get_front(&plane->surf); + struct gbm_bo *bo = wlr_drm_surface_get_front( + drm->parent ? &plane->mgpu_surf : &plane->surf); uint32_t fb_id = get_fb_for_bo(bo); struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; @@ -393,7 +398,6 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", conn->output.name, mode->width, mode->height, mode->refresh); - wlr_log(L_DEBUG, "%p %p", conn, drm); conn->possible_crtc = get_possible_crtcs(drm->fd, conn->id); if (conn->possible_crtc == 0) { goto error_conn; @@ -430,9 +434,8 @@ static bool wlr_drm_connector_set_mode(struct wlr_output *output, continue; } - if (!wlr_drm_surface_init(&crtc->primary->surf, &drm->renderer, - mode->width, mode->height, GBM_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT)) { + if (!wlr_drm_plane_surfaces_init(crtc->primary, drm, + mode->width, mode->height, GBM_FORMAT_XRGB8888)) { wlr_log(L_ERROR, "Failed to initalise renderer for plane"); goto error_conn; } @@ -782,10 +785,9 @@ static void page_flip_handler(int fd, unsigned seq, return; } - struct wlr_drm_plane *plane = conn->crtc->primary; - if (plane->surf.front) { - gbm_surface_release_buffer(plane->surf.gbm, plane->surf.front); - plane->surf.front = NULL; + wlr_drm_surface_post(&conn->crtc->primary->surf); + if (drm->parent) { + wlr_drm_surface_post(&conn->crtc->primary->mgpu_surf); } if (drm->session->active) { @@ -855,6 +857,7 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { wlr_drm_surface_finish(&crtc->planes[i]->surf); + wlr_drm_surface_finish(&crtc->planes[i]->mgpu_surf); if (crtc->planes[i] && crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index e1c6a4bc..bcadf17e 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -1,12 +1,18 @@ #include +#include +#include #include #include #include #include +#include #include #include +#include +#include +#include #include "backend/drm/drm.h" bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { @@ -22,6 +28,9 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { return false; } + struct wlr_drm_backend *drm = wl_container_of(renderer, drm, renderer); + renderer->wlr_rend = wlr_gles2_renderer_create(&drm->backend); + renderer->fd = fd; return true; } @@ -121,3 +130,111 @@ struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) { glClear(GL_COLOR_BUFFER_BIT); return wlr_drm_surface_swap_buffers(surf); } + +void wlr_drm_surface_post(struct wlr_drm_surface *surf) { + if (surf->front) { + gbm_surface_release_buffer(surf->gbm, surf->front); + surf->front = NULL; + } +} + +struct tex { + struct wlr_egl *egl; + EGLImageKHR img; + struct wlr_texture *tex; +}; + +static void free_eglimage(struct gbm_bo *bo, void *data) { + struct tex *tex = data; + + wlr_egl_destroy_image(tex->egl, tex->img); + wlr_texture_destroy(tex->tex); + free(tex); +} + +static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer, struct gbm_bo *bo) { + struct tex *tex = gbm_bo_get_user_data(bo); + if (tex) { + return tex->tex; + } + + tex = malloc(sizeof(*tex)); + if (!tex) { + wlr_log_errno(L_ERROR, "Allocation failed"); + return NULL; + } + + tex->egl = &renderer->egl; + + int dmabuf_fd = gbm_bo_get_fd(bo); + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + + EGLint attribs[] = { + EGL_WIDTH, width, + EGL_HEIGHT, height, + EGL_LINUX_DRM_FOURCC_EXT, gbm_bo_get_format(bo), + EGL_DMA_BUF_PLANE0_FD_EXT, dmabuf_fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, gbm_bo_get_offset(bo, 0), + EGL_DMA_BUF_PLANE0_PITCH_EXT, gbm_bo_get_stride_for_plane(bo, 0), + EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, + EGL_NONE, + }; + + tex->img = renderer->egl.eglCreateImageKHR(renderer->egl.display, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, NULL, attribs); + if (!tex->img) { + wlr_log(L_ERROR, "Failed to create EGL image: %s", egl_error()); + abort(); + } + + tex->tex = wlr_render_texture_create(renderer->wlr_rend); + wlr_texture_upload_eglimage(tex->tex, tex->img, width, height); + + gbm_bo_set_user_data(bo, tex, free_eglimage); + + return tex->tex; +} + +struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, struct gbm_bo *src) { + wlr_drm_surface_make_current(dest); + + struct wlr_texture *tex = get_tex_for_bo(dest->renderer, src); + + static const float matrix[16] = { + [0] = 2.0f, + [3] = -1.0f, + [5] = 2.0f, + [7] = -1.0f, + [10] = 1.0f, + [15] = 1.0f, + }; + + glViewport(0, 0, dest->width, dest->height); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + wlr_render_with_matrix(dest->renderer->wlr_rend, tex, &matrix); + + return wlr_drm_surface_swap_buffers(dest); +} + +bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm, + int32_t width, uint32_t height, uint32_t format) { + if (!drm->parent) { + return wlr_drm_surface_init(&plane->surf, &drm->renderer, width, height, + format, GBM_BO_USE_SCANOUT); + } + + if (!wlr_drm_surface_init(&plane->surf, &drm->parent->renderer, + width, height, format, GBM_BO_USE_LINEAR)) { + return false; + } + + if (!wlr_drm_surface_init(&plane->mgpu_surf, &drm->renderer, + width, height, format, GBM_BO_USE_SCANOUT)) { + wlr_drm_surface_finish(&plane->surf); + return false; + } + + return true; +} diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index a3a724bc..6106a85a 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -26,6 +26,7 @@ struct wlr_drm_plane { uint32_t possible_crtcs; struct wlr_drm_surface surf; + struct wlr_drm_surface mgpu_surf; // Only used by cursor float matrix[16]; @@ -58,6 +59,7 @@ struct wlr_drm_crtc { struct wlr_drm_backend { struct wlr_backend backend; + struct wlr_drm_backend *parent; const struct wlr_drm_interface *iface; int fd; diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 9982c25f..8fcf566d 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -7,10 +7,16 @@ #include #include +#include + +struct wlr_drm_plane; + struct wlr_drm_renderer { int fd; struct gbm_device *gbm; struct wlr_egl egl; + + struct wlr_renderer *wlr_rend; }; struct wlr_drm_surface { @@ -33,9 +39,14 @@ bool wlr_drm_surface_init(struct wlr_drm_surface *surf, struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, uint32_t format, uint32_t flags); +bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm, + int32_t width, uint32_t height, uint32_t format); + void wlr_drm_surface_finish(struct wlr_drm_surface *surf); void wlr_drm_surface_make_current(struct wlr_drm_surface *surf); struct gbm_bo *wlr_drm_surface_swap_buffers(struct wlr_drm_surface *surf); struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf); +void wlr_drm_surface_post(struct wlr_drm_surface *surf); +struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest, struct gbm_bo *src); #endif diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index fa63df0a..b3475703 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -6,7 +6,7 @@ #include struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, - struct wlr_session *session, int gpu_fd); + struct wlr_session *session, int gpu_fd, struct wlr_backend *parent); bool wlr_backend_is_drm(struct wlr_backend *backend); diff --git a/include/wlr/render.h b/include/wlr/render.h index 325f8c01..2fbfb476 100644 --- a/include/wlr/render.h +++ b/include/wlr/render.h @@ -2,6 +2,8 @@ #define WLR_RENDER_H #include +#include +#include #include #include @@ -93,8 +95,11 @@ bool wlr_texture_upload_shm(struct wlr_texture *tex, uint32_t format, * texture. The wl_resource is not used after this call. * Will fail (return false) if the given resource is no drm buffer. */ - bool wlr_texture_upload_drm(struct wlr_texture *tex, - struct wl_resource *drm_buffer); +bool wlr_texture_upload_drm(struct wlr_texture *tex, + struct wl_resource *drm_buffer); + +bool wlr_texture_upload_eglimage(struct wlr_texture *tex, + EGLImageKHR image, uint32_t width, uint32_t height); /** * Copies a rectangle of pixels from a wl_shm_buffer onto the texture. The diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index e3ba0414..cbe33822 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -2,6 +2,8 @@ #define WLR_RENDER_INTERFACE_H #include +#include +#include #include #include #include @@ -45,6 +47,8 @@ struct wlr_texture_impl { int x, int y, int width, int height, struct wl_shm_buffer *shm); bool (*upload_drm)(struct wlr_texture *texture, struct wl_resource *drm_buf); + bool (*upload_eglimage)(struct wlr_texture *texture, EGLImageKHR image, + uint32_t width, uint32_t height); void (*get_matrix)(struct wlr_texture *state, float (*matrix)[16], const float (*projection)[16], int x, int y); void (*get_buffer_size)(struct wlr_texture *texture, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 98d1a112..5e934aa4 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -205,6 +205,25 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, return true; } +static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex, + EGLImageKHR image, uint32_t width, uint32_t height) { + struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)wlr_tex; + + tex->image = image; + tex->pixel_format = &external_pixel_format; + tex->wlr_texture.valid = true; + tex->wlr_texture.width = width; + tex->wlr_texture.height = height; + + gles2_texture_ensure_texture(tex); + + GL_CALL(glActiveTexture(GL_TEXTURE0)); + GL_CALL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id)); + GL_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image)); + + return true; +} + static void gles2_texture_get_matrix(struct wlr_texture *_texture, float (*matrix)[16], const float (*projection)[16], int x, int y) { struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; @@ -270,6 +289,7 @@ static struct wlr_texture_impl wlr_texture_impl = { .upload_shm = gles2_texture_upload_shm, .update_shm = gles2_texture_update_shm, .upload_drm = gles2_texture_upload_drm, + .upload_eglimage = gles2_texture_upload_eglimage, .get_matrix = gles2_texture_get_matrix, .get_buffer_size = gles2_texture_get_buffer_size, .bind = gles2_texture_bind, diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 9faea820..4ce86bdd 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -48,6 +48,11 @@ bool wlr_texture_upload_drm(struct wlr_texture *texture, return texture->impl->upload_drm(texture, drm_buffer); } +bool wlr_texture_upload_eglimage(struct wlr_texture *texture, + EGLImageKHR image, uint32_t width, uint32_t height) { + return texture->impl->upload_eglimage(texture, image, width, height); +} + void wlr_texture_get_matrix(struct wlr_texture *texture, float (*matrix)[16], const float (*projection)[16], int x, int y) { texture->impl->get_matrix(texture, matrix, projection, x, y); From f6f9c4096544fa64b7814ac55718f1c128c15004 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Sun, 1 Oct 2017 22:44:24 +1300 Subject: [PATCH 11/14] Minor fixes --- backend/drm/backend.c | 2 +- backend/drm/drm.c | 6 +++++- backend/drm/renderer.c | 22 ++++++++++++++++------ include/backend/drm/renderer.h | 4 +++- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index e3148821..468fca6e 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -143,7 +143,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, goto error_event; } - if (!wlr_drm_renderer_init(&drm->renderer, drm->fd)) { + if (!wlr_drm_renderer_init(drm, &drm->renderer)) { wlr_log(L_ERROR, "Failed to initialize renderer"); goto error_event; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 3effa9ff..ccdc92d9 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -856,9 +856,13 @@ void wlr_drm_connector_cleanup(struct wlr_drm_connector *conn) { case WLR_DRM_CONN_CLEANUP:; struct wlr_drm_crtc *crtc = conn->crtc; for (int i = 0; i < 3; ++i) { + if (!crtc->planes[i]) { + continue; + } + wlr_drm_surface_finish(&crtc->planes[i]->surf); wlr_drm_surface_finish(&crtc->planes[i]->mgpu_surf); - if (crtc->planes[i] && crtc->planes[i]->id == 0) { + if (crtc->planes[i]->id == 0) { free(crtc->planes[i]); crtc->planes[i] = NULL; } diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index bcadf17e..c5840436 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -15,8 +15,9 @@ #include #include "backend/drm/drm.h" -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { - renderer->gbm = gbm_create_device(fd); +bool wlr_drm_renderer_init(struct wlr_drm_backend *drm, + struct wlr_drm_renderer *renderer) { + renderer->gbm = gbm_create_device(drm->fd); if (!renderer->gbm) { wlr_log(L_ERROR, "Failed to create GBM device"); return false; @@ -24,15 +25,23 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd) { if (!wlr_egl_init(&renderer->egl, EGL_PLATFORM_GBM_MESA, GBM_FORMAT_ARGB8888, renderer->gbm)) { - gbm_device_destroy(renderer->gbm); - return false; + goto error_gbm; } - struct wlr_drm_backend *drm = wl_container_of(renderer, drm, renderer); renderer->wlr_rend = wlr_gles2_renderer_create(&drm->backend); + if (!renderer->wlr_rend) { + wlr_log(L_ERROR, "Failed to create WLR renderer"); + goto error_egl; + } - renderer->fd = fd; + renderer->fd = drm->fd; return true; + +error_egl: + wlr_egl_free(&renderer->egl); +error_gbm: + gbm_device_destroy(renderer->gbm); + return false; } void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { @@ -40,6 +49,7 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) { return; } + wlr_renderer_destroy(renderer->wlr_rend); wlr_egl_free(&renderer->egl); gbm_device_destroy(renderer->gbm); } diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 8fcf566d..45127cd0 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -9,6 +9,7 @@ #include +struct wlr_drm_backend; struct wlr_drm_plane; struct wlr_drm_renderer { @@ -32,7 +33,8 @@ struct wlr_drm_surface { struct gbm_bo *back; }; -bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer, int fd); +bool wlr_drm_renderer_init(struct wlr_drm_backend *drm, + struct wlr_drm_renderer *renderer); void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer); bool wlr_drm_surface_init(struct wlr_drm_surface *surf, From f193623ca11c245e9209a8df40115dbe420bbc22 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 2 Oct 2017 21:44:33 +1300 Subject: [PATCH 12/14] Change iface prefix to suffix --- backend/drm/{iface_atomic.c => atomic.c} | 2 +- backend/drm/drm.c | 6 +++--- backend/drm/{iface_legacy.c => legacy.c} | 2 +- backend/meson.build | 4 ++-- include/backend/drm/iface.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) rename backend/drm/{iface_atomic.c => atomic.c} (99%) rename backend/drm/{iface_legacy.c => legacy.c} (97%) diff --git a/backend/drm/iface_atomic.c b/backend/drm/atomic.c similarity index 99% rename from backend/drm/iface_atomic.c rename to backend/drm/atomic.c index 1aef05d1..e7374a00 100644 --- a/backend/drm/iface_atomic.c +++ b/backend/drm/atomic.c @@ -181,7 +181,7 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, return atomic_end(drm->fd, &atom); } -const struct wlr_drm_interface iface_atomic = { +const struct wlr_drm_interface atomic_iface = { .conn_enable = atomic_conn_enable, .crtc_pageflip = atomic_crtc_pageflip, .crtc_set_cursor = atomic_crtc_set_cursor, diff --git a/backend/drm/drm.c b/backend/drm/drm.c index ccdc92d9..1a5fea9f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -32,13 +32,13 @@ bool wlr_drm_check_features(struct wlr_drm_backend *drm) { if (getenv("WLR_DRM_NO_ATOMIC")) { wlr_log(L_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); - drm->iface = &iface_legacy; + drm->iface = &legacy_iface; } else if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_ATOMIC, 1)) { wlr_log(L_DEBUG, "Atomic modesetting unsupported, using legacy DRM interface"); - drm->iface = &iface_legacy; + drm->iface = &legacy_iface; } else { wlr_log(L_DEBUG, "Using atomic DRM interface"); - drm->iface = &iface_atomic; + drm->iface = &atomic_iface; } return true; diff --git a/backend/drm/iface_legacy.c b/backend/drm/legacy.c similarity index 97% rename from backend/drm/iface_legacy.c rename to backend/drm/legacy.c index cf73bb87..d75eb2cb 100644 --- a/backend/drm/iface_legacy.c +++ b/backend/drm/legacy.c @@ -58,7 +58,7 @@ bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm, return !drmModeMoveCursor(drm->fd, crtc->id, x, y); } -const struct wlr_drm_interface iface_legacy = { +const struct wlr_drm_interface legacy_iface = { .conn_enable = legacy_conn_enable, .crtc_pageflip = legacy_crtc_pageflip, .crtc_set_cursor = legacy_crtc_set_cursor, diff --git a/backend/meson.build b/backend/meson.build index caf2c8b0..c5c73288 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -3,10 +3,10 @@ backend_files = files( 'session/direct-ipc.c', 'session/direct.c', 'session/session.c', + 'drm/atomic.c', 'drm/backend.c', 'drm/drm.c', - 'drm/iface_atomic.c', - 'drm/iface_legacy.c', + 'drm/legacy.c', 'drm/properties.c', 'drm/renderer.c', 'drm/util.c', diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index db1d7ee1..bc61eb51 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -29,7 +29,7 @@ struct wlr_drm_interface { struct wlr_drm_crtc *crtc, int x, int y); }; -extern const struct wlr_drm_interface iface_atomic; -extern const struct wlr_drm_interface iface_legacy; +extern const struct wlr_drm_interface atomic_iface; +extern const struct wlr_drm_interface legacy_iface; #endif From 6cfe47d1d891d31ef3e13deebbf899af27cadb82 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 2 Oct 2017 21:57:14 +1300 Subject: [PATCH 13/14] Add explicitly picking GPUs with environment var --- backend/session/session.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/backend/session/session.c b/backend/session/session.c index be79c34d..72eb6149 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -1,7 +1,8 @@ +#define _POSIX_C_SOURCE 200809L #include #include -#include #include +#include #include #include #include @@ -224,11 +225,44 @@ out_fd: return -1; } +static size_t explicit_find_gpus(struct wlr_session *session, + size_t ret_len, int ret[static ret_len], const char *str) { + char *gpus = strdup(str); + if (!gpus) { + wlr_log_errno(L_ERROR, "Allocation failed"); + return 0; + } + + size_t i = 0; + char *save; + char *ptr = strtok_r(gpus, ":", &save); + do { + if (i >= ret_len) { + break; + } + + ret[i] = open_if_kms(session, ptr); + if (ret[i] <= 0) { + wlr_log(L_ERROR, "Unable to open %s as DRM device", ptr); + } else { + ++i; + } + } while ((ptr = strtok_r(NULL, ":", &save))); + + free(ptr); + return i; +} + /* 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. */ size_t wlr_session_find_gpus(struct wlr_session *session, size_t ret_len, int ret[static ret_len]) { + const char *explicit = getenv("WLR_DRM_DEVICES"); + if (explicit) { + return explicit_find_gpus(session, ret_len, ret, explicit); + } + struct udev_enumerate *en = udev_enumerate_new(session->udev); if (!en) { wlr_log(L_ERROR, "Failed to create udev enumeration"); From 9ec9edc40d4694dedfd7f00eb9106ce5ed133239 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 2 Oct 2017 22:01:09 +1300 Subject: [PATCH 14/14] Check for fd failure properly --- backend/session/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/session/session.c b/backend/session/session.c index 72eb6149..b73952fd 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -242,7 +242,7 @@ static size_t explicit_find_gpus(struct wlr_session *session, } ret[i] = open_if_kms(session, ptr); - if (ret[i] <= 0) { + if (ret[i] < 0) { wlr_log(L_ERROR, "Unable to open %s as DRM device", ptr); } else { ++i;