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 }