From dc7855f674fc02637b3f4328ed5a16a3fdeee551 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 5 May 2024 13:36:33 -0400 Subject: [PATCH] backend/drm: Drop parent drm device Compositors should instead blit to secondary drm devices themselves. --- backend/backend.c | 2 +- backend/drm/atomic.c | 6 +- backend/drm/backend.c | 64 +---------------- backend/drm/drm.c | 122 ++------------------------------- backend/drm/monitor.c | 3 +- backend/drm/renderer.c | 85 ----------------------- include/backend/drm/drm.h | 10 --- include/backend/drm/renderer.h | 8 --- include/wlr/backend/drm.h | 11 +-- types/wlr_linux_dmabuf_v1.c | 12 +--- 10 files changed, 13 insertions(+), 310 deletions(-) diff --git a/backend/backend.c b/backend/backend.c index e4e8c8d8e..9d1b9b754 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -258,7 +258,7 @@ static struct wlr_backend *attempt_drm_backend(struct wlr_backend *backend, stru struct wlr_backend *primary_drm = NULL; for (size_t i = 0; i < (size_t)num_gpus; ++i) { - struct wlr_backend *drm = wlr_drm_backend_create(session, gpus[i], primary_drm); + struct wlr_backend *drm = wlr_drm_backend_create(session, gpus[i]); if (!drm) { wlr_log(WLR_ERROR, "Failed to create DRM backend"); continue; diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 16b08f7a1..d3a91efbe 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -275,9 +275,9 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo } int in_fence_fd = -1; - if (state->wait_timeline != NULL) { - in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->wait_timeline, - state->wait_point); + if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) { + in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->base->wait_timeline, + state->base->wait_point); if (in_fence_fd < 0) { return false; } diff --git a/backend/drm/backend.c b/backend/drm/backend.c index d166f4672..b66907892 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -49,14 +49,9 @@ static void backend_destroy(struct wlr_backend *backend) { wl_list_remove(&drm->session_destroy.link); wl_list_remove(&drm->session_active.link); - wl_list_remove(&drm->parent_destroy.link); wl_list_remove(&drm->dev_change.link); wl_list_remove(&drm->dev_remove.link); - if (drm->parent) { - finish_drm_renderer(&drm->mgpu_renderer); - } - finish_drm_resources(drm); struct wlr_drm_fb *fb, *fb_tmp; @@ -104,11 +99,6 @@ bool wlr_backend_is_drm(struct wlr_backend *b) { return b->impl == &backend_impl; } -struct wlr_backend *wlr_drm_backend_get_parent(struct wlr_backend *backend) { - struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); - return drm->parent ? &drm->parent->backend : NULL; -} - static void handle_session_active(struct wl_listener *listener, void *data) { struct wlr_drm_backend *drm = wl_container_of(listener, drm, session_active); @@ -159,16 +149,8 @@ static void handle_session_destroy(struct wl_listener *listener, void *data) { backend_destroy(&drm->backend); } -static void handle_parent_destroy(struct wl_listener *listener, void *data) { - struct wlr_drm_backend *drm = - wl_container_of(listener, drm, parent_destroy); - backend_destroy(&drm->backend); -} - -struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, - struct wlr_device *dev, struct wlr_backend *parent) { +struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, struct wlr_device *dev) { assert(session && dev); - assert(!parent || wlr_backend_is_drm(parent)); char *name = drmGetDeviceNameFromFd2(dev->fd); if (name == NULL) { @@ -201,15 +183,6 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, drm->fd = dev->fd; drm->name = name; - if (parent != NULL) { - drm->parent = get_drm_backend_from_backend(parent); - - drm->parent_destroy.notify = handle_parent_destroy; - wl_signal_add(&parent->events.destroy, &drm->parent_destroy); - } else { - wl_list_init(&drm->parent_destroy.link); - } - drm->dev_change.notify = handle_dev_change; wl_signal_add(&dev->events.change, &drm->dev_change); @@ -234,52 +207,17 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, goto error_event; } - if (drm->parent) { - if (!init_drm_renderer(drm, &drm->mgpu_renderer)) { - wlr_log(WLR_ERROR, "Failed to initialize renderer"); - goto error_resources; - } - - // We'll perform a multi-GPU copy for all submitted buffers, we need - // to be able to texture from them - struct wlr_renderer *renderer = drm->mgpu_renderer.wlr_rend; - const struct wlr_drm_format_set *texture_formats = - wlr_renderer_get_texture_formats(renderer, WLR_BUFFER_CAP_DMABUF); - if (texture_formats == NULL) { - wlr_log(WLR_ERROR, "Failed to query renderer texture formats"); - goto error_mgpu_renderer; - } - - // Forbid implicit modifiers, because their meaning changes from one - // GPU to another. - for (size_t i = 0; i < texture_formats->len; i++) { - const struct wlr_drm_format *fmt = &texture_formats->formats[i]; - for (size_t j = 0; j < fmt->len; j++) { - uint64_t mod = fmt->modifiers[j]; - if (mod == DRM_FORMAT_MOD_INVALID) { - continue; - } - wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format, mod); - } - } - } - drm->session_destroy.notify = handle_session_destroy; wl_signal_add(&session->events.destroy, &drm->session_destroy); return &drm->backend; -error_mgpu_renderer: - finish_drm_renderer(&drm->mgpu_renderer); -error_resources: - finish_drm_resources(drm); error_event: wl_list_remove(&drm->session_active.link); wl_event_source_remove(drm->drm_event); error_fd: wl_list_remove(&drm->dev_remove.link); wl_list_remove(&drm->dev_change.link); - wl_list_remove(&drm->parent_destroy.link); wlr_session_close_file(drm->session, dev); free(drm->name); free(drm); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index a20442d40..4d6178248 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -65,15 +65,6 @@ bool check_drm_features(struct wlr_drm_backend *drm) { return false; } - if (drm->parent) { - if (drmGetCap(drm->parent->fd, DRM_CAP_PRIME, &cap) || - !(cap & DRM_PRIME_CAP_EXPORT)) { - wlr_log(WLR_ERROR, - "PRIME export not supported on primary GPU"); - return false; - } - } - if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) { wlr_log(WLR_ERROR, "DRM universal planes unsupported"); return false; @@ -369,8 +360,6 @@ static void drm_plane_finish_surface(struct wlr_drm_plane *plane) { drm_fb_clear(&plane->queued_fb); drm_fb_clear(&plane->current_fb); - - finish_drm_surface(&plane->mgpu_surf); } void finish_drm_resources(struct wlr_drm_backend *drm) { @@ -709,52 +698,8 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn struct wlr_drm_plane *plane = crtc->primary; struct wlr_buffer *source_buf = state->base->buffer; - struct wlr_drm_syncobj_timeline *wait_timeline = NULL; - uint64_t wait_point = 0; - if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) { - wait_timeline = state->base->wait_timeline; - wait_point = state->base->wait_point; - } - assert(state->wait_timeline == NULL); - - struct wlr_buffer *local_buf; - if (drm->parent) { - struct wlr_drm_format format = {0}; - if (!drm_plane_pick_render_format(plane, &format, &drm->mgpu_renderer)) { - wlr_log(WLR_ERROR, "Failed to pick primary plane format"); - return false; - } - - // TODO: fallback to modifier-less buffer allocation - bool ok = init_drm_surface(&plane->mgpu_surf, &drm->mgpu_renderer, - source_buf->width, source_buf->height, &format); - wlr_drm_format_finish(&format); - if (!ok) { - return false; - } - - local_buf = drm_surface_blit(&plane->mgpu_surf, source_buf, - wait_timeline, wait_point); - if (local_buf == NULL) { - return false; - } - - if (plane->mgpu_surf.timeline != NULL) { - state->wait_timeline = wlr_drm_syncobj_timeline_ref(plane->mgpu_surf.timeline); - state->wait_point = plane->mgpu_surf.point; - } - } else { - local_buf = wlr_buffer_lock(source_buf); - - if (wait_timeline != NULL) { - state->wait_timeline = wlr_drm_syncobj_timeline_ref(wait_timeline); - state->wait_point = wait_point; - } - } - - bool ok = drm_fb_import(&state->primary_fb, drm, local_buf, + bool ok = drm_fb_import(&state->primary_fb, drm, source_buf, &plane->formats); - wlr_buffer_unlock(local_buf); if (!ok) { wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to import buffer for scan-out"); @@ -769,7 +714,7 @@ static bool drm_connector_set_pending_layer_fbs(struct wlr_drm_connector *conn, struct wlr_drm_backend *drm = conn->backend; struct wlr_drm_crtc *crtc = conn->crtc; - if (!crtc || drm->parent) { + if (!crtc) { return false; } @@ -828,12 +773,6 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo return false; } - if (test_only && conn->backend->parent) { - // If we're running as a secondary GPU, we can't perform an atomic - // commit without blitting a buffer. - return true; - } - if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (!drm_connector_state_update_primary_fb(conn, conn_state)) { return false; @@ -898,13 +837,6 @@ static bool drm_connector_commit_state(struct wlr_drm_connector *conn, goto out; } - if (test_only && conn->backend->parent) { - // If we're running as a secondary GPU, we can't perform an atomic - // commit without blitting a buffer. - ok = true; - goto out; - } - if (!pending.active && conn->crtc == NULL) { // Disabling an already-disabled connector ok = true; @@ -1094,28 +1026,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output, return false; } - struct wlr_buffer *local_buf; - if (drm->parent) { - struct wlr_drm_format format = {0}; - if (!drm_plane_pick_render_format(plane, &format, &drm->mgpu_renderer)) { - wlr_log(WLR_ERROR, "Failed to pick cursor plane format"); - return false; - } - - bool ok = init_drm_surface(&plane->mgpu_surf, &drm->mgpu_renderer, - buffer->width, buffer->height, &format); - wlr_drm_format_finish(&format); - if (!ok) { - return false; - } - - local_buf = drm_surface_blit(&plane->mgpu_surf, buffer, NULL, 0); - if (local_buf == NULL) { - return false; - } - } else { - local_buf = wlr_buffer_lock(buffer); - } + struct wlr_buffer *local_buf = wlr_buffer_lock(buffer); bool ok = drm_fb_import(&conn->cursor_pending_fb, drm, local_buf, &plane->formats); @@ -1209,9 +1120,6 @@ static const struct wlr_drm_format_set *drm_connector_get_cursor_formats( if (!plane) { return NULL; } - if (conn->backend->parent) { - return &conn->backend->mgpu_formats; - } return &plane->formats; } @@ -1238,9 +1146,6 @@ static const struct wlr_drm_format_set *drm_connector_get_primary_formats( if (!drm_connector_alloc_crtc(conn)) { return NULL; } - if (conn->backend->parent) { - return &conn->backend->mgpu_formats; - } return &conn->crtc->primary->formats; } @@ -1647,9 +1552,6 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn, } output->timeline = drm->iface != &legacy_iface; - if (drm->parent) { - output->timeline = output->timeline && drm->mgpu_renderer.wlr_rend->features.timeline; - } memset(wlr_conn->max_bpc_bounds, 0, sizeof(wlr_conn->max_bpc_bounds)); if (wlr_conn->props.max_bpc != 0) { @@ -2000,13 +1902,6 @@ bool commit_drm_device(struct wlr_drm_backend *drm, modeset |= output_state->base.allow_reconfiguration; } - if (test_only && drm->parent) { - // If we're running as a secondary GPU, we can't perform an atomic - // commit without blitting a buffer. - ok = true; - goto out; - } - uint32_t flags = 0; if (!test_only) { flags |= DRM_MODE_PAGE_FLIP_EVENT; @@ -2039,7 +1934,8 @@ static void handle_page_flip(int fd, unsigned seq, conn->pending_page_flip = NULL; } - uint32_t present_flags = WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION; + uint32_t present_flags = WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION | + WLR_OUTPUT_PRESENT_ZERO_COPY; if (!page_flip->async) { present_flags |= WLR_OUTPUT_PRESENT_VSYNC; } @@ -2074,14 +1970,6 @@ static void handle_page_flip(int fd, unsigned seq, drm_fb_move(&layer->current_fb, &layer->queued_fb); } - /* Don't report ZERO_COPY in multi-gpu situations, because we had to copy - * data between the GPUs, even if we were using the direct scanout - * interface. - */ - if (!drm->parent) { - present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY; - } - struct wlr_output_event_present present_event = { /* The DRM backend guarantees that the presentation event will be for * the last submitted frame. */ diff --git a/backend/drm/monitor.c b/backend/drm/monitor.c index efd853747..c01f9ad57 100644 --- a/backend/drm/monitor.c +++ b/backend/drm/monitor.c @@ -25,8 +25,7 @@ static void handle_add_drm_card(struct wl_listener *listener, void *data) { } wlr_log(WLR_DEBUG, "Creating DRM backend for %s after hotplug", event->path); - struct wlr_backend *child_drm = wlr_drm_backend_create(backend_monitor->session, - dev, backend_monitor->primary_drm); + struct wlr_backend *child_drm = wlr_drm_backend_create(backend_monitor->session, dev); if (!child_drm) { wlr_log(WLR_ERROR, "Failed to create DRM backend after hotplug"); return; diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 60acc57b9..1b3399889 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -13,35 +13,6 @@ #include "render/pixel_format.h" #include "render/wlr_renderer.h" -bool init_drm_renderer(struct wlr_drm_backend *drm, - struct wlr_drm_renderer *renderer) { - renderer->wlr_rend = renderer_autocreate_with_drm_fd(drm->fd); - if (!renderer->wlr_rend) { - wlr_log(WLR_ERROR, "Failed to create renderer"); - return false; - } - - uint32_t backend_caps = backend_get_buffer_caps(&drm->backend); - renderer->allocator = allocator_autocreate_with_drm_fd(backend_caps, - renderer->wlr_rend, drm->fd); - if (renderer->allocator == NULL) { - wlr_log(WLR_ERROR, "Failed to create allocator"); - wlr_renderer_destroy(renderer->wlr_rend); - return false; - } - - return true; -} - -void finish_drm_renderer(struct wlr_drm_renderer *renderer) { - if (!renderer) { - return; - } - - wlr_allocator_destroy(renderer->allocator); - wlr_renderer_destroy(renderer->wlr_rend); -} - void finish_drm_surface(struct wlr_drm_surface *surf) { if (!surf || !surf->renderer) { return; @@ -85,62 +56,6 @@ bool init_drm_surface(struct wlr_drm_surface *surf, return true; } -struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, - struct wlr_buffer *buffer, - struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point) { - struct wlr_renderer *renderer = surf->renderer->wlr_rend; - - if (surf->swapchain->width != buffer->width || - surf->swapchain->height != buffer->height) { - wlr_log(WLR_ERROR, "Surface size doesn't match buffer size"); - return NULL; - } - - struct wlr_texture *tex = wlr_texture_from_buffer(renderer, buffer); - if (tex == NULL) { - wlr_log(WLR_ERROR, "Failed to import source buffer into multi-GPU renderer"); - return NULL; - } - - struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain); - if (!dst) { - wlr_log(WLR_ERROR, "Failed to acquire multi-GPU swapchain buffer"); - goto error_tex; - } - - surf->point++; - const struct wlr_buffer_pass_options pass_options = { - .signal_timeline = surf->timeline, - .signal_point = surf->point, - }; - struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, &pass_options); - if (pass == NULL) { - wlr_log(WLR_ERROR, "Failed to begin render pass with multi-GPU destination buffer"); - goto error_dst; - } - - wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){ - .texture = tex, - .blend_mode = WLR_RENDER_BLEND_MODE_NONE, - .wait_timeline = wait_timeline, - .wait_point = wait_point, - }); - if (!wlr_render_pass_submit(pass)) { - wlr_log(WLR_ERROR, "Failed to submit multi-GPU render pass"); - goto error_dst; - } - - wlr_texture_destroy(tex); - - return dst; - -error_dst: - wlr_buffer_unlock(dst); -error_tex: - wlr_texture_destroy(tex); - return NULL; -} - bool drm_plane_pick_render_format(struct wlr_drm_plane *plane, struct wlr_drm_format *fmt, struct wlr_drm_renderer *renderer) { const struct wlr_drm_format_set *render_formats = diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 5b239a18e..d5e5d292c 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -19,9 +19,6 @@ struct wlr_drm_plane { uint32_t type; uint32_t id; - /* Only initialized on multi-GPU setups */ - struct wlr_drm_surface mgpu_surf; - /* Buffer submitted to the kernel, will be presented on next vblank */ struct wlr_drm_fb *queued_fb; /* Buffer currently displayed on screen */ @@ -80,7 +77,6 @@ struct wlr_drm_crtc { struct wlr_drm_backend { struct wlr_backend backend; - struct wlr_drm_backend *parent; const struct wlr_drm_interface *iface; bool addfb2_modifiers; @@ -99,7 +95,6 @@ struct wlr_drm_backend { struct wl_listener session_destroy; struct wl_listener session_active; - struct wl_listener parent_destroy; struct wl_listener dev_change; struct wl_listener dev_remove; @@ -108,15 +103,10 @@ struct wlr_drm_backend { struct wl_list page_flips; // wlr_drm_page_flip.link - /* Only initialized on multi-GPU setups */ - struct wlr_drm_renderer mgpu_renderer; - struct wlr_session *session; uint64_t cursor_width, cursor_height; - struct wlr_drm_format_set mgpu_formats; - bool supports_tearing_page_flips; }; diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 2cf98fdb9..9831a86ff 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -25,19 +25,11 @@ struct wlr_drm_surface { uint64_t point; }; -bool init_drm_renderer(struct wlr_drm_backend *drm, - struct wlr_drm_renderer *renderer); -void finish_drm_renderer(struct wlr_drm_renderer *renderer); - bool init_drm_surface(struct wlr_drm_surface *surf, struct wlr_drm_renderer *renderer, int width, int height, const struct wlr_drm_format *drm_format); void finish_drm_surface(struct wlr_drm_surface *surf); -struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, - struct wlr_buffer *buffer, - struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point); - bool drm_plane_pick_render_format(struct wlr_drm_plane *plane, struct wlr_drm_format *fmt, struct wlr_drm_renderer *renderer); diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 3ca6390ab..1f2651c68 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -32,21 +32,12 @@ struct wlr_drm_lease { /** * Creates a DRM backend using the specified GPU file descriptor (typically from * a device node in /dev/dri). - * - * To slave this to another DRM backend, pass it as the parent (which _must_ be - * a DRM backend, other kinds of backends raise SIGABRT). */ -struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, - struct wlr_device *dev, struct wlr_backend *parent); +struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, struct wlr_device *dev); bool wlr_backend_is_drm(struct wlr_backend *backend); bool wlr_output_is_drm(struct wlr_output *output); -/** - * Get the parent DRM backend, if any. - */ -struct wlr_backend *wlr_drm_backend_get_parent(struct wlr_backend *backend); - /** * Get the KMS connector object ID. */ diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index bfd97637a..4a2c88bad 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -1070,15 +1070,6 @@ static bool devid_from_fd(int fd, dev_t *devid) { return true; } -static bool is_secondary_drm_backend(struct wlr_backend *backend) { -#if WLR_HAS_DRM_BACKEND - return wlr_backend_is_drm(backend) && - wlr_drm_backend_get_parent(backend) != NULL; -#else - return false; -#endif -} - bool wlr_linux_dmabuf_feedback_v1_init_with_options(struct wlr_linux_dmabuf_feedback_v1 *feedback, const struct wlr_linux_dmabuf_feedback_v1_init_options *options) { assert(options->main_renderer != NULL); @@ -1121,8 +1112,7 @@ bool wlr_linux_dmabuf_feedback_v1_init_with_options(struct wlr_linux_dmabuf_feed wlr_log(WLR_ERROR, "Failed to intersect renderer and scanout formats"); goto error; } - } else if (options->scanout_primary_output != NULL && - !is_secondary_drm_backend(options->scanout_primary_output->backend)) { + } else if (options->scanout_primary_output != NULL) { int backend_drm_fd = wlr_backend_get_drm_fd(options->scanout_primary_output->backend); if (backend_drm_fd < 0) { wlr_log(WLR_ERROR, "Failed to get backend DRM FD");