backend/drm: remove mode argument to crtc_pageflip
Add a new wlr_drm_crtc.pending bitfield which keeps track of pending output changes. More fields will be added in the future (e.g. active, gamma).
This commit is contained in:
		
							parent
							
								
									7a149fe5ba
								
							
						
					
					
						commit
						69b2279092
					
				|  | @ -110,23 +110,24 @@ error: | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, | static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, | ||||||
| 		struct wlr_drm_connector *conn, drmModeModeInfo *mode) { | 		struct wlr_drm_connector *conn) { | ||||||
| 	struct wlr_drm_crtc *crtc = conn->crtc; | 	struct wlr_drm_crtc *crtc = conn->crtc; | ||||||
| 
 | 
 | ||||||
| 	if (mode != NULL) { | 	bool modeset = crtc->pending & WLR_DRM_CRTC_MODE; | ||||||
|  | 	if (modeset) { | ||||||
| 		if (crtc->mode_id != 0) { | 		if (crtc->mode_id != 0) { | ||||||
| 			drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); | 			drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (drmModeCreatePropertyBlob(drm->fd, mode, sizeof(*mode), | 		if (drmModeCreatePropertyBlob(drm->fd, &crtc->mode, | ||||||
| 				&crtc->mode_id)) { | 				sizeof(drmModeModeInfo), &crtc->mode_id)) { | ||||||
| 			wlr_log_errno(WLR_ERROR, "Unable to create property blob"); | 			wlr_log_errno(WLR_ERROR, "Unable to create mode property blob"); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT; | 	uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT; | ||||||
| 	if (mode != NULL) { | 	if (modeset) { | ||||||
| 		flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; | 		flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; | ||||||
| 	} else { | 	} else { | ||||||
| 		flags |= DRM_MODE_ATOMIC_NONBLOCK; | 		flags |= DRM_MODE_ATOMIC_NONBLOCK; | ||||||
|  | @ -135,7 +136,7 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, | ||||||
| 	struct atomic atom; | 	struct atomic atom; | ||||||
| 	atomic_begin(crtc, &atom); | 	atomic_begin(crtc, &atom); | ||||||
| 	atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); | 	atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); | ||||||
| 	if (mode != NULL && conn->props.link_status != 0) { | 	if (modeset && conn->props.link_status != 0) { | ||||||
| 		atomic_add(&atom, conn->id, conn->props.link_status, | 		atomic_add(&atom, conn->id, conn->props.link_status, | ||||||
| 			DRM_MODE_LINK_STATUS_GOOD); | 			DRM_MODE_LINK_STATUS_GOOD); | ||||||
| 	} | 	} | ||||||
|  | @ -151,12 +152,13 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!atomic_end(drm->fd, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : 0, &atom)) { | 	if (!atomic_end(drm->fd, modeset ? DRM_MODE_ATOMIC_ALLOW_MODESET : 0, | ||||||
|  | 			&atom)) { | ||||||
| 		drmModeAtomicSetCursor(atom.req, 0); | 		drmModeAtomicSetCursor(atom.req, 0); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!atomic_commit(drm->fd, &atom, conn, flags, mode)) { | 	if (!atomic_commit(drm->fd, &atom, conn, flags, modeset)) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -334,11 +334,10 @@ static bool drm_connector_attach_render(struct wlr_output *output, | ||||||
| 	return drm_surface_make_current(&conn->crtc->primary->surf, buffer_age); | 	return drm_surface_make_current(&conn->crtc->primary->surf, buffer_age); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool drm_crtc_page_flip(struct wlr_drm_connector *conn, | static bool drm_crtc_page_flip(struct wlr_drm_connector *conn) { | ||||||
| 		struct wlr_drm_mode *mode) { | 	struct wlr_drm_backend *drm = | ||||||
| 	struct wlr_drm_backend *drm = get_drm_backend_from_backend(conn->output.backend); | 		get_drm_backend_from_backend(conn->output.backend); | ||||||
| 	struct wlr_drm_crtc *crtc = conn->crtc; | 	struct wlr_drm_crtc *crtc = conn->crtc; | ||||||
| 	drmModeModeInfo *drm_mode = mode ? &mode->drm_mode : NULL; |  | ||||||
| 
 | 
 | ||||||
| 	if (conn->pageflip_pending) { | 	if (conn->pageflip_pending) { | ||||||
| 		wlr_log(WLR_ERROR, "Failed to page-flip output '%s': " | 		wlr_log(WLR_ERROR, "Failed to page-flip output '%s': " | ||||||
|  | @ -346,7 +345,11 @@ static bool drm_crtc_page_flip(struct wlr_drm_connector *conn, | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!drm->iface->crtc_pageflip(drm, conn, drm_mode)) { | 	bool ok = drm->iface->crtc_pageflip(drm, conn); | ||||||
|  | 
 | ||||||
|  | 	crtc->pending = 0; | ||||||
|  | 
 | ||||||
|  | 	if (!ok) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -454,7 +457,7 @@ static bool drm_connector_commit_buffer(struct wlr_output *output) { | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!drm_crtc_page_flip(conn, NULL)) { | 	if (!drm_crtc_page_flip(conn)) { | ||||||
| 		drm_fb_clear(&plane->pending_fb); | 		drm_fb_clear(&plane->pending_fb); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  | @ -661,8 +664,7 @@ 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_pageflip_renderer(struct wlr_drm_connector *conn, | static bool drm_connector_pageflip_renderer(struct wlr_drm_connector *conn) { | ||||||
| 		struct wlr_drm_mode *mode) { |  | ||||||
| 	struct wlr_drm_crtc *crtc = conn->crtc; | 	struct wlr_drm_crtc *crtc = conn->crtc; | ||||||
| 	if (!crtc) { | 	if (!crtc) { | ||||||
| 		wlr_log(WLR_ERROR, "Page-flip failed on connector '%s': no CRTC", | 		wlr_log(WLR_ERROR, "Page-flip failed on connector '%s': no CRTC", | ||||||
|  | @ -679,10 +681,12 @@ static bool drm_connector_pageflip_renderer(struct wlr_drm_connector *conn, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return drm_crtc_page_flip(conn, mode); | 	return drm_crtc_page_flip(conn); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void drm_connector_start_renderer(struct wlr_drm_connector *conn) { | static void drm_connector_start_renderer(struct wlr_drm_connector *conn) { | ||||||
|  | 	struct wlr_drm_crtc *crtc = conn->crtc; | ||||||
|  | 
 | ||||||
| 	if (conn->state != WLR_DRM_CONN_CONNECTED) { | 	if (conn->state != WLR_DRM_CONN_CONNECTED) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -690,7 +694,10 @@ static void drm_connector_start_renderer(struct wlr_drm_connector *conn) { | ||||||
| 	wlr_log(WLR_DEBUG, "Starting renderer on output '%s'", conn->output.name); | 	wlr_log(WLR_DEBUG, "Starting renderer on output '%s'", conn->output.name); | ||||||
| 
 | 
 | ||||||
| 	struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; | 	struct wlr_drm_mode *mode = (struct wlr_drm_mode *)conn->output.current_mode; | ||||||
| 	if (!drm_connector_pageflip_renderer(conn, mode)) { | 	memcpy(&crtc->mode, &mode->drm_mode, sizeof(drmModeModeInfo)); | ||||||
|  | 	crtc->pending |= WLR_DRM_CRTC_MODE; | ||||||
|  | 
 | ||||||
|  | 	if (!drm_connector_pageflip_renderer(conn)) { | ||||||
| 		wl_event_source_timer_update(conn->retry_pageflip, | 		wl_event_source_timer_update(conn->retry_pageflip, | ||||||
| 			1000000.0f / conn->output.current_mode->refresh); | 			1000000.0f / conn->output.current_mode->refresh); | ||||||
| 	} | 	} | ||||||
|  | @ -717,6 +724,9 @@ static bool drm_connector_init_renderer(struct wlr_drm_connector *conn, | ||||||
| 	} | 	} | ||||||
| 	struct wlr_drm_plane *plane = crtc->primary; | 	struct wlr_drm_plane *plane = crtc->primary; | ||||||
| 
 | 
 | ||||||
|  | 	crtc->pending |= WLR_DRM_CRTC_MODE; | ||||||
|  | 	memcpy(&crtc->mode, &mode->drm_mode, sizeof(drmModeModeInfo)); | ||||||
|  | 
 | ||||||
| 	int width = mode->wlr_mode.width; | 	int width = mode->wlr_mode.width; | ||||||
| 	int height = mode->wlr_mode.height; | 	int height = mode->wlr_mode.height; | ||||||
| 	uint32_t format = drm->renderer.gbm_format; | 	uint32_t format = drm->renderer.gbm_format; | ||||||
|  | @ -730,7 +740,7 @@ static bool drm_connector_init_renderer(struct wlr_drm_connector *conn, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!drm_plane_init_surface(plane, drm, width, height, format, 0, modifiers) || | 	if (!drm_plane_init_surface(plane, drm, width, height, format, 0, modifiers) || | ||||||
| 			!drm_connector_pageflip_renderer(conn, mode)) { | 			!drm_connector_pageflip_renderer(conn)) { | ||||||
| 		if (!modifiers) { | 		if (!modifiers) { | ||||||
| 			wlr_log(WLR_ERROR, "Failed to initialize renderer " | 			wlr_log(WLR_ERROR, "Failed to initialize renderer " | ||||||
| 				"on connector '%s': initial page-flip failed", | 				"on connector '%s': initial page-flip failed", | ||||||
|  | @ -748,7 +758,7 @@ static bool drm_connector_init_renderer(struct wlr_drm_connector *conn, | ||||||
| 				0, modifiers)) { | 				0, modifiers)) { | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		if (!drm_connector_pageflip_renderer(conn, mode)) { | 		if (!drm_connector_pageflip_renderer(conn)) { | ||||||
| 			wlr_log(WLR_ERROR, "Failed to initialize renderer " | 			wlr_log(WLR_ERROR, "Failed to initialize renderer " | ||||||
| 				"on connector '%s': initial page-flip failed", | 				"on connector '%s': initial page-flip failed", | ||||||
| 				conn->output.name); | 				conn->output.name); | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include "backend/drm/util.h" | #include "backend/drm/util.h" | ||||||
| 
 | 
 | ||||||
| static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, | static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, | ||||||
| 		struct wlr_drm_connector *conn, drmModeModeInfo *mode) { | 		struct wlr_drm_connector *conn) { | ||||||
| 	struct wlr_drm_crtc *crtc = conn->crtc; | 	struct wlr_drm_crtc *crtc = conn->crtc; | ||||||
| 	struct wlr_drm_plane *cursor = crtc->cursor; | 	struct wlr_drm_plane *cursor = crtc->cursor; | ||||||
| 
 | 
 | ||||||
|  | @ -22,9 +22,9 @@ static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (mode) { | 	if (crtc->pending & WLR_DRM_CRTC_MODE) { | ||||||
| 		if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, | 		if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, | ||||||
| 				&conn->id, 1, mode)) { | 				&conn->id, 1, &crtc->mode)) { | ||||||
| 			wlr_log_errno(WLR_ERROR, "%s: Failed to set CRTC", conn->output.name); | 			wlr_log_errno(WLR_ERROR, "%s: Failed to set CRTC", conn->output.name); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -42,8 +42,15 @@ struct wlr_drm_plane { | ||||||
| 	union wlr_drm_plane_props props; | 	union wlr_drm_plane_props props; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum wlr_drm_crtc_field { | ||||||
|  | 	WLR_DRM_CRTC_MODE = 1 << 0, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct wlr_drm_crtc { | struct wlr_drm_crtc { | ||||||
| 	uint32_t id; | 	uint32_t id; | ||||||
|  | 	uint32_t pending; // bitfield of enum wlr_drm_crtc_field
 | ||||||
|  | 
 | ||||||
|  | 	drmModeModeInfo mode; | ||||||
| 
 | 
 | ||||||
| 	// Atomic modesetting only
 | 	// Atomic modesetting only
 | ||||||
| 	uint32_t mode_id; | 	uint32_t mode_id; | ||||||
|  |  | ||||||
|  | @ -16,9 +16,9 @@ struct wlr_drm_interface { | ||||||
| 	// Enable or disable DPMS for connector
 | 	// Enable or disable DPMS for connector
 | ||||||
| 	bool (*conn_enable)(struct wlr_drm_backend *drm, | 	bool (*conn_enable)(struct wlr_drm_backend *drm, | ||||||
| 		struct wlr_drm_connector *conn, bool enable); | 		struct wlr_drm_connector *conn, bool enable); | ||||||
| 	// Pageflip on crtc. If mode is non-NULL perform a full modeset using it.
 | 	// Pageflip on crtc.
 | ||||||
| 	bool (*crtc_pageflip)(struct wlr_drm_backend *drm, | 	bool (*crtc_pageflip)(struct wlr_drm_backend *drm, | ||||||
| 		struct wlr_drm_connector *conn, drmModeModeInfo *mode); | 		struct wlr_drm_connector *conn); | ||||||
| 	// Enable the cursor buffer on crtc. Set bo to NULL to disable
 | 	// Enable the cursor buffer on crtc. Set bo to NULL to disable
 | ||||||
| 	bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, | 	bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, | ||||||
| 		struct wlr_drm_crtc *crtc, struct gbm_bo *bo); | 		struct wlr_drm_crtc *crtc, struct gbm_bo *bo); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue