mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	render/egl: don't rely on being able to open primary node
On some setups (e.g. remote access via SSH) the current user won't have the permission to open the primary node at all. It's still possible to use drmGetDevices to match the primary node name returned by EGL. Closes: https://github.com/swaywm/wlroots/issues/2488
This commit is contained in:
		
							parent
							
								
									78e9e692e8
								
							
						
					
					
						commit
						44cea53e72
					
				
					 1 changed files with 63 additions and 11 deletions
				
			
		
							
								
								
									
										74
									
								
								render/egl.c
									
										
									
									
									
								
							
							
						
						
									
										74
									
								
								render/egl.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -854,6 +854,62 @@ bool wlr_egl_destroy_surface(struct wlr_egl *egl, EGLSurface surface) {
 | 
			
		|||
	return eglDestroySurface(egl->display, surface);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool device_has_name(const drmDevice *device, const char *name) {
 | 
			
		||||
	for (size_t i = 0; i < DRM_NODE_MAX; i++) {
 | 
			
		||||
		if (!(device->available_nodes & (1 << i))) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (strcmp(device->nodes[i], name) == 0) {
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *get_render_name(const char *name) {
 | 
			
		||||
	uint32_t flags = 0;
 | 
			
		||||
	int devices_len = drmGetDevices2(flags, NULL, 0);
 | 
			
		||||
	if (devices_len < 0) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "drmGetDevices2 failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	drmDevice **devices = calloc(devices_len, sizeof(drmDevice *));
 | 
			
		||||
	if (devices == NULL) {
 | 
			
		||||
		wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	devices_len = drmGetDevices2(flags, devices, devices_len);
 | 
			
		||||
	if (devices_len < 0) {
 | 
			
		||||
		free(devices);
 | 
			
		||||
		wlr_log(WLR_ERROR, "drmGetDevices2 failed");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const drmDevice *match = NULL;
 | 
			
		||||
	for (int i = 0; i < devices_len; i++) {
 | 
			
		||||
		if (device_has_name(devices[i], name)) {
 | 
			
		||||
			match = devices[i];
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	char *render_name = NULL;
 | 
			
		||||
	if (match == NULL) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "Cannot find DRM device %s", name);
 | 
			
		||||
	} else if (!(match->available_nodes & (1 << DRM_NODE_RENDER))) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "DRM device %s has no render node", name);
 | 
			
		||||
	} else {
 | 
			
		||||
		render_name = strdup(match->nodes[DRM_NODE_RENDER]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < devices_len; i++) {
 | 
			
		||||
		drmFreeDevice(&devices[i]);
 | 
			
		||||
	}
 | 
			
		||||
	free(devices);
 | 
			
		||||
 | 
			
		||||
	return render_name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int wlr_egl_dup_drm_fd(struct wlr_egl *egl) {
 | 
			
		||||
	if (egl->device == EGL_NO_DEVICE_EXT || !egl->exts.device_drm_ext) {
 | 
			
		||||
		return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -867,25 +923,21 @@ int wlr_egl_dup_drm_fd(struct wlr_egl *egl) {
 | 
			
		|||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int primary_fd = open(primary_name, O_RDWR | O_NONBLOCK | O_CLOEXEC);
 | 
			
		||||
	if (primary_fd < 0) {
 | 
			
		||||
		wlr_log_errno(WLR_ERROR, "Failed to open primary DRM device");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	char *render_name = drmGetRenderDeviceNameFromFd(primary_fd);
 | 
			
		||||
	char *render_name = get_render_name(primary_name);
 | 
			
		||||
	if (render_name == NULL) {
 | 
			
		||||
		wlr_log_errno(WLR_ERROR, "drmGetRenderDeviceNameFromFd failed");
 | 
			
		||||
		close(primary_fd);
 | 
			
		||||
		wlr_log(WLR_ERROR, "Can't find render node name for device %s",
 | 
			
		||||
			primary_name);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	close(primary_fd);
 | 
			
		||||
 | 
			
		||||
	int render_fd = open(render_name, O_RDWR | O_NONBLOCK | O_CLOEXEC);
 | 
			
		||||
	if (render_fd < 0) {
 | 
			
		||||
		wlr_log_errno(WLR_ERROR, "Failed to open render DRM device");
 | 
			
		||||
		wlr_log_errno(WLR_ERROR, "Failed to open DRM render node %s",
 | 
			
		||||
			render_name);
 | 
			
		||||
		free(render_name);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	free(render_name);
 | 
			
		||||
 | 
			
		||||
	return render_fd;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue