summaryrefslogtreecommitdiff
path: root/render/fx_renderer/util.c
diff options
context:
space:
mode:
authorErik Reider <[email protected]>2024-01-06 02:31:14 +0100
committerGitHub <[email protected]>2024-01-06 02:31:14 +0100
commit6759e8da7ab53a46b0eb04e5045b8c67262c3a11 (patch)
treec65ed83ca04b61bdbae7e1b8a7f2c16f29b89730 /render/fx_renderer/util.c
parentb929a2bbadf467864796ad4ec90882ce86cfebff (diff)
parentace97585b2b4d8cbb5ead6cd0f72fa8e8889c9d7 (diff)
Merge pull request #24 from wlrfx/wlroots-0.17-rebase
Rebase to wlroots 0.17
Diffstat (limited to 'render/fx_renderer/util.c')
-rw-r--r--render/fx_renderer/util.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/render/fx_renderer/util.c b/render/fx_renderer/util.c
new file mode 100644
index 0000000..c262aab
--- /dev/null
+++ b/render/fx_renderer/util.c
@@ -0,0 +1,113 @@
+#define _POSIX_C_SOURCE 200809L
+#include <fcntl.h>
+#include <unistd.h>
+#include <wlr/util/log.h>
+#include <wlr/types/wlr_buffer.h>
+#include <xf86drm.h>
+
+#include "render/fx_renderer/util.h"
+
+static uint32_t backend_get_buffer_caps(struct wlr_backend *backend) {
+ if (!backend->impl->get_buffer_caps) {
+ return 0;
+ }
+
+ return backend->impl->get_buffer_caps(backend);
+}
+
+static int open_drm_render_node(void) {
+ uint32_t flags = 0;
+ int devices_len = drmGetDevices2(flags, NULL, 0);
+ if (devices_len < 0) {
+ wlr_log(WLR_ERROR, "drmGetDevices2 failed: %s", strerror(-devices_len));
+ return -1;
+ }
+ drmDevice **devices = calloc(devices_len, sizeof(*devices));
+ if (devices == NULL) {
+ wlr_log_errno(WLR_ERROR, "Allocation failed");
+ return -1;
+ }
+ devices_len = drmGetDevices2(flags, devices, devices_len);
+ if (devices_len < 0) {
+ free(devices);
+ wlr_log(WLR_ERROR, "drmGetDevices2 failed: %s", strerror(-devices_len));
+ return -1;
+ }
+
+ int fd = -1;
+ for (int i = 0; i < devices_len; i++) {
+ drmDevice *dev = devices[i];
+ if (dev->available_nodes & (1 << DRM_NODE_RENDER)) {
+ const char *name = dev->nodes[DRM_NODE_RENDER];
+ wlr_log(WLR_DEBUG, "Opening DRM render node '%s'", name);
+ fd = open(name, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ wlr_log_errno(WLR_ERROR, "Failed to open '%s'", name);
+ goto out;
+ }
+ break;
+ }
+ }
+ if (fd < 0) {
+ wlr_log(WLR_ERROR, "Failed to find any DRM render node");
+ }
+
+out:
+ for (int i = 0; i < devices_len; i++) {
+ drmFreeDevice(&devices[i]);
+ }
+ free(devices);
+
+ return fd;
+}
+
+bool open_preferred_drm_fd(struct wlr_backend *backend, int *drm_fd_ptr,
+ bool *own_drm_fd) {
+ if (*drm_fd_ptr >= 0) {
+ return true;
+ }
+
+ // Allow the user to override the render node
+ const char *render_name = getenv("WLR_RENDER_DRM_DEVICE");
+ if (render_name != NULL) {
+ wlr_log(WLR_INFO,
+ "Opening DRM render node '%s' from WLR_RENDER_DRM_DEVICE",
+ render_name);
+ int drm_fd = open(render_name, O_RDWR | O_CLOEXEC);
+ if (drm_fd < 0) {
+ wlr_log_errno(WLR_ERROR, "Failed to open '%s'", render_name);
+ return false;
+ }
+ if (drmGetNodeTypeFromFd(drm_fd) != DRM_NODE_RENDER) {
+ wlr_log(WLR_ERROR, "'%s' is not a DRM render node", render_name);
+ close(drm_fd);
+ return false;
+ }
+ *drm_fd_ptr = drm_fd;
+ *own_drm_fd = true;
+ return true;
+ }
+
+ // Prefer the backend's DRM node, if any
+ int backend_drm_fd = wlr_backend_get_drm_fd(backend);
+ if (backend_drm_fd >= 0) {
+ *drm_fd_ptr = backend_drm_fd;
+ *own_drm_fd = false;
+ return true;
+ }
+
+ // If the backend hasn't picked a DRM FD, but accepts DMA-BUFs, pick an
+ // arbitrary render node
+ uint32_t backend_caps = backend_get_buffer_caps(backend);
+ if (backend_caps & WLR_BUFFER_CAP_DMABUF) {
+ int drm_fd = open_drm_render_node();
+ if (drm_fd < 0) {
+ return false;
+ }
+ *drm_fd_ptr = drm_fd;
+ *own_drm_fd = true;
+ return true;
+ }
+
+ return false;
+}