aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/drm.c90
1 files changed, 50 insertions, 40 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 28649791..466736b4 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -631,27 +631,32 @@ struct wlr_drm_fb *plane_get_next_fb(struct wlr_drm_plane *plane) {
return plane->current_fb;
}
-static bool drm_connector_pageflip_renderer(struct wlr_drm_connector *conn,
+static bool drm_connector_test_renderer(struct wlr_drm_connector *conn,
const struct wlr_output_state *state) {
struct wlr_drm_backend *drm = conn->backend;
- struct wlr_drm_crtc *crtc = conn->crtc;
- if (!crtc) {
- wlr_drm_conn_log(conn, WLR_ERROR, "Page-flip failed: no CRTC");
- return false;
+
+ if (drm->iface == &legacy_iface) {
+ return true;
}
- // drm_crtc_page_flip expects a FB to be available
- struct wlr_drm_plane *plane = 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;
- }
+ 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, DRM_MODE_ATOMIC_TEST_ONLY);
- return drm_crtc_page_flip(conn, state);
+out:
+ drm_fb_move(&plane->pending_fb, &prev_fb);
+ return ok;
}
static bool drm_connector_init_renderer(struct wlr_drm_connector *conn,
@@ -663,29 +668,22 @@ static bool drm_connector_init_renderer(struct wlr_drm_connector *conn,
return false;
}
- wlr_drm_conn_log(conn, WLR_DEBUG, "Initializing renderer");
+ assert(conn->crtc != NULL);
- struct wlr_drm_crtc *crtc = conn->crtc;
- if (!crtc) {
- wlr_drm_conn_log(conn, WLR_ERROR,
- "Failed to initialize renderer: no CRTC");
- return false;
- }
- struct wlr_drm_plane *plane = crtc->primary;
+ wlr_drm_conn_log(conn, WLR_DEBUG, "Initializing renderer");
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;
- bool modifiers = drm->addfb2_modifiers;
- if (!drm_plane_init_surface(plane, drm, width, height, modifiers) ||
- !drm_connector_pageflip_renderer(conn, state)) {
- if (!modifiers) {
- wlr_drm_conn_log(conn, WLR_ERROR, "Failed to initialize renderer:"
- "initial page-flip failed");
- return false;
+ 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;
}
// If page-flipping with modifiers enabled doesn't work, retry without
@@ -693,19 +691,16 @@ static bool drm_connector_init_renderer(struct wlr_drm_connector *conn,
wlr_drm_conn_log(conn, WLR_INFO,
"Page-flip failed with primary FB modifiers enabled, "
"retrying without modifiers");
- modifiers = false;
+ }
- if (!drm_plane_init_surface(plane, drm, width, height, modifiers)) {
- return false;
- }
- if (!drm_connector_pageflip_renderer(conn, state)) {
- wlr_drm_conn_log(conn, WLR_ERROR, "Failed to initialize renderer:"
- "initial page-flip failed");
- return false;
- }
+ if (drm_plane_init_surface(plane, drm, width, height, false) &&
+ drm_connector_test_renderer(conn, state)) {
+ return true;
}
- 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);
@@ -787,6 +782,21 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn,
return false;
}
+ // 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;
+ }
+ }
+
+ if (!drm_crtc_page_flip(conn, state)) {
+ return false;
+ }
+
conn->state = WLR_DRM_CONN_CONNECTED;
conn->desired_mode = NULL;
wlr_output_update_mode(&conn->output, wlr_mode);