aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--render/egl.c74
1 files changed, 63 insertions, 11 deletions
diff --git a/render/egl.c b/render/egl.c
index 5b52809a..6382c0c3 100644
--- a/render/egl.c
+++ b/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;
}