diff options
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/drm/drm.c | 90 | 
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);  | 
