aboutsummaryrefslogtreecommitdiff
path: root/backend/wayland/backend.c
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2021-01-04 10:51:34 +0100
committerSimon Ser <contact@emersion.fr>2021-01-10 11:32:00 +0100
commit098094c5cbfd72ad989b9418b70acd531cbb5f17 (patch)
tree145058fd54281ce31258457c28364ea3f6c34dde /backend/wayland/backend.c
parent8f065810f6d73b244fd303323a8a58bdcb421296 (diff)
backend/wayland: use the EGL GBM platform
Just like other backends, use the EGL GBM platform. This will make it easier to move the allocator and renderer initialization out of the backends.
Diffstat (limited to 'backend/wayland/backend.c')
-rw-r--r--backend/wayland/backend.c134
1 files changed, 114 insertions, 20 deletions
diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c
index 7d7eeaf5..53da3604 100644
--- a/backend/wayland/backend.c
+++ b/backend/wayland/backend.c
@@ -10,6 +10,7 @@
#include <drm_fourcc.h>
#include <wayland-server-core.h>
+#include <xf86drm.h>
#include <wlr/backend/interface.h>
#include <wlr/interfaces/wlr_input_device.h>
@@ -23,6 +24,7 @@
#include "render/wlr_renderer.h"
#include "util/signal.h"
+#include "drm-client-protocol.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "pointer-gestures-unstable-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
@@ -99,6 +101,91 @@ static const struct zwp_linux_dmabuf_v1_listener linux_dmabuf_v1_listener = {
.modifier = linux_dmabuf_v1_handle_modifier,
};
+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;
+}
+
+static void legacy_drm_handle_device(void *data, struct wl_drm *drm,
+ const char *name) {
+ struct wlr_wl_backend *wl = data;
+
+ // TODO: get FD from linux-dmabuf hints instead
+ wl->drm_render_name = get_render_name(name);
+}
+
+static void legacy_drm_handle_format(void *data, struct wl_drm *drm,
+ uint32_t format) {
+ // This space is intentionally left blank
+}
+
+static void legacy_drm_handle_authenticated(void *data, struct wl_drm *drm) {
+ // This space is intentionally left blank
+}
+
+static void legacy_drm_handle_capabilities(void *data, struct wl_drm *drm,
+ uint32_t caps) {
+ // This space is intentionally left blank
+}
+
+static const struct wl_drm_listener legacy_drm_listener = {
+ .device = legacy_drm_handle_device,
+ .format = legacy_drm_handle_format,
+ .authenticated = legacy_drm_handle_authenticated,
+ .capabilities = legacy_drm_handle_capabilities,
+};
+
static void registry_global(void *data, struct wl_registry *registry,
uint32_t name, const char *iface, uint32_t version) {
struct wlr_wl_backend *wl = data;
@@ -139,6 +226,9 @@ static void registry_global(void *data, struct wl_registry *registry,
} else if (strcmp(iface, zwp_relative_pointer_manager_v1_interface.name) == 0) {
wl->zwp_relative_pointer_manager_v1 = wl_registry_bind(registry, name,
&zwp_relative_pointer_manager_v1_interface, 1);
+ } else if (strcmp(iface, wl_drm_interface.name) == 0) {
+ wl->legacy_drm = wl_registry_bind(registry, name, &wl_drm_interface, 1);
+ wl_drm_add_listener(wl->legacy_drm, &legacy_drm_listener, wl);
}
}
@@ -205,6 +295,7 @@ static void backend_destroy(struct wlr_backend *backend) {
wl_event_source_remove(wl->remote_display_src);
wlr_renderer_destroy(wl->renderer);
+ wlr_allocator_destroy(wl->allocator);
wlr_drm_format_set_finish(&wl->linux_dmabuf_v1_formats);
@@ -229,6 +320,7 @@ static void backend_destroy(struct wlr_backend *backend) {
if (wl->zwp_relative_pointer_manager_v1) {
zwp_relative_pointer_manager_v1_destroy(wl->zwp_relative_pointer_manager_v1);
}
+ free(wl->drm_render_name);
xdg_wm_base_destroy(wl->xdg_wm_base);
wl_compositor_destroy(wl->compositor);
wl_registry_destroy(wl->registry);
@@ -301,6 +393,11 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display,
"Remote Wayland compositor does not support xdg-shell");
goto error_registry;
}
+ if (!wl->drm_render_name) {
+ wlr_log(WLR_ERROR, "Failed to get DRM render node from remote Wayland "
+ "compositor wl_drm interface");
+ goto error_registry;
+ }
struct wl_event_loop *loop = wl_display_get_event_loop(wl->local_display);
int fd = wl_display_get_fd(wl->remote_display);
@@ -312,32 +409,28 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display,
}
wl_event_source_check(wl->remote_display_src);
- wl->renderer = wlr_renderer_autocreate(EGL_PLATFORM_WAYLAND_EXT,
- wl->remote_display);
- if (!wl->renderer) {
- wlr_log(WLR_ERROR, "Could not create renderer");
- goto error_event;
- }
-
- // TODO: get FD from linux-dmabuf hints instead
- int drm_fd = wlr_renderer_get_drm_fd(wl->renderer);
+ wlr_log(WLR_DEBUG, "Opening DRM render node %s", wl->drm_render_name);
+ int drm_fd = open(wl->drm_render_name, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (drm_fd < 0) {
- wlr_log(WLR_ERROR, "Failed to get DRM device FD from renderer");
- goto error_event;
+ wlr_log_errno(WLR_ERROR, "Failed to open DRM render node %s",
+ wl->drm_render_name);
+ goto error_registry;
}
- drm_fd = fcntl(drm_fd, F_DUPFD_CLOEXEC, 0);
- if (drm_fd < 0) {
- wlr_log_errno(WLR_ERROR, "fcntl(F_DUPFD_CLOEXEC) failed");
- goto error_event;
+ struct wlr_gbm_allocator *gbm_alloc = wlr_gbm_allocator_create(drm_fd);
+ if (gbm_alloc == NULL) {
+ wlr_log(WLR_ERROR, "Failed to create GBM allocator");
+ close(drm_fd);
+ goto error_registry;
}
+ wl->allocator = &gbm_alloc->base;
- struct wlr_gbm_allocator *alloc = wlr_gbm_allocator_create(drm_fd);
- if (alloc == NULL) {
- wlr_log(WLR_ERROR, "Failed to create GBM allocator");
- goto error_event;
+ wl->renderer = wlr_renderer_autocreate(EGL_PLATFORM_GBM_KHR,
+ gbm_alloc->gbm_device);
+ if (wl->renderer == NULL) {
+ wlr_log(WLR_ERROR, "Failed to create renderer");
+ goto error_registry;
}
- wl->allocator = &alloc->base;
uint32_t fmt = DRM_FORMAT_ARGB8888;
const struct wlr_drm_format *remote_format =
@@ -376,6 +469,7 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display,
error_event:
wl_event_source_remove(wl->remote_display_src);
error_registry:
+ free(wl->drm_render_name);
if (wl->compositor) {
wl_compositor_destroy(wl->compositor);
}