mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	backend/drm: implement wlr_backend_impl.{test,commit}
This commit is contained in:
		
							parent
							
								
									d41b5efc65
								
							
						
					
					
						commit
						52e01a9c8b
					
				
					 3 changed files with 85 additions and 2 deletions
				
			
		|  | @ -75,15 +75,29 @@ static int backend_get_drm_fd(struct wlr_backend *backend) { | ||||||
| 	return drm->fd; | 	return drm->fd; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint32_t drm_backend_get_buffer_caps(struct wlr_backend *backend) { | static uint32_t backend_get_buffer_caps(struct wlr_backend *backend) { | ||||||
| 	return WLR_BUFFER_CAP_DMABUF; | 	return WLR_BUFFER_CAP_DMABUF; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static bool backend_test(struct wlr_backend *backend, | ||||||
|  | 		const struct wlr_backend_output_state *states, size_t states_len) { | ||||||
|  | 	struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); | ||||||
|  | 	return commit_drm_device(drm, states, states_len, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool backend_commit(struct wlr_backend *backend, | ||||||
|  | 		const struct wlr_backend_output_state *states, size_t states_len) { | ||||||
|  | 	struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend); | ||||||
|  | 	return commit_drm_device(drm, states, states_len, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct wlr_backend_impl backend_impl = { | static const struct wlr_backend_impl backend_impl = { | ||||||
| 	.start = backend_start, | 	.start = backend_start, | ||||||
| 	.destroy = backend_destroy, | 	.destroy = backend_destroy, | ||||||
| 	.get_drm_fd = backend_get_drm_fd, | 	.get_drm_fd = backend_get_drm_fd, | ||||||
| 	.get_buffer_caps = drm_backend_get_buffer_caps, | 	.get_buffer_caps = backend_get_buffer_caps, | ||||||
|  | 	.test = backend_test, | ||||||
|  | 	.commit = backend_commit, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool wlr_backend_is_drm(struct wlr_backend *b) { | bool wlr_backend_is_drm(struct wlr_backend *b) { | ||||||
|  |  | ||||||
|  | @ -1870,6 +1870,73 @@ void restore_drm_device(struct wlr_drm_backend *drm) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool commit_drm_device(struct wlr_drm_backend *drm, | ||||||
|  | 		const struct wlr_backend_output_state *output_states, size_t output_states_len, | ||||||
|  | 		bool test_only) { | ||||||
|  | 	if (!drm->session->active) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct wlr_drm_connector_state *conn_states = calloc(output_states_len, sizeof(conn_states[0])); | ||||||
|  | 	if (conn_states == NULL) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool ok = false; | ||||||
|  | 	bool modeset = false; | ||||||
|  | 	size_t conn_states_len = 0; | ||||||
|  | 	for (size_t i = 0; i < output_states_len; i++) { | ||||||
|  | 		const struct wlr_backend_output_state *output_state = &output_states[i]; | ||||||
|  | 		struct wlr_output *output = output_state->output; | ||||||
|  | 		if (!output->enabled && !output_pending_enabled(output, &output_state->base)) { | ||||||
|  | 			// KMS rejects commits which disable already-disabled connectors
 | ||||||
|  | 			// and have the DRM_MODE_PAGE_FLIP_EVENT flag
 | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		struct wlr_drm_connector *conn = get_drm_connector_from_output(output); | ||||||
|  | 
 | ||||||
|  | 		if (output_pending_enabled(output, &output_state->base) && !drm_connector_alloc_crtc(conn)) { | ||||||
|  | 			wlr_drm_conn_log(conn, WLR_DEBUG, | ||||||
|  | 				"No CRTC available for this connector"); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		struct wlr_drm_connector_state *conn_state = &conn_states[conn_states_len]; | ||||||
|  | 		drm_connector_state_init(conn_state, conn, &output_state->base); | ||||||
|  | 		conn_states_len++; | ||||||
|  | 
 | ||||||
|  | 		if (!drm_connector_prepare(conn_state, test_only)) { | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (output_state->base.tearing_page_flip) { | ||||||
|  | 			wlr_log(WLR_DEBUG, "Tearing not supported for DRM device-wide commits"); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		modeset |= output_state->base.allow_reconfiguration; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	uint32_t flags = 0; | ||||||
|  | 	if (!test_only) { | ||||||
|  | 		flags |= DRM_MODE_PAGE_FLIP_EVENT; | ||||||
|  | 	} | ||||||
|  | 	struct wlr_drm_device_state dev_state = { | ||||||
|  | 		.modeset = modeset, | ||||||
|  | 		.connectors = conn_states, | ||||||
|  | 		.connectors_len = conn_states_len, | ||||||
|  | 	}; | ||||||
|  | 	ok = drm_commit(drm, &dev_state, flags, test_only); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	for (size_t i = 0; i < conn_states_len; i++) { | ||||||
|  | 		drm_connector_state_finish(&conn_states[i]); | ||||||
|  | 	} | ||||||
|  | 	free(conn_states); | ||||||
|  | 	return ok; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int mhz_to_nsec(int mhz) { | static int mhz_to_nsec(int mhz) { | ||||||
| 	return 1000000000000LL / mhz; | 	return 1000000000000LL / mhz; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -206,6 +206,8 @@ void finish_drm_resources(struct wlr_drm_backend *drm); | ||||||
| void scan_drm_connectors(struct wlr_drm_backend *state, | void scan_drm_connectors(struct wlr_drm_backend *state, | ||||||
| 	struct wlr_device_hotplug_event *event); | 	struct wlr_device_hotplug_event *event); | ||||||
| void scan_drm_leases(struct wlr_drm_backend *drm); | void scan_drm_leases(struct wlr_drm_backend *drm); | ||||||
|  | bool commit_drm_device(struct wlr_drm_backend *drm, | ||||||
|  | 	const struct wlr_backend_output_state *states, size_t states_len, bool test_only); | ||||||
| void restore_drm_device(struct wlr_drm_backend *drm); | void restore_drm_device(struct wlr_drm_backend *drm); | ||||||
| int handle_drm_event(int fd, uint32_t mask, void *data); | int handle_drm_event(int fd, uint32_t mask, void *data); | ||||||
| void destroy_drm_connector(struct wlr_drm_connector *conn); | void destroy_drm_connector(struct wlr_drm_connector *conn); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Simon Ser
						Simon Ser