mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 12:55:58 +01:00
backend/drm: remove primary swapchain
We can't nuke it completely, we still need it for multi-GPU.
This commit is contained in:
parent
85d7ad2eef
commit
f5900c1f00
4 changed files with 52 additions and 205 deletions
|
@ -329,21 +329,6 @@ static struct wlr_drm_connector *get_drm_connector_from_output(
|
||||||
return (struct wlr_drm_connector *)wlr_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,
|
static bool drm_crtc_commit(struct wlr_drm_connector *conn,
|
||||||
const struct wlr_output_state *state, uint32_t flags, bool test_only) {
|
const struct wlr_output_state *state, uint32_t flags, bool test_only) {
|
||||||
// Disallow atomic-only flags
|
// 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;
|
struct wlr_drm_crtc *crtc = conn->crtc;
|
||||||
bool ok = drm->iface->crtc_commit(conn, state, flags, test_only);
|
bool ok = drm->iface->crtc_commit(conn, state, flags, test_only);
|
||||||
if (ok && !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) {
|
if (crtc->cursor != NULL) {
|
||||||
drm_plane_set_committed(crtc->cursor);
|
drm_fb_move(&crtc->cursor->queued_fb, &crtc->cursor->pending_fb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drm_fb_clear(&crtc->primary->pending_fb);
|
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;
|
struct wlr_drm_plane *plane = crtc->primary;
|
||||||
|
|
||||||
assert(state->committed & WLR_OUTPUT_STATE_BUFFER);
|
assert(state->committed & WLR_OUTPUT_STATE_BUFFER);
|
||||||
switch (state->buffer_type) {
|
assert(state->buffer_type == WLR_OUTPUT_STATE_BUFFER_SCANOUT);
|
||||||
case WLR_OUTPUT_STATE_BUFFER_RENDER:
|
|
||||||
if (!drm_plane_lock_surface(plane, drm)) {
|
struct wlr_buffer *local_buf;
|
||||||
wlr_drm_conn_log(conn, WLR_ERROR, "drm_plane_lock_surface failed");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case WLR_OUTPUT_STATE_BUFFER_SCANOUT:;
|
// TODO: fallback to modifier-less buffer allocation
|
||||||
if (!drm_fb_import(&plane->pending_fb, drm, state->buffer,
|
bool ok = init_drm_surface(&plane->mgpu_surf, &drm->renderer,
|
||||||
&crtc->primary->formats)) {
|
state->buffer->width, state->buffer->height, format);
|
||||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
free(format);
|
||||||
"Failed to import buffer for scan-out");
|
if (!ok) {
|
||||||
return false;
|
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;
|
return true;
|
||||||
|
@ -572,11 +573,6 @@ static bool drm_connector_commit(struct wlr_output *output) {
|
||||||
return drm_connector_commit_state(conn, &output->pending);
|
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,
|
size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm,
|
||||||
struct wlr_drm_crtc *crtc) {
|
struct wlr_drm_crtc *crtc) {
|
||||||
if (crtc->props.gamma_lut_size == 0 || drm->iface == &legacy_iface) {
|
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;
|
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,
|
static bool drm_connector_init_renderer(struct wlr_drm_connector *conn,
|
||||||
const struct wlr_output_state *state) {
|
const struct wlr_output_state *state) {
|
||||||
struct wlr_drm_backend *drm = conn->backend;
|
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);
|
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};
|
drmModeModeInfo mode = {0};
|
||||||
drm_connector_state_mode(conn, state, &mode);
|
drm_connector_state_mode(conn, state, &mode);
|
||||||
|
|
||||||
struct wlr_drm_plane *plane = conn->crtc->primary;
|
struct wlr_drm_plane *plane = conn->crtc->primary;
|
||||||
int width = mode.hdisplay;
|
int width = mode.hdisplay;
|
||||||
int height = mode.vdisplay;
|
int height = mode.vdisplay;
|
||||||
|
|
||||||
if (drm->addfb2_modifiers) {
|
struct wlr_drm_format *format =
|
||||||
// Modifiers are supported, try to use them
|
drm_plane_pick_render_format(plane, &drm->renderer);
|
||||||
if (drm_plane_init_surface(plane, drm, width, height, true) &&
|
if (format == NULL) {
|
||||||
drm_connector_test_renderer(conn, state)) {
|
wlr_log(WLR_ERROR, "Failed to pick primary plane format");
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If page-flipping with modifiers enabled doesn't work, retry without
|
// TODO: fallback to modifier-less buffer allocation
|
||||||
// modifiers
|
bool ok = init_drm_surface(&plane->mgpu_surf, &drm->renderer,
|
||||||
wlr_drm_conn_log(conn, WLR_INFO,
|
width, height, format);
|
||||||
"Page-flip failed with primary FB modifiers enabled, "
|
free(format);
|
||||||
"retrying without modifiers");
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drm_plane_init_surface(plane, drm, width, height, false) &&
|
return true;
|
||||||
drm_connector_test_renderer(conn, state)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_drm_conn_log(conn, WLR_ERROR, "Failed to initialize renderer: "
|
|
||||||
"initial page-flip failed");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void realloc_crtcs(struct wlr_drm_backend *drm);
|
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
|
// drm_crtc_page_flip expects a FB to be available
|
||||||
struct wlr_drm_plane *plane = conn->crtc->primary;
|
struct wlr_drm_plane *plane = conn->crtc->primary;
|
||||||
if (!plane_get_next_fb(plane)) {
|
if (!plane_get_next_fb(plane)) {
|
||||||
if (!drm_surface_render_black_frame(&plane->surf)) {
|
wlr_drm_conn_log(conn, WLR_ERROR, "Missing FB in modeset");
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
if (!drm_plane_lock_surface(plane, drm)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drm_crtc_page_flip(conn, state)) {
|
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,
|
.set_cursor = drm_connector_set_cursor,
|
||||||
.move_cursor = drm_connector_move_cursor,
|
.move_cursor = drm_connector_move_cursor,
|
||||||
.destroy = drm_connector_destroy_output,
|
.destroy = drm_connector_destroy_output,
|
||||||
.attach_render = drm_connector_attach_render,
|
|
||||||
.test = drm_connector_test,
|
.test = drm_connector_test,
|
||||||
.commit = drm_connector_commit,
|
.commit = drm_connector_commit,
|
||||||
.rollback_render = drm_connector_rollback_render,
|
|
||||||
.get_gamma_size = drm_connector_get_gamma_size,
|
.get_gamma_size = drm_connector_get_gamma_size,
|
||||||
.get_cursor_formats = drm_connector_get_cursor_formats,
|
.get_cursor_formats = drm_connector_get_cursor_formats,
|
||||||
.get_cursor_size = drm_connector_get_cursor_size,
|
.get_cursor_size = drm_connector_get_cursor_size,
|
||||||
|
|
|
@ -176,22 +176,9 @@ void drm_plane_finish_surface(struct wlr_drm_plane *plane) {
|
||||||
drm_fb_clear(&plane->queued_fb);
|
drm_fb_clear(&plane->queued_fb);
|
||||||
drm_fb_clear(&plane->current_fb);
|
drm_fb_clear(&plane->current_fb);
|
||||||
|
|
||||||
finish_drm_surface(&plane->surf);
|
|
||||||
finish_drm_surface(&plane->mgpu_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_format *drm_plane_pick_render_format(
|
||||||
struct wlr_drm_plane *plane, struct wlr_drm_renderer *renderer) {
|
struct wlr_drm_plane *plane, struct wlr_drm_renderer *renderer) {
|
||||||
const struct wlr_drm_format_set *render_formats =
|
const struct wlr_drm_format_set *render_formats =
|
||||||
|
@ -238,53 +225,6 @@ struct wlr_drm_format *drm_plane_pick_render_format(
|
||||||
return 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) {
|
void drm_fb_clear(struct wlr_drm_fb **fb_ptr) {
|
||||||
if (*fb_ptr == NULL) {
|
if (*fb_ptr == NULL) {
|
||||||
return;
|
return;
|
||||||
|
@ -296,36 +236,6 @@ void drm_fb_clear(struct wlr_drm_fb **fb_ptr) {
|
||||||
*fb_ptr = NULL;
|
*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,
|
static struct gbm_bo *get_bo_for_dmabuf(struct gbm_device *gbm,
|
||||||
struct wlr_dmabuf_attributes *attribs) {
|
struct wlr_dmabuf_attributes *attribs) {
|
||||||
if (attribs->modifier != DRM_FORMAT_MOD_INVALID ||
|
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;
|
*new = *old;
|
||||||
*old = NULL;
|
*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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,9 +20,7 @@ struct wlr_drm_plane {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
/* Local if this isn't a multi-GPU setup, on the parent otherwise. */
|
/* Only initialized on multi-GPU setups */
|
||||||
struct wlr_drm_surface surf;
|
|
||||||
/* Local, only initialized on multi-GPU setups. */
|
|
||||||
struct wlr_drm_surface mgpu_surf;
|
struct wlr_drm_surface mgpu_surf;
|
||||||
|
|
||||||
/* Buffer to be submitted to the kernel on the next page-flip */
|
/* Buffer to be submitted to the kernel on the next page-flip */
|
||||||
|
|
|
@ -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 *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||||
struct wlr_buffer *buffer);
|
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_format *drm_plane_pick_render_format(
|
||||||
struct wlr_drm_plane *plane, struct wlr_drm_renderer *renderer);
|
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);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue