mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	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
					
				
					 5 changed files with 45 additions and 26 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue