git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

scenefx/render/fx_renderer/util.c (2.7K)

  1 #include <fcntl.h>
  2 #include <unistd.h>
  3 #include <wlr/util/log.h>
  4 #include <wlr/types/wlr_buffer.h>
  5 #include <xf86drm.h>
  6 
  7 #include "render/fx_renderer/util.h"
  8 #include "util/env.h"
  9 
 10 static int open_drm_render_node(void) {
 11 	uint32_t flags = 0;
 12 	int devices_len = drmGetDevices2(flags, NULL, 0);
 13 	if (devices_len < 0) {
 14 		wlr_log(WLR_ERROR, "drmGetDevices2 failed: %s", strerror(-devices_len));
 15 		return -1;
 16 	}
 17 	drmDevice **devices = calloc(devices_len, sizeof(*devices));
 18 	if (devices == NULL) {
 19 		wlr_log_errno(WLR_ERROR, "Allocation failed");
 20 		return -1;
 21 	}
 22 	devices_len = drmGetDevices2(flags, devices, devices_len);
 23 	if (devices_len < 0) {
 24 		free(devices);
 25 		wlr_log(WLR_ERROR, "drmGetDevices2 failed: %s", strerror(-devices_len));
 26 		return -1;
 27 	}
 28 
 29 	int fd = -1;
 30 	for (int i = 0; i < devices_len; i++) {
 31 		drmDevice *dev = devices[i];
 32 		if (dev->available_nodes & (1 << DRM_NODE_RENDER)) {
 33 			const char *name = dev->nodes[DRM_NODE_RENDER];
 34 			wlr_log(WLR_DEBUG, "Opening DRM render node '%s'", name);
 35 			fd = open(name, O_RDWR | O_CLOEXEC);
 36 			if (fd < 0) {
 37 				wlr_log_errno(WLR_ERROR, "Failed to open '%s'", name);
 38 				goto out;
 39 			}
 40 			break;
 41 		}
 42 	}
 43 	if (fd < 0) {
 44 		wlr_log(WLR_ERROR, "Failed to find any DRM render node");
 45 	}
 46 
 47 out:
 48 	for (int i = 0; i < devices_len; i++) {
 49 		drmFreeDevice(&devices[i]);
 50 	}
 51 	free(devices);
 52 
 53 	return fd;
 54 }
 55 
 56 bool open_preferred_drm_fd(struct wlr_backend *backend, int *drm_fd_ptr,
 57 		bool *own_drm_fd) {
 58 	if (*drm_fd_ptr >= 0) {
 59 		return true;
 60 	}
 61 
 62 	if (env_parse_bool("WLR_RENDERER_FORCE_SOFTWARE")) {
 63 		*drm_fd_ptr = -1;
 64 		*own_drm_fd = false;
 65 		return true;
 66 	}
 67 
 68 	// Allow the user to override the render node
 69 	const char *render_name = getenv("WLR_RENDER_DRM_DEVICE");
 70 	if (render_name != NULL) {
 71 		wlr_log(WLR_INFO,
 72 			"Opening DRM render node '%s' from WLR_RENDER_DRM_DEVICE",
 73 			render_name);
 74 		int drm_fd = open(render_name, O_RDWR | O_CLOEXEC);
 75 		if (drm_fd < 0) {
 76 			wlr_log_errno(WLR_ERROR, "Failed to open '%s'", render_name);
 77 			return false;
 78 		}
 79 		if (drmGetNodeTypeFromFd(drm_fd) != DRM_NODE_RENDER) {
 80 			wlr_log(WLR_ERROR, "'%s' is not a DRM render node", render_name);
 81 			close(drm_fd);
 82 			return false;
 83 		}
 84 		*drm_fd_ptr = drm_fd;
 85 		*own_drm_fd = true;
 86 		return true;
 87 	}
 88 
 89 	// Prefer the backend's DRM node, if any
 90 	int backend_drm_fd = wlr_backend_get_drm_fd(backend);
 91 	if (backend_drm_fd >= 0) {
 92 		*drm_fd_ptr = backend_drm_fd;
 93 		*own_drm_fd = false;
 94 		return true;
 95 	}
 96 
 97 	// If the backend hasn't picked a DRM FD, but accepts DMA-BUFs, pick an
 98 	// arbitrary render node
 99 	if (backend->buffer_caps & WLR_BUFFER_CAP_DMABUF) {
100 		int drm_fd = open_drm_render_node();
101 		if (drm_fd < 0) {
102 			return false;
103 		}
104 		*drm_fd_ptr = drm_fd;
105 		*own_drm_fd = true;
106 		return true;
107 	}
108 
109 	return false;
110 }