mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	backend/drm: simplify atomic commit logic
We don't need a per-CRTC atomic request anymore. Let's make the request per-commit so that it's easier to debug. This is also groundwork for supporting wlr_output_test properly.
This commit is contained in:
		
							parent
							
								
									06d5aa5780
								
							
						
					
					
						commit
						2ca3bdc35e
					
				
					 3 changed files with 24 additions and 49 deletions
				
			
		| 
						 | 
					@ -9,57 +9,42 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct atomic {
 | 
					struct atomic {
 | 
				
			||||||
	drmModeAtomicReq *req;
 | 
						drmModeAtomicReq *req;
 | 
				
			||||||
	int cursor;
 | 
					 | 
				
			||||||
	bool failed;
 | 
						bool failed;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void atomic_begin(struct wlr_drm_crtc *crtc, struct atomic *atom) {
 | 
					static void atomic_begin(struct atomic *atom) {
 | 
				
			||||||
	if (!crtc->atomic) {
 | 
						memset(atom, 0, sizeof(*atom));
 | 
				
			||||||
		crtc->atomic = drmModeAtomicAlloc();
 | 
					 | 
				
			||||||
		if (!crtc->atomic) {
 | 
					 | 
				
			||||||
			wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
					 | 
				
			||||||
			atom->failed = true;
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	atom->req = crtc->atomic;
 | 
						atom->req = drmModeAtomicAlloc();
 | 
				
			||||||
	atom->cursor = drmModeAtomicGetCursor(atom->req);
 | 
						if (!atom->req) {
 | 
				
			||||||
	atom->failed = false;
 | 
							wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
				
			||||||
 | 
							atom->failed = true;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool atomic_end(int drm_fd, uint32_t flags, struct atomic *atom) {
 | 
					static bool atomic_commit(struct atomic *atom,
 | 
				
			||||||
	if (atom->failed) {
 | 
							struct wlr_drm_connector *conn, uint32_t flags) {
 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	flags |= DRM_MODE_ATOMIC_TEST_ONLY;
 | 
					 | 
				
			||||||
	if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) {
 | 
					 | 
				
			||||||
		wlr_log_errno(WLR_DEBUG, "Atomic test failed");
 | 
					 | 
				
			||||||
		drmModeAtomicSetCursor(atom->req, atom->cursor);
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool atomic_commit(int drm_fd, struct atomic *atom,
 | 
					 | 
				
			||||||
		struct wlr_drm_connector *conn, uint32_t flags, bool modeset) {
 | 
					 | 
				
			||||||
	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);
 | 
				
			||||||
	if (atom->failed) {
 | 
						if (atom->failed) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, drm);
 | 
						int ret = drmModeAtomicCommit(drm->fd, atom->req, flags, drm);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		wlr_log_errno(WLR_ERROR, "%s: Atomic commit failed (%s)",
 | 
							wlr_log_errno(WLR_ERROR, "%s: Atomic %s failed (%s)",
 | 
				
			||||||
			conn->output.name, modeset ? "modeset" : "pageflip");
 | 
								conn->output.name,
 | 
				
			||||||
 | 
								(flags & DRM_MODE_ATOMIC_TEST_ONLY) ? "test" : "commit",
 | 
				
			||||||
 | 
								(flags & DRM_MODE_ATOMIC_ALLOW_MODESET) ? "modeset" : "pageflip");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drmModeAtomicSetCursor(atom->req, 0);
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return !ret;
 | 
					static void atomic_finish(struct atomic *atom) {
 | 
				
			||||||
 | 
						drmModeAtomicFree(atom->req);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t val) {
 | 
					static void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t val) {
 | 
				
			||||||
| 
						 | 
					@ -200,7 +185,7 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct atomic atom;
 | 
						struct atomic atom;
 | 
				
			||||||
	atomic_begin(crtc, &atom);
 | 
						atomic_begin(&atom);
 | 
				
			||||||
	atomic_add(&atom, conn->id, conn->props.crtc_id,
 | 
						atomic_add(&atom, conn->id, conn->props.crtc_id,
 | 
				
			||||||
		crtc->active ? crtc->id : 0);
 | 
							crtc->active ? crtc->id : 0);
 | 
				
			||||||
	if (modeset && crtc->active && conn->props.link_status != 0) {
 | 
						if (modeset && crtc->active && conn->props.link_status != 0) {
 | 
				
			||||||
| 
						 | 
					@ -227,17 +212,9 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!atomic_end(drm->fd, modeset ? DRM_MODE_ATOMIC_ALLOW_MODESET : 0,
 | 
						bool ok = atomic_commit(&atom, conn, flags);
 | 
				
			||||||
			&atom)) {
 | 
						atomic_finish(&atom);
 | 
				
			||||||
		drmModeAtomicSetCursor(atom.req, 0);
 | 
						return ok;
 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!atomic_commit(drm->fd, &atom, conn, flags, modeset)) {
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct wlr_drm_interface atomic_iface = {
 | 
					const struct wlr_drm_interface atomic_iface = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -296,7 +296,6 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
 | 
				
			||||||
	for (size_t i = 0; i < drm->num_crtcs; ++i) {
 | 
						for (size_t i = 0; i < drm->num_crtcs; ++i) {
 | 
				
			||||||
		struct wlr_drm_crtc *crtc = &drm->crtcs[i];
 | 
							struct wlr_drm_crtc *crtc = &drm->crtcs[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		drmModeAtomicFree(crtc->atomic);
 | 
					 | 
				
			||||||
		drmModeFreeCrtc(crtc->legacy_crtc);
 | 
							drmModeFreeCrtc(crtc->legacy_crtc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (crtc->mode_id) {
 | 
							if (crtc->mode_id) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,6 @@ struct wlr_drm_crtc {
 | 
				
			||||||
	// Atomic modesetting only
 | 
						// Atomic modesetting only
 | 
				
			||||||
	uint32_t mode_id;
 | 
						uint32_t mode_id;
 | 
				
			||||||
	uint32_t gamma_lut;
 | 
						uint32_t gamma_lut;
 | 
				
			||||||
	drmModeAtomicReq *atomic;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Legacy only
 | 
						// Legacy only
 | 
				
			||||||
	drmModeCrtc *legacy_crtc;
 | 
						drmModeCrtc *legacy_crtc;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue