From 15b1ce9e6ced22a90ab0df7a6b86c6d35c40ca93 Mon Sep 17 00:00:00 2001
From: Drew DeVault <sir@cmpwn.com>
Date: Sun, 7 May 2017 10:00:23 -0400
Subject: Refactor backend state management

---
 backend/drm/backend.c | 113 ++++++++++++++++++++++++--------------------------
 backend/drm/drm.c     |  51 +++++++++++------------
 backend/drm/udev.c    |   5 ++-
 3 files changed, 82 insertions(+), 87 deletions(-)

(limited to 'backend/drm')

diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 42e7f5fd..8c02669a 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -8,106 +8,101 @@
 #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"
 
-struct wlr_drm_backend *wlr_drm_backend_init(struct wl_display *display,
-	struct wlr_session *session, struct wl_listener *add, struct wl_listener *rem,
-	struct wl_listener *render) {
+static bool wlr_drm_backend_init(struct wlr_backend_state *state) {
+	wlr_drm_scan_connectors(state);
+	return true;
+}
 
-	struct wlr_drm_backend *backend = calloc(1, sizeof *backend);
-	if (!backend) {
+static void free_output(void *item) {
+	struct wlr_drm_output *out = item;
+	wlr_drm_output_cleanup(out, true);
+	free(out);
+}
+
+static void wlr_drm_backend_destroy(struct wlr_backend_state *state) {
+	if (!state) {
+		return;
+	}
+	list_foreach(state->outputs, free_output);
+	list_free(state->outputs);
+	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;
 	}
 
-	backend->session = session;
+	struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
+	if (!backend) {
+		wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
+		return NULL;
+	}
 
-	backend->outputs = list_create();
-	if (!backend->outputs) {
+	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, &backend->udev)) {
+	if (!wlr_udev_init(display, &state->udev)) {
 		wlr_log(L_ERROR, "Failed to start udev");
 		goto error_list;
 	}
 
-	backend->fd = wlr_udev_find_gpu(&backend->udev, backend->session);
-	if (backend->fd == -1) {
+	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);
 
-	backend->drm_event = wl_event_loop_add_fd(event_loop, backend->fd,
+	state->drm_event = wl_event_loop_add_fd(event_loop, state->fd,
 		WL_EVENT_READABLE, wlr_drm_event, NULL);
-	if (!backend->drm_event) {
+	if (!state->drm_event) {
 		wlr_log(L_ERROR, "Failed to create DRM event source");
 		goto error_fd;
 	}
 
-	if (!wlr_drm_renderer_init(&backend->renderer, backend->fd)) {
+	if (!wlr_drm_renderer_init(&state->renderer, state->fd)) {
 		wlr_log(L_ERROR, "Failed to initialize renderer");
 		goto error_event;
 	}
 
-	wl_signal_init(&backend->signals.output_add);
-	wl_signal_init(&backend->signals.output_rem);
-	wl_signal_init(&backend->signals.output_render);
-
-	if (add) {
-		wl_signal_add(&backend->signals.output_add, add);
-	}
-	if (rem) {
-		wl_signal_add(&backend->signals.output_rem, rem);
-	}
-	if (render) {
-		wl_signal_add(&backend->signals.output_render, render);
-	}
-
-	wlr_drm_scan_connectors(backend);
-
 	return backend;
 
 error_event:
-	wl_event_source_remove(backend->drm_event);
+	wl_event_source_remove(state->drm_event);
 error_fd:
-	wlr_session_close_file(backend->session, backend->fd);
+	wlr_session_close_file(state->session, state->fd);
 error_udev:
-	wlr_udev_free(&backend->udev);
+	wlr_udev_free(&state->udev);
 error_list:
-	list_free(backend->outputs);
+	list_free(state->outputs);
 error_backend:
+	free(state);
 	free(backend);
 	return NULL;
 }
-
-static void free_output(void *item)
-{
-	struct wlr_drm_output *out = item;
-	wlr_drm_output_cleanup(out, true);
-	free(out);
-}
-
-void wlr_drm_backend_free(struct wlr_drm_backend *backend)
-{
-	if (!backend)
-		return;
-
-	list_foreach(backend->outputs, free_output);
-
-	wlr_drm_renderer_free(&backend->renderer);
-	wlr_udev_free(&backend->udev);
-	wlr_session_close_file(backend->session, backend->fd);
-	wlr_session_finish(backend->session);
-
-	wl_event_source_remove(backend->drm_event);
-
-	list_free(backend->outputs);
-	free(backend);
-}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index b5e5739a..abb3fb26 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -13,6 +13,7 @@
 #include <GLES3/gl3.h>
 #include <wayland-server.h>
 
+#include "backend.h"
 #include "backend/drm/backend.h"
 #include "backend/drm/drm.h"
 #include "common/log.h"
@@ -167,10 +168,10 @@ static int find_id(const void *item, const void *cmp_to) {
 	}
 }
 
-void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) {
+void wlr_drm_scan_connectors(struct wlr_backend_state *state) {
 	wlr_log(L_INFO, "Scanning DRM connectors");
 
-	drmModeRes *res = drmModeGetResources(backend->fd);
+	drmModeRes *res = drmModeGetResources(state->fd);
 	if (!res) {
 		wlr_log(L_ERROR, "Failed to get DRM resources");
 		return;
@@ -179,40 +180,40 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) {
 	for (int i = 0; i < res->count_connectors; ++i) {
 		uint32_t id = res->connectors[i];
 
-		drmModeConnector *conn = drmModeGetConnector(backend->fd, id);
+		drmModeConnector *conn = drmModeGetConnector(state->fd, id);
 		if (!conn) {
 			wlr_log(L_ERROR, "Failed to get DRM connector");
 			continue;
 		}
 
 		struct wlr_drm_output *out;
-		int index = list_seq_find(backend->outputs, find_id, &id);
+		int index = list_seq_find(state->outputs, find_id, &id);
 
 		if (index == -1) {
-			out = calloc(1, sizeof *out);
+			out = calloc(1, sizeof(struct wlr_drm_output));
 			if (!out) {
 				wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
 				drmModeFreeConnector(conn);
 				continue;
 			}
 
-			out->renderer = &backend->renderer;
+			out->renderer = &state->renderer;
 			out->state = DRM_OUTPUT_DISCONNECTED;
 			out->connector = id;
 			snprintf(out->name, sizeof out->name, "%s-%"PRIu32,
 				 conn_name[conn->connector_type],
 				 conn->connector_type_id);
 
-			drmModeEncoder *curr_enc = drmModeGetEncoder(backend->fd, conn->encoder_id);
+			drmModeEncoder *curr_enc = drmModeGetEncoder(state->fd, conn->encoder_id);
 			if (curr_enc) {
-				out->old_crtc = drmModeGetCrtc(backend->fd, curr_enc->crtc_id);
+				out->old_crtc = drmModeGetCrtc(state->fd, curr_enc->crtc_id);
 				free(curr_enc);
 			}
 
-			list_add(backend->outputs, out);
+			list_add(state->outputs, out);
 			wlr_log(L_INFO, "Found display '%s'", out->name);
 		} else {
-			out = backend->outputs->items[index];
+			out = state->outputs->items[index];
 		}
 
 		if (out->state == DRM_OUTPUT_DISCONNECTED &&
@@ -244,8 +245,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend) {
 
 			out->state = DRM_OUTPUT_NEEDS_MODESET;
 			wlr_log(L_INFO, "Sending modesetting signal for '%s'", out->name);
-			wl_signal_emit(&backend->signals.output_add, out);
-
+			wl_signal_emit(&state->backend->events.output_add, out);
 		} else if (out->state == DRM_OUTPUT_CONNECTED &&
 			conn->connection != DRM_MODE_CONNECTED) {
 
@@ -270,12 +270,12 @@ struct wlr_drm_mode *wlr_drm_output_get_modes(struct wlr_drm_output *out, size_t
 }
 
 bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mode) {
-	struct wlr_drm_backend *backend = wl_container_of(out->renderer, backend, renderer);
+	struct wlr_backend_state *state = wl_container_of(out->renderer, state, renderer);
 
 	wlr_log(L_INFO, "Modesetting '%s' with '%ux%u@%u'", out->name, mode->width,
 		mode->height, mode->rate);
 
-	drmModeConnector *conn = drmModeGetConnector(backend->fd, out->connector);
+	drmModeConnector *conn = drmModeGetConnector(state->fd, out->connector);
 	if (!conn) {
 		wlr_log(L_ERROR, "Failed to get DRM connector");
 		goto error;
@@ -286,7 +286,7 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod
 		goto error;
 	}
 
-	drmModeRes *res = drmModeGetResources(backend->fd);
+	drmModeRes *res = drmModeGetResources(state->fd);
 	if (!res) {
 		wlr_log(L_ERROR, "Failed to get DRM resources");
 		goto error;
@@ -294,7 +294,7 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod
 
 	bool success = false;
 	for (int i = 0; !success && i < conn->count_encoders; ++i) {
-		drmModeEncoder *enc = drmModeGetEncoder(backend->fd, conn->encoders[i]);
+		drmModeEncoder *enc = drmModeGetEncoder(state->fd, conn->encoders[i]);
 		if (!enc)
 			continue;
 
@@ -303,8 +303,8 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod
 				continue;
 			}
 
-			if ((backend->taken_crtcs & (1 << j)) == 0) {
-				backend->taken_crtcs |= 1 << j;
+			if ((state->taken_crtcs & (1 << j)) == 0) {
+				state->taken_crtcs |= 1 << j;
 				out->crtc = res->crtcs[j];
 
 				success = true;
@@ -327,7 +327,7 @@ bool wlr_drm_output_modeset(struct wlr_drm_output *out, struct wlr_drm_mode *mod
 	out->width = mode->width;
 	out->height = mode->height;
 
-	if (!display_init_renderer(&backend->renderer, out)) {
+	if (!display_init_renderer(&state->renderer, out)) {
 		wlr_log(L_ERROR, "Failed to initalise renderer for %s", out->name);
 		goto error;
 	}
@@ -343,15 +343,14 @@ error:
 	return false;
 }
 
-static void page_flip_handler(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec,
-	void *user) {
-
+static void page_flip_handler(int fd, unsigned seq,
+		unsigned tv_sec, unsigned tv_usec, void *user) {
 	struct wlr_drm_output *out = user;
-	struct wlr_drm_backend *backend = wl_container_of(out->renderer, backend, renderer);
+	struct wlr_backend_state *state = wl_container_of(out->renderer, state, renderer);
 
 	out->pageflip_pending = false;
 	if (out->state == DRM_OUTPUT_CONNECTED) {
-		wl_signal_emit(&backend->signals.output_render, out);
+		wl_signal_emit(&state->backend->events.output_frame, out);
 	}
 }
 
@@ -388,7 +387,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *out, bool restore) {
 	}
 
 	struct wlr_drm_renderer *renderer = out->renderer;
-	struct wlr_drm_backend *backend = wl_container_of(renderer, backend, renderer);
+	struct wlr_backend_state *state = wl_container_of(renderer, state, renderer);
 
 	switch (out->state) {
 	case DRM_OUTPUT_CONNECTED:
@@ -414,7 +413,7 @@ void wlr_drm_output_cleanup(struct wlr_drm_output *out, bool restore) {
 		}
 
 		wlr_log(L_INFO, "Emmiting destruction signal for '%s'", out->name);
-		wl_signal_emit(&backend->signals.output_rem, out);
+		wl_signal_emit(&state->backend->events.output_remove, out);
 		break;
 
 	case DRM_OUTPUT_DISCONNECTED:
diff --git a/backend/drm/udev.c b/backend/drm/udev.c
index 438047d6..e5470157 100644
--- a/backend/drm/udev.c
+++ b/backend/drm/udev.c
@@ -11,6 +11,7 @@
 
 #include <wlr/session.h>
 
+#include "backend.h"
 #include "backend/drm/backend.h"
 #include "backend/drm/udev.h"
 #include "backend/drm/drm.h"
@@ -139,7 +140,7 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) {
 
 static int udev_event(int fd, uint32_t mask, void *data) {
 	struct wlr_udev *udev = data;
-	struct wlr_drm_backend *backend = wl_container_of(udev, backend, udev);
+	struct wlr_backend_state *state = wl_container_of(udev, state, udev);
 
 	struct udev_device *dev = udev_monitor_receive_device(udev->mon);
 	if (!dev) {
@@ -156,7 +157,7 @@ static int udev_event(int fd, uint32_t mask, void *data) {
 		goto out;
 	}
 
-	wlr_drm_scan_connectors(backend);
+	wlr_drm_scan_connectors(state);
 
 out:
 	udev_device_unref(dev);
-- 
cgit v1.2.3