backend/drm: introduce wlr_drm_lease
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3183
This commit is contained in:
		
							parent
							
								
									a37f538ca0
								
							
						
					
					
						commit
						86f5ecf468
					
				|  | @ -1554,17 +1554,13 @@ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) { | |||
| 	return fd; | ||||
| } | ||||
| 
 | ||||
| /* TODO: make the function return a `wlr_drm_lease` to provide a destroy event
 | ||||
|  * that can be fired when the kernel notifies us through uevent that the lease | ||||
|  * has been destroyed | ||||
|  */ | ||||
| int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs, | ||||
| 		uint32_t *lessee_id) { | ||||
| struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs, | ||||
| 		size_t n_outputs, int *lease_fd_ptr) { | ||||
| 	assert(outputs); | ||||
| 
 | ||||
| 	if (n_outputs == 0) { | ||||
| 		wlr_log(WLR_ERROR, "Can't lease 0 outputs"); | ||||
| 		return -1; | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	struct wlr_drm_backend *drm = | ||||
|  | @ -1575,11 +1571,11 @@ int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs, | |||
| 	for (size_t i = 0; i < n_outputs; ++i) { | ||||
| 		struct wlr_drm_connector *conn = | ||||
| 				get_drm_connector_from_output(outputs[i]); | ||||
| 		assert(conn->lessee_id == 0); | ||||
| 		assert(conn->lease == NULL); | ||||
| 
 | ||||
| 		if (conn->backend != drm) { | ||||
| 			wlr_log(WLR_ERROR, "Can't lease output from different backends"); | ||||
| 			return -1; | ||||
| 			return NULL; | ||||
| 		} | ||||
| 
 | ||||
| 		objects[n_objects++] = conn->id; | ||||
|  | @ -1587,7 +1583,7 @@ int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs, | |||
| 
 | ||||
| 		if (!conn->crtc) { | ||||
| 			wlr_log(WLR_ERROR, "Connector has no CRTC"); | ||||
| 			return -1; | ||||
| 			return NULL; | ||||
| 		} | ||||
| 
 | ||||
| 		objects[n_objects++] = conn->crtc->id; | ||||
|  | @ -1604,50 +1600,63 @@ int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs, | |||
| 
 | ||||
| 	assert(n_objects != 0); | ||||
| 
 | ||||
| 	wlr_log(WLR_DEBUG, "Issuing DRM lease with the %d objects", n_objects); | ||||
| 	int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, 0, | ||||
| 			lessee_id); | ||||
| 	if (lease_fd < 0) { | ||||
| 		return lease_fd; | ||||
| 	struct wlr_drm_lease *lease = calloc(1, sizeof(*lease)); | ||||
| 	if (lease == NULL) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_log(WLR_DEBUG, "Issued DRM lease %"PRIu32, *lessee_id); | ||||
| 	lease->backend = drm; | ||||
| 	wl_signal_init(&lease->events.destroy); | ||||
| 
 | ||||
| 	wlr_log(WLR_DEBUG, "Issuing DRM lease with %d objects", n_objects); | ||||
| 	int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, 0, | ||||
| 			&lease->lessee_id); | ||||
| 	if (lease_fd < 0) { | ||||
| 		free(lease); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	*lease_fd_ptr = lease_fd; | ||||
| 
 | ||||
| 	wlr_log(WLR_DEBUG, "Issued DRM lease %"PRIu32, lease->lessee_id); | ||||
| 	for (size_t i = 0; i < n_outputs; ++i) { | ||||
| 		struct wlr_drm_connector *conn = | ||||
| 				get_drm_connector_from_output(outputs[i]); | ||||
| 		conn->lessee_id = *lessee_id; | ||||
| 		conn->crtc->lessee_id = *lessee_id; | ||||
| 		conn->lease = lease; | ||||
| 		conn->crtc->lease = lease; | ||||
| 	} | ||||
| 
 | ||||
| 	return lease_fd; | ||||
| 	return lease; | ||||
| } | ||||
| 
 | ||||
| bool wlr_drm_backend_terminate_lease(struct wlr_backend *backend, | ||||
| 		uint32_t lessee_id) { | ||||
| 	wlr_log(WLR_DEBUG, "Terminating DRM lease %d", lessee_id); | ||||
| void wlr_drm_lease_terminate(struct wlr_drm_lease *lease) { | ||||
| 	struct wlr_drm_backend *drm = lease->backend; | ||||
| 
 | ||||
| 	assert(backend); | ||||
| 	struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); | ||||
| 
 | ||||
| 	int r = drmModeRevokeLease(drm->fd, lessee_id); | ||||
| 	if (r < 0) { | ||||
| 		wlr_log_errno(WLR_DEBUG, "Failed to terminate lease"); | ||||
| 	wlr_log(WLR_DEBUG, "Terminating DRM lease %d", lease->lessee_id); | ||||
| 	int ret = drmModeRevokeLease(drm->fd, lease->lessee_id); | ||||
| 	if (ret < 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "Failed to terminate lease"); | ||||
| 	} | ||||
| 
 | ||||
| 	drm_lease_destroy(lease); | ||||
| } | ||||
| 
 | ||||
| void drm_lease_destroy(struct wlr_drm_lease *lease) { | ||||
| 	struct wlr_drm_backend *drm = lease->backend; | ||||
| 
 | ||||
| 	wlr_signal_emit_safe(&lease->events.destroy, NULL); | ||||
| 
 | ||||
| 	struct wlr_drm_connector *conn; | ||||
| 	wl_list_for_each(conn, &drm->outputs, link) { | ||||
| 		if (conn->lessee_id == lessee_id) { | ||||
| 			conn->lessee_id = 0; | ||||
| 			/* Will be re-initialized in scan_drm_connectors */ | ||||
| 		if (conn->lease == lease) { | ||||
| 			conn->lease = NULL; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (size_t i = 0; i < drm->num_crtcs; ++i) { | ||||
| 		if (drm->crtcs[i].lessee_id == lessee_id) { | ||||
| 			drm->crtcs[i].lessee_id = 0; | ||||
| 		if (drm->crtcs[i].lease == lease) { | ||||
| 			drm->crtcs[i].lease = NULL; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return r >= 0; | ||||
| 	free(lease); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ struct wlr_drm_plane { | |||
| 
 | ||||
| struct wlr_drm_crtc { | ||||
| 	uint32_t id; | ||||
| 	uint32_t lessee_id; | ||||
| 	struct wlr_drm_lease *lease; | ||||
| 
 | ||||
| 	// Atomic modesetting only
 | ||||
| 	uint32_t mode_id; | ||||
|  | @ -118,7 +118,7 @@ struct wlr_drm_connector { | |||
| 	enum wlr_drm_connector_status status; | ||||
| 	bool desired_enabled; | ||||
| 	uint32_t id; | ||||
| 	uint32_t lessee_id; | ||||
| 	struct wlr_drm_lease *lease; | ||||
| 
 | ||||
| 	struct wlr_drm_crtc *crtc; | ||||
| 	uint32_t possible_crtcs; | ||||
|  | @ -157,6 +157,7 @@ bool drm_connector_is_cursor_visible(struct wlr_drm_connector *conn); | |||
| bool drm_connector_supports_vrr(struct wlr_drm_connector *conn); | ||||
| size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, | ||||
| 	struct wlr_drm_crtc *crtc); | ||||
| void drm_lease_destroy(struct wlr_drm_lease *lease); | ||||
| 
 | ||||
| struct wlr_drm_fb *plane_get_next_fb(struct wlr_drm_plane *plane); | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,20 @@ | |||
| #include <wlr/backend/session.h> | ||||
| #include <wlr/types/wlr_output.h> | ||||
| 
 | ||||
| struct wlr_drm_backend; | ||||
| 
 | ||||
| struct wlr_drm_lease { | ||||
| 	int fd; | ||||
| 	uint32_t lessee_id; | ||||
| 	struct wlr_drm_backend *backend; | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct wl_signal destroy; | ||||
| 	} events; | ||||
| 
 | ||||
| 	void *data; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Creates a DRM backend using the specified GPU file descriptor (typically from | ||||
|  * a device node in /dev/dri). | ||||
|  | @ -41,18 +55,20 @@ uint32_t wlr_drm_connector_get_id(struct wlr_output *output); | |||
| int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend); | ||||
| 
 | ||||
| /**
 | ||||
|  * Leases a given output to the caller. The output must be from the associated | ||||
|  * DRM backend. | ||||
|  * Returns a valid opened DRM FD or -1 on error. | ||||
|  * Leases the given outputs to the caller. The outputs must be from the | ||||
|  * associated DRM backend. | ||||
|  * | ||||
|  * Returns NULL on error. | ||||
|  */ | ||||
| int wlr_drm_create_lease(struct wlr_output **outputs, size_t n_outputs, | ||||
| 		uint32_t *lessee_id); | ||||
| struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs, | ||||
| 	size_t n_outputs, int *lease_fd); | ||||
| 
 | ||||
| /**
 | ||||
|  * Terminates a given lease. The output will be owned again by the backend | ||||
|  * Terminates and destroys a given lease. | ||||
|  * | ||||
|  * The outputs will be owned again by the backend. | ||||
|  */ | ||||
| bool wlr_drm_backend_terminate_lease(struct wlr_backend *backend, | ||||
| 	uint32_t lessee_id); | ||||
| void wlr_drm_lease_terminate(struct wlr_drm_lease *lease); | ||||
| 
 | ||||
| /**
 | ||||
|  * Add mode to the list of available modes | ||||
|  |  | |||
|  | @ -81,14 +81,13 @@ struct wlr_drm_lease_request_v1 { | |||
| 
 | ||||
| struct wlr_drm_lease_v1 { | ||||
| 	struct wl_resource *resource; | ||||
| 	struct wlr_drm_lease *drm_lease; | ||||
| 
 | ||||
| 	struct wlr_drm_lease_device_v1 *device; | ||||
| 
 | ||||
| 	struct wlr_drm_lease_connector_v1 **connectors; | ||||
| 	size_t n_connectors; | ||||
| 
 | ||||
| 	uint32_t lessee_id; | ||||
| 
 | ||||
| 	struct wl_list link; // wlr_drm_lease_device_v1::leases
 | ||||
| 
 | ||||
| 	void *data; | ||||
|  |  | |||
|  | @ -52,13 +52,11 @@ static void drm_lease_v1_destroy(struct wlr_drm_lease_v1 *lease) { | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_log(WLR_DEBUG, "Destroying lease %"PRIu32, lease->lessee_id); | ||||
| 	wlr_log(WLR_DEBUG, "Destroying lease %"PRIu32, lease->drm_lease->lessee_id); | ||||
| 
 | ||||
| 	wp_drm_lease_v1_send_finished(lease->resource); | ||||
| 
 | ||||
| 	struct wlr_drm_lease_device_v1 *device = lease->device; | ||||
| 	wlr_drm_backend_terminate_lease(device->backend, lease->lessee_id); | ||||
| 	lease->lessee_id = 0; | ||||
| 	wlr_drm_lease_terminate(lease->drm_lease); | ||||
| 
 | ||||
| 	for (size_t i = 0; i < lease->n_connectors; ++i) { | ||||
| 		lease->connectors[i]->active_lease = NULL; | ||||
|  | @ -171,10 +169,10 @@ struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant( | |||
| 		outputs[i] = request->connectors[i]->output; | ||||
| 	} | ||||
| 
 | ||||
| 	int fd = wlr_drm_create_lease(outputs, request->n_connectors, | ||||
| 			&lease->lessee_id); | ||||
| 	if (fd < 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "drm_create_lease failed"); | ||||
| 	int fd; | ||||
| 	lease->drm_lease = wlr_drm_create_lease(outputs, request->n_connectors, &fd); | ||||
| 	if (!lease->drm_lease) { | ||||
| 		wlr_log(WLR_ERROR, "wlr_drm_create_lease failed"); | ||||
| 		wp_drm_lease_v1_send_finished(lease->resource); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | @ -183,6 +181,7 @@ struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant( | |||
| 			sizeof(struct wlr_drm_lease_connector_v1 *)); | ||||
| 	if (!lease->connectors) { | ||||
| 		wlr_log(WLR_ERROR, "Failed to allocate lease connectors list"); | ||||
| 		close(fd); | ||||
| 		wp_drm_lease_v1_send_finished(lease->resource); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | @ -212,7 +211,7 @@ void wlr_drm_lease_request_v1_reject( | |||
| 
 | ||||
| void wlr_drm_lease_v1_revoke(struct wlr_drm_lease_v1 *lease) { | ||||
| 	assert(lease); | ||||
| 	wlr_log(WLR_DEBUG, "Revoking lease %"PRIu32, lease->lessee_id); | ||||
| 	wlr_log(WLR_DEBUG, "Revoking lease %"PRIu32, lease->drm_lease->lessee_id); | ||||
| 
 | ||||
| 	drm_lease_v1_destroy(lease); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue