aboutsummaryrefslogtreecommitdiff
path: root/backend/drm/backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/drm/backend.c')
-rw-r--r--backend/drm/backend.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
new file mode 100644
index 00000000..0da84745
--- /dev/null
+++ b/backend/drm/backend.c
@@ -0,0 +1,103 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <wayland-server.h>
+
+#include <wlr/session.h>
+#include <wlr/common/list.h>
+
+#include "backend.h"
+#include "backend/drm/backend.h"
+#include "backend/drm/drm.h"
+#include "backend/drm/udev.h"
+#include "common/log.h"
+
+static bool wlr_drm_backend_init(struct wlr_backend_state *state) {
+ wlr_drm_scan_connectors(state);
+ return true;
+}
+
+static void wlr_drm_backend_destroy(struct wlr_backend_state *state) {
+ if (!state) {
+ return;
+ }
+ // TODO: free outputs in shared backend code
+ wlr_drm_renderer_free(&state->renderer);
+ wlr_udev_free(&state->udev);
+ wlr_session_close_file(state->session, state->fd);
+ wlr_session_finish(state->session);
+ wl_event_source_remove(state->drm_event);
+ free(state);
+}
+
+static struct wlr_backend_impl backend_impl = {
+ .init = wlr_drm_backend_init,
+ .destroy = wlr_drm_backend_destroy
+};
+
+struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
+ struct wlr_session *session) {
+ struct wlr_backend_state *state = calloc(1, sizeof(struct wlr_backend_state));
+ if (!state) {
+ wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
+ return NULL;
+ }
+
+ struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
+ if (!backend) {
+ wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
+ return NULL;
+ }
+
+ state->backend = backend;
+ state->session = session;
+ state->outputs = list_create();
+ if (!state->outputs) {
+ wlr_log(L_ERROR, "Failed to allocate list");
+ goto error_backend;
+ }
+
+ if (!wlr_udev_init(display, &state->udev)) {
+ wlr_log(L_ERROR, "Failed to start udev");
+ goto error_list;
+ }
+
+ state->fd = wlr_udev_find_gpu(&state->udev, state->session);
+ if (state->fd == -1) {
+ wlr_log(L_ERROR, "Failed to open DRM device");
+ goto error_udev;
+ }
+
+ struct wl_event_loop *event_loop = wl_display_get_event_loop(display);
+
+ state->drm_event = wl_event_loop_add_fd(event_loop, state->fd,
+ WL_EVENT_READABLE, wlr_drm_event, NULL);
+ if (!state->drm_event) {
+ wlr_log(L_ERROR, "Failed to create DRM event source");
+ goto error_fd;
+ }
+
+ // TODO: what is the difference between the per-output renderer and this
+ // one?
+ if (!wlr_drm_renderer_init(&state->renderer, state->fd)) {
+ wlr_log(L_ERROR, "Failed to initialize renderer");
+ goto error_event;
+ }
+
+ return backend;
+
+error_event:
+ wl_event_source_remove(state->drm_event);
+error_fd:
+ wlr_session_close_file(state->session, state->fd);
+error_udev:
+ wlr_udev_free(&state->udev);
+error_list:
+ list_free(state->outputs);
+error_backend:
+ free(state);
+ free(backend);
+ return NULL;
+}