From f5900c1f00f86078f576f5367f6cd707fdeec8c3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 8 Jun 2021 11:05:50 +0200 Subject: [PATCH] backend/drm: remove primary swapchain We can't nuke it completely, we still need it for multi-GPU. --- backend/drm/drm.c | 146 ++++++++++++--------------------- backend/drm/renderer.c | 103 ----------------------- include/backend/drm/drm.h | 4 +- include/backend/drm/renderer.h | 6 -- 4 files changed, 53 insertions(+), 206 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index e6e45455..54b225a0 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -329,21 +329,6 @@ static struct wlr_drm_connector *get_drm_connector_from_output( return (struct wlr_drm_connector *)wlr_output; } -static bool drm_connector_attach_render(struct wlr_output *output, - int *buffer_age) { - struct wlr_drm_connector *conn = get_drm_connector_from_output(output); - return drm_surface_make_current(&conn->crtc->primary->surf, buffer_age); -} - -static void drm_plane_set_committed(struct wlr_drm_plane *plane) { - drm_fb_move(&plane->queued_fb, &plane->pending_fb); - - if (plane->queued_fb && plane->surf.swapchain) { - wlr_swapchain_set_buffer_submitted(plane->surf.swapchain, - plane->queued_fb->wlr_buf); - } -} - static bool drm_crtc_commit(struct wlr_drm_connector *conn, const struct wlr_output_state *state, uint32_t flags, bool test_only) { // Disallow atomic-only flags @@ -353,9 +338,9 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc = conn->crtc; bool ok = drm->iface->crtc_commit(conn, state, flags, test_only); if (ok && !test_only) { - drm_plane_set_committed(crtc->primary); + drm_fb_move(&crtc->primary->queued_fb, &crtc->primary->pending_fb); if (crtc->cursor != NULL) { - drm_plane_set_committed(crtc->cursor); + drm_fb_move(&crtc->cursor->queued_fb, &crtc->cursor->pending_fb); } } else { drm_fb_clear(&crtc->primary->pending_fb); @@ -411,21 +396,37 @@ static bool drm_connector_set_pending_fb(struct wlr_drm_connector *conn, struct wlr_drm_plane *plane = crtc->primary; assert(state->committed & WLR_OUTPUT_STATE_BUFFER); - switch (state->buffer_type) { - case WLR_OUTPUT_STATE_BUFFER_RENDER: - if (!drm_plane_lock_surface(plane, drm)) { - wlr_drm_conn_log(conn, WLR_ERROR, "drm_plane_lock_surface failed"); + assert(state->buffer_type == WLR_OUTPUT_STATE_BUFFER_SCANOUT); + + struct wlr_buffer *local_buf; + if (drm->parent) { + struct wlr_drm_format *format = + drm_plane_pick_render_format(plane, &drm->renderer); + if (format == NULL) { + wlr_log(WLR_ERROR, "Failed to pick primary plane format"); return false; } - break; - case WLR_OUTPUT_STATE_BUFFER_SCANOUT:; - if (!drm_fb_import(&plane->pending_fb, drm, state->buffer, - &crtc->primary->formats)) { - wlr_drm_conn_log(conn, WLR_DEBUG, - "Failed to import buffer for scan-out"); + + // TODO: fallback to modifier-less buffer allocation + bool ok = init_drm_surface(&plane->mgpu_surf, &drm->renderer, + state->buffer->width, state->buffer->height, format); + free(format); + if (!ok) { return false; } - break; + + local_buf = drm_surface_blit(&plane->mgpu_surf, state->buffer); + } else { + local_buf = wlr_buffer_lock(state->buffer); + } + + bool ok = drm_fb_import(&plane->pending_fb, drm, local_buf, + &crtc->primary->formats); + wlr_buffer_unlock(local_buf); + if (!ok) { + wlr_drm_conn_log(conn, WLR_DEBUG, + "Failed to import buffer for scan-out"); + return false; } return true; @@ -572,11 +573,6 @@ static bool drm_connector_commit(struct wlr_output *output) { return drm_connector_commit_state(conn, &output->pending); } -static void drm_connector_rollback_render(struct wlr_output *output) { - struct wlr_drm_connector *conn = get_drm_connector_from_output(output); - return drm_surface_unset_current(&conn->crtc->primary->surf); -} - size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc) { if (crtc->props.gamma_lut_size == 0 || drm->iface == &legacy_iface) { @@ -615,34 +611,6 @@ struct wlr_drm_fb *plane_get_next_fb(struct wlr_drm_plane *plane) { return plane->current_fb; } -static bool drm_connector_test_renderer(struct wlr_drm_connector *conn, - const struct wlr_output_state *state) { - struct wlr_drm_backend *drm = conn->backend; - - if (drm->iface == &legacy_iface) { - return true; - } - - struct wlr_drm_plane *plane = conn->crtc->primary; - - struct wlr_drm_fb *prev_fb = NULL; - drm_fb_move(&prev_fb, &plane->pending_fb); - - bool ok = false; - if (!drm_surface_render_black_frame(&plane->surf)) { - goto out; - } - if (!drm_plane_lock_surface(plane, drm)) { - goto out; - } - - ok = drm_crtc_commit(conn, state, 0, true); - -out: - drm_fb_move(&plane->pending_fb, &prev_fb); - return ok; -} - static bool drm_connector_init_renderer(struct wlr_drm_connector *conn, const struct wlr_output_state *state) { struct wlr_drm_backend *drm = conn->backend; @@ -654,37 +622,33 @@ static bool drm_connector_init_renderer(struct wlr_drm_connector *conn, assert(conn->crtc != NULL); - wlr_drm_conn_log(conn, WLR_DEBUG, "Initializing renderer"); + if (drm->parent) { + wlr_drm_conn_log(conn, WLR_DEBUG, "Initializing multi-GPU renderer"); - drmModeModeInfo mode = {0}; - drm_connector_state_mode(conn, state, &mode); + drmModeModeInfo mode = {0}; + drm_connector_state_mode(conn, state, &mode); - struct wlr_drm_plane *plane = conn->crtc->primary; - int width = mode.hdisplay; - int height = mode.vdisplay; - - if (drm->addfb2_modifiers) { - // Modifiers are supported, try to use them - if (drm_plane_init_surface(plane, drm, width, height, true) && - drm_connector_test_renderer(conn, state)) { - return true; - } + struct wlr_drm_plane *plane = conn->crtc->primary; + int width = mode.hdisplay; + int height = mode.vdisplay; - // If page-flipping with modifiers enabled doesn't work, retry without - // modifiers - wlr_drm_conn_log(conn, WLR_INFO, - "Page-flip failed with primary FB modifiers enabled, " - "retrying without modifiers"); - } + struct wlr_drm_format *format = + drm_plane_pick_render_format(plane, &drm->renderer); + if (format == NULL) { + wlr_log(WLR_ERROR, "Failed to pick primary plane format"); + return false; + } - if (drm_plane_init_surface(plane, drm, width, height, false) && - drm_connector_test_renderer(conn, state)) { - return true; + // TODO: fallback to modifier-less buffer allocation + bool ok = init_drm_surface(&plane->mgpu_surf, &drm->renderer, + width, height, format); + free(format); + if (!ok) { + return false; + } } - wlr_drm_conn_log(conn, WLR_ERROR, "Failed to initialize renderer: " - "initial page-flip failed"); - return false; + return true; } static void realloc_crtcs(struct wlr_drm_backend *drm); @@ -778,12 +742,8 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn, // drm_crtc_page_flip expects a FB to be available struct wlr_drm_plane *plane = conn->crtc->primary; if (!plane_get_next_fb(plane)) { - if (!drm_surface_render_black_frame(&plane->surf)) { - return false; - } - if (!drm_plane_lock_surface(plane, drm)) { - return false; - } + wlr_drm_conn_log(conn, WLR_ERROR, "Missing FB in modeset"); + return false; } if (!drm_crtc_page_flip(conn, state)) { @@ -1023,10 +983,8 @@ static const struct wlr_output_impl output_impl = { .set_cursor = drm_connector_set_cursor, .move_cursor = drm_connector_move_cursor, .destroy = drm_connector_destroy_output, - .attach_render = drm_connector_attach_render, .test = drm_connector_test, .commit = drm_connector_commit, - .rollback_render = drm_connector_rollback_render, .get_gamma_size = drm_connector_get_gamma_size, .get_cursor_formats = drm_connector_get_cursor_formats, .get_cursor_size = drm_connector_get_cursor_size, diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 5c38f8fb..2d3adfd4 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -176,22 +176,9 @@ 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->surf); finish_drm_surface(&plane->mgpu_surf); } -static struct wlr_drm_format *create_linear_format(uint32_t format) { - struct wlr_drm_format *fmt = wlr_drm_format_create(format); - if (fmt == NULL) { - return NULL; - } - if (!wlr_drm_format_add(&fmt, DRM_FORMAT_MOD_LINEAR)) { - free(fmt); - return NULL; - } - return fmt; -} - struct wlr_drm_format *drm_plane_pick_render_format( struct wlr_drm_plane *plane, struct wlr_drm_renderer *renderer) { const struct wlr_drm_format_set *render_formats = @@ -238,53 +225,6 @@ struct wlr_drm_format *drm_plane_pick_render_format( return format; } -bool drm_plane_init_surface(struct wlr_drm_plane *plane, - struct wlr_drm_backend *drm, int32_t width, uint32_t height, - bool with_modifiers) { - struct wlr_drm_format *format = - drm_plane_pick_render_format(plane, &drm->renderer); - if (format == NULL) { - wlr_log(WLR_ERROR, "Failed to pick render format for plane %"PRIu32, - plane->id); - return false; - } - - if (!with_modifiers) { - struct wlr_drm_format *format_implicit_modifier = - wlr_drm_format_create(format->format); - free(format); - format = format_implicit_modifier; - } - - drm_plane_finish_surface(plane); - - bool ok = true; - if (!drm->parent) { - ok = init_drm_surface(&plane->surf, &drm->renderer, - width, height, format); - } else { - struct wlr_drm_format *format_linear = create_linear_format(format->format); - if (format_linear == NULL) { - free(format); - return false; - } - - ok = init_drm_surface(&plane->surf, &drm->parent->renderer, - width, height, format_linear); - free(format_linear); - - if (ok && !init_drm_surface(&plane->mgpu_surf, &drm->renderer, - width, height, format)) { - finish_drm_surface(&plane->surf); - ok = false; - } - } - - free(format); - - return ok; -} - void drm_fb_clear(struct wlr_drm_fb **fb_ptr) { if (*fb_ptr == NULL) { return; @@ -296,36 +236,6 @@ void drm_fb_clear(struct wlr_drm_fb **fb_ptr) { *fb_ptr = NULL; } -bool drm_plane_lock_surface(struct wlr_drm_plane *plane, - struct wlr_drm_backend *drm) { - assert(plane->surf.back_buffer != NULL); - struct wlr_buffer *buf = wlr_buffer_lock(plane->surf.back_buffer); - - // Unset the current EGL context ASAP, because other operations may require - // making another context current. - drm_surface_unset_current(&plane->surf); - - struct wlr_buffer *local_buf; - if (drm->parent) { - // Perform a copy across GPUs - local_buf = drm_surface_blit(&plane->mgpu_surf, buf); - if (!local_buf) { - wlr_log(WLR_ERROR, "Failed to blit buffer across GPUs"); - return false; - } - } else { - local_buf = wlr_buffer_lock(buf); - } - wlr_buffer_unlock(buf); - - bool ok = drm_fb_import(&plane->pending_fb, drm, local_buf, NULL); - if (!ok) { - wlr_log(WLR_ERROR, "Failed to import buffer"); - } - wlr_buffer_unlock(local_buf); - return ok; -} - static struct gbm_bo *get_bo_for_dmabuf(struct gbm_device *gbm, struct wlr_dmabuf_attributes *attribs) { if (attribs->modifier != DRM_FORMAT_MOD_INVALID || @@ -478,16 +388,3 @@ void drm_fb_move(struct wlr_drm_fb **new, struct wlr_drm_fb **old) { *new = *old; *old = NULL; } - -bool drm_surface_render_black_frame(struct wlr_drm_surface *surf) { - if (!drm_surface_make_current(surf, NULL)) { - return false; - } - - struct wlr_renderer *renderer = surf->renderer->wlr_rend; - wlr_renderer_begin(renderer, surf->width, surf->height); - wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 1.0 }); - wlr_renderer_end(renderer); - - return true; -} diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 8c0b0777..881d4718 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -20,9 +20,7 @@ struct wlr_drm_plane { uint32_t type; uint32_t id; - /* Local if this isn't a multi-GPU setup, on the parent otherwise. */ - struct wlr_drm_surface surf; - /* Local, only initialized on multi-GPU setups. */ + /* Only initialized on multi-GPU setups */ struct wlr_drm_surface mgpu_surf; /* Buffer to be submitted to the kernel on the next page-flip */ diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 468dd41e..17025dfc 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -58,15 +58,9 @@ void drm_fb_move(struct wlr_drm_fb **new, struct wlr_drm_fb **old); struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, struct wlr_buffer *buffer); -bool drm_surface_render_black_frame(struct wlr_drm_surface *surf); struct wlr_drm_format *drm_plane_pick_render_format( struct wlr_drm_plane *plane, struct wlr_drm_renderer *renderer); -bool drm_plane_init_surface(struct wlr_drm_plane *plane, - struct wlr_drm_backend *drm, int32_t width, uint32_t height, - bool with_modifiers); void drm_plane_finish_surface(struct wlr_drm_plane *plane); -bool drm_plane_lock_surface(struct wlr_drm_plane *plane, - struct wlr_drm_backend *drm); #endif